Q: Shifting a hash anf and array

Hi,

I am looking for a neat "trick" to shift the contents of an array and
an hash. I know, that this is more or less explicitely programmable
in a few lines, but may be there is something faster, trickier, nicer
than that. It should work like this:

Contents of the array before the trick:

1 2 3 4 5 6 7 8 9 0 index
A B C D E F G H I J contents

(execute *trick*)

Contents of the array after the trick:

1 2 3 4 5 6 7 8 9 0 index
J A B C D E F G H I contents

And now the shift of an hash:

Contents of the hash before the trick:

A B C D E F G H I J key
1 2 3 4 5 6 7 8 9 0 value

(execute *trick*)

Contents of the hash after the trick:

A B C D E F G H I J key
0 1 2 3 4 5 6 7 8 9 value

Both are very similiar.

I am curious, how "compressed" and/or "tricky" a working code can be to do the
*trick*.... :slight_smile:

(I know, that this most often does not result in "good code" or
"something which can be taken as an example for master
programming" :slight_smile: ...but I always intersted in "thinking tricky" ...
just for the fun of it and for the production release :)))

Thank you very much fro any idea!

Ruby.use!
Meino

I used my algorithm skills to come up with this strange solution:
swap every consecutive values starting from the beginning of the array,
which can be written with the methods:

class Array
  def left_shift!
    each_index do |i|
    self[i], self[i+1] = self[i+1], self[i] if self[i+1]
  end
  end

  # of course you can prefer the cleaner:
  def left_shift_v2!
    obj = shift
  self << obj
  end

  def right_shift!
    obj = pop
  unshift obj
  end
end

···

On 2004-08-17, Meino Christian Cramer <Meino.Cramer@gmx.de> wrote:

Contents of the array before the trick:

1 2 3 4 5 6 7 8 9 0 index
A B C D E F G H I J contents

Contents of the array after the trick:

1 2 3 4 5 6 7 8 9 0 index
J A B C D E F G H I contents

--
Olivier D.

Contents of the array before the trick:

1 2 3 4 5 6 7 8 9 0 index
A B C D E F G H I J contents

(execute *trick*)

Contents of the array after the trick:

1 2 3 4 5 6 7 8 9 0 index
J A B C D E F G H I contents

array.unshift(array.pop)

And now the shift of an hash:

Contents of the hash before the trick:

A B C D E F G H I J key
1 2 3 4 5 6 7 8 9 0 value

(execute *trick*)

Contents of the hash after the trick:

A B C D E F G H I J key
0 1 2 3 4 5 6 7 8 9 value

Both are very similiar.

Not really :slight_smile: Hashes are inherently unordered, so the concept of a
rotation is a bit trickier. This works on the assumption that
Hash#values returns values in positions corresponding to the keys in
Hash#keys...

class Array
  def rot1
    unshift(pop)
  end
end

Hash[*(hash.keys.rot1.zip(hash.values.rot1).flatten)]

martin

···

Meino Christian Cramer <Meino.Cramer@gmx.de> wrote:

"Martin DeMello" <martindemello@yahoo.com> schrieb im Newsbeitrag
news:u_gUc.122944$M95.4319@pd7tw1no...

>
> Contents of the array before the trick:
>
> 1 2 3 4 5 6 7 8 9 0 index
> A B C D E F G H I J contents
>
> (execute *trick*)
>
> Contents of the array after the trick:
>
> 1 2 3 4 5 6 7 8 9 0 index
> J A B C D E F G H I contents

array.unshift(array.pop)

or array.push(array.shift) for the other direction.

> And now the shift of an hash:
>
> Contents of the hash before the trick:
>
> A B C D E F G H I J key
> 1 2 3 4 5 6 7 8 9 0 value
>
> (execute *trick*)
>
> Contents of the hash after the trick:
>
> A B C D E F G H I J key
> 0 1 2 3 4 5 6 7 8 9 value
>
> Both are very similiar.

Not really :slight_smile: Hashes are inherently unordered, so the concept of a
rotation is a bit trickier. This works on the assumption that
Hash#values returns values in positions corresponding to the keys in
Hash#keys...

class Array
  def rot1
    unshift(pop)
  end
end

Hash[*(hash.keys.rot1.zip(hash.values.rot1).flatten)]

Hm, IMHO there is one "rot1" too much: you're rotating keys *and* values
while you should only rotate one of them. Otherwise I figure the result
will be the same as the original hash... :slight_smile:

The other drawback of your solution is that it relys on #keys and #values
returning elements in matching order, i.e., if you zip both you get the same
hash. Although that might work it makes me feel a bit wary because AFAIK
it's not a guaranteed property of Hash (and I wouldn't want to rely on it).
This might even change over time if the Hash implementation was changed for
any reasons.

How about these one liners, that avoids the problem:

h = {0=>"a", 1=>"b", 2=>"c"}
# put rotated in h2
(h2={}).send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]})
# rotate inplace
h.send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h[k1]=v2; [k2, v1]})

:slight_smile:

Note: you can omit the sort in the first example, but IMHO an order should
be imposed on keys. Otherwise the rotation does not make much sense IMHO.
You can omit the sort in the second example, too, which seems to work
because the set of keys of the hash doesn't change. But this seems a bit
hackish to me, too. You can substitute "sort" by "dup" though.

Kind regards

    robert

PS: Enumerable#inject is cool. :wink:

···

Meino Christian Cramer <Meino.Cramer@gmx.de> wrote:

Hi Martin, Hi Robert,

thank you very much for your sources !
Great! :slight_smile:

I have an additional question below.....vvvvvv

"Martin DeMello" <martindemello@yahoo.com> schrieb im Newsbeitrag
news:u_gUc.122944$M95.4319@pd7tw1no...
> >
> > Contents of the array before the trick:
> >
> > 1 2 3 4 5 6 7 8 9 0 index
> > A B C D E F G H I J contents
> >
> > (execute *trick*)
> >
> > Contents of the array after the trick:
> >
> > 1 2 3 4 5 6 7 8 9 0 index
> > J A B C D E F G H I contents
>
> array.unshift(array.pop)

or array.push(array.shift) for the other direction.

> > And now the shift of an hash:
> >
> > Contents of the hash before the trick:
> >
> > A B C D E F G H I J key
> > 1 2 3 4 5 6 7 8 9 0 value
> >
> > (execute *trick*)
> >
> > Contents of the hash after the trick:
> >
> > A B C D E F G H I J key
> > 0 1 2 3 4 5 6 7 8 9 value
> >
> > Both are very similiar.
>
> Not really :slight_smile: Hashes are inherently unordered, so the concept of a
> rotation is a bit trickier. This works on the assumption that
> Hash#values returns values in positions corresponding to the keys in
> Hash#keys...
>
> class Array
> def rot1
> unshift(pop)
> end
> end
>
> Hash[*(hash.keys.rot1.zip(hash.values.rot1).flatten)]

Hm, IMHO there is one "rot1" too much: you're rotating keys *and* values
while you should only rotate one of them. Otherwise I figure the result
will be the same as the original hash... :slight_smile:

The other drawback of your solution is that it relys on #keys and #values
returning elements in matching order, i.e., if you zip both you get the same
hash. Although that might work it makes me feel a bit wary because AFAIK
it's not a guaranteed property of Hash (and I wouldn't want to rely on it).
This might even change over time if the Hash implementation was changed for
any reasons.

How about these one liners, that avoids the problem:

h = {0=>"a", 1=>"b", 2=>"c"}
# put rotated in h2
(h2={}).send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]})

  I tried to understand this...

  "h = {0=>"a", 1=>"b", 2=>"c"}" generates an hash...ok

  "(h2={}).send(:=" generates h2, another hash and sends to its =
  (element assignment) the....

  "*h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]})"

  ...?... I stumbled over the "*" at *h.sort.....What does it mean?

# rotate inplace
h.send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h[k1]=v2; [k2, v1]})

  ...same here...

:slight_smile:

Note: you can omit the sort in the first example, but IMHO an order should
be imposed on keys. Otherwise the rotation does not make much sense IMHO.

  Absolutely correct. I was searching for something like "an array
  with indices not being integers but ordered".

You can omit the sort in the second example, too, which seems to work
because the set of keys of the hash doesn't change. But this seems a bit
hackish to me, too. You can substitute "sort" by "dup" though.

Kind regards

    robert

PS: Enumerable#inject is cool. :wink:

  PS: Undertstanding and writing such code is much cooler... !

  Ruby.use!
  Meino

···

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: Q: Shifting a hash anf and array
Date: Tue, 17 Aug 2004 17:21:01 +0900

> Meino Christian Cramer <Meino.Cramer@gmx.de> wrote:

> Hash[*(hash.keys.rot1.zip(hash.values.rot1).flatten)]

Hm, IMHO there is one "rot1" too much: you're rotating keys *and* values
while you should only rotate one of them. Otherwise I figure the result
will be the same as the original hash... :slight_smile:

Doh :slight_smile:

The other drawback of your solution is that it relys on #keys and #values
returning elements in matching order, i.e., if you zip both you get the same
hash. Although that might work it makes me feel a bit wary because AFAIK
it's not a guaranteed property of Hash (and I wouldn't want to rely on it).
This might even change over time if the Hash implementation was changed for
any reasons.

I know, but that was the only way I could think of to avoid the
one-lookup-per-key.

How about these one liners, that avoids the problem:

h = {0=>"a", 1=>"b", 2=>"c"}
# put rotated in h2
(h2={}).send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]})
# rotate inplace
h.send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h[k1]=v2; [k2, v1]})

Neat - I didn't know there was a Hash#sort

martin

···

Robert Klemme <bob.news@gmx.net> wrote:

"Meino Christian Cramer" <Meino.Cramer@gmx.de> schrieb im Newsbeitrag
news:20040817.105109.41634481.Meino.Cramer@gmx.de...

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: Q: Shifting a hash anf and array
Date: Tue, 17 Aug 2004 17:21:01 +0900

Hi Martin, Hi Robert,

thank you very much for your sources !
Great! :slight_smile:

You're welcome!

I have an additional question below.....vvvvvv

Ok, answers below.

>
> "Martin DeMello" <martindemello@yahoo.com> schrieb im Newsbeitrag
> news:u_gUc.122944$M95.4319@pd7tw1no...
> > >
> > > Contents of the array before the trick:
> > >
> > > 1 2 3 4 5 6 7 8 9 0 index
> > > A B C D E F G H I J contents
> > >
> > > (execute *trick*)
> > >
> > > Contents of the array after the trick:
> > >
> > > 1 2 3 4 5 6 7 8 9 0 index
> > > J A B C D E F G H I contents
> >
> > array.unshift(array.pop)
>
> or array.push(array.shift) for the other direction.
>
> > > And now the shift of an hash:
> > >
> > > Contents of the hash before the trick:
> > >
> > > A B C D E F G H I J key
> > > 1 2 3 4 5 6 7 8 9 0 value
> > >
> > > (execute *trick*)
> > >
> > > Contents of the hash after the trick:
> > >
> > > A B C D E F G H I J key
> > > 0 1 2 3 4 5 6 7 8 9 value
> > >
> > > Both are very similiar.
> >
> > Not really :slight_smile: Hashes are inherently unordered, so the concept of a
> > rotation is a bit trickier. This works on the assumption that
> > Hash#values returns values in positions corresponding to the keys in
> > Hash#keys...
> >
> > class Array
> > def rot1
> > unshift(pop)
> > end
> > end
> >
> > Hash[*(hash.keys.rot1.zip(hash.values.rot1).flatten)]
>
> Hm, IMHO there is one "rot1" too much: you're rotating keys *and* values
> while you should only rotate one of them. Otherwise I figure the result
> will be the same as the original hash... :slight_smile:
>
> The other drawback of your solution is that it relys on #keys and

#values

> returning elements in matching order, i.e., if you zip both you get the

same

> hash. Although that might work it makes me feel a bit wary because

AFAIK

> it's not a guaranteed property of Hash (and I wouldn't want to rely on

it).

> This might even change over time if the Hash implementation was changed

for

> any reasons.
>
> How about these one liners, that avoids the problem:
>
> h = {0=>"a", 1=>"b", 2=>"c"}
> # put rotated in h2
> (h2={}).send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2,

v1]})

  I tried to understand this...

  "h = {0=>"a", 1=>"b", 2=>"c"}" generates an hash...ok

  "(h2={}).send(:=" generates h2, another hash and sends to its =
  (element assignment) the....

  "*h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]})"

  ...?... I stumbled over the "*" at *h.sort.....What does it mean?

If you execute h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]} you'll
see the result is an array:

h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]}

=> [2, "a"]

You need unary "*" to make this an argument list for the invocation of =.
Some example usage of "*" for clarification (hopefully):

def foo(*args) p args end

=> nil

foo 1

[1]
=> nil

foo [1]

[[1]]
=> nil

foo(1,2,3)

[1, 2, 3]
=> nil

foo([1,2,3])

[[1, 2, 3]]
=> nil

> # rotate inplace
> h.send(:=, *h.sort.inject {|(k1,v1),(k2,v2)| h[k1]=v2; [k2, v1]})

  ...same here...

> :slight_smile:
>
> Note: you can omit the sort in the first example, but IMHO an order

should

> be imposed on keys. Otherwise the rotation does not make much sense

IMHO.

  Absolutely correct. I was searching for something like "an array
  with indices not being integers but ordered".

> You can omit the sort in the second example, too, which seems to work
> because the set of keys of the hash doesn't change. But this seems a

bit

> hackish to me, too. You can substitute "sort" by "dup" though.
>
> Kind regards
>
> robert
>
>
> PS: Enumerable#inject is cool. :wink:

  PS: Undertstanding and writing such code is much cooler... !

:-))

#inject works like this: the block receives two values, the result of the
last block execution and the current iteration element. The result of
inject is the value of the last block evaluation. At first invocation the
value of the last execution is either the value provided as argument to
inject if there is one or otherwise the first element of the iteration and
the current element is the second element:

%w{a b c d}.inject("foo") {|*args| p args; args.join('|')}

["foo", "a"]
["foo|a", "b"]
["foo|a|b", "c"]
["foo|a|b|c", "d"]
=> "foo|a|b|c|d"

%w{a b c d}.inject {|*args| p args; args.join('|')}

["a", "b"]
["a|b", "c"]
["a|b|c", "d"]
=> "a|b|c|d"

You can do all sorts of cool things with inject, in fact you can implement
all Enumerable methods based on inject - although that's not always the most
elegant or efficient method. Counting is probably the easiest:

module Enumerable
  def count
    inject(0) {|cnt,| cnt + 1}
  end
end

%w{a b c d}.count

=> 4

But other algorithms work, too:

module Enumerable
  def find_elem
    inject() {|sel, item| sel << item if yield item; sel}
  end
end

%w{a b c d}.find_elem {|e| /^a/ =~ e}

=> ["a"]

Another feature I used was bracketing of block arguments to assign keys and
values to individual variables. During a Hash iteration with inject, the
current element is a two element array with key and value:

{1=>"a",2=>"b",3=>"c"}.inject {|*args| p args}

[[1, "a"], [2, "b"]]
[nil, [3, "c"]]
=> nil

By using brackets you can control assignment of array elemtens to variables:

test = lambda {|(a,b),c,*d| p a, b, c, d}

=> #<Proc:0x10180b30@(irb):18>

test.call [1,2],3,4,5,6,7,8

1
2
3
[4, 5, 6, 7, 8]
=> nil

test = lambda {|a,(b,*c),*d| p a, b, c, d}

=> #<Proc:0x101a0108@(irb):23>

test.call 1,[2,3,4],5,6,7,8,9

1
2
[3, 4]
[5, 6, 7, 8, 9]
=> nil

In my code the first value is carried through the whole iteration while the
key of the last value is always the last key, which is assigned the current
value.

I hope that made things a bit clearer. :slight_smile:

  Ruby.use!

Definitely!

Kind regards

    robert

···

> > Meino Christian Cramer <Meino.Cramer@gmx.de> wrote:

hi meino-

i have written such a beast:

   ~ > cat a.rb

···

On Tue, 17 Aug 2004, Meino Christian Cramer wrote:

Absolutely correct. I was searching for something like "an array
with indices not being integers but ordered".

   #
   # http://raa.ruby-lang.org/project/arrayfields/
   #
   require 'arrayfields'

   fields = %w( zero one two )
   array = [0,1,2]

   array.fields = fields

   p array['zero']
   p array['one']
   p array['two']

   p array.values_at 'zero', 'one', 'two'

   p array[0]
   p array[1]
   p array[2]

   p array.values_at 0,1,2

   array['three'] = 3 # assignment to un-named fields appends
   p array.fields
   p array['three']

   ~ > ruby a.rb
   0
   1
   2
   [0, 1, 2]
   0
   1
   2
   [0, 1, 2]
   ["zero", "one", "two", "three"]
   3

regards.

-a
--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

Hi Robert !

*MANY* BIG thanks for your Pickaxe.inject ! :wink:

I think I have to read it some more times to understand it fully but
currently I understand already that I will understand it.

("Programmer's Dictionary":
                Recursion:
                    see Recursion
) :wink:

Ruby.use!
Meino

"Meino Christian Cramer" <Meino.Cramer@gmx.de> schrieb im Newsbeitrag

  <snipped only to not to repost the whole stuff again....>

···

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: Q: Shifting a hash anf and array
Date: Tue, 17 Aug 2004 19:11:03 +0900

Hi Ara and the other problem solvers,

WHOW! (<- that's describing the best... :wink:

There was ever a difficulty for me and will ever be:
I dont know, what I like most: Ruby or its mailing list people ! :O)

Really, not joking! How often I heard: "Open Source? No costs - no
hotline ! This can not be serious software for serious software
development." According to so called "hotlines" I think, the best
what ever could happen to Open Source is NOT HAVEING that kind of
hotlines!

Tell me ONE commercial product, for what you get THAT much valuable
help in THAT short time (less than 12 hours)! Only ONE!

:slight_smile:

Ok, back to the arrays'n'hashes....

Three days ago I saw a british film on TV about the decyphering of the
Enigma machine in Blechtley Park...FASZINATING! Very good film!

What follows was a googling party "in search of the Enigma".... :wink:

I found a bash script, which implements a lot of different Enigmas
and I thought it would be a good opportunity to learn more Ruby to
implement the Enigma in Ruby.

One of the basic concepts of the Enigma machine are the wheels. Those
wheels had 26 input terminals on the one side and 26 output terminals
on the other side. Each terminal was representing one letter. The
connnection between the front and back terminals were "crossed wired"
-- or irregular (right word?). What was put as an "A" on the front
came out as (fro example) "Q" on the back.

Three or four wheels were packed on one axis. Which each letter input
the wheels were rotated one position (I haven't figured out, how
exactly this works until now...). That means: "AAA" came out as (for
example) "QZF" and not as "QQQ".

I thought of implementing the wheels as such
not-integer-but-ordered-indexed "arrays". And my question about all
this rotating and shiofting stuff was to figure out how to "rotate"
my wheel-arrays.

There much other stuff to figure out...there was also a "Reflector"
(whatever it was used for) and a so called "Steckerboard" ("Stecker"
is german for "plug", but every site about the Enigma calls this a
"Steckerboard" and "...the code was steckered..." ("connected" or
"plugged in" or so in English)

OT: If anyone knows a good site with detailed description of the
mechanical "inside" and the meachnisms of the different Enigma
machines...hu,hu...me! Here, please! :)))

Sorry for this longish "book about the Enigma" :))).

But I thought it could be interesting.

Thank you all for all your help!

Ruby.use!
Meino

···

From: "Ara.T.Howard" <ahoward@noaa.gov>
Subject: Re: Q: Shifting a hash anf and array
Date: Tue, 17 Aug 2004 08:33:24 -0600 (MDT)

On Tue, 17 Aug 2004, Meino Christian Cramer wrote:

> Absolutely correct. I was searching for something like "an array
> with indices not being integers but ordered".

hi meino-

i have written such a beast:

   ~ > cat a.rb
   #
   # http://raa.ruby-lang.org/project/arrayfields/
   #
   require 'arrayfields'

   fields = %w( zero one two )
   array = [0,1,2]

   array.fields = fields

   p array['zero']
   p array['one']
   p array['two']

   p array.values_at 'zero', 'one', 'two'

   p array[0]
   p array[1]
   p array[2]

   p array.values_at 0,1,2

   array['three'] = 3 # assignment to un-named fields appends
   p array.fields
   p array['three']

   ~ > ruby a.rb
   0
   1
   2
   [0, 1, 2]
   0
   1
   2
   [0, 1, 2]
   ["zero", "one", "two", "three"]
   3

regards.

-a
--

> EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
> PHONE :: 303.497.6469
> A flower falls, even though we love it;
> and a weed grows, even though we do not love it.
> --Dogen

very. something like this perhaps?

   jib:~ > cat b.rb
   require 'arrayfields'
   module Enigma
     class Wheel < Array
       FORWARD = 0
       BACKWARD = 1
       attr :terminals
       def initialize terminals
         self.fields = *terminals
         self.replace terminals
       end
       def rotate! direction = FORWARD
         if direction == FORWARD
           push shift
         else
           unshift pop
         end
       end
       def inspect
         fields.inject(''){|s,f| s << "#{ f } - #{ self[f] }\n"}
       end
     end
   end

   w = Enigma::Wheel.new %w(A B C D E F)
   p w
   w.rotate!
   p w

   jib:~ > ruby b.rb
   A - A
   B - B
   C - C
   D - D
   E - E
   F - F

   A - B
   B - C
   C - D
   D - E
   E - F
   F - A

keep us tuned!

-a

···

On Wed, 18 Aug 2004, Meino Christian Cramer wrote:

Three days ago I saw a british film on TV about the decyphering of the
Enigma machine in Blechtley Park...FASZINATING! Very good film!

What follows was a googling party "in search of the Enigma".... :wink:

I found a bash script, which implements a lot of different Enigmas
and I thought it would be a good opportunity to learn more Ruby to
implement the Enigma in Ruby.

One of the basic concepts of the Enigma machine are the wheels. Those
wheels had 26 input terminals on the one side and 26 output terminals
on the other side. Each terminal was representing one letter. The
connnection between the front and back terminals were "crossed wired"
-- or irregular (right word?). What was put as an "A" on the front
came out as (fro example) "Q" on the back.

Three or four wheels were packed on one axis. Which each letter input
the wheels were rotated one position (I haven't figured out, how
exactly this works until now...). That means: "AAA" came out as (for
example) "QZF" and not as "QQQ".

I thought of implementing the wheels as such
not-integer-but-ordered-indexed "arrays". And my question about all
this rotating and shiofting stuff was to figure out how to "rotate"
my wheel-arrays.

There much other stuff to figure out...there was also a "Reflector"
(whatever it was used for) and a so called "Steckerboard" ("Stecker"
is german for "plug", but every site about the Enigma calls this a
"Steckerboard" and "...the code was steckered..." ("connected" or
"plugged in" or so in English)

OT: If anyone knows a good site with detailed description of the
mechanical "inside" and the meachnisms of the different Enigma
machines...hu,hu...me! Here, please! :)))

Sorry for this longish "book about the Enigma" :))).

But I thought it could be interesting.

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

===============================================================================

"Meino Christian Cramer" <Meino.Cramer@gmx.de> schrieb im Newsbeitrag
news:20040817.184616.92576207.Meino.Cramer@gmx.de...

From: "Ara.T.Howard" <ahoward@noaa.gov>
Subject: Re: Q: Shifting a hash anf and array
Date: Tue, 17 Aug 2004 08:33:24 -0600 (MDT)

Hi Ara and the other problem solvers,

WHOW! (<- that's describing the best... :wink:

There was ever a difficulty for me and will ever be:
I dont know, what I like most: Ruby or its mailing list people ! :O)

:-))

One of the basic concepts of the Enigma machine are the wheels. Those
wheels had 26 input terminals on the one side and 26 output terminals
on the other side. Each terminal was representing one letter. The
connnection between the front and back terminals were "crossed wired"
-- or irregular (right word?). What was put as an "A" on the front
came out as (fro example) "Q" on the back.

Three or four wheels were packed on one axis. Which each letter input
the wheels were rotated one position (I haven't figured out, how
exactly this works until now...). That means: "AAA" came out as (for
example) "QZF" and not as "QQQ".

I thought of implementing the wheels as such
not-integer-but-ordered-indexed "arrays". And my question about all
this rotating and shiofting stuff was to figure out how to "rotate"
my wheel-arrays.

IMHO rotating is much too inefficient. I'd rather use a changing offset
like this:

module Enigma
  class Wheel
    def initialize(mapping)
      @code = mapping
      @offset = 0
    end

    def rotate
      @offset = (@offset + 1) % @code.size
    end

    def encode(char)
      @code[(normalize(char) + @offset) % @code.size]
    end

private
    def normalize(char)
      case char
        when String
          char.upcase[0] - ?A
        when ?a..?z
          char - ?a
        when ?A..?Z
          char - ?A
        else
          raise ArgumentError, "Dunno what to do with #{char.inspect}"
      end
    end
  end
end

wheel = Enigma::Wheel.new [?x, ?z, ?e]
p( wheel.encode( ?A ).chr )
wheel.rotate
p( wheel.encode( ?A ).chr )
p( wheel.encode( "A" ).chr )

Kind regards

    robert

Hi Codebreakers!

<Enigma stuff encyphered, folded, erased then thrown away : TOP SECRET! :slight_smile:

very. something like this perhaps?

  "YesNo" or in coding style

  answer = Trulse
  
  Or in boolean notation:

  0.5

  Enough junk from my brain output terminal...I had to stop myself
  here and now from flooding mails with random white noise. :wink:

  The principle is ok, Ara -- but the resulting cypher is the so
  called "Caesar's code", which means, a) Caesar has used it b) it is
  very weak. (By the milky way: The Enigma cyphering mechanism is by
  no means safe!!! In todays computer environments it is broken in times
  you need to login (or nearly...I exegrate a little too much).

  And never,never,never it should be used in serious cyphering
  tasks!!!

  But what makes the Enigma machines so interesting to me (and
  may be others...;):

  You can really watch how letter by letter is moved through this
  wheel drum unit until finally one letter came out. And from a
  mechanical craftsman point of view: It is a beautiful machine! (BY
  NO MEANS I AM FORGETTING HERE FOR WHAT THIS BEAST WAS USED! But it
  was fascinating to watch the TV film to see how the "egg heads"
  (only meant positively!) in Bletchley Park were trying to temper and
  finally breaking the code -- with the help of MECHANICAL CODE
  BREAKING COMPUTERS and a lot of brain power! Lots of big boards with
  rotating wheels, which try to find the settings of the wheels of
  Enigma currently used for sending the encyphered text via shortwave.

  But I am loosing my path...

  What .... I want to say......was....hrmmmm.....AH! NOW!

  Caesar's code is a so called "replacement alphabet code":

  in (clear text) : ABCDEFGHIJKLMNOPQRSTUVWXYZ
  out (encyphered text): UVWXYZABCDEFGHIJKLMNOPQRST

  which means, that the "structure" of text remains untouched. For
  example the count of the different letters used in a certain
  language remains the same .... only for a different letter.

  This is one weak point of this cypher.

  When putting more cyphering stages on a line like this:

  in (clear text) : ABCDEFGHIJKLMNOPQRSTUVWXYZ
  out (encyphered text): UVWXYZABCDEFGHIJKLMNOPQRST
  in (clear text) : UVWXYZABCDEFGHIJKLMNOPQRST
  out (encyphered text): MNOPQRSTUVWXYZABCDEFGHIJKL
  in (clear text) : MNOPQRSTUVWXYZABCDEFGHIJKL
  out (encyphered text): EFGHIJKLMNOPQRSTUVWXYZABCD
  in (clear text) : EFGHIJKLMNOPQRSTUVWXYZABCD
  out (encyphered text): YZABCDEFGHIJKLMNOPQRSTUVWX
  
  you gain nothing but more mechanical stuff in your "Caesar-Enigma",
  since this can be simplyfied to:

  in (clear text) : ABCDEFGHIJKLMNOPQRSTUVWXYZ
  out (encyphered text): YZABCDEFGHIJKLMNOPQRSTUVWX

  The first "enhancement" the Enigma introduced were the "wild"
  wireing" of the wheels like this:

  in (clear text) : ABCDEFGHIJKLMNOPQRSTUVWXYZ
  out (encyphered text): CDKLMPEYZAFBGHIJQRVXWNSOUT

  Next were using three (or four for the Naval version of the Enigma)
  wheels with different "wild wireings" like this (I think I should
  write a short lisp code for my emacs to generate all this "random
  wild wireings (is this "wirerings" or is "wireings" correct...damn,
  before trying to build a cyphering Enigma I should learn to decypher
  my own English...;):

  in (clear text) : ABCDEFGHIJKLMNOPQRSTUVWXYZ
  out (encyphered text): CDKLMPEYZAFBGHIJQRVXWNSOUT
  in (clear text) : CDKLMPEYZAFBGHIJQRVXWNSOUT
  out (encyphered text): MCDLKPZYAEFIGBSOUTJHQVRXNW
  in (clear text) : MCDLKPZYAEFIGBSOUTJHQVRXNW
  out (encyphered text): SOUCDKLMPIJFBGHVQREYZAXWNT

  ("wild wireing" by "hand random"....urks...)

  But the real trick was to turn each wheel after each input
  letter. There was a certain algorithm in which way and when what
  wheel was turned...I have no source of information until now for
  that. Any hint is welcome...

  After three or for stages of "wheeling the letters" there was a so
  called "Deflector", which injects (TADA!) the encyphered letter back
  into the drum of wheels and this letter was again encyphered three
  times by the truning wheels the way back.

  The the letter reaches the "Steckerboard" and was "steckered"
  (whatever that means ...I dont know...source of information
  currently missing...) and at last the voltage (did I say, that this
  wireing was for makeing _electrical_ connections?...Oh, I think I
  forgot that...sorry) reaches a little lamp (NO LED!:wink: behind a
  letter of the alphabet showing the final encyphered letter.

  You need three persons for using the Enigma!!!

  The resulting code was symmetrical. That means, feeding the
  encyphered text again through the machine with the same starting
  settings results in the clear text.

  The enourmous huge amount of possible settings of the wheels for the
  start positions of the wheels, the additional possibilities of the
  deflector settings and the "steckering" of the "Steckerboard"
  blinded the inventors of the weakness of the codeing algorithm. So
  luckily the code was finally broken by the people at Bletchley Park
  and Polish mathematicans.

···

From: "Ara.T.Howard" <ahoward@noaa.gov>
Subject: Re: POT (partly offtopic) Re: Q: Shifting a hash anf and array
Date: Wed, 18 Aug 2004 02:40:59 +0900

  ----------

  Homework for all ongoing codebreakers til Friday:

   Encyphere this email to reasonable readable English.

   Hint: It is no Caesar's cypher. The used code has something to do
   with random typos and lack of correct vocabulary.

  ;) X-)

  :O)

  -----------

  As soon as I know somthing more about the inside of the Enigmas
  (there were 17 different models ....) I will post more -- if it is
  wanted, since it is ... offtopic.

  Ruby.use!
  Meino
  

   jib:~ > cat b.rb
   require 'arrayfields'
   module Enigma
     class Wheel < Array
       FORWARD = 0
       BACKWARD = 1
       attr :terminals
       def initialize terminals
         self.fields = *terminals
         self.replace terminals
       end
       def rotate! direction = FORWARD
         if direction == FORWARD
           push shift
         else
           unshift pop
         end
       end
       def inspect
         fields.inject(''){|s,f| s << "#{ f } - #{ self[f] }\n"}
       end
     end
   end

   w = Enigma::Wheel.new %w(A B C D E F)
   p w
   w.rotate!
   p w

   jib:~ > ruby b.rb
   A - A
   B - B
   C - C
   D - D
   E - E
   F - F

   A - B
   B - C
   C - D
   D - E
   E - F
   F - A

keep us tuned!

-a
--

> EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
> PHONE :: 303.497.6469
> A flower falls, even though we love it;
> and a weed grows, even though we do not love it.
> --Dogen

> I dont know, what I like most: Ruby or its mailing list people ! :O)

:-))

  I only can repeat what I said previously about my inabillity to
  decide between both ! :O)

> I thought of implementing the wheels as such
> not-integer-but-ordered-indexed "arrays". And my question about all
> this rotating and shifting stuff was to figure out how to "rotate"
> my wheel-arrays.

IMHO rotating is much too inefficient. I'd rather use a changing offset
like this:

module Enigma
  class Wheel
    def initialize(mapping)
      @code = mapping
      @offset = 0
    end

    def rotate
      @offset = (@offset + 1) % @code.size
    end

    def encode(char)
      @code[(normalize(char) + @offset) % @code.size]
    end

private
    def normalize(char)
      case char
        when String
          char.upcase[0] - ?A
        when ?a..?z
          char - ?a
        when ?A..?Z
          char - ?A
        else
          raise ArgumentError, "Dunno what to do with #{char.inspect}"
      end
    end
  end
end

wheel = Enigma::Wheel.new [?x, ?z, ?e]
p( wheel.encode( ?A ).chr )
wheel.rotate
p( wheel.encode( ?A ).chr )
p( wheel.encode( "A" ).chr )

  Ok, this looks more like the Enigma++ or Enigma Pro or Enigma Deluxe
  ;) (by the way...currently it seems that there were 17 different
  models of the encyphering machine...)

  Unfortunately there is not only the one offset needed for rotating
  the wheels -- there is also one offset to be take into account for
  the outer ring or "tyre" of the wheels which was used to adjust the
  alphabet against the internal wireing and an additional offset for
  the start positions of the wheels.

  I think I will do first "rotate" the "wheels" into the initial
  position takeing the outer ring position and the start position of the
  wheels into account. This only happens once.

  And then I will "robertize" the "wheels" according to your code
  above, Robert. Since this happens for each letter to encypher it is
  far more important for this part of the code to be fast. And the
  code does not get too complex because of haveing three different
  offsets to be calculated each time.

  What do you think, Robert?

  Thank you very much for all the help I got from this list.
  
  Hopefully I will find the rest of informations I need about the
  technical specs of the different Enigmas.

Kind regards

    robert

Ruby.use!
Meino

···

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: POT (partly offtopic) Re: Q: Shifting a hash anf and array
Date: Wed, 18 Aug 2004 19:10:56 +0900

Hi Robert, Hi Rubyaner ! :slight_smile:

Enigma is growing. Currently it does scrambling text. Unfortunately
it is an absolut safe encyphiering algorithm at the moment...there is
NO way back to the clear text...even for the sender. Or to call it
more realistic: Enigma is currently still a little buggy :slight_smile:

With the real Enigma you could change the wheels (or "rotors"). Each
wheel had have an hardwired inside.

I thought of simulating this by creating an rotot-object for each
wheel. rotor.encode(<char>) would encode the letter, which was "feed
into" the certain wheel.

By putting three (or four) rotor-objects in serial this would
simulate the encoding phase of all wheels currently "put into" the
Enigma.

The rotating algorithm is a liitle more difficult. Each letter feed
into the first wheel will rotate this wheel by one step. At certain
positions of the rotation of the first wheel, the second wheel was
rotated by one step. And so on.

To abstract this from the user choosen configuration of the Enigma I
want to do something a little similiar to C's function pointer call.

Is there a way to put different instances of the same class into an
array, then stepping through the array and call a certain method for
each of the objects?

Something like:

       objarray=Array.new
       objarray[idx]=Rotor.new(config)
       encchar=objarray[idx].method(param)
?

How do I have to tell this to Ruby ?

Thank you very much for any hint or help in advance!
Meino

···

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: POT (partly offtopic) Re: Q: Shifting a hash anf and array
Date: Wed, 18 Aug 2004 19:10:56 +0900

"Meino Christian Cramer" <Meino.Cramer@gmx.de> schrieb im Newsbeitrag
news:20040818.135303.74729997.Meino.Cramer@gmx.de...

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: POT (partly offtopic) Re: Q: Shifting a hash anf and array
Date: Wed, 18 Aug 2004 19:10:56 +0900

>
> > I dont know, what I like most: Ruby or its mailing list people ! :O)
>
> :-))

  I only can repeat what I said previously about my inabillity to
  decide between both ! :O)

Take your time. :slight_smile:

> > I thought of implementing the wheels as such
> > not-integer-but-ordered-indexed "arrays". And my question about all
> > this rotating and shifting stuff was to figure out how to "rotate"
> > my wheel-arrays.
>
> IMHO rotating is much too inefficient. I'd rather use a changing offset
> like this:

<snip>code</snip>

  Ok, this looks more like the Enigma++ or Enigma Pro or Enigma Deluxe
  ;) (by the way...currently it seems that there were 17 different
  models of the encyphering machine...)

Why Enigma++? Personally I find it the easiest and most natural to create
those classes that abstract exactly the concepts of natural world that I
want to model. So having a Wheel class would be most natural for me, even
if it had only one or two methods.

  Unfortunately there is not only the one offset needed for rotating
  the wheels -- there is also one offset to be take into account for
  the outer ring or "tyre" of the wheels which was used to adjust the
  alphabet against the internal wireing and an additional offset for
  the start positions of the wheels.

Well, you can calculate all offsets in one step.

  I think I will do first "rotate" the "wheels" into the initial
  position takeing the outer ring position and the start position of the
  wheels into account. This only happens once.

  And then I will "robertize" the "wheels" according to your code
  above, Robert. Since this happens for each letter to encypher it is
  far more important for this part of the code to be fast. And the
  code does not get too complex because of haveing three different
  offsets to be calculated each time.

Sounds quite reasonable. In that case maybe I'd change the encode method to
accept one offset argument (or a list of offsets) so you only have to do the
modulo once, i.e., you can sum them all up and then do "% @code.size".
Example with arbitrary many offsets:

    def encode(char, *offsets)
      @code[(normalize(char) + offsets.inject(@offset){|sum,x| sum + x} ) %
@code.size]
    end

  What do you think, Robert?

  Thank you very much for all the help I got from this list.

You're welcome!

  Hopefully I will find the rest of informations I need about the
  technical specs of the different Enigmas.

Good luck! Some links that Google revealed:

http://www.mirrors.wiretapped.net/security/cryptography/algorithms/enigma/
http://www.javaworld.com/jw-08-1998/jw-08-indepth-p3.html

http://mathforum.org/library/topics/cryptography/

Kind regards

    robert

"Meino Christian Cramer" <Meino.Cramer@gmx.de> schrieb im Newsbeitrag
news:20040819.092154.74751728.Meino.Cramer@gmx.de...

From: "Robert Klemme" <bob.news@gmx.net>
Subject: Re: POT (partly offtopic) Re: Q: Shifting a hash anf and array
Date: Wed, 18 Aug 2004 19:10:56 +0900

Hi Robert, Hi Rubyaner ! :slight_smile:

Enigma is growing. Currently it does scrambling text. Unfortunately
it is an absolut safe encyphiering algorithm at the moment...there is
NO way back to the clear text...even for the sender. Or to call it
more realistic: Enigma is currently still a little buggy :slight_smile:

With the real Enigma you could change the wheels (or "rotors"). Each
wheel had have an hardwired inside.

I thought of simulating this by creating an rotot-object for each
wheel. rotor.encode(<char>) would encode the letter, which was "feed
into" the certain wheel.

By putting three (or four) rotor-objects in serial this would
simulate the encoding phase of all wheels currently "put into" the
Enigma.

The rotating algorithm is a liitle more difficult. Each letter feed
into the first wheel will rotate this wheel by one step. At certain
positions of the rotation of the first wheel, the second wheel was
rotated by one step. And so on.

To abstract this from the user choosen configuration of the Enigma I
want to do something a little similiar to C's function pointer call.

Is there a way to put different instances of the same class into an
array, then stepping through the array and call a certain method for
each of the objects?

Something like:

   objarray=Array.new
   objarray[idx]=Rotor.new(config)
   encchar=objarray[idx].method(param)
?

How do I have to tell this to Ruby ?

Like this?

encoded = objarray.inject(letter) {|param, rotor| rotor.encode param}

I assume, all Rotors are connected, i.e. the first one receives the original
char and the second the result of the first and so forth. Otherwise you can
use #each or #map.

Regards

    robert

Hi Robert, Hi Rubyaner !

I think in a week or two we can publish "The Enigma Mails" as a
paperback at Addison Wesley or so... :wink:

I will snip some parts to make it easier to...hrmmm...print for
Addison's .. :wink:

> Ok, this looks more like the Enigma++ or Enigma Pro or Enigma Deluxe
> :wink: (by the way...currently it seems that there were 17 different
> models of the encyphering machine...)

Why Enigma++? Personally I find it the easiest and most natural to create
those classes that abstract exactly the concepts of natural world that I
want to model. So having a Wheel class would be most natural for me, even
if it had only one or two methods.

  Sorry, Robert! This was only a nonsense joke. The only thing I
  wanted to say was, that your non-rotating-but-offsetting-algorithm
  will improve (therefore a kind of "incrementation of the Enigma
  code") the code of the Enigma. Nothing more...

> Unfortunately there is not only the one offset needed for rotating
> the wheels -- there is also one offset to be take into account for
> the outer ring or "tyre" of the wheels which was used to adjust the
> alphabet against the internal wireing and an additional offset for
> the start positions of the wheels.

Well, you can calculate all offsets in one step.

  Yes, yes, yes....:O) I finally figured it out by myself. It is far less
  complicate as I first thought. I am using offsets everywhere, where
  I have to rotate something.

> I think I will do first "rotate" the "wheels" into the initial
> position takeing the outer ring position and the start position of the
> wheels into account. This only happens once.
>
> And then I will "robertize" the "wheels" according to your code
> above, Robert. Since this happens for each letter to encypher it is
> far more important for this part of the code to be fast. And the
> code does not get too complex because of haveing three different
> offsets to be calculated each time.

Sounds quite reasonable. In that case maybe I'd change the encode method to
accept one offset argument (or a list of offsets) so you only have to do the
modulo once, i.e., you can sum them all up and then do "% @code.size".
Example with arbitrary many offsets:

    def encode(char, *offsets)
      @code[(normalize(char) + offsets.inject(@offset){|sum,x| sum + x} ) %
@code.size]
    end

  Oh...I have to do a deeper look into my Enigma code...I think the
  code isn't rubyish enough...

> What do you think, Robert?
>
> Thank you very much for all the help I got from this list.

You're welcome!

  :O)

> Hopefully I will find the rest of informations I need about the
> technical specs of the different Enigmas.

Good luck! Some links that Google revealed:

http://www.mirrors.wiretapped.net/security/cryptography/algorithms/enigma/
http://www.javaworld.com/jw-08-1998/jw-08-indepth-p3.html

Classroom Resources - National Council of Teachers of Mathematics

Kind regards

    robert

That's really funny, Robert!
What do you think, how often I hammered keywords like "Enigma",
"cryptography and such into Google the last days...but I never stumbled
across these...

Thanks a lot...I will start a surf party in a few minutes :wink:

> Something like:
>
> objarray=Array.new
> objarray[idx]=Rotor.new(config)
> encchar=objarray[idx].method(param)
> ?
>
> How do I have to tell this to Ruby ?

Like this?

  My fault...I thought "It couldn't be THAT easy...but it works right
  the way as I mailed it...

  This is the inversion of "Principle of last surprise" Ruby uses:

  One is surprised, that it is SUCH easy. :wink:

encoded = objarray.inject(letter) {|param, rotor| rotor.encode param}

  Looks very rubyish! Nice code.

  I will try to use it...there one additional parameter I need to take
  care of here.

  Each wheel has a notch (or two), which will turn "the next" wheel
  one step at a certain point of rotation -- like the carry bit used
  in assembly programming. I implemented this notch as a object
  variable, which is set true at the position in question and has to
  be evaluated by the "next wheel"-object.

  Like this?

  @carry=true # cause the first rotor is always rotated by one step if
                          # a new letter arrives to be encoded

  encoded = objarray.inject(letter) {|param, rotor|
                  rotor.rotate(@carry)
                  @carry=rotor.carry
                  rotor.encode param
                  }

I assume, all Rotors are connected, i.e. the first one receives the original
char and the second the result of the first and so forth. Otherwise you can
use #each or #map.

  Yes, totally right...only a little more complex. Like this:

  keyboard-->letter
  letter-->Steckerboard--->letter (simply letter mapping char->another ch
ar)
  letter-->ETW--->letter (ETW="Eintrittswalze", Entry wheel)
  letter-->Wheel1--->letter
  letter-->Wheel2--->letter
  letter-->Wheel3--->letter
  letter-->UKW--->letter (UKW="Umkehrwalze", Rfelector)
  letter-->Wheel3--->letter
  letter-->Wheel2--->letter
  letter-->Wheel1--->letter
  letter-->ETW--->letter (ETW="Eintrittswalze", Entry wheel)
  letter-->Steckerboard--->letter (simply letter mapping char->another ch
ar)
  lamp signaling the encyphered letter

  The pressing of one key of the keyboard rotates the first wheel (and
  the following when the notch appears) and depressing encodes the letter.

  Only the wheels were rotating, the "Steckers" of the "Steckerbaord"
  (I like this word mixed from German and English. "steckered" is even
  funnier!) (plugs in a plugboard) could be changed (only 13
  connection are allowed, mapping one letter to _another_ letter), the
  UKWs and ETWs of some models could be changed against others but as
  far as I know at this point they do not rotate.

  Another nice site I found about all this is here:

    Enigma-E

Regards

    robert

Thanks!.alot(Robert)

Ruby.use!
Meino

"Meino Christian Cramer" <Meino.Cramer@gmx.de> schrieb im Newsbeitrag
news:20040819.123945.92579085.Meino.Cramer@gmx.de...

  Sorry, Robert! This was only a nonsense joke. The only thing I
  wanted to say was, that your non-rotating-but-offsetting-algorithm
  will improve (therefore a kind of "incrementation of the Enigma
  code") the code of the Enigma. Nothing more...

Ah, ok. :slight_smile:

> Good luck! Some links that Google revealed:
>
>

http://www.mirrors.wiretapped.net/security/cryptography/algorithms/enigma/

> http://www.javaworld.com/jw-08-1998/jw-08-indepth-p3.html
>
> Classroom Resources - National Council of Teachers of Mathematics
>
>
> Kind regards
>
> robert

That's really funny, Robert!
What do you think, how often I hammered keywords like "Enigma",
"cryptography and such into Google the last days...but I never stumbled
across these...

I searched for "enigma algorithms". I think they're all on the first page.

  Each wheel has a notch (or two), which will turn "the next" wheel
  one step at a certain point of rotation -- like the carry bit used
  in assembly programming. I implemented this notch as a object
  variable, which is set true at the position in question and has to
  be evaluated by the "next wheel"-object.

  Like this?

  @carry=true # cause the first rotor is always rotated by one step if
                          # a new letter arrives to be encoded

  encoded = objarray.inject(letter) {|param, rotor|
                  rotor.rotate(@carry)
                  @carry=rotor.carry
                  rotor.encode param
                  }

or

encoded = objarray.inject( [letter, true] ) do |(param, carry), rotor|
  rotor.rotate carry
  [rotor.encode( param ), rotor.carry]
end.shift

Regards

    robert