Mando
Mando

Reputation: 19

Can't figure out how to get basic ruby 'encryptor' to work

Basically want to make 'abc' into 'bcd'. I was thinking if I add the letter the follows the first to the end of the phrase and dropped the original first letter, eventually I'd get the final solution. Got kinda stuck and was hoping someone could shed some light on it for me. Thanks

def encrypt(str)
  index = 0
  encrypted_str = ""
  duration = str.length
  until index == str.length
    encrypted_str = str + str[0].next
    encrypted_str = encrypted_str + encrypted_str.delete(str[index])
    index += 1 
  end
  puts encrypted_str
end

#puts "What would you like to encrypt?"
message = "abc"
puts encrypt(message)

Upvotes: 0

Views: 75

Answers (3)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230346

Another option, which uses more power of stdlib :)

def original
  "abcdefghijklmnopqrstuvwxyz"
end
def replacement 
  "bcdefghijklmnopqrstuvwxyza" 
end

def encrypt(str)
  str.tr(original, replacement)
end

def decrypt(str)
  str.tr(replacement, original)
end


encrypt('abc') # => "bcd"
decrypt('bcd') # => "abc"

Quite flexible too (compared to succ-based approach). You can change replacement alphabet to define arbitrary transformation rules.

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110685

ENCRYPT = [*'a'..'z'].zip([*'b'..'z', 'a']).to_h
  #=> {"a"=>"b", "b"=>"c",..., "y"=>"z", "z"=>"a"}
DECRYPT = ENCRYPT.invert
  #=> {"b"=>"a", "c"=>"b",..., "z"=>"y", "a"=>"z"}

def encrypt(str)
  crypt(str, ENCRYPT)
end

def decrypt(str)
  crypt(str, DECRYPT)
end

def crypt(str, mapping)
  str.gsub(/./, mapping)
end

encrypt('abc')   #=> "bcd"
decrypt('bcd')   #=> "abc"

encrypt('amnrz') #=> "bnosa"
decrypt('bnosa') #=> "amnrz"

This uses the form of String#gsub that takes a hash as an argument. See also Hash#invert.

Upvotes: 2

Md. Farhan Memon
Md. Farhan Memon

Reputation: 6121

Your code analysis.. Since you already initializing encrypted_str with empty string, there's no need to append it to original string and then slice it again..that's where it is getting messed up..just do the following..

until index == duration #you are not using duration too if assigned it to a variable
  encrypted_str += str[index].next[0]
  index += 1 
end

Taking the index 0 for next string because 'z'.next returns aa

An alternative one liner approach would be..

message.each_char.map { |s| s.next[0] }.join
  • chars will split the message into individual characters

  • map collects the manipulated characters into an array

  • join will join individual characters from mapped array to a string again


To Decrypt

encrypted_str.each_char.map { |s| s.eql?('a') ? 'z' : (s.ord-1).chr }.join

Upvotes: 3

Related Questions