advent-of-code

Perserverance, or the lack thereof

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

main.go (2402B)

    1 package main
    2 
    3 import (
    4 	"bufio"
    5 	"fmt"
    6 	"os"
    7 	"regexp"
    8 )
    9 
   10 const (
   11 	E = iota
   12 	SE
   13 	SW
   14 	W
   15 	NW
   16 	NE
   17 	WHITE = 0
   18 	BLACK = 1
   19 )
   20 
   21 type pos [2]int
   22 
   23 func (this pos) move(dir int) pos {
   24 	other := pathToCoord([]int{dir})
   25 	return pos{this[0] + other[0], this[1] + other[1]}
   26 }
   27 
   28 func readInput(filename string) (res [][]int) {
   29 	file, _ := os.Open(filename)
   30 	defer file.Close()
   31 
   32 	scanner := bufio.NewScanner(file)
   33 	matcher := regexp.MustCompile(`e|se|sw|w|nw|ne`)
   34 	dirMap := map[string]int{
   35 		"e": E, "se": SE, "sw": SW, "w": W, "nw": NW, "ne": NE,
   36 	}
   37 	for scanner.Scan() {
   38 		curr := []int{}
   39 		for _, dir := range matcher.FindAllStringSubmatch(scanner.Text(), -1) {
   40 			curr = append(curr, dirMap[dir[0]])
   41 		}
   42 		res = append(res, curr)
   43 	}
   44 	return
   45 }
   46 
   47 func main() {
   48 	input := readInput("./input.txt")
   49 	// 382
   50 	fmt.Println(part1(input))
   51 	// 3964
   52 	fmt.Println(part2(input))
   53 }
   54 
   55 func pathToCoord(path []int) (coord pos) {
   56 	// Use E/W axis as x, NW/SE axis as y.
   57 	for _, dir := range path {
   58 		switch dir {
   59 		case E, NE:
   60 			coord[0] += 1
   61 		case W, SW:
   62 			coord[0] -= 1
   63 		}
   64 		switch dir {
   65 		case NW, NE:
   66 			coord[1] += 1
   67 		case SE, SW:
   68 			coord[1] -= 1
   69 		}
   70 	}
   71 	return
   72 }
   73 
   74 func part1(input [][]int) (blackCount int) {
   75 	tileColor := map[pos]int{}
   76 	for _, path := range input {
   77 		coord := pathToCoord(path)
   78 		tileColor[coord] = 1 - tileColor[coord]
   79 	}
   80 	for _, v := range tileColor {
   81 		if v == BLACK {
   82 			blackCount += 1
   83 		}
   84 	}
   85 	return
   86 }
   87 
   88 func flip(tileColor map[pos]int, steps int) map[pos]int {
   89 	// Same as day 17.
   90 	curr, next := tileColor, map[pos]int{}
   91 	for i := 0; i < steps; i++ {
   92 		// Update neighbor black count.
   93 		next = map[pos]int{}
   94 		for p, v := range curr {
   95 			next[p] = next[p] // ensure key exists
   96 			for _, dir := range []int{E, SE, SW, W, NW, NE} {
   97 				next[p.move(dir)] += v
   98 			}
   99 		}
  100 		// Update state.
  101 		for p, blackCount := range next {
  102 			switch curr[p] {
  103 			case BLACK:
  104 				if blackCount == 0 || blackCount > 2 {
  105 					next[p] = WHITE
  106 				} else {
  107 					next[p] = BLACK
  108 				}
  109 			case WHITE:
  110 				if blackCount == 2 {
  111 					next[p] = BLACK
  112 				} else {
  113 					next[p] = WHITE
  114 				}
  115 			}
  116 		}
  117 		curr = next
  118 	}
  119 	return curr
  120 }
  121 
  122 func part2(input [][]int) (blackCount int) {
  123 	tileColor := map[pos]int{}
  124 	for _, path := range input {
  125 		coord := pathToCoord(path)
  126 		tileColor[coord] = 1 - tileColor[coord]
  127 	}
  128 	tileColor = flip(tileColor, 100)
  129 	for _, v := range tileColor {
  130 		if v == BLACK {
  131 			blackCount += 1
  132 		}
  133 	}
  134 	return
  135 }