Translation Project

Hello all! This is my first post! I started learning Ruby about 3 weeks
ago and have a personal project I would like to do, so I was wondering
if someone could help me out a bit, so I can get it started.

I would like to have a request made by Ruby to the user for some text.
Then Ruby would take their input and split the text up by every
individual character and assign it a new value based on what letter it
is.

For instance if:

“A” = [A,B,C,D,E,F] “B” = [G,H,I,J,K,L]
“C” = [M,N,O,P,Q,R] “D” = [S,T,U,V,W,X,Y,Z]

So with the info above, Ruby would look at a sentence like, “Hello
World” and it would say, "Ok, “H” is in “B’s” array, so it’s new value
is “B”… and would do that for each character in the text. Then, when
it’s done, it would show the result after it’s been put together. So the
final product would be, “BABBC DCCBA”. Spaces being accounted for as
they are shown in the original text.

If you know how this would be done, I would greatly appreciate your
help. Otherwise, if you know a portion of how it might work, I would
appreciate that as well. I’m grateful for any help anyone could provide.

Thank you

$h={
“A” => %w{A B C D E F},
“B” => %w{G H I J K L},
“C” => %w{M N O P Q R},
“D” => %w{S T U V W X Y Z}
}
$reverseh= $h.inject({}) { |h,(k,a)| a.each {|l| h[l]=k } ; h }

def conv(letter) $reverseh[letter] || letter end

puts ARGV.map { |word|
word.upcase.split(//).map { |l| conv(l) }.join("")
}.join(" ")

ruby essai.rb So, whe do your work ? lazy Jeremy…
DC, DBA AC DCDC DCCB ? BADD BACACD…

Thank you very much for your quick reply, however, I’m confused. This
makes no request for user input?

I tried adding into it:

‘user_input = gets.chomp’

But it doesn’t do anything. It didn’t do anything without it. I’m
running Ruby 1.8.3. Am I doing something wrong?

Thank you again for your help.

And I apologize if I gave the impression that I’m not doing any work,
this is only the beginning, this is just a foundation I’m trying to get
setup.

print “Word ? "
while (word=$stdin.gets).size>1
puts word.chomp.upcase.split(//).map { |l| conv(l) }.join(”")
print "Word ? "
end

$h={
“A” => %w{A B C D E F},
“B” => %w{G H I J K L},
“C” => %w{M N O P Q R},
“D” => %w{S T U V W X Y Z}
}
$reverseh= $h.inject({}) { |h,(k,a)| a.each {|l| h[l]=k } ; h }

def wconv(word)
word.upcase.split(//).map { |l| $reverseh[l]||l}.join("")
end

require ‘Ruiby’

Ruiby.app :width=>200,:height=>50 do
stack do
flow { label(" Word ?") ; @e=entry("") ; space}
space
separator
flow do
button(“Translate please”) {
alert( wconv(@e.text)) if @e.text.size>0
}
button(“Exit”) { exit!(0) }
end
end
end

What are you running this in? Because I can’t get it to run with it
requiring the ruiby.app. I am trying to work on it in CodeAcademy Labs
and it keeps hitting the error:

(eval):12: (eval):12:in `require’: no such file to load – Ruiby
(LoadError)
from (eval):12

Even when I would run it as the original two posts you made:

print “Word ? "
while (word=$stdin.gets).size>1
puts word.chomp.upcase.split(//).map { |l| conv(l) }.join(”")
print "Word ? "
end

$h={
“A” => %w{A B C D E F},
“B” => %w{G H I J K L},
“C” => %w{M N O P Q R},
“D” => %w{S T U V W X Y Z}
}
$reverseh= $h.inject({}) { |h,(k,a)| a.each {|l| h[l]=k } ; h }

def conv(letter) $reverseh[letter] || letter end

puts ARGV.map { |word|
word.upcase.split(//).map { |l| conv(l) }.join("")
}.join(" ")

It hits the error:

(eval):14: undefined method conv' for main:Object (NoMethodError) from (eval):14:inmap’
from (eval):14

complete file is :

$h={
“A” => %w{A B C D E F},
“B” => %w{G H I J K L},
“C” => %w{M N O P Q R},
“D” => %w{S T U V W X Y Z}
}
$reverseh= $h.inject({}) { |h,(k,a)| a.each {|l| h[l]=k } ; h }

def conv(letter) $reverseh[letter] || letter end

print “Word ? "
while (word=$stdin.gets).size>1
puts word.chomp.upcase.split(//).map { |l| conv(l) }.join(”")
print "Word ? "
end

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

for Ruiby do a

gem install gtk3
gem install gtk2
gem install Ruiby

and run with ruby 1.9 or 2.0 (not tested with ruby 1.8)

On 03/28/2013 01:00 PM, Jeremy H. wrote:

If you know how this would be done, I would greatly appreciate your
help. Otherwise, if you know a portion of how it might work, I would
appreciate that as well. I’m grateful for any help anyone could provide.

Thank you

Welcome to Ruby!

What parts have you already written? What parts are you having trouble
with?

Regis’ answers are not very newbie-friendly nor idiomatic and do not
make total sense, so feel free to try a different approach.

-Justin

On 29/03/2013, at 7:00 AM, Jeremy H. [email protected]
wrote:

If you know how this would be done, I would greatly appreciate your
help. Otherwise, if you know a portion of how it might work, I would
appreciate that as well. I’m grateful for any help anyone could provide.

Thank you

Hi Jeremy,

Ruby is a very concise and expressive programming language. It’s
possible to pack a lot of code in a short number of lines.

Thus, while this code that I wrote as a solution to your problem solves
your problem, it’s necessary to explain what it does.

input = “hello”
dict = {a: “abcdef”, b: “ghijkl”, c: “mnopqr”, d: “stuvwxyz”}
puts input.each_char.map do |char|
key, value = dict.detect{|key, value| value.include?(char)}
end.join

Here is an annotated version:

set the input string to “hello”

input = “hello”

create a Ruby Hash (also called a dictionary in some languages) and

set it to the variable dict.

we are using single letter strings for keys, and those keys are then

defined by a string with a series of letters in each.

Commas separate the key-value pairs, and keys are separated by values

by =>

thus, if we were to ask dict for what it defines as “a”, we’d get back

“abcdef”

We can do this by saying dict[“a”] and ruby will then return “abcdef”

I suggest you read up on the Hash class and ruby hashes. They’re very

powerful and interesting.
dict = {“a” => “abcdef”, “b” => “ghijkl”, “c” => “mnopqr”, “d” =>
“stuvwxyz”}

this is an iterator - ie a loop. It’s actually a reasonably complex

one because I’ve chained two together.

input.each_char will give an Enumerator, which effectively gives us

the equivalent of an Array (a list) that has

in it a series of strings, each with just one character in it. In

other words, it will yield to us a series of items, each which

is one single character string out of the “input” string.

input.each_char.map is equivalent to setting a variable to

input.each_char and then sending that variable

the map message.

now, map is a method that takes some enumerable object such as Array

or Enumerator, and evaluates

a chunk of code (called a block in ruby) on each element of that

array. I.E. it gives us a new array where each element of the new

array represents the result of evaluating the block of code that is

passed to map against each element of the object that map is

called on.

it’s much easier to understand it in examples than it is in

explanation

So, this is a good example:

>> [“hello”, “this”, “is”, “fun”].map{|item| item.upcase}

this will yield:

=> [“HELLO”, “THIS”, “IS”, “FUN”]

You can see each element of the input array, which is a string with a

lowercase word in it, has been “processed” by the block (indicated with
{} braces)

in the block {|item| item.upcase}, item represents each element, and

then the bit after (item.upcase) is the code that will be executed on
each item.

So, in summary, the following code goes through each character as a

separate string and assigns it to the variable “char” in the block:

the “puts” call just outputs the result of the input.each_char.map

puts input.each_char.map do |char|

now, if we take the next bit in reverse, it’ll be more easy to

explain. There are three parts to it:

string objects (in fact most enumerables) have a method called

“include?” which basically returns true if it is included

So:

>> “doggie”.include?(“dog”)

=> true

should make sense

Hash or dictionary objects have a method called detect (or find) which

is an iterator/enumerator that looks over each

key and value pair, and returns the first pair (as an array) where the

block it takes evaluates to true

thus:

>> {“hello” => “goodbye”, “yes” => “no”}.detect{|key,value| key ==

“yes”}

=> [“yes”, “no”]

… should come as no surprise

now, ruby has a way of pulling out values of an array and assigning

them to other variables

it’s called multiple assignment and this should explain it

>> x,y = [3,4]

=> [3, 4]

>> x

=> 3

>> y

=> 4

so, x is 3 and y is 4.

so what I’m doing in the next line of code is assigning key and value

to be the key and value of the first element

of the dict variable whose value includes the char variable’s value.

key, value = dict.detect{|key, value| value.include?(char)}

that is then returned as the result of the map. At this point, we

would be fine to simply put end to mark the end of the map block

(ruby can use {} or do … end to mark blocks)

but we want to build the single-char strings array into a single

string. We do that with join.

ie:

>> [“cool”, " beans"].join

=> “cool beans”

end.join

and that’s all! :slight_smile:

hope that helped!

Julian

On 30/03/2013, at 2:48 AM, Jeremy H. [email protected]
wrote:

whatever needed to be done.

I’m going to read through everything bit by bit and see if I can get it
}
print "DNAS: Additional Input? "


Posted via http://www.ruby-forum.com/.

class String
def dna_conv
dict = {“A” => “ABCDEF”, “B” => “GHIJKL”, “C” => “MNOPQR”, “D” =>
“STUVWXYZ”}
self.upcase.each_char.map{|input_char| dict.detect{|key, value|
value.include?(input_char)}.first}.join
end
end

puts "DNAS: Sequencing Open… Input? "
while (word=$stdin.gets.chomp).size>1
puts word.dna_conv
puts
puts "DNAS: Additional Input? "
end

Better?

Yes, I love how compressed it is. Like Regis’ though, it can’t handle
apostrophes. I assume I’ll need to add some kind of exception for them
into it.

Thank you very much Regis, Justin, and Julian! I am grateful that you
have taken the time to not just respond, but to make this educational as
well, that is exactly what I was looking for.

Regis:

I have tested your code on codeacademy labs and it does work on 1.8.3,
but seems to have a problem with not running multiple times, I believe
that is an issue with their site though. When running, it works very
smoothly!

Recurring issue with it: It cannot accept apostrophe’s. It will lock up
the site if an apostrophe is anywhere in the text. Which I will work on
resolving.

Justin:

Up until my conversation with Regis yesterday, I had no coding down,
just the concept. Knowing that there would be multiple possible
approaches, I was wanting to see at least one possible way that someone
knew how to do it, and then assess, reconfigure, rebuild, etc…
whatever needed to be done.

My goal is to create an encrypter that mimics DNA sequencing which only
uses four letters: A, T, G, C. Wherein there is a rule they must follow,
A always pairs with T, and C always pairs with G.

So this encrypter would take text, reassign it’s values to one of the
four letters (this assigning could then be changed in a whim if anyone
ever figured it out), and then spit out the result.

{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{

The end product would then be to have a way of re-combining everything
on the receiving end. Which is the hard part. I want it to take the
code, assess the different possible letters, for instance, “You”
translated in the example above WOULD be “DCD”, which then re-translated
back COULD be any combination of [S,T,U,V,W,X,Y,Z] [M,N,O,P,Q,R]
[S,T,U,V,W,X,Y,Z]. It would need to compare the possible combinations to
a dictionary, which would be ranked on the most probable words, and then
spit out the most accurate answer.

{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{

So, there is still a lot of work to do. I just wanted a good footing to
base it on. So that’s where I’m at now.

Julian:

Thank you very much for your solution, but also for the detailed
explanation and breakdown! I have learned about a lot of the different
components you mentioned through Code Academy, but also a lot of them I
either haven’t gotten to, or they don’t teach it. So THANK YOU!

I’m going to read through everything bit by bit and see if I can get it
to run on code academy labs. Then play with it as need be.

Here are the small changes I have made to Regis’ solution so far (mostly
spacing and rewording of the request for input):

$h={
“A” => %w{A B C D E F},
“T” => %w{G H I J K L},
“G” => %w{M N O P Q R},
“C” => %w{S T U V W X Y Z}
}
$reverseh= $h.inject({}) { |h,(k,a)| a.each {|l| h[l]=k } ; h }

def conv(letter) $reverseh[letter] || letter end

print “DNAS: Sequencing Open… Input? "
puts " "
while (word=$stdin.gets).size>1
puts word.chomp.upcase.split(//).map { |l| conv(l) }.join(”")
puts " "
print "DNAS: Additional Input? "
puts " "
end

Again, thank you very much everybody! I don’t want anyone to think that
I am asking you to do the work for me. I want to learn all of this and
will do it all myself if it comes to it, it just helps to have solid
grounding to work with. Not to mention, I will give credit on everyone’s
contributions at the end of this all and in the final product, unless
they ask me not to. I’m not here to steal work. :slight_smile:

On 30/03/2013, at 3:42 AM, Jeremy H. [email protected]
wrote:

Yes, I love how compressed it is. Like Regis’ though, it can’t handle
apostrophes. I assume I’ll need to add some kind of exception for them
into it.


Posted via http://www.ruby-forum.com/.

Yeah, you didn’t specify what you wanted it to do. This one allows you
to specify with the default_char variable what unspecified chars will be
mapped to (presently it’s at a space, but you could replace with an
empty string or some other default char/string easily).

class String
def dna_conv
default_char = " "
dict = {“A” => “ABCDEF”, “B” => “GHIJKL”, “C” => “MNOPQR”, “D” =>
“STUVWXYZ”}
self.upcase.each_char.map{|input_char| found_pair = dict.detect{|key,
value| value.include?(input_char)}; (found_pair && found_pair.first) ||
default_char}.join
end
end

puts "DNAS: Sequencing Open… Input? "
while (word=$stdin.gets.chomp).size>1
puts word.dna_conv
puts
puts "DNAS: Additional Input? "
end

Am 30.03.2013 08:19, schrieb Julian L.:

Clarity around capturing of intent can’t be overrated in my opinion when it
comes time to programming.

I don’t have the previous messages around anymore, so I’m not sure
whether this has been brought up before, but I don’t think so.

Very clear in my opinion is String#tr:

“hello world”.tr(‘aeiou’, '’) # => "hll* w*rld"

On 30/03/2013, at 3:42 AM, Jeremy H. [email protected]
wrote:

Yes, I love how compressed it is. Like Regis’ though, it can’t handle
apostrophes. I assume I’ll need to add some kind of exception for them
into it.

By the way, compressed is overrated IMHO. If you love compressed, you
might like PERL, or if you like powerful ideas expressed simply, you
might like LISP.
However, when it comes time to actually maintain code (and all code
needs maintaining), you will probably find simple Ruby to be much easier
to read and understand.

Clarity around capturing of intent can’t be overrated in my opinion when
it comes time to programming.

What else have you programmed in, if anything?

Julian

It would need to compare the possible combinations to
a dictionary, which would be ranked on the most probable words

This can help you:

http://raubarede.tumblr.com/rubyresume.html#c15
http://blog.invisible.ch/2005/01/15/markov-chains-in-ruby/

BA CACAAADBCC ADD ADDABCDA, CCC CAD BCCDCDBB CD A CBDD CBAC A ABCDDAC,
CABD BCCDCDBB CD A CBDD CBAC A CADBCAC
Antoine de Saint-Exupéry

sorry :slight_smile:

On 31/03/2013, at 1:42 AM, [email protected] wrote:

However, when it comes time to actually maintain code (and all code needs
maintaining), you will probably find simple Ruby to be much easier to read and
understand.


https://github.com/stomar/

It is very clear, but it doesn’t help here, does it? What we want is
parallel translation.

Julian

While not as brief, the code that follows is more understandable IMHO:

class String
def dna_conv
self.upcase.each_char.map do |input_char|
case
when “ABCDEF”[input_char] then “A”
when “GHIJKL”[input_char] then “B”
when “MNOPQR”[input_char] then “C”
when “STUVWXYZ”[input_char] then “D”
else
" "
end
end.join
end
end

puts "DNAS: Sequencing Open… Input? "
while (word=$stdin.gets.chomp).size>1
puts word.dna_conv
puts
puts "DNAS: Additional Input? "
end

it can be shorted:

class String
def dna_conv
upcase.tr(“A-Z”,?A6+?B6+?C6+?D8)
end
end

but ?A only works as i want at 1.9 :stuck_out_tongue:

And this one ? :

============================================================
def c(letter)
(“ABCDEF”[letter]&&“A”)||(“GHIJKL”[letter]&&“B”)||
(“MNOPQR”[letter]&&“C”)||(“STUVWXYZ”[letter]&&“D”)||letter
end

loop {
print “Word ? "
str=STDIN.gets.chomp
break if str.size==0
puts str.upcase.each_char.map {|letter| c(letter)}.join(”")
}