Advertisement
Guest User

[Day 7] Recursive Solution in Go

a guest
Dec 8th, 2015
218
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.     "bufio"
  5.     "fmt"
  6.     "os"
  7.     "regexp"
  8.     "strconv"
  9.     "strings"
  10. )
  11.  
  12. var mostOps = regexp.MustCompile(`(AND|OR|RSHIFT|LSHIFT)`)
  13. var isInt = regexp.MustCompile(`^[0-9]+$`)
  14.  
  15. type Wire struct {
  16.     sig  uint16
  17.     op   string
  18.     args []string
  19. }
  20.  
  21. type Circuit struct {
  22.     plan map[string]*Wire
  23. }
  24.  
  25. func main() {
  26.     // Declare a new circuit
  27.     c := NewCircuit()
  28.  
  29.     // Open the input for reading
  30.     f, _ := os.Open(os.Args[1])
  31.     defer f.Close()
  32.  
  33.     // read and parse the input
  34.     c.ReadInput(f)
  35.  
  36.     // Evaluate wire "a"
  37.     fmt.Printf("a: %v\n", c.GetSignal("a"))
  38. }
  39.  
  40. func NewCircuit() *Circuit {
  41.     c := new(Circuit)
  42.     c.plan = make(map[string]*Wire)
  43.     return c
  44. }
  45.  
  46. func (c *Circuit) ReadInput(file *os.File) {
  47.     s := bufio.NewScanner(file)
  48.     for s.Scan() {
  49.         w := new(Wire) // Declare a new wire to be added to circuit plan
  50.  
  51.         // Get wire id and operation
  52.         l := strings.Split(s.Text(), "->")
  53.         op, id := strings.TrimSpace(l[0]), strings.TrimSpace(l[1])
  54.  
  55.         // break down operation into components
  56.         l = strings.Split(op, " ")
  57.         if mostOps.MatchString(op) { // see mostOps regex at the to to see what matches
  58.             w.op = l[1]
  59.             w.args = append(w.args, l[0], l[2])
  60.         } else if len(l) == 1 { // direct assign, if it's a number then assign to the wire's signal
  61.             if isInt.MatchString(l[0]) {
  62.                 v, _ := strconv.ParseInt(l[0], 10, 16) // Convert value to 16bit int
  63.                 w.sig = uint16(v)
  64.             } else { // Other wise assign to the arguments so it can be evaluated later
  65.                 w.args = append(w.args, l[0])
  66.             }
  67.         } else { // Last possible option is that it's a NOT operation
  68.             w.op = l[0]
  69.             w.args = append(w.args, l[1])
  70.         }
  71.  
  72.         // Assign the parsed wire to the circuit plan
  73.         c.plan[id] = w
  74.     }
  75. }
  76.  
  77. // Recursively evaluate the signal for a given wire
  78. func (c *Circuit) GetSignal(wire string) uint16 {
  79.     if !c.HasSignal(wire) { // if a wire has no arguments then it has a signal
  80.         args := c.plan[wire].args
  81.         fmt.Printf("\n-->%v [%v, %v]\n", wire, args, c.plan[wire].op)
  82.  
  83.         // Let's cut to the chase with operation arguments and make them uints that we can pass
  84.         // stright to the operation
  85.         opArgs := make([]uint16, len(args), len(args))
  86.  
  87.         // evaluate each argument and see if it has a signal
  88.         for i := 0; i < len(args); i++ {
  89.             arg := args[i] // let's make this easier to read
  90.             fmt.Printf("?%v\n", arg)
  91.  
  92.             if !isInt.MatchString(arg) { // if the arg is not a number it's a wire
  93.                 if !c.HasSignal(arg) { // if it has no signal we should get one
  94.                     c.plan[arg].sig = c.GetSignal(arg)
  95.                     opArgs[i] = c.plan[arg].sig
  96.  
  97.                     fmt.Printf("%v = %v\n", arg, c.plan[arg].sig)
  98.                 } else if c.HasSignal(arg) { // if it has a signal we should give it to the args
  99.                     opArgs[i] = c.plan[arg].sig
  100.                 }
  101.             } else { // otherwise it's just a number so give it to the args
  102.                 v, _ := strconv.ParseInt(arg, 10, 16)
  103.                 opArgs[i] = uint16(v)
  104.             }
  105.         }
  106.  
  107.         // Perform the operation now that all requirements are satisfied and clear the args
  108.         // to indicate that this wire is complete.
  109.         c.plan[wire].sig = c.PerformOperation(wire, opArgs)
  110.         c.plan[wire].args = nil
  111.     }
  112.     return c.plan[wire].sig
  113. }
  114.  
  115. func (c *Circuit) PerformOperation(wire string, args []uint16) uint16 {
  116.     var result uint16
  117.     switch c.plan[wire].op {
  118.     case "AND":
  119.         result = args[0] & args[1]
  120.     case "OR":
  121.         result = args[0] | args[1]
  122.     case "LSHIFT":
  123.         result = args[0] << args[1]
  124.     case "RSHIFT":
  125.         result = args[0] >> args[1]
  126.     case "NOT":
  127.         result = ^args[0]
  128.     default:
  129.         result = args[0]
  130.     }
  131.     return result
  132. }
  133.  
  134. func (c *Circuit) HasSignal(w string) bool {
  135.     if len(c.plan[w].args) == 0 {
  136.         return true
  137.     }
  138.     return false
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement