Advertisement
sveta_t

expression

Aug 3rd, 2022 (edited)
956
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.59 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "fmt"
  5.     "log"
  6. )
  7.  
  8. func main() {
  9.     /*
  10.         c = a - b
  11.         x = c + d
  12.  
  13.         a = 5
  14.         b = 3
  15.         d = -2
  16.  
  17.         c, x = ? (c = 2, x = 0)
  18.      */
  19.  
  20.     a := Field{
  21.         Name: "a",
  22.         Expression: NewExpression(),
  23.     }
  24.  
  25.     b := Field{
  26.         Name: "b",
  27.         Expression: NewExpression(),
  28.     }
  29.  
  30.     d := Field{
  31.         Name: "d",
  32.         Expression: NewExpression(),
  33.     }
  34.  
  35.     c := Field{
  36.         Name: "c",
  37.         Expression: NewExpression().Add(a).Sub(b),
  38.         // (a - b)
  39.     }
  40.  
  41.     x := Field{
  42.         Name: "x",
  43.         Expression: NewExpression().Add(c).Add(d),
  44.         // (c + d)
  45.     }
  46.  
  47.     y := Field{
  48.         Name: "y",
  49.         Expression: NewExpression().Add(x).Add(a).Add(b),
  50.         // (x + a + b)
  51.     }
  52.  
  53.  
  54.     ctx := NewContext()
  55.     ctx.Put(a, 5)
  56.     ctx.Put(b, 3)
  57.     ctx.Put(d, -1)
  58.     ctx.Declare(c)
  59.     ctx.Declare(y)
  60.     ctx.Declare(x)
  61.  
  62.     res, err := ctx.Calc()
  63.     if err != nil {
  64.         panic(err)
  65.     }
  66.  
  67.     if res[c] != 2 {
  68.         panic(fmt.Sprintf("Wrong 'c' = %v", res[c]))
  69.     }
  70.  
  71.     if res[x] != 1 {
  72.         panic(fmt.Sprintf("Wrong 'x' = %v", res[x]))
  73.     }
  74.  
  75.     if res[y] != 9 {
  76.         panic(fmt.Sprintf("Wrong 'y' = %v", res[y]))
  77.     }
  78.  
  79.     log.Print("Successful!")
  80. }
  81.  
  82. type FieldValue struct {
  83.     value float64
  84.     calculated bool
  85. }
  86.  
  87. type Context struct {
  88.     fields map[Field]FieldValue
  89.     dependencies map[Field][]Dependency
  90. }
  91.  
  92. func NewContext() *Context{
  93.     c := &Context{}
  94.     c.fields = make(map[Field]FieldValue)
  95.     c.dependencies = make(map[Field][]Dependency)
  96.     return c
  97. }
  98.  
  99. func (c Context) Put(f Field, val float64) {
  100.     c.fields[f] = FieldValue{
  101.         value: val,
  102.         calculated: true,
  103.     }
  104.     c.dependencies[f] = nil
  105. }
  106.  
  107. func (c Context) Declare(f Field) {
  108.     c.fields[f] = FieldValue{
  109.         calculated: false,
  110.     }
  111.     c.dependencies[f] = f.Expression.dependencies
  112. }
  113.  
  114. func (c Context) Calc() (map[Field]float64, error) {
  115.     for {
  116.         haveUncalculated := false
  117.         for f, v := range c.fields {
  118.             if v.calculated {
  119.                 continue
  120.             }
  121.  
  122.             if c.readyToCalculate(f) {
  123.                 c.fields[f] = FieldValue{
  124.                     value:      c.calcField(f),
  125.                     calculated: true,
  126.                 }
  127.             } else {
  128.                 haveUncalculated = true
  129.             }
  130.         }
  131.  
  132.         if !haveUncalculated {
  133.             break
  134.         }
  135.     }
  136.  
  137.     res := make(map[Field]float64)
  138.     for f, v := range c.fields {
  139.         res[f] = v.value
  140.     }
  141.  
  142.     return res, nil
  143. }
  144.  
  145. func (c Context) readyToCalculate(f Field) bool {
  146.     deps, found := c.dependencies[f]
  147.     if !found {
  148.         return true
  149.     }
  150.  
  151.     for _, d := range deps {
  152.         if !c.fields[d.field].calculated {
  153.             return false
  154.         }
  155.     }
  156.  
  157.     return true
  158. }
  159.  
  160. func (c Context) calcField(f Field) float64 {
  161.     deps, found := c.dependencies[f]
  162.     if !found {
  163.         panic(fmt.Sprintf("Empty deps"))
  164.     }
  165.  
  166.     var res float64
  167.     for _, d := range deps {
  168.         switch d.operation {
  169.         case OperationAdd:
  170.             res += c.fields[d.field].value
  171.         case OperationSub:
  172.             res = res - c.fields[d.field].value
  173.         default:
  174.             //todo
  175.         }
  176.     }
  177.     return res
  178. }
  179.  
  180. //--------------------------------------------
  181. type Field struct {
  182.     Name string
  183.     Expression *Expression
  184. }
  185.  
  186. //--------------------------------------------
  187.  
  188. type Operation string
  189.  
  190. const (
  191.     OperationAdd Operation = "add"
  192.     OperationSub Operation = "sub"
  193. )
  194.  
  195. //--------------------------------------------
  196.  
  197. type Dependency struct {
  198.     field Field
  199.     operation Operation
  200. }
  201.  
  202. type Expression struct {
  203.     dependencies []Dependency
  204. }
  205.  
  206. func NewExpression() *Expression {
  207.     return &Expression{}
  208. }
  209.  
  210. func (e *Expression) Add(field Field) *Expression {
  211.     d := Dependency{
  212.         field: field,
  213.         operation: OperationAdd,
  214.     }
  215.     e.dependencies = append(e.dependencies, d)
  216.     return e
  217. }
  218.  
  219. func (e *Expression) Sub(field Field) *Expression {
  220.     d := Dependency{
  221.         field: field,
  222.         operation: OperationSub,
  223.     }
  224.     e.dependencies = append(e.dependencies, d)
  225.     return e
  226. }
  227.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement