advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.go (2350B)

    1 package main
    2 
    3 import (
    4 	"bufio"
    5 	"fmt"
    6 	"os"
    7 	"regexp"
    8 	"strconv"
    9 )
   10 
   11 const (
   12 	MASK = iota
   13 	MEM
   14 )
   15 
   16 type program struct {
   17 	len   int
   18 	ops   []int
   19 	args1 []int64
   20 	args2 []int64
   21 }
   22 
   23 func (this program) get(i int) (int, int64, int64) {
   24 	return this.ops[i], this.args1[i], this.args2[i]
   25 }
   26 
   27 func readInput(filename string) (res program) {
   28 	file, _ := os.Open(filename)
   29 	defer file.Close()
   30 
   31 	scanner := bufio.NewScanner(file)
   32 	matcher := regexp.MustCompile(`(mask|mem)\[?([0-9]*)\]? = ([X10]{36}|[0-9]+)`)
   33 	for scanner.Scan() {
   34 		matches := matcher.FindAllStringSubmatch(scanner.Text(), -1)
   35 		switch matches[0][1] {
   36 		case "mask":
   37 			res.ops = append(res.ops, MASK)
   38 			mask0 := int64(0)
   39 			mask1 := int64(0)
   40 			for _, ch := range matches[0][3] {
   41 				mask0 <<= 1
   42 				mask1 <<= 1
   43 				switch ch {
   44 				case '0':
   45 					mask0 += 1
   46 				case '1':
   47 					mask1 += 1
   48 				}
   49 			}
   50 			res.args1 = append(res.args1, mask0)
   51 			res.args2 = append(res.args2, mask1)
   52 		case "mem":
   53 			res.ops = append(res.ops, MEM)
   54 			args1, _ := strconv.ParseInt(matches[0][2], 10, 64)
   55 			res.args1 = append(res.args1, args1)
   56 			args2, _ := strconv.ParseInt(matches[0][3], 10, 64)
   57 			res.args2 = append(res.args2, args2)
   58 		}
   59 		res.len += 1
   60 	}
   61 	return
   62 }
   63 
   64 func main() {
   65 	input := readInput("./input.txt")
   66 	// 4297467072083
   67 	fmt.Println(part1(input))
   68 	// 5030603328768
   69 	fmt.Println(part2(input))
   70 }
   71 
   72 func part1(input program) (res int64) {
   73 	var (
   74 		mask0 int64
   75 		mask1 int64
   76 		mem   = map[int64]int64{}
   77 	)
   78 	for i := 0; i < input.len; i++ {
   79 		op, arg1, arg2 := input.get(i)
   80 		switch op {
   81 		case MASK:
   82 			mask0, mask1 = arg1, arg2
   83 		case MEM:
   84 			mem[arg1] = (arg2 &^ mask0) | mask1
   85 		}
   86 	}
   87 	for _, v := range mem {
   88 		res += v
   89 	}
   90 	return
   91 }
   92 
   93 func part2(input program) (res int64) {
   94 	var (
   95 		mask1 int64
   96 		maskX int64
   97 		mem   = map[int64]int64{}
   98 	)
   99 	for i := 0; i < input.len; i++ {
  100 		op, arg1, arg2 := input.get(i)
  101 		switch op {
  102 		case MASK:
  103 			mask1, maskX = arg2, 0xFFFFFFFFF&^(arg1|arg2)
  104 		case MEM:
  105 			addrs := []int64{arg1 | mask1}
  106 			for i := int64(1); i <= (1 << 36); i <<= 1 {
  107 				if i&maskX > 0 {
  108 					addrsNew := []int64{}
  109 					for _, addr := range addrs {
  110 						addrsNew = append(addrsNew, addr|i)
  111 						addrsNew = append(addrsNew, addr&^i)
  112 					}
  113 					addrs = addrsNew
  114 				}
  115 			}
  116 			for _, addr := range addrs {
  117 				mem[addr] = arg2
  118 			}
  119 		}
  120 	}
  121 	for _, v := range mem {
  122 		res += v
  123 	}
  124 	return
  125 }