package fourteen import ( "bufio" "fmt" "os" "strconv" "strings" ) type command struct { mem int pointer int mask string isMask bool } type computer struct { memory map[int]uint64 m map[int]bool mask string ones uint64 zeros uint64 input []command executed bool } func (c *computer) load(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { inputs := strings.Split(scanner.Text(), " = ") if len(inputs) != 2 { return fmt.Errorf("Unable to parse input %q", scanner.Text()) } if inputs[0] == "mask" { c.input = append(c.input, command{ isMask: true, mask: inputs[1], }) } else { var pointer, mem int count, err := fmt.Sscanf(inputs[0], "mem[%d]", &pointer) if count != 1 || err != nil { return fmt.Errorf("Unable to parse memory location from %s", inputs[0]) } mem, err = strconv.Atoi(inputs[1]) c.input = append(c.input, command{ isMask: false, mem: mem, pointer: pointer, }) } } c.memory = make(map[int]uint64, len(c.input)) return nil } func newComputer(filename string) *computer { c := &computer{} c.mask = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" c.executed = false if err := c.load(filename); err != nil { fmt.Println(err.Error()) return nil } return c } func (c *computer) execute() { c.executed = true for _, input := range c.input { if input.isMask { c.mask = input.mask c.ones = 0 c.zeros = 0 for i := 0; i < len(input.mask); i++ { switch string(input.mask[len(input.mask)-1-i]) { case "0": c.zeros += 1 << i case "1": c.ones += 1 << i } } continue } value := uint64(input.mem) value |= c.ones value &^= c.zeros c.memory[input.pointer] = value } } func (c *computer) executeV2() { c.executed = true for _, input := range c.input { if input.isMask { c.mask = input.mask c.ones = 0 c.zeros = 0 for i := 0; i < len(input.mask); i++ { switch string(input.mask[len(input.mask)-1-i]) { case "0": c.zeros += 1 << i case "1": c.ones += 1 << i } } continue } value := uint64(input.mem) location := uint64(input.pointer) | c.ones for _, p := range c.memMask(location) { c.memory[p] = value } } } func (c *computer) memMask(p uint64) []int { locations := []int{0} for i := 0; i < len(c.mask); i++ { switch string(c.mask[len(c.mask)-1-i]) { case "X": for j, l := range locations { locations = append(locations, int(l|(1<