aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2015-04-08 20:36:25 +0200
committerDimitri Sokolyuk <demon@dim13.org>2015-04-08 20:36:25 +0200
commit72c353d58fa33d11d58eb9276d2095e538ecebb8 (patch)
treee9cf67c2d7bb2a1f05c41ad2999a0db8e1fb42cb
parent60ac54b9ffd6f8d57e9807f710ace28900955366 (diff)
Rewrite
-rw-r--r--ops.go74
-rw-r--r--roman.go25
-rw-r--r--verify.go120
3 files changed, 115 insertions, 104 deletions
diff --git a/ops.go b/ops.go
index 75b21a8..73a2d38 100644
--- a/ops.go
+++ b/ops.go
@@ -2,92 +2,82 @@ package main
import (
"container/list"
- "fmt"
"log"
)
type (
- List struct{ *list.List }
+ // Set is ordered set of alphabet
+ Set struct{ *list.List }
+
+ // Element of ordered set
Element struct{ *list.Element }
)
var (
- alphabet List
+ alphabet Set
zero, one Element
)
func init() {
- alphabet = List{list.New()}
+ alphabet = Set{list.New()}
for i := 0; i <= maxValue; i++ {
- alphabet.PushBack(formatRoman(i))
+ alphabet.PushBack(i)
}
zero = Element{alphabet.Front()}
one = Element{zero.Next()}
}
-// next returns next char in alphabet
-func (n Element) next() Element {
- if nxt := n.Next(); nxt != nil {
+func (m Element) next() Element {
+ if nxt := m.Next(); nxt != nil {
return Element{nxt}
}
- log.Fatal("out of range ", n)
+ log.Fatal("out of range ", m)
return Element{}
}
-// prev returns previous char in alphabet
-func (n Element) prev() Element {
- if prv := n.Prev(); prv != nil {
+func (m Element) prev() Element {
+ if prv := m.Prev(); prv != nil {
return Element{prv}
}
return zero
}
-// add defines addition
-func add(m, n Element) Element {
+// Add defines addition
+func Add(m, n Element) Element { return m.add(n) }
+
+func (m Element) add(n Element) Element {
if m == zero {
return n
}
- return add(m.prev(), n).next()
+ return m.prev().add(n).next()
}
-// times defines mutiplication
-func times(m, n Element) Element {
+// Mul defines mutiplication
+func Mul(m, n Element) Element { return m.mul(n) }
+
+func (m Element) mul(n Element) Element {
if m == zero {
return zero
}
- return add(times(m.prev(), n), n)
+ return m.prev().mul(n).add(n)
}
-// pot defines power function
-func pot(m, n Element) Element {
+// Pot defines power function
+func Pot(m, n Element) Element { return m.pot(n) }
+
+func (m Element) pot(n Element) Element {
if n == zero {
return one
}
- return times(pot(m, n.prev()), m)
+ return m.pot(n.prev()).mul(m)
}
-// sub defines substraction
-func sub(m, n Element) Element {
+// Sub defines substraction
+func Sub(m, n Element) Element { return m.sub(n) }
+
+func (m Element) sub(n Element) Element {
if n == zero {
return m
}
- return sub(m, n.prev()).prev()
-}
-
-// scan lookups n-th element representation
-func scan(n int) Element {
- if n > alphabet.Len() {
- log.Fatal("out of range ", n)
- return Element{}
- }
- e := alphabet.Front()
- for i := 0; i < n; i++ {
- e = e.Next()
- }
- return Element{e}
-}
-
-// String pretty-prints value
-func (n Element) String() string {
- return fmt.Sprint(n.Value)
+ return m.sub(n.prev()).prev()
}
diff --git a/roman.go b/roman.go
deleted file mode 100644
index b1c5355..0000000
--- a/roman.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Roman Numerals, stollen from http://rosettacode.org/wiki/Roman_numerals/Encode#Go
-
-package main
-
-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", "I̅V̅", "V̅", "V̅I̅", "V̅I̅I̅", "V̅I̅I̅I̅", "I̅X̅"}
- m4 = []string{"", "X̅", "X̅X̅", "X̅X̅X̅", "X̅L̅", "L̅", "L̅X̅", "L̅X̅X̅", "L̅X̅X̅X̅", "X̅C̅"}
- m5 = []string{"", "C̅", "C̅C̅", "C̅C̅C̅", "C̅D̅", "D̅", "D̅C̅", "D̅C̅C̅", "D̅C̅C̅C̅", "C̅M̅"}
- m6 = []string{"", "M̅", "M̅M̅", "M̅M̅M̅"}
-)
-
-func formatRoman(n int) string {
- switch {
- case n == 0:
- return "N"
- case n < 0 || n >= 4e6:
- return "N̅"
- default:
- return m6[n/1e6] + m5[n%1e6/1e5] + m4[n%1e5/1e4] +
- m3[n%1e4/1e3] + m2[n%1e3/1e2] + m1[n%100/10] + m0[n%10]
- }
-}
diff --git a/verify.go b/verify.go
index ffdc816..7c2a4c8 100644
--- a/verify.go
+++ b/verify.go
@@ -2,57 +2,103 @@ package main
import (
"fmt"
+ "log"
"math"
"math/rand"
"time"
)
+type testCase struct {
+ function func(Element, Element) Element
+ expect func(int, int) int
+ maxm, maxn int
+ order bool
+}
+
func init() {
rand.Seed(time.Now().Unix())
}
-var f = map[string]func(Element, Element) Element{
- "+": add,
- "-": sub,
- "*": times,
- "^": pot,
+var cases = map[string]testCase{
+ "+": testCase{
+ function: Add,
+ expect: testAdd,
+ maxm: 100,
+ maxn: 100,
+ order: false,
+ },
+ "*": testCase{
+ function: Mul,
+ expect: testMul,
+ maxm: 10,
+ maxn: 10,
+ order: false,
+ },
+ "^": testCase{
+ function: Pot,
+ expect: testPot,
+ maxm: 10,
+ maxn: 3,
+ order: false,
+ },
+ "-": testCase{
+ function: Sub,
+ expect: testSub,
+ maxm: 100,
+ maxn: 100,
+ order: true,
+ },
}
-// verify perfoms tests
func verify(op string) (string, bool) {
- var mm, nn, rr int
- switch op {
- case "+":
- mm = rand.Intn(100)
- nn = rand.Intn(100)
- rr = mm + nn
- case "-":
- mm = rand.Intn(100)
- nn = rand.Intn(100)
- if nn > mm {
- mm, nn = nn, mm
- }
- rr = mm - nn
- case "*":
- mm = rand.Intn(10)
- nn = rand.Intn(10)
- rr = mm * nn
- case "^":
- mm = rand.Intn(10)
- nn = rand.Intn(3)
- rr = int(math.Pow(float64(mm), float64(nn)))
+ c, ok := cases[op]
+ if !ok {
+ log.Fatal("unknown case")
+ }
+
+ m := rand.Intn(c.maxm)
+ n := rand.Intn(c.maxn)
+ if c.order && n > m {
+ m, n = n, m
+ }
+ e := c.expect(m, n)
+
+ me := scan(m)
+ ne := scan(n)
+ ee := scan(e)
+ re := c.function(me, ne)
+
+ return fmt.Sprint(me, op, ne, "=", re), re.equals(ee)
+}
+
+func scan(n int) Element {
+ if n > alphabet.Len() {
+ log.Fatal("out of range ", n)
+ return Element{}
+ }
+ e := alphabet.Front()
+ for i := 0; i < n; i++ {
+ e = e.Next()
}
- m := scan(mm)
- n := scan(nn)
- r := f[op](m, n)
- expected := scan(rr)
- ok := r.Value == expected.Value
- return fmt.Sprint(m, op, n, "=", r), ok
+ return Element{e}
}
+func testAdd(m, n int) int { return m + n }
+func testMul(m, n int) int { return m * n }
+func testPot(m, n int) int { return int(math.Pow(float64(m), float64(n))) }
+func testSub(m, n int) int { return m - n }
+
func verifyAll() {
- fmt.Println(verify("+"))
- fmt.Println(verify("-"))
- fmt.Println(verify("*"))
- fmt.Println(verify("^"))
+ for op := range cases {
+ fmt.Println(verify(op))
+ }
+}
+
+// String pretty-prints value
+func (m Element) String() string {
+ return fmt.Sprint(m.Value)
+}
+
+func (m Element) equals(n Element) bool {
+ return m.Value == n.Value
}