Begin forwarded message:
Below is my first solution to this quiz.
- donald
Ruby Q. 121
Donald A. Ball Jr.
Version 1.0
class Morse
CODES = {
:A => ‘.-’,
:N => ‘-.’,
:B => ‘-…’,
=> ‘—’,
:C => ‘-.-.’,
=> ‘.–.’,
=> ‘-…’,
:Q => ‘–.-’,
:E => ‘.’,
:R => ‘.-.’,
:F => ‘…-.’,
:S => ‘…’,
:G => ‘–.’,
:T => ‘-’,
:H => ‘…’,
:U => ‘…-’,
:I => ‘…’,
:V => ‘…-’,
:J => ‘.—’,
:W => ‘.–’,
:K => ‘-.-’,
:X => ‘-…-’,
:L => ‘.-…’,
:Y => ‘-.–’,
:M => ‘–’,
:Z => ‘–…’
}
LETTERS = CODES.invert
def self.translate(cipher)
results = []
LETTERS.each_pair do |code, letter|
next unless cipher.slice(0, code.length) == code
if cipher.length == code.length
results << letter.to_s
else
translate(cipher.slice(code.length, cipher.length)).each do
|result|
results << (letter.to_s << result)
end
end
end
results
end
end
Morse.translate(ARGV[0]).each{|word| puts word}
Below is my second solution.
- donald
Ruby Q. 121
Donald A. Ball Jr.
Version 1.1
class String
def split_at(index)
[slice(0, index), slice(index, length)]
end
end
class Morse
CODES = {
:A => ‘.-’,
:B => ‘-…’,
:C => ‘-.-.’,
=> ‘-…’,
:E => ‘.’,
:F => ‘…-.’,
:G => ‘–.’,
:H => ‘…’,
:I => ‘…’,
:J => ‘.—’,
:K => ‘-.-’,
:L => ‘.-…’,
:M => ‘–’,
:N => ‘-.’,
=> ‘—’,
=> ‘.–.’,
:Q => ‘–.-’,
:R => ‘.-.’,
:S => ‘…’,
:T => ‘-’,
:U => ‘…-’,
:V => ‘…-’,
:W => ‘.–’,
:X => ‘-…-’,
:Y => ‘-.–’,
:Z => ‘–…’
}
def self.decipher(cipher)
CODES.each_pair do |letter, code|
prefix, suffix = cipher.split_at(code.length)
next unless prefix == code
if suffix == ‘’
yield letter.to_s
else
decipher(suffix) {|result| yield letter.to_s << result }
end
end
end
end
Morse.decipher(ARGV[0]) {|word| puts word}
Here’s my solution to Ruby Q. #121.
Jim Barnett
#!/usr/bin/env ruby
class MorseCode
attr_accessor :results
attr_reader :words
Alphabet = {
‘A’ => ‘.-’, ‘B’ => ‘-…’, ‘C’ => ‘-.-.’, ‘D’ => ‘-…’,
‘E’ => ‘.’, ‘F’ => ‘…-.’, ‘G’ => ‘–.’, ‘H’ => ‘…’, ‘I’ =>
‘…’,
‘J’ => ‘.—’, ‘K’ => ‘-.-’, ‘L’ => ‘.-…’, ‘M’ => ‘–’, ‘N’ =>
‘-.’,
‘O’ => ‘—’, ‘P’ => ‘.–.’, ‘Q’ => ‘–.-’, ‘R’ => ‘.-.’, ‘S’ =>
‘…’,
‘T’ => ‘-’, ‘U’ => ‘…-’, ‘V’ => ‘…-’, ‘W’ => ‘.–’, ‘X’ =>
‘-…-’,
‘Y’ => ‘-.–’, ‘Z’ => ‘–…’
}
def initialize
@results = []
@words = []
@words << load_dictionary
end
def to_text(input, output = “”, words = @words)
unless input.empty?
m = matches(input)
m.each do |char|
to_text(input[Alphabet[char].length, input.length], output +
char)
end
else
@results << output
end
end
def matches(input)
Alphabet.select { |key, value| input[0, value.length] ==
value }.map { |v| v.first }.sort
end
def load_dictionary
# dictionary.txt from
http://java.sun.com/docs/books/tutorial/collections/interfaces/examples/dictionary.txt
File.open(“dictionary.txt”, “r”) do |file|
file.each_line do |line|
@words << line.chomp.upcase if line
end
end
@words << ‘SOFIA’
@words << ‘EUGENIA’
end
def in_dictionary?(str)
@words.include?(str)
end
end
$mc = MorseCode.new
$mc.to_text(ARGV[0])
$mc.results.each { |r| puts “#{r} #{ $mc.in_dictionary?(r) ? “(in
dictionary)” : “” }” }
On 4/22/07, Ball, Donald A Jr (Library) [email protected]
wrote:
end
end
end
Morse.decipher(ARGV[0]) {|word| puts word}
That’s pretty much what I did (as well as some others) but yours is
much more elegant. I didn’t really think about using a block with the
recursion. Cool.
That’s pretty much what I did (as well as some others) but yours is
much more elegant. I didn’t really think about using a block with the
recursion. Cool.
Thanks. That’s actually the first time I’ve written code that yields.
It’s actually bit unclear to me as to when it’s better to return results
and when it’s better to yield them. I guess the best thing to do would
be to check, what is it, block_given? and either yield or collect the
results as appropriate. Do more advanced rubyists have any guidance to
offer in this regard?
- donald
On Apr 22, 2007, at 9:35 PM, Ball, Donald A Jr (Library) wrote:
That’s pretty much what I did (as well as some others) but yours is
much more elegant. I didn’t really think about using a block with the
recursion. Cool.Thanks. That’s actually the first time I’ve written code that
yields. It’s actually bit unclear to me as to when it’s better to
return results and when it’s better to yield them. I guess the best
thing to do would be to check, what is it, block_given? and either
yield or collect the results as appropriate. Do more advanced
rubyists have any guidance to offer in this regard?
I prefer to yield whenever you don’t need a full set of results to do
something useful. This means I don’t have to aggregate results,
which saves memory. It also means the calling code gets answers as
soon as they are available. Plus, if that calling code really wanted
to fill an Array with the results they can certainly do that.
Basically, it gives the caller more choices.
James Edward G. II
On Apr 22, 2007, at 1:03 PM, James Edward G. II wrote:
Begin forwarded message:
From: “Jesús Gabriel y Galán” [email protected]
Date: April 21, 2007 5:01:15 PM CDT
To: [email protected]
Subject: Re: [QUIZ] Morse Code (#121)
Also, I’m fairly new to Ruby, only programming little things to
learn,
but nothing serious. So I’d appreciate any feedback you have on my
Ruby.
Some minor suggestions:
- Drop the parentheses on if/while statement conditions
- while !queue.empty? could be until queue.empty?
- This bit of code:
sorted_keys = letters.keys.sort_by {|x| x.length}
min_length = sorted_keys[0].length
max_length = sorted_keys[-1].length
could be:
min_length = letters.keys.min {|a,b| a.length <=> b.length }
max_length = letters.keys.max {|a,b| a.length <=> b.length }
or:
min_length, max_length = letters.keys.sort_by {|x| x.length}.values_at
(0, -1)
Just some thoughts.
Welcome to Ruby.
James Edward G. II
On 4/23/07, James Edward G. II [email protected] wrote:
From: “Jesús Gabriel y Galán” [email protected]
or:
min_length, max_length = letters.keys.sort_by {|x| x.length}.values_at
(0, -1)Just some thoughts.
In fact, I have done a modification to my version, to generalize that
thing: instead of assuming we have keys from min to max I actually get
an array with all the possible key lengths with:
key_lengths = letters.keys.map {|x| x.length}.uniq
and then modify the min_length.upto(up_to) with key_lengths.each
which optimizes the loop for arbitrary key lengths… but haven’t been
able to test my code yet.
Welcome to Ruby.
Thanks, I’m in complete love with the language, and the community is
great. Ruby Q. is a great tool to learn.
Jesus.