[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: [QUIZ][SOLUTION] The Solitaire Cipher (#1

Warren Brown

10/4/2004 5:25:00 PM

I *finally* had a chance to play with this. On the premise of "better
late than never"...

My solution is pretty bare-bones, but uses regular expressions to
"simplify" the deck manipulations. I didn't keep the suit/rank notation
of the description except for the jokers being A and B. The rest of the
cards are simply their numeric values. Of course this means that the
"deck" string contains a newline, so all regular expressions involving a
'.' have to be multiline.




module SolitaireCipher
class Keystream
ORDERED_DECK = (("\000".."\063").to_a + ['A','B']).join

def initialize(deck = ORDERED_DECK.dup)
@deck = deck
@original_deck = @deck.dup
end

def reset
@deck = @original_deck.dup
self
end

def next_key
case @deck
when /A\z/ then @deck.sub!(/(.*)A/m,'A\1')
else @deck.sub!(/A(.)/m,'\1A')
end
case @deck
when /B\z/ then @deck.sub!(/(..)(.*)B/m,'\1B\2')
when /B.\z/m then @deck.sub!(/(.)(.*)B/m,'\1B\2')
else @deck.sub!(/B(..)/m,'\1B')
end
@deck.sub!(/(.*)([AB].*[AB])(.*)/m,'\3\2\1')
count = if @deck =~ /[AB]\z/ then 53 else @deck[-1] + 1 end
@deck.sub!(/(.{#{count}})(.*)(.)/m,'\2\1\3')
count = if @deck =~ /\A[AB]/ then 53 else @deck[0] + 1 end
if @deck[count..count] =~ /[AB]/ then next_key else @deck[count] +
1 end
end
end

def self.text2intarray(text)
intarray = []
text.upcase.delete('^A-Z').each_byte { |letter| intarray << (letter
- ?A) }
intarray.fill((?X - ?A), intarray.length, (-intarray.length) % 5)
end

def self.intarray2text(intarray)
text = ''
intarray.each { |int| text += (int + ?A).chr }
text.gsub(/(.....)(?=.)/,'\1 ')
end

def self.encode(plaintext,keystream)
intarray2text(text2intarray(plaintext).map { |int| (int +
keystream.next_key) % 26 })
end

def self.decode(ciphertext,keystream)
intarray2text(text2intarray(ciphertext).map { |int| (int -
keystream.next_key) % 26 })
end
end

keystream = SolitaireCipher::Keystream.new
puts ciphertext = SolitaireCipher.encode("Code in Ruby, live
longer!",keystream)
puts SolitaireCipher.decode(ciphertext,keystream.reset)
puts SolitaireCipher.decode('CLEPK HHNIY CFPWH FDFEH',keystream.reset)
puts SolitaireCipher.decode('ABVAW LWZSY OORYK DUPVH',keystream.reset)




- Warren Brown




1 Answer

James Gray

10/4/2004 5:37:00 PM

0

On Oct 4, 2004, at 12:25 PM, Warren Brown wrote:

> I *finally* had a chance to play with this. On the premise of "better
> late than never"...
>
> My solution is pretty bare-bones, but uses regular expressions to
> "simplify" the deck manipulations. I didn't keep the suit/rank
> notation
> of the description except for the jokers being A and B. The rest of
> the
> cards are simply their numeric values. Of course this means that the
> "deck" string contains a newline, so all regular expressions involving
> a
> '.' have to be multiline.

Clever trick. This is similar to how the Perl version works which you
can find on the official site I linked to in the summary. Thanks for
sending this in.

James Edward Gray II