Skip to content

Instantly share code, notes, and snippets.

@queerviolet
Last active August 29, 2015 14:11
Show Gist options
  • Save queerviolet/6aacdbe8affc3f2732a9 to your computer and use it in GitHub Desktop.
Save queerviolet/6aacdbe8affc3f2732a9 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
ROMAN = {
1000 => 'M',
900 => 'CM',
800 => 'DCCC',
500 => 'D',
400 => 'CD',
100 => 'C',
90 => 'XC',
50 => 'L',
40 => 'XL',
10 => 'X',
9 => 'IX',
5 => 'V',
4 => 'IV',
1 => 'I'
}
ROMAN_OLD = {
1000 => 'M',
500 => 'D',
100 => 'C',
50 => 'L',
10 => 'X',
5 => 'V',
1 => 'I'
}
US_CURRENCY = {
100 => 'dollar',
25 => 'quarters',
10 => 'dimes',
5 => 'nickels',
1 => 'pennies'
}
NUMBERS = {
1e12.to_i => 'trillion',
1e9.to_i => 'billion',
1e6.to_i => 'million',
1e3.to_i => 'thousand',
100 => 'hundred',
90 => 'ninety',
80 => 'eighty',
70 => 'seventy',
60 => 'sixty',
50 => 'fifty',
40 => 'forty',
30 => 'thirty',
20 => 'twenty',
19 => 'nineteen',
18 => 'eighteen',
17 => 'seventeen',
16 => 'sixteen',
15 => 'fifteen',
14 => 'fourteen',
13 => 'thirteen',
12 => 'twelve',
11 => 'eleven',
10 => 'ten',
9 => 'nine',
8 => 'eight',
7 => 'seven',
6 => 'six',
5 => 'five',
4 => 'four',
3 => 'three',
2 => 'two',
1 => 'one',
0 => 'zero'
}
def num_to_symbols(num, symbols)
if symbols.include? num
return {symbols[num] => 1}
end
Hash[symbols.sort_by { |value, symbol| -value }.map do |value, symbol|
if value != 0
count = num / value
num = num % value
[symbol, count]
end
end]
end
def parse_sym_str(str, symbols)
symbols.sort_by { |value, symbol| -symbol.length }.map { |value, symbol|
count = str.scan(symbol).count
str = str.gsub(symbol, '')
count * value
}.reduce(:+)
end
def to_words(num)
num_to_symbols(num, NUMBERS).map do |symbol, count|
if count > 0
if NUMBERS[symbol] > 99
[to_words(count), symbol]
else
symbol
end
end
end.flatten.reject { |x| x == nil }.join(' ')
end
#!/usr/bin/env rspec
## paste student code here ##
## test harness ##
require_relative 'number_symbols'
def spec_to_roman_modern(num)
num_to_symbols(num, ROMAN).map { |symbol, count| symbol * count }.join('')
end
def spec_to_roman_old(num)
num_to_symbols(num, ROMAN_OLD).map { |symbol, count| symbol * count }.join('')
end
def spec_parse_roman(str)
parse_sym_str(str, ROMAN)
end
describe 'to_roman' do
it 'should be reversible' do
(1..10_000).each do |num|
expect(spec_parse_roman(to_roman(num))).to eq(num), <<EOF
to_roman(#{num}) -> #{to_roman(num).inspect}:
spec_parse_roman(#{to_roman(num).inspect}) == expected #{num}
got #{spec_parse_roman(to_roman(num))}"
EOF
end
end
end
describe 'to_roman_modern' do
it 'should be reversible' do
(1..10_000).each do |num|
expect(spec_parse_roman(to_roman_modern(num))).to eq(num), <<EOF
to_roman_modern(#{num}) -> #{to_roman_modern(num).inspect}:
expected spec_parse_roman(#{to_roman_modern(num).inspect}) == #{num}
got #{spec_parse_roman(to_roman_modern(num))}
EOF
end
end
it 'should be optimal' do
(1..10_000).each do |num|
expect(to_roman_modern(num)).to eq(spec_to_roman_modern(num)), <<EOF
to_roman_modern(#{num}) ->
expected #{spec_to_roman_modern(num).inspect}
got #{to_roman_modern(num).inspect}
EOF
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment