I've tried inputting your code in jqt several times, each time
with a
new
jqt terminal and keep encountering errors. Here's the last try:
move_table=:
<:(,|."1)(#~0<*/"1)~.,/,/_3&{.\@/:~"1(,|:"2)>|:((;|.)@(1++)+/)\i.5
flip=: ~: (i.15)&e.
legal_moves=: [ #~ 6 = 2 #. {
search=:3 :0
((15#1) flip y) search i.0 3
NB. x: board; y: moves
:
if. 1=+/x do. y return. end.
for_move. move_table legal_moves x do.
r=.(x flip move) search move,y
if. #r do. r return. end.
end.
i.0 3
solitaire=:3 :0
path=. search y
if. #path do. path else. 'No solution' end.
|spelling error
| if. #path do. path else. 'No solution' end.
| ^
B/t/w, does it work for:
solitaire 0 10 14?
I remember you had some question about that.
Michael
On Thu, Jun 8, 2017 at 6:44 AM, Raul Miller <[email protected]>
I've already posted code for changing a board and extracting legal
moves
from it that satisfactorily produced a path to a win. If you like,
you're
free to take a swing at finishing it any way you think will work.
I thought I had posted a finished implementation?
http://www.jsoftware.com/pipermail/programming/2017-June/047522.html
solitaire 5
14 9 5
2 5 9
3 4 5
10 6 3
1 3 6
12 7 3
13 8 4
9 5 2
2 4 7
11 7 4
6 3 1
0 1 3
3 4 5
If you feel there's something wrong with this approach, let me know
and I'll see if I can wrap my head around those issues.
Thanks,
--
Raul
On Wed, Jun 7, 2017 at 11:21 PM, Michael Rice <[email protected]>
wrote:
@ Raul Miller
"I guess I disagree with the model you posted here, about how to
implement the peg game"
I've already posted code for changing a board and extracting legal
moves
from it that satisfactorily produced a path to a win. If you like,
you're
free to take a swing at finishing it any way you think will work.
Here's
my
Clojure code (see below) for the two remaining functions,
*search* and
*solitaire*.
The *recur* function calls just act as calls to the original
function
that
called them, and could be replaced with the name of that
function and
get
the same result.
Search function:
That first *if-let* tries to pull a move off the top of the
incoming
moves
list. If it fails, i.e., moves was empty, it drops through to
the *if*
statement below it where it checks the board for just one
remaining
peg.
If
true, it returns the path to the solution. If not it checks the
history
stack. If it's empty, it prints "No solution." Otherwise it pulls a
board
and move-list (the move list being the rest of the moves for a
previous
move that led to a dead-end) off the history stack, and recurs with
that
board, its move list, the path list minus the last move added,
and the
rest
of the history stack. As you can see, the elements of the history
stack
are
lists with two sublists, one for the board, the other for its
remaining
moves.
If the search function gets a move, you can see for yourself
what it
does:
1) create the next board
2) recur(next-board, moves for next-board, move added to path,
the
current
board and the rest of its moves pushed onto the history stack)
Solitaire function:
The board is modeled like the J code I posted.
The recursion is kicked off with that board, its moves, an empty
vector
to
accumulate the path (see note below), and an empty history
stack (a
list).
Note: A nice feature of Clojure is using a vector instead of a
list to
accumulate a path. An item is added to a list at its top. An
item is
added
to a vector at its end. Popping a list removes the first element.
Popping a
vector removes the last element. Using a list to accumulate a path
requires
reversing the list before printing it. Using a vector
eliminates that
requirement. Lists are enclosed in parentheses, vectors in
brackets.
If you, or anyone else, pursues this, feel free to ask any
questions
you
might have.
Michael
Code (Change font to fixed-width if it doesn't come across as
that.
It's
easier to read with proper indentatation):
(defn search
[board moves path history]
(if-let [move (when-let [s (seq moves)] (first s))]
(let [next-board (make-move board move)]
(recur next-board (find-moves next-board) (conj path move)
(conj
history (list board (rest moves)))))
(if (= (reduce + 0 board) 1)
path
(if-let [backtrack (when-let [s (seq history)] (first s))]
(let [[board moves] backtrack]
(recur board moves (pop path) (rest history)))
"No solution."))))
(defn solitaire
; lst: empty board location(s)
[lst]
(let [board (reduce #(assoc %1 %2 0) [1 1 1 1 1 1 1 1 1 1 1
1 1 1
1]
lst)]
(search board (find-moves board) [] ())))
;user=> (solitaire '(5))
;[[0 2 5] [3 1 0] [5 4 3] [6 3 1] [0 1 3] [11 7 4] [3 4 5] [9 5 2]
[13 12
11] [10 11 12] [12 8 5] [2 5 9] [14 9 5]]
On Wed, Jun 7, 2017 at 3:23 PM, Raul Miller
<[email protected]>
wrote:
Oh... well...
I guess I disagree with the model you posted here, about how to
implement the peg game: I think that a spec requiring five
arrays is
unnecessarily redundant.
That said, I did make an error in one of my posts, which I am
only
just now realizing: the move_table depends on the size of the
board,
and I didn't deal with that in my supposed general case
implementation. Fortunately, the fix is straightforward, and I
could
post that if you wanted.
Anyways... to address the complexity argument you're raising,
you can
have up to four hetrogenous unboxed array parameters in a
recursive
context in J without resorting to objects to represent them.
Specifically: verbs can take one or two arguments, adverbs
give you
an
additional argument and conjunctions another on top of that. With
objects, or with boxing, you can go much higher - but that can
indeed
feel kludgy if you need an object or box for every recursive
invocation. But you can also often rearrange things to not
need so
many recursive parameters.
And for the peg problem, I only see three significant arrays: the
board, the moves to reach that board and the list of legal moves.
Recursive contexts give you a stack, allowing you to backtrack
with
these arrays. I'm not seeing why you need more than that?
Thanks,
--
Raul
On Wed, Jun 7, 2017 at 2:26 PM, Michael Rice
<[email protected]>
wrote:
Thanks for the paste tip. I was unaware of that feature.
I'm "giving up on" the peg game. I didn't think that needed
identifying
as
it's been my only focus. I think of "academic exercises" as
homework,
seeking answers to which is, rightly, taboo on computer language
web-sites.
The peg game search function has five arrays it recursively
manipulates
to
a solution, three of which begin as empty, all having varying
shapes,
even
empty, as they pass through recursions. From what I've read in
*Learning J*,
for their heterogeneous shapes they would have to be boxed to be
passed
as
a functional parameter, un-boxed inside a recursive pass to be
altered,
and
then boxed again to be passed on to the next recursion. I didn't
say
it
was
impossible, just that it seemed kludgy, or, as you put it
"forced."
I spent quite a bit of time with Haskell. As a functional
language
it's
hard to beat, but some problems on which I used it I felt like I
was
having
to go around the block just to get next door. Why bother?
Thanks for your input.
On Wed, Jun 7, 2017 at 1:11 PM, Raul Miller
<[email protected]
wrote:
When pasting into gmail, please use "Paste and match style" to
avoid
the extra blank lines that someone at google somehow managed to
work
into the default Paste action.
That said:
my_empty =: }. 1
< my_empty
┌┐
││
└┘
What you are seeing here is not an empty list of boxes but a
box
containing an empty. Or, ok, yes: "an empty box".
Note also that a: is the same:
a:
┌┐
││
└┘
a: -: <}.1
1
(Finally, I should perhaps note that I have no idea what
problem
you
are giving up on. Usually, though, "academic exercises" - which
typically focus more on how the goal is reached than on
reaching
the
goal - tend to feel forced in J.)
Thanks,
--
Raul
On Wed, Jun 7, 2017 at 1:03 PM, Michael Rice
<[email protected]
wrote:
@robert therriault
my_empty =: }. 1
my_empty
f my_empty
1
< my_empty
┌┐
││
└┘
An empty box?
I'm beginning to see the problem I was thinking of doing in
J is
ill-suited
to the language. It could be done, as it could in any computer
language,
but the solution would be pretty kludgy.
I'll soon think of something else on which to apply J. It's
already
invading my sleep. Going through exercises is no way to get
into a
language. One needs a problem on which to focus it. I've been
wanting
to
explore cryptography more deeply, and J seems ideal for it.
Thanks to all,
Michael
On Wed, Jun 7, 2017 at 12:01 PM, robert therriault <
[email protected]>
wrote:
I'm going to look at these results through the lens of Shape
($)
f =: (1&,)
f 2
1 2
$ f 2 NB. shape is 2
2
f ''
1
$ f '' NB. shape is 1
1
empty NB. it is a verb in my environment
(i.0 0)"_
f empty
f empty NB. result of two verbs and no arguments is just
the
two
verbs
f empty 2 NB. this is where you expect to have a 1
returned
$ f empty 2 NB. shape is 1 0
1 0 NB. one line of no items means no display
I think it is the second dimension of EMPTY as opposed to
NULL
that
is
tripping you up.
NULL=.''
$ NULL
0
EMPTY
$EMPTY
0 0
EMPTY-:empty 1
1
In answer to your most recent question Michael, I would say
just
make
sure
that the empty list that you pass is the right shape.
Cheers, bob
On Jun 7, 2017, at 8:48 AM, Raul Miller <
[email protected]>
wrote:
empty is a verb
f is a verb
so f empty is a verb (a hook)
f=: 1&,
(f empty) 3
$(f empty) 3
3 0
$(f empty) 5
5 0
The reasons for this are documented at
http://www.jsoftware.com/help/dictionary/dictf.htm (hooks)
and
http://www.jsoftware.com/help/dictionary/d630n.htm (x m&v
y).
That said, verbs take arguments and empty is a verb - it
always
produces an empty result, but only when it gets an argument.
I hope this helps,
--
Raul
On Wed, Jun 7, 2017 at 11:39 AM, Michael Rice <
[email protected]
wrote:
Oops! Guess I creamed empty. Will close and regen Jqt before
proceeding.
Done!
f =: (1&,)
f 2
1 2
f empty
f empty
Shouldn't it have returned
1
?
On Wed, Jun 7, 2017 at 11:22 AM, robert therriault <
[email protected]>
wrote:
One thing to remember is that empty is already defined as a
verb
empty
(i.0 0)"_
So if you overwrite this you may break some code if you
have
previously
relied on the existing verb definition.
I think along the lines that Pascal mentioned that null
could
be
similarly
defined as
null NB. check that it is not already used
|value error: null
null=:(i.0)"_
NULL NB. check that it is not already used -
uppercase
for
global
nouns is a convention I like and is often seen in J code
|value error: NULL
NULL=:'' NB. I use this as the null string (same as
what
John
suggested)
NULL-:null 2 NB. any argument produces NULL from null
1
Hope this helps,
Cheers, bob
On Jun 7, 2017, at 8:09 AM, 'Jon Hough' via Programming <
[email protected]> wrote:
I may be wrong in doing this, but I usually write
empty=: ''
to signify an empty list, array, matrix etc.
On Jun 7, 2017, 23:59, at 23:59, Michael Rice <
[email protected]
wrote:
Is there a special "noun" for an empty list?
Creating one seems enigmatic.
empty =: 1 2
empty
1 2
empty =: }. empty
empty
2
empty =: }. empty
empty
empty1 =:
|syntax error
| empty1=:
------------------------------
------------------------------
----------
For information about J forums see
http://www.jsoftware.com/
forums.htm
------------------------------
------------------------------
----------
For information about J forums see
http://www.jsoftware.com/
forums.htm
------------------------------
------------------------------
----------
For information about J forums see
http://www.jsoftware.com/
forums.htm
------------------------------
------------------------------
----------
For information about J forums see
http://www.jsoftware.com/
forums.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/
forums.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/
forums.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/
forums.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/
forums.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/
forums.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/forum
s.htm
------------------------------------------------------------
----------
For information about J forums see http://www.jsoftware.com/forum
s.htm
----------------------------------------------------------------------
For information about J forums see
http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see
http://www.jsoftware.com/forums.htm