galaxy_converter 2.1.2 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +4 -4
- data/README.md +0 -28
- data/bin/galaxy_converter +1 -2
- data/galaxy_converter.gemspec +4 -6
- data/lib/galaxy_converter.rb +5 -3
- data/lib/galaxy_converter/constraint.rb +44 -0
- data/lib/galaxy_converter/converter.rb +21 -0
- data/lib/galaxy_converter/{recognizer.rb → detector.rb} +11 -16
- data/lib/galaxy_converter/note.rb +26 -6
- data/lib/galaxy_converter/responder.rb +8 -31
- data/lib/galaxy_converter/roman_numeral.rb +26 -30
- data/lib/galaxy_converter/stretcher.rb +20 -0
- data/lib/galaxy_converter/version.rb +1 -1
- data/notes.txt +12 -0
- metadata +15 -30
- data/lib/galaxy_converter/abacus.rb +0 -24
- data/lib/galaxy_converter/cli.rb +0 -47
- data/lib/galaxy_converter/roman_constraint.rb +0 -31
- data/lib/galaxy_converter/roman_rule.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 87b623ff14335cdeefbdd51a3576e5c17873cce273ff1000285d5e42ab5ed5e1
|
4
|
+
data.tar.gz: fcd3f01c18c0c377fc6756c1e5d02a4ae64f0cdd6f571b0642bda9aa6147313a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d01ea972a57072f1704ca1b96f1e7a26d2b8c3d3c0b0a1b63fdb2b68f382a56a9a4417ae11d3bb466fbfbeaf47ece3b924d4b4010673bf04704ddb9933abde4f
|
7
|
+
data.tar.gz: '0592b1427e97f9f8fd7664708d130695faaab4d53e93d3bcbb391dea33c6250606aa3657f7221c7530c3fc106f6f7b5f175b3ef1b095ab623a97db46865004d5'
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,6 @@
|
|
5
5
|
* [Roman numerals](#roman-numerals)
|
6
6
|
* [Installation](#installation)
|
7
7
|
* [Usage](#usage)
|
8
|
-
* [Library](#library)
|
9
8
|
* [CLI](#cli)
|
10
9
|
|
11
10
|
## Scope
|
@@ -28,35 +27,8 @@ gem install galaxy_converter
|
|
28
27
|
|
29
28
|
## Usage
|
30
29
|
|
31
|
-
### Library
|
32
|
-
Just require the library into your program and pass an array of notes to the converter:
|
33
|
-
```ruby
|
34
|
-
require "galaxy_converter"
|
35
|
-
|
36
|
-
notes = ["glob is I", "prok is V", "pish is X", "tegj is L", "glob glob Silver is 34 Credits", "glob prok Gold is 57800 Credits", "pish pish Iron is 3910 Credits", "how much is pish tegj glob glob ?", "how many Credits is glob prok Silver ?", "how many Credits is glob prok Gold ?", "how many Credits is glob prok Iron ?", "how much wood could a woodchuck chuck if a woodchuck could chuck wood ? "]
|
37
|
-
|
38
|
-
puts GalaxyConverter.call(notes)
|
39
|
-
# pish tegj glob glob is 42
|
40
|
-
# glob prok Silver is 68 Credits
|
41
|
-
# glob prok Gold is 57800 Credits
|
42
|
-
# glob prok Iron is 782 Credits
|
43
|
-
# I have no idea what you are talking about
|
44
|
-
```
|
45
|
-
|
46
30
|
### CLI
|
47
31
|
The gem provides a CLI interface.
|
48
|
-
Once installed you will be able to use the `galaxy_converter` command from the terminal.
|
49
|
-
|
50
|
-
#### Help
|
51
|
-
You can print CLI help by:
|
52
|
-
```shell
|
53
|
-
galaxy_converter -h
|
54
|
-
Usage: galaxy_converter ~/notes.txt
|
55
|
-
-h --help Print this help
|
56
|
-
<path-to-file> Load conversion notes
|
57
|
-
```
|
58
|
-
|
59
|
-
#### Input
|
60
32
|
The program accepts as input a file containing several conversion notes:
|
61
33
|
```txt
|
62
34
|
# ~/notes.txt
|
data/bin/galaxy_converter
CHANGED
data/galaxy_converter.gemspec
CHANGED
@@ -16,10 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.bindir = "bin"
|
17
17
|
s.executables << "galaxy_converter"
|
18
18
|
s.require_paths = ["lib"]
|
19
|
-
s.required_ruby_version = ">= 2.
|
20
|
-
|
21
|
-
s.add_development_dependency "
|
22
|
-
s.add_development_dependency "
|
23
|
-
s.add_development_dependency "minitest", "~> 5.0"
|
24
|
-
s.add_development_dependency "benchmark-ips", "~> 2"
|
19
|
+
s.required_ruby_version = ">= 2.4.1"
|
20
|
+
s.add_development_dependency "bundler", "~> 2.0"
|
21
|
+
s.add_development_dependency "rake", "~> 12.3"
|
22
|
+
s.add_development_dependency "minitest", "~> 5.11"
|
25
23
|
end
|
data/lib/galaxy_converter.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require "galaxy_converter/version"
|
2
|
-
require "galaxy_converter/
|
2
|
+
require "galaxy_converter/responder"
|
3
3
|
|
4
4
|
module GalaxyConverter
|
5
5
|
extend self
|
6
6
|
|
7
|
-
def call(
|
8
|
-
|
7
|
+
def call(path_to_file)
|
8
|
+
f = File.expand_path(path_to_file)
|
9
|
+
return unless File.exist?(f)
|
10
|
+
notes = Note.from(File.readlines(f).map(&:strip))
|
9
11
|
Responder.new(notes).call
|
10
12
|
end
|
11
13
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module GalaxyConverter
|
2
|
+
module Constraint
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def call(value)
|
6
|
+
return if value.empty?
|
7
|
+
violations.any? { |violation| value.index(violation) }
|
8
|
+
end
|
9
|
+
|
10
|
+
private def violations
|
11
|
+
@violations ||= repetitions + subtractions
|
12
|
+
end
|
13
|
+
|
14
|
+
private def repetitions
|
15
|
+
too_many_repetitions + unrepeatable
|
16
|
+
end
|
17
|
+
|
18
|
+
private def too_many_repetitions
|
19
|
+
%w[I X C M].map { |c| c * 4 }
|
20
|
+
end
|
21
|
+
|
22
|
+
private def unrepeatable
|
23
|
+
%w[D L V].map { |c| c * 2 }
|
24
|
+
end
|
25
|
+
|
26
|
+
private def subtractions
|
27
|
+
repeated_sub + wrong_sub
|
28
|
+
end
|
29
|
+
|
30
|
+
private def repeated_sub
|
31
|
+
%w[V X].map { |c| "II#{c}"} +
|
32
|
+
%w[L C].map { |c| "XX#{c}"} +
|
33
|
+
%w[D M].map { |c| "CC#{c}"}
|
34
|
+
end
|
35
|
+
|
36
|
+
private def wrong_sub
|
37
|
+
%w[L C D M].map { |c| "I#{c}" } +
|
38
|
+
%w[D M].map { |c| "X#{c}" } +
|
39
|
+
%w[X L C D M].map { |c| "V#{c}" } +
|
40
|
+
%w[C D M].map { |c| "L#{c}"} +
|
41
|
+
%w[M].map { |c| "D#{c}" }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "galaxy_converter/roman_numeral"
|
2
|
+
|
3
|
+
module GalaxyConverter
|
4
|
+
class Converter
|
5
|
+
def initialize(mapping = {}, unit = RomanNumeral)
|
6
|
+
@mapping = mapping
|
7
|
+
@unit = unit
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(units)
|
11
|
+
converted = convert(units)
|
12
|
+
@unit.new(converted).to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
private def convert(units)
|
16
|
+
units.split(" ").reduce("") do |acc, unit|
|
17
|
+
acc << @mapping.fetch(unit, "")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,44 +1,39 @@
|
|
1
|
-
require "galaxy_converter/
|
1
|
+
require "galaxy_converter/converter"
|
2
2
|
require "galaxy_converter/note"
|
3
3
|
|
4
4
|
module GalaxyConverter
|
5
|
-
class
|
6
|
-
|
5
|
+
class Detector
|
6
|
+
MAPPING_RULE = /(\w+) is (\w+)/
|
7
|
+
GOODS_RULE = /([\w+\s]+) (\w+) is (\d+) credits/i
|
7
8
|
|
8
|
-
|
9
|
+
attr_reader :converter
|
10
|
+
|
11
|
+
def initialize(notes, converter = Converter)
|
9
12
|
notes = notes.reject(&:question?)
|
10
13
|
@commercials, @assertions = notes.partition(&:commercial?)
|
11
|
-
@
|
14
|
+
@converter = converter.new(mapping)
|
12
15
|
end
|
13
16
|
|
14
17
|
def goods
|
15
18
|
@goods ||= @commercials.reduce({}) do |acc, note|
|
16
|
-
matching = note.body.match(
|
19
|
+
matching = note.body.match(GOODS_RULE)
|
17
20
|
next acc unless matching
|
18
21
|
units, name, credits = matching.captures
|
19
|
-
value = @
|
22
|
+
value = @converter.call(units)
|
20
23
|
next acc if value.zero?
|
21
24
|
acc[name] = credits.to_f / value
|
22
25
|
acc
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
26
|
-
private def goods_rule
|
27
|
-
/([#{mapping.keys.join("|")}\s]+) (\w+) is (\d+)/
|
28
|
-
end
|
29
|
-
|
30
29
|
private def mapping
|
31
30
|
@mapping ||= @assertions.reduce({}) do |acc, note|
|
32
|
-
matching = note.body.match(
|
31
|
+
matching = note.body.match(MAPPING_RULE)
|
33
32
|
next acc unless matching
|
34
33
|
unit, roman = matching.captures
|
35
34
|
acc[unit.strip] = roman.upcase
|
36
35
|
acc
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
40
|
-
private def mapping_rule
|
41
|
-
/(\w+) is (\w)/
|
42
|
-
end
|
43
38
|
end
|
44
39
|
end
|
@@ -1,28 +1,48 @@
|
|
1
1
|
module GalaxyConverter
|
2
2
|
class Note
|
3
3
|
PREFIXES = ["how much is", "how many credits is"]
|
4
|
-
|
4
|
+
QUESTION = "?"
|
5
|
+
NO_IDEA = "I have no idea what you are talking about"
|
5
6
|
|
6
|
-
def self.
|
7
|
+
def self.from(notes)
|
7
8
|
Array(notes).map { |body| new(body) }
|
8
9
|
end
|
9
10
|
|
10
|
-
attr_reader :body
|
11
|
+
attr_reader :body, :units, :good
|
11
12
|
|
12
13
|
def initialize(body)
|
13
14
|
@body = body.to_s.strip.downcase
|
15
|
+
@units, @good = detect
|
14
16
|
end
|
15
17
|
|
16
18
|
def question?
|
17
|
-
@body.end_with?(
|
19
|
+
@body.end_with?(QUESTION)
|
18
20
|
end
|
19
21
|
|
20
22
|
def commercial?
|
21
23
|
!!@body.index("credits")
|
22
24
|
end
|
23
25
|
|
24
|
-
def
|
25
|
-
|
26
|
+
def answer(total = 0)
|
27
|
+
return NO_IDEA if total.zero?
|
28
|
+
[].tap do |s|
|
29
|
+
s << units
|
30
|
+
s << good.to_s.capitalize
|
31
|
+
s << "is"
|
32
|
+
s << "%g" % total
|
33
|
+
s << "Credits" if commercial?
|
34
|
+
end.reject(&:empty?).join(" ")
|
35
|
+
end
|
36
|
+
|
37
|
+
private def detect
|
38
|
+
tokens = stripped.split
|
39
|
+
return [tokens.join(" "), nil] unless commercial?
|
40
|
+
good = tokens.pop
|
41
|
+
[tokens.join(" "), good]
|
42
|
+
end
|
43
|
+
|
44
|
+
private def stripped
|
45
|
+
@body.sub(/#{PREFIXES.join("|")}/, "").sub(QUESTION, "").strip
|
26
46
|
end
|
27
47
|
end
|
28
48
|
end
|
@@ -1,49 +1,26 @@
|
|
1
1
|
require "forwardable"
|
2
|
-
require "galaxy_converter/
|
2
|
+
require "galaxy_converter/detector"
|
3
3
|
|
4
4
|
module GalaxyConverter
|
5
5
|
class Responder
|
6
6
|
extend Forwardable
|
7
7
|
|
8
|
-
def_delegators :@
|
8
|
+
def_delegators :@detector, :goods, :converter
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(notes, recognizer = Recognizer, abacus = Abacus)
|
10
|
+
def initialize(notes, detector = Detector)
|
13
11
|
@questions = notes.select(&:question?)
|
14
|
-
@
|
12
|
+
@detector = detector.new(notes)
|
15
13
|
end
|
16
14
|
|
17
15
|
def call
|
18
16
|
@questions.reduce([]) do |acc, note|
|
19
|
-
|
20
|
-
|
21
|
-
acc << to_s(units, good, total, note.commercial?)
|
22
|
-
acc
|
17
|
+
total = total(note)
|
18
|
+
acc << note.answer(total)
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
|
-
private def
|
27
|
-
|
28
|
-
[].tap do |s|
|
29
|
-
s << units
|
30
|
-
s << good.to_s.capitalize
|
31
|
-
s << "is"
|
32
|
-
s << "%g" % total
|
33
|
-
s << "Credits" if commercial
|
34
|
-
end.reject(&:empty?).join(" ")
|
35
|
-
end
|
36
|
-
|
37
|
-
private def total(units, good)
|
38
|
-
return abacus.call(units) unless good
|
39
|
-
abacus.call(units) * goods.fetch(good, 0)
|
40
|
-
end
|
41
|
-
|
42
|
-
private def detect(note)
|
43
|
-
tokens = note.stripped.split
|
44
|
-
return [tokens.join(" "), nil] unless note.commercial?
|
45
|
-
good = tokens.pop
|
46
|
-
[tokens.join(" "), good]
|
22
|
+
private def total(note)
|
23
|
+
converter.call(note.units) * goods.fetch(note.good, 1)
|
47
24
|
end
|
48
25
|
end
|
49
26
|
end
|
@@ -1,39 +1,35 @@
|
|
1
|
-
require "galaxy_converter/
|
2
|
-
require "galaxy_converter/
|
1
|
+
require "galaxy_converter/constraint"
|
2
|
+
require "galaxy_converter/stretcher"
|
3
3
|
|
4
4
|
module GalaxyConverter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
5
|
+
class RomanNumeral
|
6
|
+
SYMBOLS = {
|
7
|
+
"M" => 1000,
|
8
|
+
"D" => 500,
|
9
|
+
"C" => 100,
|
10
|
+
"L" => 50,
|
11
|
+
"X" => 10,
|
12
|
+
"V" => 5,
|
13
|
+
"I" => 1
|
14
|
+
}
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
def initialize(value, constraint = Constraint, stretcher = Stretcher)
|
17
|
+
@value = value.to_s.upcase
|
18
|
+
@constraint = constraint
|
19
|
+
@stretcher = stretcher
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def to_s
|
23
|
+
@value
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
26
|
+
def to_i
|
27
|
+
return 0 unless valid?
|
28
|
+
@stretcher.call(@value).chars.sum { |symbol| SYMBOLS.fetch(symbol, 0) }
|
29
|
+
end
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
!@constraint.violated?(@value)
|
36
|
-
end
|
31
|
+
private def valid?
|
32
|
+
!@constraint.call(@value)
|
37
33
|
end
|
38
34
|
end
|
39
35
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GalaxyConverter
|
2
|
+
module Stretcher
|
3
|
+
extend self
|
4
|
+
|
5
|
+
LONG_TO_SHORT = {
|
6
|
+
"DCCCC" => "CM", # 900
|
7
|
+
"CCCC" => "CD", # 400
|
8
|
+
"LXXXX" => "XC", # 90
|
9
|
+
"XXXX" => "XL", # 40
|
10
|
+
"VIIII" => "IX", # 9
|
11
|
+
"IIII" => "IV" # 4
|
12
|
+
}
|
13
|
+
|
14
|
+
def call(value)
|
15
|
+
LONG_TO_SHORT.reduce(value) do |to_convert, (long, short)|
|
16
|
+
to_convert.gsub(short, long)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/notes.txt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
glob is I
|
2
|
+
prok is V
|
3
|
+
pish is X
|
4
|
+
tegj is L
|
5
|
+
glob glob Silver is 34 Credits
|
6
|
+
glob prok Gold is 57800 Credits
|
7
|
+
pish pish Iron is 3910 Credits
|
8
|
+
how much is pish tegj glob glob ?
|
9
|
+
how many Credits is glob prok Silver ?
|
10
|
+
how many Credits is glob prok Gold ?
|
11
|
+
how many Credits is glob prok Iron ?
|
12
|
+
how much wood could a woodchuck chuck if a woodchuck could chuck wood ?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: galaxy_converter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- costajob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,56 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '12.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '12.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '5.
|
47
|
+
version: '5.11'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '5.
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: benchmark-ips
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '2'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '2'
|
54
|
+
version: '5.11'
|
69
55
|
description:
|
70
56
|
email:
|
71
57
|
- costajob@gmail.com
|
@@ -84,15 +70,15 @@ files:
|
|
84
70
|
- bin/setup
|
85
71
|
- galaxy_converter.gemspec
|
86
72
|
- lib/galaxy_converter.rb
|
87
|
-
- lib/galaxy_converter/
|
88
|
-
- lib/galaxy_converter/
|
73
|
+
- lib/galaxy_converter/constraint.rb
|
74
|
+
- lib/galaxy_converter/converter.rb
|
75
|
+
- lib/galaxy_converter/detector.rb
|
89
76
|
- lib/galaxy_converter/note.rb
|
90
|
-
- lib/galaxy_converter/recognizer.rb
|
91
77
|
- lib/galaxy_converter/responder.rb
|
92
|
-
- lib/galaxy_converter/roman_constraint.rb
|
93
78
|
- lib/galaxy_converter/roman_numeral.rb
|
94
|
-
- lib/galaxy_converter/
|
79
|
+
- lib/galaxy_converter/stretcher.rb
|
95
80
|
- lib/galaxy_converter/version.rb
|
81
|
+
- notes.txt
|
96
82
|
homepage: https://github.com/costajob/galaxy_converter
|
97
83
|
licenses:
|
98
84
|
- MIT
|
@@ -105,15 +91,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
91
|
requirements:
|
106
92
|
- - ">="
|
107
93
|
- !ruby/object:Gem::Version
|
108
|
-
version: 2.
|
94
|
+
version: 2.4.1
|
109
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
96
|
requirements:
|
111
97
|
- - ">="
|
112
98
|
- !ruby/object:Gem::Version
|
113
99
|
version: '0'
|
114
100
|
requirements: []
|
115
|
-
|
116
|
-
rubygems_version: 2.6.11
|
101
|
+
rubygems_version: 3.0.3
|
117
102
|
signing_key:
|
118
103
|
specification_version: 4
|
119
104
|
summary: Implementation of the Merchant's Guide to the Galaxy kata
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require "galaxy_converter/roman_numeral"
|
2
|
-
|
3
|
-
module GalaxyConverter
|
4
|
-
class Abacus
|
5
|
-
def initialize(mapping = {}, unit = Roman::Numeral)
|
6
|
-
@mapping = mapping
|
7
|
-
@unit = unit
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(units)
|
11
|
-
converted = convert(units)
|
12
|
-
result = @unit.new(converted)
|
13
|
-
return 0 unless result.valid?
|
14
|
-
result.to_i
|
15
|
-
end
|
16
|
-
|
17
|
-
private def convert(units)
|
18
|
-
units.split(" ").reduce("") do |to_convert, unit|
|
19
|
-
return unless @mapping[unit]
|
20
|
-
to_convert << @mapping[unit]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/galaxy_converter/cli.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require "galaxy_converter/note"
|
2
|
-
require "galaxy_converter/responder"
|
3
|
-
|
4
|
-
module GalaxyConverter
|
5
|
-
class CLI
|
6
|
-
HELP_FLAGS = %w[-h --help]
|
7
|
-
COL_WIDTH = 23
|
8
|
-
|
9
|
-
def initialize(input,
|
10
|
-
pipe = STDOUT,
|
11
|
-
responder = Responder,
|
12
|
-
note = Note)
|
13
|
-
@input = input
|
14
|
-
@pipe = pipe
|
15
|
-
@responder = responder
|
16
|
-
@note = note
|
17
|
-
end
|
18
|
-
|
19
|
-
def call
|
20
|
-
@pipe.puts output
|
21
|
-
end
|
22
|
-
|
23
|
-
private def output
|
24
|
-
return help if help?
|
25
|
-
return unless file?
|
26
|
-
data = File.readlines(@input).map(&:strip)
|
27
|
-
notes = @note.bulk(data)
|
28
|
-
@responder.new(notes).call
|
29
|
-
end
|
30
|
-
|
31
|
-
private def file?
|
32
|
-
File.file?(File.expand_path(@input))
|
33
|
-
end
|
34
|
-
|
35
|
-
private def help?
|
36
|
-
HELP_FLAGS.include?(@input)
|
37
|
-
end
|
38
|
-
|
39
|
-
private def help
|
40
|
-
[].tap do |h|
|
41
|
-
h << %q{Usage: galaxy_converter ~/notes.txt}
|
42
|
-
h << " %-#{COL_WIDTH}s Print this help" % "-h --help"
|
43
|
-
h << " %-#{COL_WIDTH}s Load conversion notes" % "<path-to-file>"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module GalaxyConverter
|
2
|
-
module Roman
|
3
|
-
module Constraint
|
4
|
-
extend self
|
5
|
-
|
6
|
-
def violated?(value)
|
7
|
-
violations.any? { |violation| value.index(violation) }
|
8
|
-
end
|
9
|
-
|
10
|
-
private def violations
|
11
|
-
@violations ||= repetitions + subtractions
|
12
|
-
end
|
13
|
-
|
14
|
-
private def repetitions
|
15
|
-
%w[I X C M].map { |c| c * 4 } +
|
16
|
-
%w[D L V].map { |c| c * 2 }
|
17
|
-
end
|
18
|
-
|
19
|
-
private def subtractions
|
20
|
-
%w[V X].map { |c| "II#{c}"} +
|
21
|
-
%w[L C].map { |c| "XX#{c}"} +
|
22
|
-
%w[D M].map { |c| "CC#{c}"} +
|
23
|
-
%w[L C D M].map { |c| "I#{c}" } +
|
24
|
-
%w[D M].map { |c| "X#{c}" } +
|
25
|
-
%w[X L C D M].map { |c| "V#{c}" } +
|
26
|
-
%w[C D M].map { |c| "L#{c}"} +
|
27
|
-
["DM"]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module GalaxyConverter
|
2
|
-
module Roman
|
3
|
-
module Rule
|
4
|
-
extend self
|
5
|
-
|
6
|
-
LONG_TO_SHORT = {
|
7
|
-
"DCCCC" => "CM", # 900
|
8
|
-
"CCCC" => "CD", # 400
|
9
|
-
"LXXXX" => "XC", # 90
|
10
|
-
"XXXX" => "XL", # 40
|
11
|
-
"VIIII" => "IX", # 9
|
12
|
-
"IIII" => "IV" # 4
|
13
|
-
}
|
14
|
-
|
15
|
-
def call(value)
|
16
|
-
LONG_TO_SHORT.reduce(value) do |to_convert, (long, short)|
|
17
|
-
to_convert.gsub(short, long)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|