```On Sep 26, 2004, at 9:39 AM, Jamis Buck wrote:

> (Not sure how best to post my solution, so I'm just replying to
> Florian's message...figured it might be nice to keep the solutions all
> in the same thread, at least...)

Sounds good to me.

My own solution is below.  Eating my own dog food, as it were.

I went for a nice boring step by step translation into Ruby.  No
classes.  I too just treated the deck as an array of numbers and the
two jokers.  I didn't provide a way to key the deck.  Pretty boring
stuff here.

James Edward Gray II

#!/usr/bin/ruby -w

\$deck = (1..52).to_a + ["A", "B"]		# Unkeyed deck - Keystream Step 1

def encrypt(message)
# Step 1
message = message.upcase.tr("^A-Z", "")
i = 5
while i < message.size
message[i, 0] = " "
i += 6
end
message += "X" while message.rindex(" ") != message.size - 6

# Step 2
key_stream = generate(message.count("^ "))

# Step 3
values = message.split("").map { |letter| letter[0] - ?A + 1 }

# Step 4
key_values = key_stream.split("").map { |letter| letter[0] - ?A + 1 }

# Step 5
values.each_with_index do |value, index|
next if value < 0
values[index] = value + key_values[index]
values[index] -= 26 if values[index] > 26
end

# Step 6
message = (values.map { |number| (number - 1 + ?A).chr }).join("")

return message
end

def decrypt(message)
# Step 1
key_stream = generate(message.size)

# Step 2
values = message.split("").map { |letter| letter[0] - ?A + 1 }

# Step 3
key_values = key_stream.split("").map { |letter| letter[0] - ?A + 1 }

# Step 4
values.each_with_index do |value, index|
next if value < 0
if value <= key_values[index]
values[index] = value + 26 - key_values[index]
else
values[index] = value - key_values[index]
end
end

# Step 5
message = (values.map { |number| (number - 1 + ?A).chr }).join("")

return message
end

def generate(count)		# Keystream Steps
key_stream = [ ]

until key_stream.size == count
# Step 2
a = \$deck.index("A")
if a == 53
\$deck.insert(1, \$deck.pop)
else
\$deck.insert(a + 1, \$deck.delete_at(a))
end

# Step 3
b = \$deck.index("B")
if b == 53
\$deck.insert(2, \$deck.pop)
elsif b == 52
\$deck.insert(1, \$deck.delete_at(b))
else
\$deck.insert(b + 2, \$deck.delete_at(b))
end

# Step 4
a = \$deck.index("A")
b = \$deck.index("B")
top = [a, b].min
bottom = [a, b].max
\$deck = \$deck.values_at((bottom + 1)..53, top..bottom, 0...top)

# Step 5
if \$deck[53].kind_of? Integer
\$deck = \$deck.values_at(\$deck[53]..52, 0...\$deck[53], 53)
end

# Step 5
if \$deck[0].kind_of? Integer
if \$deck[\$deck[0]].kind_of? Integer
key_stream.push(\$deck[\$deck[0]])
end
else
if \$deck[53].kind_of? Integer
key_stream.push(\$deck[53])
end
end
end		# Step 7

key_stream.map! do |number|
if number > 26
(number - 26 - 1 + ?A).chr
else
(number - 1 + ?A).chr
end
end
key_stream = key_stream.join("")
i = 5
while i < key_stream.size
key_stream[i, 0] = " "
i += 6
end
return key_stream
end