solitaire encryption in joy

stevan apter — 2000-05-28 16:34:23

i'm nibbling at the edges of coding up the solitaire encryption
algorithm in joy. as a guide, i'm using my k implementation, which
makes heavy use of list operations in place of explicit iteration.

one of the operations used by the solitaire algorithm is "triple
cut". here is how the operation is documented:

Perform a triple cut. That is, swap the cards above the first joker with the
cards below the second joker. If the deck used to look like:

2 4 6 B 5 8 7 1 A 3 9

then after the triple cut operation it will look like:

3 9 B 5 8 7 1 A 2 4 6

"First" and "second" jokers refer to whatever joker is nearest to, and furthest
from, the top of the deck. Ignore the "A" and "B" designations for this step.

Remember that the jokers and the cards between them don't move; the other cards
move around them. This is easy to do in your hands. If there are no cards in one
of the three sections (either the jokers are adjacent, or one is on top or the
bottom), just treat that section as empty and move it anyway. If the deck used
to look like:

B 5 8 7 1 A 3 9

then after the triple cut operation it will look like:

3 9 B 5 8 7 1 A

A deck that looks like:

B 5 8 7 1 A

will remain unchanged by this step.

and here is my k implementation:

t:{,/|(0,0 1+{x@<x}x?/:A,B)_ x}

here is how it works:

t is a lambda which takes one argument x, the deck.
the deck is a vector of 54 cards (the standard deck + 2 jokers)
A and B are the two jokers.

suppose x is as above, where A = 10 and B = 11:

x:2 4 6 11 5 8 7 1 10 3 9

then t does the following:

x?/:A,B / find the indices of A and B in x
8 3

sort the result:

{x@<x}8 3
3 8

add 0 and 1 to the result:

0 1+3 8
3 9

prepend a 0:

0,4 9
0 3 9

cut the deck into three lists at those positions:

0 3 9 _ x
(2 4 6
11 5 8 7 1 10
3 9)

reverse this list:

| 0 3 9 _ x
(3 9
11 5 8 7 1 10
2 4 6)

and flatten it:

,/|0 3 9 _ x
3 9 11 5 8 7 1 10 2 4 6

we are done.

a joy implementation of triple cut therefore might look like this:

deck
deck A find
deck B find
upsort
[0 1] +
0 swoncat
cut
reverse
flatten

find, upsort, and cut are easy to implement in joy. in my k implementation
this is just:

find:Two[{y?x}]
cut:Two[{y _ x}]
upsort:Two[{x@<x}]