Ah... ignore my noise here - Brian Schott pointed out my problem off list.

(I had a 16 where I should have had a 15 and I was not paying
attention to the error - it was not an error from the assert but an
error from the definition, which means the definition I was running
was a different one.)

I'll fix this up, but for now.. just ignore my earlier post here.

Thanks,

-- 
Raul


On Sat, Jan 6, 2018 at 12:40 AM, Raul Miller <[email protected]> wrote:
> Hmm...
>
> It seems to me that this kind of problem could use a sequential
> machine (dyadic ;:) implementation to do some of the heavy lifting.
>
> Sadly, I believe i have run into a J engine bug, which prevents me
> from completing this idea.
>
> I'll drop my broken code here to show what I mean:
>
> m345=:(5;(0 10#:10*T=:".;._2]0 :0))&;:
>  0.1  2.1
>  1.0  1.0
>  1.0  3.0
>  1.0  4.0
>  5.0  1.0
>  5.0  6.0
>  1.0  7.0
>  1.0  8.0
>  1.0  9.0
> 10.0  1.0
> 10.0 11.0
>  1.0 12.0
>  1.0 13.0
>  1.0 14.0
>  1.0 15.0
> 16.0  1.0
> )
>
> assert 1-:m345 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0
> assert 0-:m345 1 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0
>
> My original idea was to use function code 13 and then use (,15)-: ...
> as the implementation. That doesn't work, though. So I was looking at
> a trace of the execution (the function code 5 thing that's currently
> there, and ... well, look at this:
>
>    (,.((-<.T){~2{"1 m345),.m345) 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0
> 0  0 _2  0 _1 0 0 0 1
> 1  0 _2  1  0 0 1 2 1
> 1 _1 _3  2  1 2 1 3 0
> 1 _1 _4  3  1 3 1 4 0
> 0 _5 _1  4  1 4 0 5 0
> 0 _5 _6  5  1 5 0 5 0
> 0 _5 _6  6  1 5 0 5 0
> 1 _5 _6  7  1 5 1 6 0
> 1 _1 _7  8  1 6 1 7 0
> 1 _1 _8  9  1 7 1 8 0
> 1 _1 _9 10  1 8 1 1 0
> 0 _1 _1 11  1 1 0 1 0
> 1 _1 _1 12  1 1 1 1 0
> 1 _1 _1 13  1 1 1 1 0
> 1 _1 _1 14  1 1 1 1 0
> 1 _1 _1 15  1 1 1 1 0
> 1 _1 _1 16  1 1 1 1 0
> 0 _1 _1 17  1 1 0 1 0
> 0 _1 _1 18  1 1 0 1 0
> 0 _1 _1 19  1 1 0 1 0
>
> The columns here are (left to right), the input bit, two columns for
> the relevant row from my machine definition (I am just interested in
> the next state from T, and I made those negative so they stand out)
> and the columns of the trace.
>
> Column 0 of the trace is an index into the input bits. Column 2 is
> used to pick the relevant row of T, and the bit chooses one of those
> two values, which then appears in column 4 of the trace.
>
> This works just fine, right up until the bit with index 10. There, the
> bit is 1, and the relevant row from T was 1 9 and 1{1 9 should be 9,
> but the trace shows that I'm getting a 1 instead.
>
> So either I am overlooking something critical (which I doubt ... but
> it's not like i have never made a mistake, before) or there's a bug in
> ;: (which might explain why other people have been discouraged from
> using ;:?)
>
> First thing though - does this work the same way for other people? If
> this behavior cannot be reproduced by some else, that introduces a
> whole different line of thinking...
>
> Thanks,
>
> --
> Raul
>
>
> On Fri, Jan 5, 2018 at 6:26 PM, Nick S <[email protected]> wrote:
>> Great suggestion.  I actually played with it for quite a while last night,
>> got it all working.  The solver can solve any puzzle I throw at it,
>> including those that barely have enough definition to hold together.  I can
>> imagine puzzles it can't solve but those would have to be constructed to be
>> unsolvable.
>>
>> I ended up using a lot of throws and trys and such.  In some cases, the
>> only exit from a routine is a set of throws with flag variables set, as in
>> the example, to communicate, and it took a heck of a lot of code.  In fact,
>> when I start the project, it takes way longer than it used to because there
>> is just way too much procedural code.
>>
>> I wonder just how expensive try. is.  I used to get solutions in the under
>> 2 second range.  Now I am getting solutions in the 3.5 second range.  But
>> this seems to be totally based on the amount of processing.  My first
>> solutions were solved without trial placement or backtracking, but the long
>> solutions require trial placement and backtracking.  I just checked one of
>> my old testcases and it is still under 2 seconds cpu for a solution.
>>
>> I also have hand coded backtracking, so that I can execute a trial solution
>> and easily give it up when it goes nowhere.
>>
>> J makes it easy to create relatively complex data structures (like stacks
>> for backtracking environments).  I ended up with a lot of code but most
>> other languages would have required five times as much code.
>>
>> My basic concept was that I kept a recursion count. and in my try./catcht/
>> I used the entry level to control what I did - generally at any level where
>> I recursed, I would just throw. again and at the entry level I would put
>> out an error message and then return.  So I don't get error messages when I
>> pick up the uncaught throw.  Now I am catching all my throws and always
>> reporting errors or successes from the top level.
>>
>> I appreciate all the advice I got while writing this.  I will work on it a
>> bit more to clean up the messages and any other bugs I find.  But I have
>> entered about 15 test cases, and it seems to be able to solve them all.
>>
>> I have used a lot of if-then-else and case logic.  I know, I should be
>> writing all this stuff as tacit one liners.  But I don't see how.  For
>> example, given the length of a boolean vector as 20, is there a way to
>> return  all of the possible placements of three groups of 1's with length
>> of 3, 4, and 5, always in that order, and with at least one zero between
>> them? There can be zero or more zeros between the placements and the wall.
>> In other words, all the vectors that, when converted to a character string,
>> match this regular expression:
>>
>> ^0*1{3}0+1{4}0+1{5}0*$
>>
>> 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0 matches
>>
>> 1 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0 does not.  The first group is too
>> long.  There are a very large number of possible wrong solutions, but there
>> are also a large number of valid solutions.
>>
>> I could not figure out how to do it - so I ended up writing a recursive
>> routine where I place the first piece and then pass the rest of the work (a
>> shortened string and fewer placements) to the recursive call.  The routine
>> has the advantage of letting me do early pruning of solutions where what I
>> have already placed violates constraints, and so forth.  And I never have
>> to generate a huge binary table, just to filter and compress it to get the
>> results that I need for the solution.
>>
>> I tried using adverse.  For me it was a miserable failure - I didn't
>> realize that (u y)::(error yy) was probably returning nouns, while adverse
>> wants verbs as you showed. I have not tried using generated errors.  What
>> is fun about this language, for me, is that scutwork (coding loops to
>> compare arrays or to move arrays) vanishes, while you can concentrate on
>> the logic of your program.
>>
>>
>>
>> On Sun, Dec 31, 2017 at 11:28 AM, Ian Clark <[email protected]> wrote:
>>
>>> What's "normal" and what's an "error"? (Or, for that matter, a "crash"?)
>>>
>>> When looking for the best solution to a coding problem, we can be prisoners
>>> of our emotive use of language. Way back in IBM in the 1980s I recall the
>>> end-user of a bespoke app written in APL picking up the phone in fury when
>>> it spat out at her the all-too-familiar APL message:
>>>       RANK ERROR
>>> – she thought the coder was being gratuitously offensive.
>>>
>>> Stripped of its pejorative connotations, error recovery is just a way of
>>> letting a deeply nested function escape and cut back the function stack –
>>> and to do it in a way that doesn't look to the end-user like a coding
>>> error. Or conversely, treating her to the sight of a raw coding error when
>>> she'd appreciate a polite message geared to her needs and competency.
>>>
>>> I use (::) a lot for this purpose. Far from being "ugly" I think it is
>>> clean and respectable, avoiding the need for (…but not precluding) a
>>> cumbersome system of error diagnostics – which then needs debugging in its
>>> own right.
>>>
>>> It also establishes a clear separation between "normal" code and
>>> special-case handling (including error recovery), which lets you design the
>>> former and then bolt-on as much of the latter as you need, and no more —
>>> which to my mind (try./catch.) doesn't.
>>>
>>> Paste this into a temp script and run it:
>>> ————————————————————————————————————————
>>>
>>> NB. Use of (::) to escape to the session in a clean and respectable way.
>>>
>>> NB. Avoid tainting the escape route with disapproval
>>>
>>> NB.  by using "general" not "normal" and "special" not "error".
>>>
>>>
>>> myApp=: general :: special
>>>
>>> general=: verb define
>>>   general1 y
>>> )
>>>
>>> general1=: verb define
>>>   NB. nest it deeper
>>>   addOne y
>>> )
>>>
>>> addOne=: verb define
>>>   NB. recognise special cases...
>>>   if. y<0 do. @@ end.
>>>   if. y>99 do. @@ end.
>>>   NB. else handle the general case...
>>>   y+1
>>> )
>>>
>>> special=: verb define
>>>   'myApp: cannot handle the argument: ' , ":y
>>> )
>>> ————————————————————————————————————————
>>>
>>> Running the app…
>>>
>>>    myApp 5 NB. handles general case ok
>>> 6
>>>    myApp _5 NB. rejects y<0
>>> myApp: cannot handle the argument: _5
>>>    myApp 100 NB. rejects y>99
>>> myApp: cannot handle the argument: 100
>>>    myApp '?' NB. forces a syntax error
>>> myApp: cannot handle the argument: ?
>>>
>>> Now, crashing (general) by executing (@@) is not everyone's idea of "clean
>>> and respectable". But worse – you can't tell a deliberate crash from an
>>> accidental one, as (myApp'?') shows.
>>>
>>> However instead of (@@) you can signal a quasi-error with your own private
>>> error number, and progressively code just the error diagnostics you need
>>> into verb: (special) to report any bona-fide coding errors you haven't
>>> fixed yet.
>>
>>
>>> NuVoc explains how:
>>>
>>> http://code.jsoftware.com/wiki/Vocabulary/ErrorMessages#Defi
>>> ning_your_own_error_conditions
>>>
>>> Thus you could redefine (addOne) and (special) like this…
>>>
>>> ————————————————————————————————————————
>>> addOne=: verb define
>>>   NB. recognise special cases...
>>>   if. y<0 do. signalErrorNumber 255 end.
>>>   if. y>99 do. signalErrorNumber 99 end.
>>>   NB. else handle the general case...
>>>   y+1
>>> )
>>>
>>> special=: verb define
>>>   select. latestErrorNumber''
>>>   case. 99 do. 'myApp: cannot handle y>99: ' , ":y
>>>   case. 255 do. 'myApp: cannot handle y<0: ' , ":y
>>>   case. do. latestErrorMessage''
>>>   end.
>>> )
>>>
>>> signalErrorNumber=: 13!:8
>>> latestErrorNumber=: 13!:11
>>> latestErrorMessage=: 13!:12
>>> ————————————————————————————————————————
>>>
>>> Now running the app…
>>>
>>>    myApp 5 NB. handles general case ok
>>> 6
>>>    myApp _5 NB. rejects y<0
>>> myApp: cannot handle y<0: _5
>>>    myApp 100 NB. rejects y>99
>>> myApp: cannot handle y>99: 100
>>>    myApp '?' NB. forces a coding error
>>> |domain error: addOne
>>> |   y    <0
>>>
>>>
>>>
>>>
>> ----------------------------------------------------------------------
>> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to