This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
["Two", "Birds", "In", "Hand"].each_with_index.map { |element, index| | |
"#{element}: #{index}" | |
} | |
# => ["Two: 0", "Birds: 1", "In: 2", "Hand: 3"] |
Even now, I'm learning things about Ruby. The rabbit hole is deep.
Anyway, a post about learning how to code fast came across my desk. I knew that I wasn't quite as fast as other coders, but I had always thought that I thought deeper on the solution. But I think what he says makes sense. I know that violinists slowly ramp up their speed to a point where they're almost making mistakes, faster than they'd actually play the piece to practice playing it at the correct speed. Same with drawing. The more you practice drawing faster, the better you get at being economic with your strokes. So I figured I'd try the same with programming, since I've never done much of this type of exercise.
I decided to do the first Ruby Quiz, since I was most familiar with Ruby, and I should be able to do it quickly. It took me about three hours, including reading the instructions, going on bathroom breaks, etc. I think I should have been faster, and I noticed where I slowed down. I found myself trying things out in irb a lot because I didn't know the exact behavior of some array and string functions. Also, I spent some time in the beginning pondering how to structure it--should it be a class, or just a collection of functions, or should I extend the classes?
I'm not thrilled about how it's structured, but it works. Well, there's a small bug in there, but I'm going to refrain from fixing it. It'll tack on another 30 mins. The point of the exercise is that I can see what I need to work on. I'll try again next time with the next ruby quiz.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
class Encrypter | |
private | |
def value(symbol) | |
return 53 if symbol == "A" or symbol == "B" | |
return symbol.to_i | |
end | |
def triple_cut | |
if @deck.index("A") > @deck.index("B") | |
top_index = @deck.index("A") | |
bottom_index = @deck.index("B") | |
else | |
top_index = @deck.index("B") | |
bottom_index = @deck.index("A") | |
end | |
bottom = @deck[0...bottom_index] | |
middle = @deck[bottom_index..top_index] | |
top = @deck[(top_index) + 1..-1] | |
@deck = top + middle + bottom | |
end | |
def count_cut | |
count = value(@deck.first) | |
@deck = [@deck[0]] + @deck[-count..-1] + @deck[1...-count] | |
end | |
public | |
def initialize | |
@deck = ["B", "A"] + (1..52).to_a.reverse | |
# key the deck | |
end | |
def next_key | |
jokerA_index = @deck.index("A") | |
@deck.move(jokerA_index, jokerA_index - 1) | |
jokerB_index = @deck.index("B") | |
@deck.move(jokerB_index, jokerB_index - 2) | |
@deck = triple_cut | |
@deck = count_cut | |
top_count = value(@deck.last) | |
return [@deck[-(top_count + 1)]].to_alpha | |
end | |
end | |
class String | |
def keystream | |
enc = Encrypter.new | |
self.gsub(/[^A-Za-z]/, "").split("").map { |char| | |
enc.next_key | |
}.join | |
end | |
def segment_by(number) | |
segments = [] | |
self.gsub(/[^A-Za-z]/, "").upcase.split("").each_slice(number) do |slice| | |
segments << slice.join | |
end | |
(number - segments.last.length).times { segments.last << "X" } if segments.last.length < number | |
return segments | |
end | |
def to_numeric | |
self.split("").map { |char| char[0] - 64 } | |
end | |
end | |
class Array | |
def to_alpha | |
self.map { |number| (number.to_i % 26 + 64).chr }.join | |
end | |
def move(from, to) | |
element = self.delete_at(from) | |
to -= 1 if (to < 0) | |
self.insert(to, element) | |
end | |
end | |
def merge_numerics(message, keystream) | |
message.each_with_index.map do |segment, segment_index| | |
segment.each_with_index.map do |message_number, char_index| | |
keystream_number = keystream[segment_index][char_index] | |
yield message_number, keystream_number | |
end | |
end | |
end | |
def codec(command, message) | |
message_numerics = message.segment_by(5).map { |s| s.to_numeric } | |
keystream_numerics = message.keystream.segment_by(5).map { |s| s.to_numeric } | |
merge_numerics(message_numerics, keystream_numerics) { |m, k| | |
case command | |
when "encode" | |
(m + k) % 26 | |
when "decode" | |
(m - k) % 26 | |
end | |
}.map { |segment| | |
segment.to_alpha | |
} | |
end | |
puts "Welcome to the Solitaire Cipher" | |
puts | |
# get the input | |
command = ARGV.shift | |
message = ARGV.shift | |
puts "You entered: #{message}" | |
puts "Output: #{codec(command, message).join.inspect}" |
No comments:
Post a Comment