package subex import ( "fmt" "math" ) type NumberExpr interface { String() string Eval(float64) float64 } type NumberExprVariable struct {} func (ev NumberExprVariable) String() string { return "n" } func (ev NumberExprVariable) Eval(v float64) float64 { return v } type NumberExprLiteral struct { Value float64 } func (el NumberExprLiteral) String() string { return fmt.Sprintf("%v", el.Value) } func (el NumberExprLiteral) Eval(v float64) float64 { return el.Value } type NumberExprAnd struct { Left NumberExpr Right NumberExpr } func (ea NumberExprAnd) String() string { return fmt.Sprintf("(%v & %v)", ea.Left, ea.Right) } func (ea NumberExprAnd) Eval(v float64) float64 { left := ea.Left.Eval(v) if left != 0.0 { return ea.Right.Eval(v) } else { return left } } type NumberExprOr struct { Left NumberExpr Right NumberExpr } func (eo NumberExprOr) String() string { return fmt.Sprintf("(%v | %v)", eo.Left, eo.Right) } func (eo NumberExprOr) Eval(v float64) float64 { left := eo.Left.Eval(v) if left != 0.0 { return left } else { return eo.Right.Eval(v) } } type NumberExprNot struct { Right NumberExpr } func (en NumberExprNot) String() string { return fmt.Sprintf("(!%v)", en.Right) } func (en NumberExprNot) Eval(v float64) float64 { inner := en.Right.Eval(v) if inner == 0.0 { return 1.0 } return 0.0 } type NumberExprEqual struct { Left NumberExpr Right NumberExpr } func (ee NumberExprEqual) String() string { return fmt.Sprintf("(%v = %v)", ee.Left, ee.Right) } func (ee NumberExprEqual) Eval(v float64) float64 { if ee.Left.Eval(v) == ee.Right.Eval(v) { return 1.0 } else { return 0.0 } } type NumberExprAtMost struct { Left NumberExpr Right NumberExpr } func (ea NumberExprAtMost) String() string { return fmt.Sprintf("(%v <= %v)", ea.Left, ea.Right) } func (ea NumberExprAtMost) Eval(v float64) float64 { if ea.Left.Eval(v) <= ea.Right.Eval(v) { return 1.0 } else { return 0.0 } } type NumberExprLessThan struct { Left NumberExpr Right NumberExpr } func (el NumberExprLessThan) String() string { return fmt.Sprintf("(%v < %v)", el.Left, el.Right) } func (el NumberExprLessThan) Eval(v float64) float64 { if el.Left.Eval(v) < el.Right.Eval(v) { return 1.0 } else { return 0.0 } } type NumberExprGreaterThan struct { Left NumberExpr Right NumberExpr } func (eg NumberExprGreaterThan) String() string { return fmt.Sprintf("(%v > %v)", eg.Left, eg.Right) } func (eg NumberExprGreaterThan) Eval(v float64) float64 { if eg.Left.Eval(v) > eg.Right.Eval(v) { return 1.0 } else { return 0.0 } } type NumberExprAtLeast struct { Left NumberExpr Right NumberExpr } func (ea NumberExprAtLeast) String() string { return fmt.Sprintf("(%v >= %v)", ea.Left, ea.Right) } func (ea NumberExprAtLeast) Eval(v float64) float64 { if ea.Left.Eval(v) >= ea.Right.Eval(v) { return 1.0 } else { return 0.0 } } type NumberExprAdd struct { Left NumberExpr Right NumberExpr } func (ea NumberExprAdd) String() string { return fmt.Sprintf("(%v + %v)", ea.Left, ea.Right) } func (ea NumberExprAdd) Eval(v float64) float64 { return ea.Left.Eval(v) + ea.Right.Eval(v) } type NumberExprSubtract struct { Left NumberExpr Right NumberExpr } func (es NumberExprSubtract) String() string { return fmt.Sprintf("(%v - %v)", es.Left, es.Right) } func (es NumberExprSubtract) Eval(v float64) float64 { return es.Left.Eval(v) - es.Right.Eval(v) } type NumberExprMultiply struct { Left NumberExpr Right NumberExpr } func (em NumberExprMultiply) String() string { return fmt.Sprintf("(%v * %v)", em.Left, em.Right) } func (em NumberExprMultiply) Eval(v float64) float64 { return em.Left.Eval(v) * em.Right.Eval(v) } type NumberExprDivide struct { Left NumberExpr Right NumberExpr } func (ed NumberExprDivide) String() string { return fmt.Sprintf("(%v / %v)", ed.Left, ed.Right) } func (ed NumberExprDivide) Eval(v float64) float64 { return ed.Left.Eval(v) / ed.Right.Eval(v) } type NumberExprMod struct { Left NumberExpr Right NumberExpr } func (em NumberExprMod) String() string { return fmt.Sprintf("(%v %% %v)", em.Left, em.Right) } func (em NumberExprMod) Eval(v float64) float64 { return math.Mod(em.Left.Eval(v), em.Right.Eval(v)) } type NumberExprExponent struct { Left NumberExpr Right NumberExpr } func (ee NumberExprExponent) String() string { return fmt.Sprintf("(%v * %v)", ee.Left, ee.Right) } func (ee NumberExprExponent) Eval(v float64) float64 { return ee.Left.Eval(v) * ee.Right.Eval(v) }