Created
October 2, 2012 15:08
-
-
Save bil-bas/3819927 to your computer and use it in GitHub Desktop.
Encoding and decoding of strings for KevinSjoberg's problem (https://gist.github.com/3818527)
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
=begin | |
Problem Solving Challenge #1 (https://gist.github.com/3818527) | |
Problem solving challenges are fun. They make use of one's problem solving skills and stimulate the programmer's need to challenge themselves. | |
Here we go | |
These 1151159511610110199114 numbers represent a word. | |
The word may only contain a-zA-Z_ | |
The word is of size 8. | |
In this particular case the secret word was s_ecrets. | |
Write two functionsthat can encrypt an arbitrary string and return a string of numbers such as the one above. The program should also be able to take a string of numbers and return the original word. | |
Happy hacking! | |
=end | |
# Perhaps a little over-engineered, but I think a complete and robust solution. | |
module Encoder | |
class << self | |
# Create a mapping of encoded string back to characters { "115" => "s" } | |
valid_chars = ("A".."Z").to_a + ("a".."z").to_a + ["_"] | |
VALID_BYTES = Set.new valid_chars.join.bytes | |
ASCII_TO_CHAR = valid_chars.each_with_object({}) do |c, mapping| | |
mapping[c.bytes.to_a[0].to_s] = c | |
end | |
# Encode a string - validating. | |
def encode(string) | |
encoded = string.each_byte.map do |byte| | |
raise ArgumentError, "Bad character: '#{byte.chr}'" unless VALID_BYTES.include? byte | |
byte.to_s | |
end | |
riffle(encoded).join | |
end | |
# Decode string - validating. | |
def decode(string) | |
pos = 0 # Current position in string. | |
decoded = [] | |
# Code is 2 or 3 character strings. Take 2 characters and | |
# see if it is valid, otherwise take another char and check that. | |
until pos >= string.length | |
if (s = string[pos, 2]) and ASCII_TO_CHAR.has_key? s | |
decoded << ASCII_TO_CHAR[s] | |
pos += 2 | |
elsif (s << string[pos + 2]) and ASCII_TO_CHAR.has_key? s | |
decoded << ASCII_TO_CHAR[s] | |
pos += 3 | |
else | |
raise ArgumentError, "Bad encoding at string position #{pos}" | |
end | |
end | |
unriffle(decoded).join | |
end | |
protected | |
# Take first and last element from array until array is empty, | |
# to build a new array. | |
def riffle(array) | |
# Split into two halves. | |
first, second = array.each_slice(array.size / 2).to_a | |
# Take from the start and end until empty. | |
first.zip(second.reverse).inject([]) do |memo, (a, b)| | |
memo.push a, b | |
end | |
end | |
protected | |
# Reverse the effect of #riffle | |
def unriffle(array) | |
first, second = [], [] | |
array.each_slice(2).each do |a, b| | |
first << a | |
second.unshift b | |
end | |
first + second | |
end | |
end | |
end | |
# Run with "rspec" rather than "ruby" on the command line to run the specs. | |
if defined? RSpec | |
ENCODED = "1151159511610110199114" | |
STRING = "s_ecrets" | |
describe Encoder do | |
describe "encode" do | |
it "should encode a string" do | |
Encoder.encode(STRING).should eq ENCODED | |
end | |
it "should fail with a bad string" do | |
->{ Encoder.encode("abcd123") }.should raise_error ArgumentError, "Bad character: '1'" | |
end | |
end | |
describe "decode" do | |
it "should decode a string" do | |
Encoder.decode(ENCODED).should eq STRING | |
end | |
it "should fail with a bad encoded string" do | |
->{ Encoder.decode("11599123455") }.should raise_error ArgumentError, "Bad encoding at string position 5" | |
end | |
end | |
describe "riffle" do | |
it "should riffle an array" do | |
Encoder.send(:riffle, [1, 3, 4, 2]).should eq [1, 2, 3, 4] | |
end | |
end | |
describe "unriffle" do | |
it "should unriffle an array" do | |
Encoder.send(:unriffle, [1, 2, 3, 4]).should eq [1, 3, 4, 2] | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment