summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-08-28 02:36:40 +0200
committerDimitri Sokolyuk <demon@dim13.org>2016-08-28 02:36:40 +0200
commit6e5c7cbb5923f7627abc3b720600b6f1df718132 (patch)
tree9a210bd3782fa8db78d2d47029f14e4a375d158e
parentf43656022928caaf5a9882d93ffdf64eb069fbab (diff)
Solve roman
-rw-r--r--go/roman-numerals/README.md61
-rw-r--r--go/roman-numerals/cases_test.go31
-rw-r--r--go/roman-numerals/roman_numerals.go19
-rw-r--r--go/roman-numerals/roman_numerals_test.go39
4 files changed, 150 insertions, 0 deletions
diff --git a/go/roman-numerals/README.md b/go/roman-numerals/README.md
new file mode 100644
index 0000000..fdcbc5a
--- /dev/null
+++ b/go/roman-numerals/README.md
@@ -0,0 +1,61 @@
+# Roman Numerals
+
+Write a function to convert from normal numbers to Roman Numerals: e.g.
+
+The Romans were a clever bunch. They conquered most of Europe and ruled
+it for hundreds of years. They invented concrete and straight roads and
+even bikinis. One thing they never discovered though was the number
+zero. This made writing and dating extensive histories of their exploits
+slightly more challenging, but the system of numbers they came up with
+is still in use today. For example the BBC uses Roman numerals to date
+their programmes.
+
+The Romans wrote numbers using letters - I, V, X, L, C, D, M. (notice
+these letters have lots of straight lines and are hence easy to hack
+into stone tablets).
+
+```
+ 1 => I
+10 => X
+ 7 => VII
+```
+
+There is no need to be able to convert numbers larger than about 3000.
+(The Romans themselves didn't tend to go any higher)
+
+Wikipedia says: Modern Roman numerals ... are written by expressing each
+digit separately starting with the left most digit and skipping any
+digit with a value of zero.
+
+To see this in practice, consider the example of 1990.
+
+In Roman numerals 1990 is MCMXC:
+
+1000=M
+900=CM
+90=XC
+
+2008 is written as MMVIII:
+
+2000=MM
+8=VIII
+
+See also: http://www.novaroma.org/via_romana/numbers.html
+
+To run the tests simply run the command `go test` in the exercise directory.
+
+If the test suite contains benchmarks, you can run these with the `-bench`
+flag:
+
+ go test -bench .
+
+For more detailed info about the Go track see the [help
+page](http://exercism.io/languages/go).
+
+## Source
+
+The Roman Numeral Kata [http://codingdojo.org/cgi-bin/wiki.pl?KataRomanNumerals](http://codingdojo.org/cgi-bin/wiki.pl?KataRomanNumerals)
+
+## Submitting Incomplete Problems
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.
+
diff --git a/go/roman-numerals/cases_test.go b/go/roman-numerals/cases_test.go
new file mode 100644
index 0000000..8e99b8e
--- /dev/null
+++ b/go/roman-numerals/cases_test.go
@@ -0,0 +1,31 @@
+package romannumerals
+
+// Source: exercism/x-common
+// Commit: 6985644 Merge pull request #121 from mikeyjcat/add-roman-numerals-test-definition
+
+type romanNumeralTest struct {
+ arabic int
+ roman string
+ hasError bool
+}
+
+var romanNumeralTests = []romanNumeralTest{
+ {1, "I", false},
+ {2, "II", false},
+ {3, "III", false},
+ {4, "IV", false},
+ {5, "V", false},
+ {6, "VI", false},
+ {9, "IX", false},
+ {27, "XXVII", false},
+ {48, "XLVIII", false},
+ {59, "LIX", false},
+ {93, "XCIII", false},
+ {141, "CXLI", false},
+ {163, "CLXIII", false},
+ {402, "CDII", false},
+ {575, "DLXXV", false},
+ {911, "CMXI", false},
+ {1024, "MXXIV", false},
+ {3000, "MMM", false},
+}
diff --git a/go/roman-numerals/roman_numerals.go b/go/roman-numerals/roman_numerals.go
new file mode 100644
index 0000000..21727e2
--- /dev/null
+++ b/go/roman-numerals/roman_numerals.go
@@ -0,0 +1,19 @@
+package romannumerals
+
+import "errors"
+
+const testVersion = 2
+
+var (
+ m0 = []string{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}
+ m1 = []string{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}
+ m2 = []string{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}
+ m3 = []string{"", "M", "MM", "MMM"}
+)
+
+func ToRomanNumeral(n int) (string, error) {
+ if n < 1 || n >= 4000 {
+ return "", errors.New("out of range")
+ }
+ return m3[n%1e4/1e3] + m2[n%1e3/1e2] + m1[n%1e2/1e1] + m0[n%1e1], nil
+}
diff --git a/go/roman-numerals/roman_numerals_test.go b/go/roman-numerals/roman_numerals_test.go
new file mode 100644
index 0000000..637e52e
--- /dev/null
+++ b/go/roman-numerals/roman_numerals_test.go
@@ -0,0 +1,39 @@
+package romannumerals
+
+import "testing"
+
+const targetTestVersion = 2
+
+func TestRomanNumerals(t *testing.T) {
+ if testVersion != targetTestVersion {
+ t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
+ }
+ tc := append(romanNumeralTests, []romanNumeralTest{
+ {0, "", true},
+ {-1, "", true},
+ {4000, "", true},
+ {3999, "MMMCMXCIX", false},
+ }...)
+ for _, test := range tc {
+ actual, err := ToRomanNumeral(test.arabic)
+ if err == nil && test.hasError {
+ t.Errorf("ToRomanNumeral(%d) should return an error.", test.arabic)
+ continue
+ }
+ if err != nil && !test.hasError {
+ t.Errorf("ToRomanNumeral(%d) should not return an error.", test.arabic)
+ continue
+ }
+ if actual != test.roman {
+ t.Errorf("ToRomanNumeral(%d): %s, expected %s", test.arabic, actual, test.roman)
+ }
+ }
+}
+
+func BenchmarkRomanNumerals(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, test := range romanNumeralTests {
+ ToRomanNumeral(test.arabic)
+ }
+ }
+}