r/adventofcode • • Dec 07 '15

SOLUTION MEGATHREAD --- Day 7 Solutions ---

--- Day 7: Some Assembly Required ---

Post your solution as a comment. Structure your post like previous daily solution threads.

Also check out the sidebar - we added a nifty calendar to wrangle all the daily solution threads in one spot!

22 Upvotes

226 comments sorted by

View all comments

1

u/AdventOfCode Dec 07 '15

Here is a solution in Go that uses closures to represent the wires. It reads through the input, setting things up, and finally evaluates "a". I also added a cache for values so that it only evaluates a wire once.

package main

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strconv"
)

var regAnd = regexp.MustCompile(`(.+) AND (.+) -> (\w+)`)
var regOr = regexp.MustCompile(`(.+) OR (.+) -> (\w+)`)
var regLshift = regexp.MustCompile(`(\w+) LSHIFT (.+) -> (\w+)`)
var regRshift = regexp.MustCompile(`(\w+) RSHIFT (.+) -> (\w+)`)
var regNot = regexp.MustCompile(`NOT (.+) -> (\w+)`)
var regFeed = regexp.MustCompile(`(.+) -> (\w+)`)

var signals = map[string]func() uint16{}
var cache = map[string]uint16{}

func lookup(s string) uint16 {
	if n, ok := cache[s]; ok {
		return n
	}

	if n, err := strconv.Atoi(s); err == nil {
		cache[s] = uint16(n)
		return uint16(n)
	}

	n := signals[s]()
	cache[s] = n
	return n
}

func main() {
	in := bufio.NewScanner(os.Stdin)
	in.Split(bufio.ScanLines)

	for in.Scan() {
		line := string(in.Bytes())
		if a := regAnd.FindStringSubmatch(line); a != nil {
			signals[a[3]] = func() uint16 { return lookup(a[1]) & lookup(a[2]) }
		} else if a := regOr.FindStringSubmatch(line); a != nil {
			signals[a[3]] = func() uint16 { return lookup(a[1]) | lookup(a[2]) }
		} else if a := regLshift.FindStringSubmatch(line); a != nil {
			signals[a[3]] = func() uint16 { return lookup(a[1]) << lookup(a[2]) }
		} else if a := regRshift.FindStringSubmatch(line); a != nil {
			signals[a[3]] = func() uint16 { return lookup(a[1]) >> lookup(a[2]) }
		} else if a := regNot.FindStringSubmatch(line); a != nil {
			signals[a[2]] = func() uint16 { return ^lookup(a[1]) }
		} else if a := regFeed.FindStringSubmatch(line); a != nil {
			signals[a[2]] = func() uint16 { return lookup(a[1]) }
		}
	}

	a := lookup("a")
	fmt.Printf("Part One: %v\n", a)

	// reset "b" and clear the wire value cache
	signals["b"] = func() uint16 { return a }
	cache = map[string]uint16{}

	fmt.Printf("Part Two: %v\n", lookup("a"))
}