Skip to content

Instantly share code, notes, and snippets.

@mmcdole
Created December 19, 2015 05:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmcdole/9676ad84570b41777e8e to your computer and use it in GitHub Desktop.
Save mmcdole/9676ad84570b41777e8e to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
)
var (
r = regexp.MustCompile(`([a-z0-9]+)? ?([A-Z]+)? ?([0-9]+)? ?([a-z0-9]+)? -> ([a-z]+)`)
wireVals = map[string]int16{}
ops = []*Operation{}
)
type Operation struct {
Name string
Left string
Right string
Arg string
Dest string
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
op := parseOperation(line)
ops = append(ops, op)
}
for len(ops) > 0 {
for i := len(ops) - 1; i >= 0; i-- {
didEval := evaluate(ops[i])
if didEval {
ops = append(ops[:i], ops[i+1:]...)
}
}
}
fmt.Printf("Value of wire a: %d\n", wireVals["a"])
}
func parseOperation(line string) *Operation {
result := r.FindStringSubmatch(line)
return &Operation{
Name: result[2],
Left: result[1],
Right: result[4],
Arg: result[3],
Dest: result[5],
}
}
func evaluate(op *Operation) bool {
var lval, rval, result int16
var hlval, hrval bool
lval, hlval = resolveOperand(op.Left)
rval, hrval = resolveOperand(op.Right)
if !hlval || !hrval {
return false
}
if op.Name == "AND" {
result = lval & rval
} else if op.Name == "OR" {
result = lval | rval
} else if op.Name == "RSHIFT" {
shiftArg, _ := strconv.ParseUint(op.Arg, 10, 0)
result = lval >> shiftArg
} else if op.Name == "LSHIFT" {
shiftArg, _ := strconv.ParseUint(op.Arg, 10, 0)
result = lval << shiftArg
} else if op.Name == "NOT" {
result = ^rval
} else if op.Name == "" {
result = lval
}
// fmt.Printf("%s %s %s %s -> %s = %d\n", op.Left, op.Name, op.Arg, op.Right, op.Dest, result)
wireVals[op.Dest] = result
return true
}
func resolveOperand(val string) (int16, bool) {
// Operand is empty. We consider this resolved
if val == "" {
return 0, true
}
// Value is an integer literal
val64, err := strconv.ParseInt(val, 10, 16)
if err == nil {
return int16(val64), true
}
// Check if we have a wire val for this wire name
if wv, ok := wireVals[val]; ok {
return wv, true
}
// Value is an unresolved wire name
return 0, false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment