# Cipher

**URL:** <https://www.ruby-forum.com/t/cipher/132102>\
**Category:** Ruby\
**Created:** [March 17, 2008, 1:52am UTC](https://www.ruby-forum.com/t/cipher/132102 "2008-03-17T01:52:19Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 1:52am UTC](https://www.ruby-forum.com/t/cipher/132102/1 "2008-03-17T01:52:19Z")

</div>

I am trying to make a program that takes what you input, and encrypts it  
by turning a to p, b to q, z to b, etc. It moves the letter 2 spaces to  
the left (a to c) and moves it down (c to p). (See below.) Even though  
you can just say that a will be n, how do you seperate each letter and  
turn it into a string? Please put it in terms that a Ruby beginner  
would understand.  
abcdefghijklm  
nopqrstuvwxyz

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 2:18am UTC](https://www.ruby-forum.com/t/cipher/132102/2 "2008-03-17T02:18:40Z")

</div>

On Mon, Mar 17, 2008 at 1:50 AM, Max Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I am trying to make a program that takes what you input, and encrypts it by turning a to p, b to q, z to b, etc. It moves the letter 2 spaces to the left (a to c) and moves it down (c to p). (See below.) Even though you can just say that a will be n, how do you seperate each letter and turn it into a string? Please put it in terms that a Ruby beginner would understand.  
> abcdefghijklm  
> nopqrstuvwxyz

You can split a string with the String#split method:  
irb

> “Foobar”.split(//)  
> =\> [“F”, “o”, “o”, “b”, “a”, “r”]

You can get the ASCII value of a character either with ?character:

> ?F  
> =\> 70

If you want to loop the splitted string, try eval(has anyone a better  
solution?):

> “Foobar”.split(//).each { |c| puts eval(“?#{c}”) }

You can use Fixnum#chr to turn an ASCII value in a character:

> 65.chr #=\> “A”

You’re trying to implement the ROT13 or ROTx algorithm. A naive  
approach, still buggy might look like that:  
plaintext = “Hello”  
encrypted = “”  
plaintext.split(//).each { |c| i=eval(“?#{c}”); encrypted \<\< (i+13).chr  
}  
puts encrypted #=\> Uryy|

As you see, the encrypted string contains a |(vertical line) and it  
also chokes on spaces. I leave the rest to you. Ask again if you’re  
stuck.

Regards, Thomas

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 2:33am UTC](https://www.ruby-forum.com/t/cipher/132102/3 "2008-03-17T02:33:54Z")

</div>

input = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ  
!@#$%^&\*()\_±={}|[];':“,./\<\>?`~' input.tr! "A-Za-z", "N-ZA-Mn-za-m" => "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM !@\#$%^&*()_+-={}|[]\\;':\",./<>?`~”

On Mon, Mar 17, 2008 at 11:16 AM, Thomas W.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> You can split a string with the String#split method:
> 
> > “Foobar”.split(//).each { |c| puts eval(“?#{c}”) }
> 
> As you see, the encrypted string contains a |(vertical line) and it  
> also chokes on spaces. I leave the rest to you. Ask again if you’re  
> stuck.
> 
> Regards, Thomas

–

“Every child has many wishes. Some include a wallet, two chicks and a  
cigar,  
but that’s another story.”

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 3:04am UTC](https://www.ruby-forum.com/t/cipher/132102/4 "2008-03-17T03:04:22Z")

</div>

On Sun, Mar 16, 2008 at 9:00 PM, Todd B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> On Sun, Mar 16, 2008 at 7:50 PM, Max Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > I am trying to make a program that takes what you input, and encrypts it by turning a to p, b to q, z to b, etc. It moves the letter 2 spaces to the left (a to c) and moves it down (c to p). (See below.) Even though you can just say that a will be n, how do you seperate each letter and turn it into a string? Please put it in terms that a Ruby beginner would understand.

Also, I forgot to mention that you should realize that a String object  
should be thought of as really just an ordering of bytes with some  
special methods to make it human readable.

Todd

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 11:22am UTC](https://www.ruby-forum.com/t/cipher/132102/5 "2008-03-17T11:22:12Z")

</div>

On Sun, Mar 16, 2008 at 9:00 PM, Todd B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> On Sun, Mar 16, 2008 at 7:50 PM, Max Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > I am trying to make a program that takes what you input, and encrypts it by turning a to p, b to q, z to b, etc. It moves the letter 2 spaces to the left (a to c) and moves it down (c to p). (See below.) Even though you can just say that a will be n, how do you seperate each letter and turn it into a string? Please put it in terms that a Ruby beginner would understand.  
> > abcdefghijklm  
> > nopqrstuvwxyz
> > 
> > * * *

Just for fun, I revisited this. To include the printable characters  
on an english-based system (ASCII codes 32 through 126), not including  
tab, return, line-feed, etc…

puts str = “Hello, world! Yabba dabba doo!”  
puts

char\_set = (32…126).map.pack(‘c\*’)  
start, finish, offset = ?a, ?p, ?p - ?a  
puts “char\_set:\n” + char\_set = (?\s…?~).map.pack(‘c\*’)  
puts

size = char\_set.size  
new\_str = “”  
str.each\_byte do |byte|  
new\_str \<\< char\_set[(byte + offset - char\_set[0]) % size]  
end  
puts “enciphered: \n” + new\_str

Todd

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 3:00am UTC](https://www.ruby-forum.com/t/cipher/132102/6 "2008-03-17T03:00:51Z")

</div>

On Sun, Mar 16, 2008 at 7:50 PM, Max Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I am trying to make a program that takes what you input, and encrypts it by turning a to p, b to q, z to b, etc. It moves the letter 2 spaces to the left (a to c) and moves it down (c to p). (See below.) Even though you can just say that a will be n, how do you seperate each letter and turn it into a string? Please put it in terms that a Ruby beginner would understand.  
> abcdefghijklm  
> nopqrstuvwxyz
> 
> * * *
> 
> Never miss a thing. Make Yahoo your homepage.

There are many ways to do it, but if it was all lower case, I would  
probably…

a = “abcdefghijklmnopqrstuvwxyz”  
ascii\_offset = 15 - 97  
str = “antidisestablishmentarianism”  
str.each\_byte {|b| new\_str \<\< a[(b + ascii\_offset) % a.size]}  
puts new\_str

The 15 is to turn a into a p (?p - ?a == 15). The minus 97 part is to  
make sure we work in the ascii byte code range. each\_byte runs  
through each byte of the string, where, in the block, the offset is  
added and the mod by the size of a (26) to keep the index of a within  
the correct bounds. a[] selects a byte to be appended (\<\<) to  
new\_str.

You could wrap this in a method or make it part of String class.  
Ideally, I think a person would really want to include the full 256  
character set to deal with punctuation and spaces.

Todd

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 10:21pm UTC](https://www.ruby-forum.com/t/cipher/132102/7 "2008-03-17T22:21:30Z")

</div>

On Sun, Mar 16, 2008 at 9:00 PM, Todd B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> a = “abcdefghijklmnopqrstuvwxyz”  
> ascii\_offset = 15 - 97  
> new\_str = “”  
> str = “antidisestablishmentarianism”  
> str.each\_byte {|b| new\_str \<\< a[(b + ascii\_offset) % a.size]}  
> puts new\_str

I think I’m going to drop google mail; that, or come up with a more  
clear way to cut and paste 😕

Todd

---

<div class="post-metadata">

**Author:** ![Max\_Z](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@Max\_Z](https://www.ruby-forum.com/u/Max_Z)\
**Post date:** [March 17, 2008, 11:34am UTC](https://www.ruby-forum.com/t/cipher/132102/8 "2008-03-17T11:34:08Z")

</div>

On Mon, Mar 17, 2008 at 5:21 AM, Todd B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > > * * *
> 
> start, finish, offset = ?a, ?p, ?p - ?a  
> puts “char\_set:\n” + char\_set = (?\s…?~).map.pack(‘c\*’)  
> puts
> 
> size = char\_set.size  
> new\_str = “”  
> str.each\_byte do |byte|  
> new\_str \<\< char\_set[(byte + offset - char\_set[0]) % size]  
> end  
> puts “enciphered: \n” + new\_str

Dang it! Another thing that unit tests won’t catch: code that is  
redundant! Removing the first “char\_set =” line will have the same  
result…

puts str = “Hello, world! Yabba dabba doo!”  
puts

start, finish, offset = ?a, ?p, ?p - ?a  
puts “char\_set:\n” + char\_set = (?\s…?~).map.pack(‘c\*’)  
puts

size = char\_set.size  
new\_str = “”  
str.each\_byte do |byte|  
new\_str \<\< char\_set[(byte + offset - char\_set[0]) % size]  
end  
puts “enciphered: \n” + new\_str

Todd
