Initial commit d01-24

This commit is contained in:
IamTheFij 2021-01-04 11:55:10 -05:00
commit 071c20222a
76 changed files with 20666 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.pyc
__pycache__
tags
tags.lock
tags.temp

5
.golangci.yml Normal file
View File

@ -0,0 +1,5 @@
---
linters:
disable:
- gochecknoglobals
- goerr113

5
README.md Normal file
View File

@ -0,0 +1,5 @@
https://adventofcode.com/
Each day is organized in a subfolder. There is no consistency at all.
Good luck!

200
d01/aoc-d1-input.txt Normal file
View File

@ -0,0 +1,200 @@
1934
1702
1571
1737
1977
1531
1428
1695
1794
1101
13
1164
1235
1289
1736
1814
1363
1147
1111
1431
1765
1515
1184
1036
1803
1791
1638
1809
1283
1980
1854
1878
1574
1352
1151
730
1581
1990
1919
2003
1538
1663
1735
1772
1830
1152
1022
1774
1544
1551
1835
1383
1614
1396
1715
1530
295
1208
1978
1104
1691
1176
1183
1909
1192
1535
1924
1268
1969
1954
1760
1077
1734
1371
1676
1933
1400
1928
1982
1541
1106
1248
1346
1782
1142
1849
1798
1362
1379
1886
1265
1226
1751
1575
1027
1710
1601
1205
1922
1452
1206
1263
2000
1957
1951
1834
1533
1149
1245
1564
1182
1237
1013
1254
1895
1504
1480
1556
1821
1589
1864
1573
1698
1927
1434
516
1722
1360
1940
1212
1329
1675
1812
1917
1302
1604
1336
1233
1405
1179
1169
1081
1941
1553
1236
1824
1923
1938
1475
1446
1545
1853
1664
317
1489
1884
1743
1621
1128
1474
1505
394
1387
1509
1627
1914
1913
1949
1843
1847
1882
1486
1082
1802
1645
1690
1629
1377
2004
1044
1191
1014
1857
1813
1572
1055
1002
1721
1273
1417
1968
1888
1863
1278
1141
1964
1259
1823
1181
1779

81
d01/main.go Normal file
View File

@ -0,0 +1,81 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func part1() {
seen := map[int]bool{}
err := proccessLines("./aoc-d1-input.txt", func(line string) (bool, error) {
num, err := strconv.Atoi(line)
if err != nil {
return true, err
}
pair := 2020 - num
if _, ok := seen[pair]; ok {
fmt.Printf("Found pair! %d + %d = 2020 Product = %d\n", num, pair, num*pair)
return true, nil
}
seen[num] = true
return false, nil
})
if err != nil {
log.Fatal(err)
}
}
type numberPair struct {
A, B int
}
func part2() {
singles := map[int]bool{}
doubles := map[int]numberPair{}
err := proccessLines("./aoc-d1-input.txt", func(line string) (bool, error) {
num, err := strconv.Atoi(line)
if err != nil {
return true, err
}
remain := 2020 - num
if pair, ok := doubles[remain]; ok {
fmt.Printf("Found set! %d + %d + %d = 2020 Prouct = %d\n", num, pair.A, pair.B, num*pair.A*pair.B)
return true, nil
}
for single := range singles {
doubles[num+single] = numberPair{num, single}
}
singles[num] = true
return false, nil
})
if err != nil {
log.Fatal(err)
}
}
func main() {
part1()
part2()
}

36
d01/main.py Executable file
View File

@ -0,0 +1,36 @@
#! /usr/bin/env python3
def part1():
print("Part1:")
seen = set()
with open("./aoc-d1-input.txt", "r") as f:
for line in f:
v = int(line)
remain = 2020 - v
if remain in seen:
print(f"{v} * {remain} = {v*remain}")
break
seen.add(v)
def part2():
print("Part2:")
singles = set()
doubles = {}
with open("./aoc-d1-input.txt", "r") as f:
for line in f:
v = int(line)
remain = 2020 - v
if remain in doubles:
n2, n3 = doubles[remain]
print(f"{v} * {n2} * {n3} = {v*n2*n3}")
break
for n1 in singles:
doubles[v+n1] = (v, n1)
singles.add(v)
if __name__ == "__main__":
part1()
part2()

1000
d02/input.txt Normal file

File diff suppressed because it is too large Load Diff

110
d02/main.go Normal file
View File

@ -0,0 +1,110 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
var matcher = regexp.MustCompile(`([0-9]+)-([0-9]+) ([a-zA-Z]): ([a-zA-Z]+)`)
func part1() {
totalValid := 0
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
results := matcher.FindStringSubmatch(line)
if results == nil {
err = fmt.Errorf("invalid line %s", line)
return
}
minCount, err := strconv.Atoi(results[1])
if err != nil {
return
}
maxCount, err := strconv.Atoi(results[2])
if err != nil {
return
}
letter := results[3]
password := results[4]
// fmt.Printf("Make sure %s is in %s between %d and %d times\n", letter, password, minCount, maxCount)
// Validate
count := strings.Count(password, letter)
if minCount <= count && count <= maxCount {
totalValid++
}
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total valid %d\n", totalValid)
}
func part2() {
totalValid := 0
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
results := matcher.FindStringSubmatch(line)
if results == nil {
err = fmt.Errorf("invalid line %s", line)
return
}
pos1, err := strconv.Atoi(results[1])
if err != nil {
return
}
pos2, err := strconv.Atoi(results[2])
if err != nil {
return
}
// 1 vs 0 indexed
pos1--
pos2--
letter := results[3]
password := results[4]
// fmt.Printf("Make sure %s is in %s between %d and %d times\n", letter, password, minCount, maxCount)
// Validate
if pos1 >= len(password) || pos2 >= len(password) {
return
}
letter1 := string(password[pos1])
letter2 := string(password[pos2])
if (letter == letter1 || letter == letter2) && letter1 != letter2 {
totalValid++
}
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total valid %d\n", totalValid)
}
func main() {
part1()
part2()
}

44
d02/main.py Executable file
View File

@ -0,0 +1,44 @@
#! /usr/bin/env python3
import re
def part1():
print("Part1:")
total_valid = 0
with open("./input.txt", "r") as f:
for line in f:
g = re.search("([0-9]+)-([0-9]+) ([a-zA-Z]): ([a-zA-Z]+)", line)
min_count = int(g.group(1))
max_count = int(g.group(2))
letter = g.group(3)
password = g.group(4)
# print(f"min: {min_count} max: {max_count} letter: {letter} password: {password}")
count = password.count(letter)
if min_count <= count <= max_count:
total_valid += 1
print(f"Total valid {total_valid}")
def part2():
print("Part2:")
total_valid = 0
with open("./input.txt", "r") as f:
for line in f:
g = re.search("([0-9]+)-([0-9]+) ([a-zA-Z]): ([a-zA-Z]+)", line)
password = g.group(4)
try:
pos1 = password[int(g.group(1))-1]
pos2 = password[int(g.group(2))-1]
except IndexError:
continue
letter = g.group(3)
if (pos1 == letter or pos2 == letter) and pos1 != pos2:
total_valid += 1
print(f"Total valid {total_valid}")
if __name__ == "__main__":
part1()
part2()

323
d03/input.txt Normal file
View File

@ -0,0 +1,323 @@
.........#..##..#..#........#..
#...#..#..#...##.....##.##.#...
....#..............#....#....#.
#.#..#.....#...#.##..#.#.#.....
........#..#.#..#.......#......
.#........#.#..###.#....#.#.#..
........#........#.......#.....
...##..#.#.#........##.........
#.#.##..###............#...#...
............#....#.......###.##
....##....##..#........#......#
............#.#..........#.....
#.#....#....##...#.....#.....#.
......#.#.#...#.....###....#..#
...........##..#.........#..#.#
..#..#.................#..#..#.
.#....###...#.......#.........#
#.#.#.#...#......#.......#...#.
.......#.#.#...#..............#
...##.......#..##.#.......##...
#.#.##....#..##..##..###...###.
.#......##.##.#....#.##........
..###.............##..##..#....
.....#.#...........#..##..##...
.###.#.#......#.....#........##
...#.......#...##..#..#..#.....
..............#.#..##.##..##..#
#..#.#......#............#.....
........#..#....#..............
...#...#..............#.#####..
...##......#........#.#...#....
..##......#............#..#..#.
....#.........#.#.#.....###.#..
#....#........#........#....#.#
.....#...#..##.....##...#.....#
#...#.#.#...##..##.###.#.#.....
......#.#..........#...#.##....
..............##...#..#.......#
........##.....#.....#.#....#..
..............#..#..#...#.....#
##......##.......##...#.#....#.
.....#.............#.#.........
#.........##..#..#.........##..
..#..#.....#####.........##.#..
.......##.#......#........#....
#.................#.#...#....#.
...#........#.###.##.##.....#..
#.....##..#...##.#.#......#....
.....#..#.#..........##..#.##..
..###.............#..#..#...#..
...###..#...#.....##..........#
#.......#.#...#....#..##..#..#.
.#..#.........#..............#.
..######.....#....##......#....
#..##...#......#..#.#....#.....
.#...................#.#.....#.
..#...#.#..#.#......#..#...#..#
..##..##.#.##.........#.#.#....
...#...#...........#..##.##...#
#...#....#....#....#..#.##..#..
..#.##....#....###..#..........
#.#..##.#.#...##.#..#.##..#.#..
#......##...#.#..........#..#..
#.#...#..#...#.#.#..#........#.
#.#.##.#..#...#..#.#.##........
.....#......#........#..#......
...#....#.#....#...............
....#..###..#....#..#....#....#
.#........###..........##.##.#.
#.#......##....##...##.#......#
#..##.##...#...........##.#.#..
.#.....#.#...#.................
##..........#..#....#.....#...#
....#.#..........##..#.....#.##
#.#..#..#..##..........#.......
..#.#.###......................
......##..##.....#..##.##....#.
...#.......#.##....#......#....
...#...#........#...#.#...#..##
##...#....#.#...#.#.##..##...#.
...#.....#...#...#....###.#..#.
..#.#..#........#......#..##..#
...#......#...#.#.##...##.#.#.#
....#.#....#....#.....#.....##.
.....#.#..##.#....##....##.....
.#...###..#.....#............#.
#..#.#.#..#..#...#....#...#....
#.....#..#...#................#
..........#..#.......#......#.#
...#..#......#...#......#......
.#.#.....#.#.#.#......#..#..#..
.....#.........#.#.#.....##.#..
.....#.#.....#..#..#..#.....###
##....#......##....##.#....#.#.
#####........#..........##.....
.#...##...#...#.......#....#...
#.#.##...##...##..##........#..
#.#..............#.#...#...###.
...#.....##..#.........#....#.#
#.#....#....#..##.#..#...#.....
..#....#.#..#...#...##.....#...
....#...#......................
..#...#.......#..#...##....#...
.#........#...#.....##.##...#..
#......#..............#..#..#..
...........#.#..#.#.#....#....#
.##..##.......#...#..#.....#..#
...#.........#.........###..#..
...#.##....#....#.....#.....#..
.#.#.#.........#.#.#....#....#.
...#..........##..#....#.#.....
...#....##................#....
#....##..#..#........##...#....
#...#...##.#............#....#.
##..#....#...#...............#.
..........#.#...#..##..#.#.....
..##...##..#....#.#......#.....
.......#......#.#.....#.....##.
#...###.....##..##....#.#....#.
.###......#.....#.#............
#.....#.....####.##....#..#....
......###.............#......##
.........##.......##..#..#..#..
.#.......#....#...#...#.#......
#...#..#...#........#...##..#..
.#....#........#.........##..#.
..............##.#...##..#.##.#
.#....#...#....#......#..#.....
#....##.#...#.#.....###..#....#
#.......##.#..###..............
#..#..#..#......#.#..#...#..#.#
.......#.#.#..#..#...#..#......
.#..#......#.....#......##..##.
....#....#.......#.......#.#.##
.......#.#................#...#
#.#.....#.......#.#........#...
.....#....##...#......#.....##.
.#......#.#...#..#....#....#.##
##...#.###.#....#..#....#.#...#
....#.##..##.#.............#...
#..#.............##.......#.#..
##.#..#..#.#...........###...##
.#.#.....#......###........#...
#.#...#.#....##......#.#....#..
#.........#..........#.........
.......#....#...#..#.....#...##
.......................#...#..#
.###...........##...#........##
#.#....######.#........#..##.#.
..#.##.#...#.#.......#.##.##..#
#.............###..#.##.#......
...#..##......#...#..###.....#.
..........#.....#..#...##..#...
..##..........#.#..#.....#...#.
...#.......#.....##.........#..
#..#.#...#..#...###...#...#.#..
#.##....#..#.#.......#..#..#...
..#.##.#......#.#......#....#..
..........#...##.....###.......
...#...##..#......#...##.......
....#........#.#.......#..###..
.....#.#..........##.#..#..#.#.
.............##.....#.#..##....
...#...............##...#......
....#......#..#....#...##..#...
.##.#....#.#.....#.#.........#.
.....#.###....#..###..#.#.....#
.#.........##.........##...#...
..#.....###....##..........#..#
........#..#.#.#..#.......#..##
..#.#..#.#............#.##.#..#
.#....#.....#..#...#.......##..
.#...........#.#..#..###.###...
..#.....#..#........#.#........
.#........##........#..#.##....
......#.....##........##..#....
.#..................##....#.#..
.#..#.#..#.#...#........#......
...#..##.#......#..#..........#
....#.##...#....##.............
#....#.##....##.###..#..#..#...
..........#..#...##.##....#..#.
.###.#.....#...#...#...#.......
............#...............#.#
#....#...#......#....#.#.#.#.##
...#..........#.#.#.....###....
#.#...##...#..#.....###...#....
......#...#..#..#..#.##...##...
...#..#.#....#...#.#.........##
##....#..###.#.##.....##.......
..#.#...#..##.......#.#.......#
##......#...........#......#...
.......#..###....###..##.#...##
.........#.....#..#.......##..#
.......#.##..#....#...#.#...#..
#..#.#..................##.#..#
...#..#..#.....#..#........#...
...#.#..###..#.....##...#....#.
..#..#......#...........#...#..
#...##.##..###.......##........
.#.....#..#....#.....#.##....#.
#..#........#.#....#..#...#.###
..#...#.#.#.....#.....#..#.....
.##.............#.#......##...#
.#....#####............#.....##
#.###.......#.#...##.....#.....
......#.##..#...#..#..##.#..##.
......#.#...##.....#...#....##.
....#............#...#...#....#
.........##.#.#....#....#....##
.#...##.#...#.......#.##....#.#
#....#.#...#.#...#.#.#...#.....
.#.#.........##..#..#..........
.#.........#.#.....#..#.#..###.
....##.#.#..........#..####....
....#..#.#.#...#...#..#....#...
..#.#...#...##.......#.#.#..#..
...##...#......#.....#.#...#..#
......#.###.#.......##...#...#.
.....#.#.#......##..........###
##.#.#.#..#....#...............
.#.#.##.......#....#.#.....#..#
.........#...#.#..#.......#....
....#.####.#......#...#...##...
#..#..#..#..#....#...##.....##.
......####.#..##..#.....##.....
##.#.........#........#..#.#...
.#.#....#....#.......#.#....##.
....#....#.......##..#.....#...
.#......#..#....#.#............
#..#.#.##.....#..#.#.#.#.#.##..
.#.....#.....#...#..#.#...#.#..
.#.#.##............#.#.#.#.#.#.
.##..........#.....#...###.....
#.#...#...#................#.#.
##...#.##.....#.....#.#.##.....
####.....##..........#......#..
#.............#..............#.
.###....#.#...#..#..#..#.......
..#.#.....#...#..#..####.......
...#.#..#........#..##..#..#.##
.#........#..........#.#...##..
.#.......#.#.#..#...#..#.#...##
.#.....##......##..............
......#..#.#.##...##.#.....#...
.........#.#...##.....##....#.#
.....##...#........#..#.#..#.#.
.#.##..#.....##...#...###.#.#..
...##...#...#..#.#..#..........
##..............#...#...#.#..#.
......#..#......#..#.....#...#.
.......#...#..#....#.....#.....
..##.....##..#.#........#......
.###.#...#.....................
..#...#.................#...#..
#..#.##...####.............#...
.##....#..####.......#.........
#..#...###...#...#..#..##......
....#.##.#.#.........#.....#..#
.....#...#.....#.#.#.##.#...##.
.............#........#.....#..
...##.###.#....##.......#..#...
#..#....#....#.#............#..
.........#.##........##.....#..
.........#.#.#..#..#.......#...
.......#.#..#.......#.....#.#..
##.#.....##...##.....#.#.......
.#.#.#......##.##.#.........#..
..#.##..###.....###.........##.
.#......#..#..##...#.#...##.#.#
......#.#............#.....#...
###.#..#..#..#..#.##...#.......
.#.#.##..###....#......##..###.
#...#.#.#..#..#..##.#.##....#..
..#...#...####...#......####.##
..##.#.####........#..#......#.
.#..#.......#...#.#.........#..
........#.#....#..#####..#.....
.#...........#..#..#..#...#....
....#....#...#.................
....##..#....##....#..#....#.##
....#.##.....###...#...##.##...
......##.#..##.#.#.#....#.#.#..
##.#...###....#.#..#.#.###....#
......###..#..#..........##...#
..........#.##...##..#....##.#.
.#...#.#..#.#.#..#.....#.......
.#....#..#.#..#.#...##.#.#.....
.##.....#...#..##.#........#...
....#......#.........#....#..##
.#..#.#.#.#..#..#.#.........#..
.........#.....#...#....#......
#..#..#........#...#.#.........
...#.#.#...##.#.#...#..#......#
#.#.#.#........#...#..#.....#..
.###..#..#..###..#..#..........
.....#......#.#..#...#.......#.
##.##.........#.......##.......
#...##.......#..#.#.......#....
#..#..#.....#...#......#.......
.#..#..#.##....#.#..#...#...#..
.#...#.....#..#.........#..#...
...#.#.#.......#....#..##.....#
.........#..##.#..#..#.#.......
#.##.....##..###..#..#..#.##...
........#......#...##...###..##
.##....##..#..#..###......#....
............##......#...#..##..
...##.......#......#...##.##..#
...#..#..#.#...####.#.......#..
..#.##..#....#......#.#.....#..
..#.##..............#..##.....#
.....##....#......#....#......#
......#..#......#.........#..#.
...#.##.###...###..#.##........
..........####.#.##.....#..#.##
#...##...........#...........##
#.#..#.#....#.#..#....##......#
.......#...#.....#......#.#.##.
....#.##..##..........#..#.....
#.#.#...#......#...#.....#.##.#
........#.......#..##.....##...
.....####.#....#.#.............

120
d03/main.go Normal file
View File

@ -0,0 +1,120 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
)
var (
tree = "#"
snow = "."
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
type world struct {
x, y int
dx, dy int
worldMap []string
}
func (w *world) move(dx, dy int) string {
result := w.peek(dx, dy)
w.x += dx
w.y += dy
return result
}
func (w world) peek(dx, dy int) string {
row := w.worldMap[w.y+dy]
return string(row[(w.x+dx)%len(row)])
}
func (w world) atEnd() bool {
return w.y >= len(w.worldMap)-1
}
func (w *world) setSlope(dx, dy int) {
w.dx = dx
w.dy = dy
}
func (w *world) ski() int {
trees := 0
for !w.atEnd() {
space := w.move(w.dx, w.dy)
if space == tree {
trees++
}
}
return trees
}
func (w *world) takeLift() {
w.x, w.y = 0, 0
}
func readMap() world {
worldMap := []string{}
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
worldMap = append(worldMap, line)
return
})
if err != nil {
log.Fatal(err)
}
return world{worldMap: worldMap}
}
func part1() {
theWorld := readMap()
theWorld.setSlope(3, 1)
trees := theWorld.ski()
fmt.Printf("Total trees: %d\n", trees)
}
func part2() {
trees := []int{}
theWorld := readMap()
product := 1
for _, slope := range [][]int{
[]int{1, 1},
[]int{3, 1},
[]int{5, 1},
[]int{7, 1},
[]int{1, 2},
} {
theWorld.setSlope(slope[0], slope[1])
count := theWorld.ski()
product *= count
trees = append(trees, count)
theWorld.takeLift()
}
fmt.Printf("Total trees: %v, product: %d\n", trees, product)
}
func main() {
part1()
part2()
}

107
d03/main.py Executable file
View File

@ -0,0 +1,107 @@
#! /usr/bin/env python3
import functools
TREE = "#"
SNOW = "."
class LoopingList(list):
def __getitem__(self, key):
if isinstance(key, int):
return super().__getitem__(key % len(self))
if isinstance(key, slice):
return [
self[x]
for x in range(key.start, key.stop, key.step or 1)
]
def read_map():
world_map = []
with open("input.txt") as f:
for line in f:
world_map.append(LoopingList(line.strip()))
return world_map
class World(object):
def __init__(self, world_map, x=0, y=0):
self._world_map = world_map
self._x = x
self._y = y
# Default slopes
self._dx = 1
self._dy = 1
def move(self, dx, dy, should_print=False, print_buffer=0):
self._x += dx
self._y += dy
if should_print:
print("".join(self._world_map[self._y][0:self._x+print_buffer]))
return self._world_map[self._y][self._x]
def print_row(self):
print("".join(self._world_map[self._y]))
def peek(self, dx, dy):
return self._world_map[dy + self._y][dx + self._x]
def at_end(self):
return self._y >= len(self._world_map) - 1
def set_slope(self, dx, dy):
self._dx = dx
self._dy = dy
def ski(self, count_trees=True):
trees = 0
while not self.at_end():
try:
space = self.move(self._dx, self._dy)
if count_trees and space == TREE:
trees += 1
except IndexError:
print("At end of the world")
return trees
def take_lift(self):
self._x = 0
self._y = 0
def part1():
world_map = read_map()
world = World(world_map)
world.set_slope(3, 1)
trees = world.ski()
print("Total trees", trees)
def part2():
slopes = {
(1, 1): None,
(3, 1): None,
(5, 1): None,
(7, 1): None,
(1, 2): None,
}
world_map = read_map()
world = World(world_map)
for slope in slopes:
world.take_lift()
world.set_slope(*slope)
slopes[slope] = world.ski()
print(slopes)
print("Answer:", functools.reduce(lambda x, y: x*y, slopes.values()))
if __name__ == "__main__":
part1()
part2()

1100
d04/input.txt Normal file

File diff suppressed because it is too large Load Diff

13
d04/invalid.txt Normal file
View File

@ -0,0 +1,13 @@
eyr:1972 cid:100
hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
iyr:2019
hcl:#602927 eyr:1967 hgt:170cm
ecl:grn pid:012533040 byr:1946
hcl:dab227 iyr:2012
ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
hgt:59cm ecl:zzz
eyr:2038 hcl:74454a iyr:2023
pid:3556412378 byr:2007

149
d04/main.go Normal file
View File

@ -0,0 +1,149 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func between(low, mid, high int) bool {
return low <= mid && mid <= high
}
type validator = func(v string) bool
var heightMatcher = regexp.MustCompile(`^([0-9]+)(cm|in)$`)
func heightValidator(v string) bool {
result := heightMatcher.FindStringSubmatch(v)
if result == nil {
return false
}
value, err := strconv.Atoi(result[1])
if err != nil {
return false
}
switch result[2] {
case "cm":
return between(150, value, 193)
case "in":
return between(59, value, 76)
}
return false
}
func betweenValidator(low, high int) validator {
return func(v string) bool {
val, err := strconv.Atoi(v)
if err != nil {
return false
}
return between(low, val, high)
}
}
func valueInValidator(valid ...string) validator {
validValues := map[string]bool{}
for _, value := range valid {
validValues[value] = true
}
return func(v string) bool {
_, ok := validValues[v]
return ok
}
}
var requiredKeys = map[string]validator{
"byr": betweenValidator(1920, 2002),
"iyr": betweenValidator(2010, 2020),
"eyr": betweenValidator(2020, 2030),
"hgt": heightValidator,
"hcl": regexp.MustCompile(`^#[0-9a-f]{6}$`).MatchString,
"ecl": valueInValidator("amb", "blu", "brn", "gry", "grn", "hzl", "oth"),
"pid": regexp.MustCompile(`^[0-9]{9}$`).MatchString,
}
func parseKeys(text string) map[string]string {
d := map[string]string{}
for _, kvp := range strings.Split(text, " ") {
parts := strings.Split(kvp, ":")
d[parts[0]] = parts[1]
}
return d
}
func validateKeys(d map[string]string) bool {
for key := range requiredKeys {
if _, ok := d[key]; !ok {
return false
}
}
return true
}
func validateValues(d map[string]string) bool {
for key, f := range requiredKeys {
var v string
var ok bool
if v, ok = d[key]; !ok {
return false
}
if !f(v) {
return false
}
}
return true
}
func main() {
validKeys, validValues, total := 0, 0, 0
buffer := []string{}
processBuffer := func(buffer []string) {
d := parseKeys(strings.Join(buffer, " "))
if validateKeys(d) {
validKeys++
}
if validateValues(d) {
validValues++
}
total++
}
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
if line == "" {
processBuffer(buffer)
buffer = []string{}
} else {
buffer = append(buffer, line)
}
return
})
if err != nil {
log.Fatal(err)
}
processBuffer(buffer)
fmt.Printf("Total: %d, Valid keys: %d, Valid values: %d\n", total, validKeys, validValues)
}

121
d04/main.py Executable file
View File

@ -0,0 +1,121 @@
#! /usr/bin/env python3
import re
def height_validator(x):
match = re.match(r"^([0-9]+)(cm|in)$", x.strip())
if not match:
return False
if match.group(2) == "cm":
return 150 <= int(match.group(1)) <= 193
elif match.group(2) == "in":
return 59 <= int(match.group(1)) <= 76
return False
required_keys = {
"byr": lambda x: 1920 <= int(x) <= 2002,
"iyr": lambda x: 2010 <= int(x) <= 2020,
"eyr": lambda x: 2020 <= int(x) <= 2030,
"hgt": height_validator,
"hcl": lambda x: re.match(r"^#[0-9a-f]{6}$", x.strip()),
"ecl": lambda x: x in ("amb", "blu", "brn", "gry", "grn", "hzl", "oth"),
"pid": lambda x: re.match(r"^[0-9]{9}$", x.strip()),
}
optional_keys = {
"cid": lambda x: True,
}
class Passport(object):
def __init__(self, s):
self.d = {}
for kvp in s.split():
parts = kvp.partition(":")
self.d[parts[0]] = parts[2]
def key_set(self):
return set(self.d.keys())
def is_valid(self, deep=False):
valid = set(required_keys.keys()) <= self.key_set()
if not valid or not deep:
# print(f"Valid: {valid}. Missing: {set(required_keys.keys()) - self.key_set()}")
return valid
for key, validator in required_keys.items():
valid = validator(self.d[key])
if not valid:
# print(f"Invalid value for {key}: {self.d[key]}")
return False
# print("Valid!", self.d)
return valid
def parse_passport(buffer):
s = " ".join(buffer)
return Passport(s)
def part1():
num_valid = 0
total_passports = 0
with open("input.txt") as f:
buffer = []
for line in f:
line = line.strip()
if line == "":
p = parse_passport(buffer)
total_passports += 1
if p.is_valid():
num_valid += 1
buffer = []
else:
buffer.append(line)
# if total_passports == 4:
# break
if buffer:
p = parse_passport(buffer)
total_passports += 1
if p.is_valid():
num_valid += 1
print("Total passports:", total_passports)
print("Total valid passports:", num_valid)
def part2():
num_valid = 0
total_passports = 0
# with open("valid.txt") as f:
# with open("invalid.txt") as f:
with open("input.txt") as f:
buffer = []
for line in f:
line = line.strip()
if line == "":
p = parse_passport(buffer)
total_passports += 1
if p.is_valid(deep=True):
num_valid += 1
buffer = []
else:
buffer.append(line)
# if total_passports == 4:
# break
if buffer:
p = parse_passport(buffer)
total_passports += 1
if p.is_valid(deep=True):
num_valid += 1
print("Total passports:", total_passports)
print("Total valid passports:", num_valid)
if __name__ == "__main__":
part1()
part2()

12
d04/valid.txt Normal file
View File

@ -0,0 +1,12 @@
pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
hcl:#623a2f
eyr:2029 ecl:blu cid:129 byr:1989
iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
hcl:#888785
hgt:164cm byr:2001 iyr:2015 cid:88
pid:545766238 ecl:hzl
eyr:2022
iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719

874
d05/input.txt Normal file
View File

@ -0,0 +1,874 @@
FBFBFFFLLL
FFBBBBFLRR
BFBFBBBLLL
FFBBBBBLLL
BFFBBBBRLL
BBBFFBFRLL
FFBBFFFRRR
FFBFFBBLRL
FBFFBFBRRR
FBFFBFBRLL
BFFBFFFRLR
FFFBBFFRRR
BFBFBBFLLL
FBFBBFFRRL
BFFBFBFLRL
FBFFFBFRRL
FBFBFFBRRR
FBFBFFBRLL
BFBFFFBLLL
BFBFFBBLRL
FBFFFFBRRL
BFFFBFFRRL
FBFBFFFRLR
BFFFFBBLLR
FFBFFFFRLR
BBFBBFFLLL
FFBFFBFRRR
FBFBFBBRRR
BBBFFFFLRR
FFFBFFBRRR
BFFBFBFLRR
BFFFBBBRLL
FFBFBBBRLR
FBFFFFBLLR
FBBFBFFLRL
FBFFFFFRLL
FBBBBFBRLL
BFBBBBFLLL
FBBBFBBRRR
BFFFBFBLLL
FBBBBBFLRL
BFBBBFFLRR
BFBBFBBLRR
FFBBBFFLRR
FFBBBBFRLR
BFFFBFFLLR
FBBFFFBRRL
FBBBFBBLRR
FFBBFBFRRL
FFFBFBBLRR
FBFBBBBRLR
FBFFBFBLLL
FBBFFFFRLL
BBBFFFBLRL
FBBFBBBLLL
FFBBFBBLLR
FBFFFBBRLR
BBFBBFFRRL
FFFBBFFRLL
FBFFBBBLRL
BFFBFFFLRL
FFFFBBFRRR
FBBFBBFLLR
BFBFBFBRRL
BBFBFBBRRR
BBBFFFBLLL
BFBFFBFRLL
FFBBFFBRRR
BFBBFFFRRL
BFBBBFBRRL
BFBBBBBRRR
BBFBFBFRLL
BBFFBFFLRL
BFFBBFFLLL
BFBFBFFLLL
FBBBFFFRLR
BFFFBBBLRL
FBFBFFFLRR
FBBBFBBLRL
FFBBFBBRLR
FBBFFFFLRL
FFFBFBBLLL
FBFBFFBRRL
BBFFBBFRRR
BFFFFBFRLR
FBFBFFBLRL
FFBFFBBLLL
FBFBBFBRLR
BFFBBFBRLR
FFBFBFBLLL
FFBBFFBRLR
FBBBBBBLLL
FFFBBBBRRL
BFBBFBBRLL
BBFFFBFLLR
FFBBBBFRRR
BFBFFFBRLL
BFBFFBFLRR
FFFFBBBLLR
FBFFBBFRLL
FFFFBBBRRL
FFBFFBBLLR
FBFFFBBLLL
FFBBBBFRLL
BBFFBFFLLL
BFBBBBBRRL
BFFBFBFLLL
FFBFBBFLLR
FFBFBBBLRL
BFFBFFBLRL
FBBBFFFRRR
FBBFFBBRRL
FBBFFBBLLR
BBFBBBFLRR
BBFFFBFRRL
FBFBFBFRRL
FFBFBBFRRR
FBFFBBBLLR
BBFBFFBRLL
BFBBBFBLRL
FFBBFFFLRR
BFFFBFFLRL
BFFBBBFLLL
FBBFFFBLRL
BBBFFBFLLL
BFBBFBBRLR
FBBBBBFRLL
FBBBBFBLRR
FFBFBBFRLR
BBFFFFBLLL
FBFBBBFRLR
FBBFBBBLRL
BBFFBBBRLL
FFBFBFFLLR
FFFBBFBRLL
FFBBBFFRLL
BFBBFFFLRR
FBBBFBFRLL
BBFBFBFLRR
BFBBBFFRLL
FFBFFFFRRR
BFBBBBBLLR
FBBBBBBRRR
BBFBBFFLRR
BFBFFBBLRR
BFFBFBBLRR
BFFBBFFRLR
FBBBFFBRRR
FFFFBBBRLR
FBFFFFFLLL
BBFFFBFLRR
BFFFFBFLRL
BFFBFFBLLL
BFFBBFBRRL
FFFBBFFLLR
FBFFFFBLRL
FBFFFBFLLR
FFBBFBBRLL
FFBFFBBRLR
FFBFFFBRRL
FFFBFBFLRR
BBFFBFFRRR
BBFFFFFLLL
FBBFBFBRLR
BBFBBFBLLR
BBFBBBFRRL
BFBFFBBLLR
FBBFFFFLLR
FFBFBFFRRL
FFFBFFBRRL
FBFBFFBRLR
BFBBFBFRLL
BBFBBBBLLR
BFBBBFFLLL
BBFBBBBRRL
BFBFBFBRLR
BFFFBFBRRL
BFFBBBFRRL
BFFFBFBRLL
FBFBFBFLRR
FFBFFBFLRR
BBFBBBBRLL
BFBBBFFLRL
FBBBBFBLLL
BBFBBBFLRL
BFBBFBFLLL
FBBBBBBLRL
FFBFFFBLLL
FFBBBBBRRL
FBBFFFBLLL
FBBBFFBLRR
BBBFFBFLLR
FFFFBBBLLL
FBBBBBBRLR
FFBFFBBRRR
BFFFBFFRLL
BBBFFFBRRR
FBBFBFFLLL
FBFBFBBRLR
FBFFFFFLRL
FFBBBBBRLR
FBBBFFBRRL
BFBBBBFRRL
FBFBBFBLLR
BBFFBBBLLL
BBBFFBFRLR
FFBBFFFLLL
FFBFFBBRRL
FBBBBFFLLL
FBBBBBFRRR
FBFFBBFLLR
FFFBFFFLRL
FFFBFBBRRL
BFFFBFFLLL
FBBBFBBLLL
FFBFBBBLLL
BFFFFFBLRL
FBBBFBFLRR
BBFFBBFLLR
FBFFBBBRLR
BFBFFFFLLR
BFBBBFBLLL
BBFBFBBRLR
FFFBBFBLLR
BFFBFBBRRL
BBFFBBFLRR
BFFBBBFLRR
FBFBBBBRRL
BFBFBFFRRL
BBFBBFFRLR
BBFBBBBRLR
FFBBFFFLLR
BBFBFBBLRR
FBFBFBFLLL
BFFFFBBRRR
BFBBBBFRRR
BFFFFFFLRL
BBBFFBFLRR
FFFBBBBRLR
FBBFFFBRLL
BBFFBBFLRL
FFBBBBBRRR
BBFFBFFRLL
BFFFFFBRRR
FBBFBFBRRR
BFFFFBFRRR
FBBFBBBRLL
FFFBFBBRLR
FBBBBFFRLR
FBBFFFBLLR
FFBBFFBLLR
BFBFFFBLRR
FFBFBBBRRR
BFBFBFBLRR
BFFBBFBLRR
FBFFBFFRLL
BFFBBBFRLR
FBFFFBFRLR
FFFBFBFRLL
FBBFBBFLLL
BFBBFFFLRL
FBBFBFFLRR
BBFFFBFRRR
FBBFBFBLRL
FBBBFBFLLR
FBFBBBBLLR
BBBFFFFLLR
BFBBFBFRRR
FFBFBFFRLR
FFBBFBBLLL
BFFFFFBLLR
FBBBFBFLLL
FBBFBBFRLR
BBFFFFFRLL
BFBFBFFLRR
FBFBBFFLRR
BBFBBFBRLR
BFFFBBFRLR
FBFFBBFRRR
FBFFFBFLLL
FBBFBBBRRR
BBFFFBBLRL
FFBFFBFLLR
BBFFBFFLLR
BBBFFBFRRL
FBFBBFBRRR
FBBBBBBRLL
FBFFFBBLRR
FFFBFFFLLL
BBFBBFFRLL
BBFFFBFRLL
BBFFFBFLLL
FFBBFBBRRL
FFFFBBFLRL
BFBBBBFLRL
BBFBBFFLLR
BBFFBFBRRR
FBFBBFFRLL
FBFBBFBLLL
BFBBBFFRRR
FFBBBFBRLL
FFBFBBBRRL
BFBBFBFRLR
BBFBFBFRLR
FBFBBBFLLR
FBFBBBFLRL
BBFFBBFRLR
FFBBFFFLRL
FFFFBBFLRR
FFFBBFFLRL
FFFBFBFRRR
FBBFFBBLRR
BBFBBFBLRR
BFFBBBFLRL
FBFFBFFRLR
FBFFFBFRRR
BFFBBFFRRL
BFFFBBFRLL
BFBFBBBLRR
FFBFFFBLRL
FBFBBFBRLL
FBBBBFBLLR
FFBFBFBLRL
FBFBBBFLRR
FFBBBBBLRR
FFBFFFBLLR
BBFFFBBRLL
BBFFBBFLLL
FFFBBFBLRL
FBBBFBFRRR
BBFBBBBRRR
FBBBFFBLLR
FBBBBFBLRL
FBFBFFFRRL
FBBFFFFLRR
BFFFBFBLRL
BFFBFFBRLL
BFBFFFBLRL
FBFBFBFRLL
BBFBFBFLLL
FBBBBBFRRL
BFFBFFFRLL
FBBBFBBRRL
BFBBFFBRLR
FFBFBFFLLL
FFBBBBBLLR
FFBFBFBRRL
FFFBFFBLRL
BBFFFBFLRL
FBFBFBBRRL
BFFBFFBRRL
BBFBFBBLRL
BBFBFBFRRR
FBFFBBFRLR
FBFBBFBLRR
FBBFFFFLLL
FFFBFFFLRR
FFFBBBBRRR
BBFFFBBRLR
FFBFFFFRLL
FBFFBFBRLR
FBFBFBBRLL
FBBBBFFLRR
FBBFBFBRLL
FBBBFBFLRL
BBFBBBFLLR
FFBFBBBLLR
BFFBBBFRRR
FFBBFBFLLL
BFBBBFBRLR
FFBFBBBRLL
FFBFBFFLRR
FBFBFBBLLL
BFBBBBFLLR
FFBBFBFRRR
FBFBFBBLRR
BFFFBFBLLR
BFFBFBFRRL
FFFBBBFRLR
FFFBBFFRRL
FFFBBBFLRL
FFFFBBFLLL
BBBFFFBLRR
FBFFFFBRRR
FFFFBBFRRL
FBFBBFFRLR
BFFBBBBLRL
FBFFFFBLRR
FFFBBFBLRR
FFFFBBFRLL
FFFBBFBRRR
FBFFBBBRRL
BBFFFFFLRL
BBFFBBFRRL
BFFFBBBLLL
FBBBBBBLRR
FBBBFFFRLL
FBFFBFFLRR
FFBFBBFLLL
FFBBBFBRRR
BFFFBFBRRR
BBFFBFBRRL
BFFFBBBRLR
FBFFFBBRRR
BBFBBFBRLL
BBFFBBBRRR
FBFFBFBLLR
FFBFFBBLRR
FBBFBBFLRL
FFBFFBFLLL
FFFBFFFRRL
BBBFFFBRLL
BFBFBBBRRL
FFBFBFBLLR
FFFBBBFRLL
BFFFBBFRRR
BFBBFFFRLR
FBBFFBBRLL
BFBBBBBLRL
BBFBFBFLRL
BFBBBFBLLR
FBBFFBBRRR
BFFFFBBLRR
FBBFBBBLLR
BFBFBFBRLL
BFBFBFBRRR
BFFFFBFRRL
FBFBBFFLLR
FBBFBBFRRL
BBFBFBBLLL
BFFBFFBRRR
FBBFBFBLRR
BFFBBFBLLR
BFBFBBBRLL
FBFFBBBLRR
BBFFBFBLRR
BBFFFFFRLR
BBBFFBBLLR
BBFBBFFRRR
BBFFFBBLLR
BFFBFFBRLR
FBFFBFFLLL
BFBBFFFRLL
FFFBFBBRLL
FBFBFBBLRL
FFFBBBFRRL
BFBFBBFRLR
BBFFFFFRRL
FBBFBFFLLR
BFFFBBFLRR
BBFBBFBRRR
BBFFBBBLRR
FBFBBFFRRR
BFFFBFFRLR
FFBBFBFLLR
FBFBFFBLRR
FBFFBFBLRL
FFBFBFBRLR
FBBFBBBRRL
FFBBFFFRLR
FFFBFBBRRR
FBBFBFFRLL
FFBFBFFRLL
FFBFBBBLRR
FFBBBFFLLR
BFBFFFFLRR
FFBBBFBLRL
BBFFFBBRRL
FFBFFBFRRL
FFBBBFBRLR
BFBFFBFLLL
BBFBBBFRLR
BFBFFBFRLR
FFBBBBBLRL
FFFBBFFLLL
BBFFBFFRRL
BFBBFBBLRL
BFFBFFFLRR
BBBFFFFLRL
BFBFFBBRLL
FBBBFFBLLL
FBBFFBBLLL
BBFFFFFLLR
FFBBFFBLRR
BFBBFBFLRR
BBFFFFFLRR
BFFBFBFLLR
FBFBBBBLLL
FBBBFFBRLR
FBBBFBBLLR
BFBFBBBLRL
BFFFBFBRLR
FBBFFBFRRR
BFFFBBFLLL
FFBFFFBRLR
FFBFFFBRRR
FFFBFFBRLR
BBFBFFFRLL
BFBFFBFRRL
BFBFBBFRRL
FBBBBBFLRR
BFFBBBBLRR
FFBFFBFLRL
BFBFBBFLRL
BFFFFFFLLR
FBFFBBBRRR
BFBFFBBRLR
FBBFBFFRLR
BFFBBBFLLR
BFBFFFBLLR
FFBFFFFRRL
FFFBBBBLRR
FFFBBFBLLL
BFFBFBBLLR
FBFFBFBLRR
FFFBBBBRLL
BBBFFFBRLR
BFBBFFFLLL
BFBBBFFLLR
BFBFBFFRRR
BFFFFBFLLR
FBBBBFBRLR
BFFBBBBRRL
FBFBFBFRLR
FFBFBBFRRL
BFFFBBFLLR
FFBBBFBLLL
FFBFBBFLRR
BFFFFBFLLL
FBBBBBFRLR
BBFBBBFLLL
FBFBBFBRRL
FFBBFBFRLL
BFBFFFFRRR
FBFFFFFRLR
FFBBFFBLRL
BBFBBBBLRL
FBBFFBFLRL
BFFFBFBLRR
FBFFFBBRRL
BBFBFFBRLR
FFBBFBBLRL
FBBBBFFLRL
BFFFFBBRLR
FBFFBBFLRR
FFBFBFFRRR
FFBBFBFLRR
BFFBFFFRRL
FBBFFBFRLR
FBBFBFBLLR
BFBFFBBRRL
FBFFFBFLRR
FBFBBFBLRL
BFFFFBFRLL
BFBFBBBRRR
FFFBFFFLLR
FBBBFFFLRR
FFBFBBFLRL
BFFFFBBLRL
BBFFBFFLRR
FBBFFFFRRR
FFFBFBBLRL
BFFFBFFLRR
BFBBFBFLRL
FBFFBFBRRL
BFBFFFFLRL
FBBFFFBRRR
FFBBFFBRLL
FFBFFBFRLL
BBFBFBBLLR
BFBFBFFLLR
BFFFBBBRRL
BBFBFFFLLR
FBFBFFFLRL
BFFBBFFRRR
BFFBFBBRLR
BBBFFBFLRL
BBFBFFBLRR
BBFBFFFLLL
FFBBBBFLLL
BFBBFBBRRR
BBFFFFBRRL
FFBFFBBRLL
FBBFFFBLRR
FFFFBBBLRL
FFBFBFFLRL
FBBBBFBRRR
BFFBBFBRRR
BFFFBBBLLR
BFFBFBFRLR
BFFBBBFRLL
FFFFBBBLRR
BFBFBBBRLR
BFBFBFFRLL
FFBBFFFRRL
FBBFFBFRRL
BBFFBBFRLL
FBBFFBBRLR
BFBBFFFRRR
BFBBFFBRRL
FBFFFBBRLL
FBBBBBBRRL
FBFFFFBRLR
BFBBFFBLLR
BBFBFFBRRL
BFFBBFFLLR
BFFFFBBRLL
BBFFBFBLLL
FBBFFFFRLR
FBBFFBFLRR
BFFBBFFRLL
BFBBFBBLLL
FBFBFBFLLR
BFFFBBBLRR
BFBFBFBLRL
BBBFFFFRRR
FFBFBFBRLL
FBFFBFFRRR
FFBFFFBRLL
FBBFBBFRRR
FFFBBBFRRR
FBFFBFFRRL
FFBBFFBRRL
FBBBFFFLLR
BBFBBFBRRL
BBFBFFFRRL
FFFBBBBLRL
FBBBFFFRRL
BFBBFFBLRL
FBFFFFFLRR
FBFFBBFLRL
BBFFBBBRRL
BBBFFBBLLL
FBFFBBBRLL
BBBFFFFRLL
FFBBBFFRLR
BBFFFFBRLL
FBFFFBBLLR
BFFBFBFRRR
FBFFBBBLLL
FBFBBBFRLL
BFFFFFBLRR
BFFBBFFLRL
FFBBFBBRRR
FBFFBFFLLR
BFFBBBBLLR
BFFFFFFRRR
BBFBBBFRRR
BBFFFFBLRR
BFFBBFBLLL
FFBBFFBLLL
BBBFFFFRRL
FBBFBBFLRR
FBBFFFBRLR
FBFBBFFLRL
FBFBFFFRLL
FBBFFBBLRL
BFFBBBBRRR
FFFFBBFLLR
BBFFBBBRLR
BFFFFFFRLL
FBBBBBBLLR
BBFFFBBLRR
BFFFFFBLLL
FBBBBFFLLR
BBFBFFFRRR
FBFBFFBLLL
FBFFFFBLLL
FFBFFBFRLR
BFBFFBBLLL
BFFBBFFLRR
FBBBBBFLLL
FFBBBFBLRR
BFFFFFBRLR
BBFBFBBRRL
BBFFFFBRRR
FFFBFBFLRL
FBFBBBBLRR
BFBFFBBRRR
FFBFFFFLLL
BFBFFBFLLR
FBBFBBBRLR
FFFBFFFRLL
FFFBFBFRLR
FFBBBFFLRL
BFFBBBBRLR
FBFFBBFLLL
FFFBBFFLRR
BBFBFBFLLR
FFBBFBFLRL
BBFFBBBLRL
BBFFFFBLLR
FFBFFFBLRR
BFBBFBFLLR
BFBBBBBLLL
BBFBBFBLRL
BBFBFFFRLR
BFFBFFFLLL
BBFBFFBRRR
FBFBBBFRRR
FBBBBFFRLL
BFFBBFBLRL
BBFBFFBLRL
BFBBFFBRRR
BBBFFFFLLL
BFBFFFFRRL
FBFFFFFRRR
BFFFFBBLLL
BFBBFFBRLL
FFBBBBBRLL
BFFBFBBRRR
BFBBFFFLLR
BFBBFBBLLR
FBBBBFBRRL
FBFBFBFLRL
BFBBBBFRLL
FFFBFFBLLL
BFFBFFFLLR
BFBBBFBRLL
FFFBBFBRRL
FFBFBFBRRR
FFFBFBBLLR
BFBBBFBRRR
FBBFBBFRLL
BFBBFBBRRL
BFBBBBFRLR
FFFBBBBLLL
BBFFFBBLLL
FFBBBBFLRL
BFBBBBBRLL
FBBFFBFRLL
FBFFFBBLRL
FBBFBFFRRR
FFFBFBFLLR
FFBBBFFRRL
FBBBFBBRLR
BBFBFFFLRR
FBFBBFFLLL
BBFFBFFRLR
BBFBFFFLRL
FBBBBFFRRR
FFBBBFBLLR
BBBFFFBRRL
FBFBFFFLLR
BBFBFFBLLL
FFFBBFBRLR
FBFFFBFLRL
BFFBFBBLLL
BBFBFBBRLL
FBFFBBFRRL
BFBFFFFRLL
BBBFFBBLRL
FFFBFFBLLR
BFFBFBBRLL
FFBFBFBLRR
BBFBFBFRRL
FBBBFBFRRL
FFFBBBBLLR
FBBBFBBRLL
BFBFBBFLRR
BFFFFFFLLL
FFFBFFFRLR
BFBBBFFRLR
BFFFFFBRLL
FBFFFFFLLR
FBBBFFBRLL
FBBFFBFLLR
BFFBFFBLRR
FBFBBBFLLL
FBFFFFFRRL
BBFFFFBLRL
BFBFFFFRLR
FBBFFFFRRL
BFFBBBBLLL
FFFFBBBRRR
FFBBFBBLRR
FBBFFBFLLL
BFFFFBBRRL
FFBBBBFRRL
BFFFFBFLRR
BFFFBBFRRL
BFBBBFFRRL
BFFFBFFRRR
FBFBBBBRRR
FBFFBFFLRL
FBBBBBFLLR
BFBFBBFLLR
BBBFFBFRRR
BFBBFFBLRR
FBBFBFFRRL
BBFBBFBLLL
BFBBFFBLLL
FFBBBFBRRL
BFBFBFBLLL
BFFBFBFRLL
BBFFBBBLLR
FFFBFBFLLL
FFBBBBFLLR
FFFBFBFRRL
BFBFFFBRRR
FFBFBBFRLL
FFFBBBFLLR
FBBFBFBLLL
BBFFFFFRRR
FFFBFFFRRR
BFFFBBBRRR
FFBFFFFLRL
FFFBFFBLRR
FFBBFBFRLR
FBBFBBBLRR
BFFBBFBRLL
BBFFFBBRRR
FFFFBBFRLR
FBBFBFBRRL
FBFBFFBLLR
FBFBFBBLLR
BFBFBBFRRR
BBFFBFBLLR
FFBBBFFLLL
BBFFBFBRLL
BFFFBBFLRL
BFBFBFFRLR
BFBFFFFLLL
FFBBBFFRRR
BBFBFFBLLR
BFBBBBFLRR
BFFBFBBLRL
FFBBFFFRLL
FFBFFFFLLR
BFBFFFBRRL
BFBFBFFLRL
BFFFFFFLRR
BBFBBFFLRL
FBFFFFBRLL
BBFFBFBRLR
FBBBFFFLLL
FFFBBBFLLL
BFFBFFFRRR
BBFBBBBLLL
BBFFFBFRLR
FBFBFFFRRR
FFFBBFFRLR
BFFBFFBLLR
BBFFBFBLRL
BFBFBFBLLR
FBFFFBFRLL
BBFBBBFRLL
BFBBBBBRLR
BFBFFFBRLR
FFFBBBFLRR
BFBFFBFLRL
BBFBBBBLRR
BFBFBBFRLL
FFFFBBBRLL
BFBBBBBLRR
FBFBBBBRLL
BFBBFBFRRL
BBFFFFBRLR
FBBBFBFRLR
BFBFFBFRRR
FBFBBBBLRL
BFBFBBBLLR
FFBFFFFLRR
FBFBBBFRRL
FBFBFBFRRR
BFFFFFFRLR
FBBBBFFRRL
BFFFFFBRRL
BBBFFFFRLR
FBBBFFBLRL
FBBBFFFLRL
FFFBFFBRLL
BFFFFFFRRL
BBBFFFBLLR

128
d05/main.go Normal file
View File

@ -0,0 +1,128 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"sort"
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
type seat struct {
row, column, id int
}
func paritionSearch(partitions string, start, end float64, lower, upper string) (int, error) {
if start == end {
return int(start), nil
}
if partitions == "" {
return 0, fmt.Errorf("empty partitions are invalid")
}
if start > end {
return 0, fmt.Errorf("start cannot be greater than end")
}
if lower == "" || upper == "" {
return 0, fmt.Errorf("invalid upper and lower bounds")
}
mid := (end - start) / 2.0
direction := string(partitions[0])
switch direction {
case lower:
return paritionSearch(partitions[1:], start, mid+start-.5, lower, upper)
case upper:
return paritionSearch(partitions[1:], mid+start+.5, end, lower, upper)
}
return 0, fmt.Errorf("unknown direction %s", direction)
}
func parseSeat(code string) (seat, error) {
totalRows, totalCols := 128, 8
if len(code) != 10 {
return seat{}, fmt.Errorf("invalid code length %s", code)
}
row, err := paritionSearch(code[:7], 0.0, float64(totalRows-1), "F", "B")
if err != nil {
return seat{}, err
}
col, err := paritionSearch(code[7:], 0.0, float64(totalCols-1), "L", "R")
if err != nil {
return seat{}, err
}
return seat{
row: row,
column: col,
id: row*8 + col,
}, nil
}
func part1() {
max := -1
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
s, err := parseSeat(line)
if err != nil {
return
}
if s.id > max {
max = s.id
}
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Max id is %d\n", max)
}
func part2() {
seatIds := []int{}
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
s, err := parseSeat(line)
if err != nil {
return
}
seatIds = append(seatIds, s.id)
return
})
if err != nil {
log.Fatal(err)
}
sort.Ints(seatIds)
lastID := -3
for _, id := range seatIds {
if id == lastID+2 {
fmt.Printf("Found my seat! %d", lastID+1)
break
}
lastID = id
}
}
func main() {
part1()
part2()
}

65
d05/main.py Executable file
View File

@ -0,0 +1,65 @@
#! /usr/bin/env python3
from collections import namedtuple
Seat = namedtuple("Seat", ["row", "column", "id"])
def partition_search(partitions, start, end, lower, upper):
if start == end:
return start
assert partitions
assert start < end
assert all((lower, upper))
# print(f"Searching: range {start}:{end} {partitions[0]}")
mid = (end - start) / 2
direction = partitions.pop(0)
if direction == lower:
return partition_search(partitions, start, start + mid - .5, lower, upper)
elif direction == upper:
return partition_search(partitions, start + mid + .5, end, lower, upper)
raise ValueError(f"Unknown direction {direction}")
def parse_seat(code, total_rows=128, total_cols=8):
if len(code) != 10:
raise ValueError(f"Invalid code length: {code}")
row_partitions = list(code[:7])
row = partition_search(row_partitions, 0, total_rows-1, "F", "B")
col_partitions = list(code[7:])
col = partition_search(col_partitions, 0, total_cols-1, "L", "R")
return Seat(int(row), int(col), int(row*8+col))
def part1():
with open("input.txt") as f:
max_seat = max((parse_seat(line.strip()).id
for line in f))
print(f"Max seat id: {max_seat}")
def part2():
seats = []
with open("input.txt") as f:
seats = list(sorted((parse_seat(line.strip()).id
for line in f)))
last_id = None
for id in seats:
# print("Seat:", id)
if last_id is None:
last_id = id
continue
if id == last_id + 2:
print(f"My seat: {last_id+1}")
return
last_id = id
else:
print("Didn't find seat")
if __name__ == "__main__":
# print(parse_seat("FBFBBFFRLR"))
part1()
part2()

2199
d06/input.txt Normal file

File diff suppressed because it is too large Load Diff

141
d06/main.go Normal file
View File

@ -0,0 +1,141 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func processGroups(path string, f func([]string) (stop bool, err error)) error {
group := []string{}
if err := processLines(path, func(line string) (stop bool, err error) {
if strings.HasPrefix(line, "mask") {
stop, err = f(group)
if stop || err != nil {
return
}
group = []string{}
} else {
group = append(group, line)
}
return
}); err != nil {
return err
}
_, err := f(group)
return err
}
// StringSet is a set of strings
type StringSet struct {
d map[string]bool
}
// Add an item to a StringSet
func (s *StringSet) Add(v string) {
s.d[v] = true
}
// Len gives the length of a StringSet
func (s StringSet) Len() int {
return len(s.d)
}
// NewStringSet creates an empty string set
func NewStringSet() StringSet {
return StringSet{map[string]bool{}}
}
// Union returns the union of two SringSets
func Union(s1, s2 StringSet) StringSet {
union := NewStringSet()
for v := range s1.d {
union.Add(v)
}
for v := range s2.d {
union.Add(v)
}
return union
}
// Intersection returns the union of two SringSets
func Intersection(s1, s2 StringSet) StringSet {
intersect := NewStringSet()
for v := range s1.d {
if _, ok := s2.d[v]; ok {
intersect.Add(v)
}
}
return intersect
}
func part1() {
total := 0
err := processGroups("input.txt", func(group []string) (stop bool, err error) {
questions := NewStringSet()
for _, person := range group {
for _, q := range person {
questions.Add(string(q))
}
}
total += questions.Len()
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Part 1 answer %d\n", total)
}
func part2() {
total := 0
err := processGroups("input.txt", func(group []string) (stop bool, err error) {
result := NewStringSet()
for _, q := range group[0] {
result.Add(string(q))
}
for _, person := range group[1:] {
questions := NewStringSet()
for _, q := range person {
questions.Add(string(q))
}
result = Intersection(result, questions)
}
total += result.Len()
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Part 2 answer %d\n", total)
}
func main() {
part1()
part2()
}

43
d06/main.py Executable file
View File

@ -0,0 +1,43 @@
#! /usr/bin/env python3
def iter_groups():
group_responses = []
with open("input.txt") as f:
for line in f:
line = line.strip()
if line == "":
# Group divider
yield group_responses
group_responses = []
else:
group_responses.append(line)
else:
if group_responses:
yield group_responses
def part1():
total = 0
for group in iter_groups():
questions = set()
for person in group:
for question in person:
questions.add(question)
total += len(questions)
print("Total", total)
def part2():
total = 0
for group in iter_groups():
result = set(group[0])
for person in group[1:]:
result = result & set(person)
total += len(result)
print("Total", total)
if __name__ == "__main__":
part1()
part2()

594
d07/input.txt Normal file
View File

@ -0,0 +1,594 @@
striped green bags contain 5 posh indigo bags.
light yellow bags contain 3 wavy turquoise bags.
bright lime bags contain 2 striped crimson bags, 3 dull red bags.
dull blue bags contain 4 posh coral bags, 3 mirrored coral bags, 2 striped fuchsia bags.
vibrant coral bags contain 2 shiny blue bags, 2 muted gray bags.
mirrored gold bags contain 2 dotted maroon bags.
drab lavender bags contain 4 pale turquoise bags, 5 faded lime bags, 2 bright aqua bags.
mirrored red bags contain 4 shiny tan bags, 4 muted aqua bags, 4 pale salmon bags, 5 bright violet bags.
clear gray bags contain 4 bright lavender bags, 2 dotted plum bags, 1 drab coral bag, 3 faded aqua bags.
dull aqua bags contain 2 wavy coral bags.
muted yellow bags contain 3 drab olive bags, 4 pale lime bags, 2 striped crimson bags, 3 wavy blue bags.
shiny chartreuse bags contain 5 bright yellow bags.
posh turquoise bags contain 3 dotted blue bags, 4 pale lime bags, 1 mirrored fuchsia bag.
faded maroon bags contain 5 striped indigo bags, 2 light aqua bags, 3 dim chartreuse bags, 4 vibrant tomato bags.
dotted lavender bags contain 3 pale crimson bags, 3 wavy gray bags, 2 plaid plum bags, 5 mirrored bronze bags.
striped olive bags contain 5 dull lime bags.
vibrant aqua bags contain 3 drab tan bags, 5 bright coral bags, 3 pale brown bags.
wavy aqua bags contain 4 dim lime bags, 4 dotted bronze bags, 1 bright gray bag.
pale green bags contain 1 shiny purple bag, 4 dim plum bags.
vibrant purple bags contain 2 pale gray bags, 2 dull crimson bags.
faded green bags contain 4 dotted plum bags, 1 light white bag.
posh orange bags contain 4 light blue bags.
drab tomato bags contain 1 dull salmon bag, 3 plaid orange bags, 3 posh gray bags.
vibrant beige bags contain 2 dull fuchsia bags.
wavy orange bags contain 2 bright tan bags, 5 light beige bags, 2 vibrant turquoise bags.
light salmon bags contain 1 dark blue bag, 2 bright orange bags.
light blue bags contain 3 clear chartreuse bags, 5 dull olive bags.
dull crimson bags contain 4 dim gold bags, 5 dark tan bags, 5 dark lavender bags.
dim teal bags contain 3 striped gray bags, 4 shiny fuchsia bags, 2 vibrant chartreuse bags, 2 drab plum bags.
striped crimson bags contain no other bags.
dark brown bags contain 1 dim plum bag.
dotted tan bags contain 1 striped fuchsia bag.
bright turquoise bags contain 3 light orange bags, 2 wavy bronze bags, 2 light beige bags.
drab salmon bags contain 4 wavy silver bags.
light brown bags contain 1 clear gold bag.
plaid aqua bags contain 4 shiny maroon bags, 2 mirrored gray bags.
posh chartreuse bags contain 3 clear maroon bags, 4 wavy black bags, 3 vibrant white bags.
wavy gray bags contain 3 shiny violet bags, 2 striped silver bags, 5 pale lime bags.
dim crimson bags contain 1 wavy blue bag, 1 dull red bag, 1 dotted plum bag.
wavy black bags contain 5 dim crimson bags, 5 dotted chartreuse bags.
faded gray bags contain 4 plaid white bags, 2 mirrored yellow bags.
muted violet bags contain 5 vibrant blue bags, 5 shiny beige bags.
dull white bags contain 1 dull olive bag, 5 clear chartreuse bags, 1 dull red bag, 1 wavy red bag.
light bronze bags contain 4 bright gray bags, 3 light tomato bags, 2 shiny white bags, 2 clear silver bags.
plaid violet bags contain 2 vibrant indigo bags, 2 dim turquoise bags.
posh purple bags contain 5 wavy purple bags.
bright olive bags contain 4 muted bronze bags, 4 mirrored green bags, 2 dim plum bags, 5 bright silver bags.
vibrant olive bags contain 1 vibrant beige bag, 4 striped gold bags, 4 shiny beige bags, 1 faded blue bag.
muted fuchsia bags contain 3 vibrant red bags.
plaid indigo bags contain 4 dull lime bags, 3 faded violet bags.
wavy chartreuse bags contain 3 dotted yellow bags.
posh magenta bags contain 4 bright gray bags, 4 dotted turquoise bags.
drab teal bags contain 5 dotted plum bags, 2 light white bags, 2 dark plum bags, 4 dim crimson bags.
dark coral bags contain 3 wavy chartreuse bags, 3 plaid bronze bags, 1 muted magenta bag.
posh white bags contain 4 dotted turquoise bags, 1 mirrored lime bag.
mirrored brown bags contain 2 shiny chartreuse bags, 1 light bronze bag, 4 bright bronze bags, 5 dotted crimson bags.
faded cyan bags contain 2 dull crimson bags, 4 light chartreuse bags, 4 light salmon bags.
bright maroon bags contain 3 dotted yellow bags, 1 bright gray bag, 2 dim yellow bags, 5 light fuchsia bags.
clear silver bags contain 4 faded green bags, 4 posh white bags, 4 dark plum bags.
shiny crimson bags contain 4 dark lavender bags, 3 dotted gold bags, 3 dark tan bags.
wavy olive bags contain 4 dotted cyan bags.
wavy coral bags contain 3 dim gold bags, 4 dim silver bags, 4 faded green bags, 2 muted purple bags.
striped chartreuse bags contain 4 mirrored plum bags, 4 dull tan bags, 5 muted gold bags.
bright blue bags contain 5 mirrored beige bags, 4 muted bronze bags, 1 dark tan bag, 5 dark cyan bags.
vibrant red bags contain 3 light chartreuse bags, 2 faded indigo bags, 3 drab teal bags, 1 striped indigo bag.
dim cyan bags contain 5 faded silver bags, 3 wavy coral bags.
muted gold bags contain 4 pale coral bags.
wavy violet bags contain 2 dotted gray bags, 1 clear tan bag, 5 plaid brown bags.
light maroon bags contain 5 faded silver bags.
light cyan bags contain 5 pale brown bags, 3 pale black bags, 3 light tomato bags, 2 faded violet bags.
pale turquoise bags contain 1 dull white bag, 1 muted tomato bag, 2 clear gold bags.
clear plum bags contain 2 dotted orange bags, 1 bright olive bag, 3 striped violet bags.
plaid silver bags contain 5 muted olive bags, 1 vibrant bronze bag, 5 dull lavender bags, 3 dark purple bags.
clear gold bags contain 1 dotted turquoise bag, 3 dark indigo bags.
muted indigo bags contain 1 mirrored orange bag, 3 dull beige bags.
light plum bags contain 3 drab brown bags, 4 wavy cyan bags, 3 vibrant lavender bags.
dim maroon bags contain 4 dull tan bags.
pale lime bags contain 4 dotted maroon bags, 2 faded silver bags, 5 shiny tomato bags.
shiny black bags contain 2 dull crimson bags.
wavy indigo bags contain 1 light fuchsia bag.
dull lime bags contain no other bags.
shiny fuchsia bags contain 2 drab fuchsia bags, 1 shiny cyan bag, 1 muted black bag, 2 dull aqua bags.
muted lavender bags contain 4 dull fuchsia bags, 1 dim chartreuse bag, 1 vibrant gold bag, 2 shiny beige bags.
bright cyan bags contain 5 dark gold bags, 2 vibrant cyan bags, 1 pale coral bag.
posh black bags contain 3 dull violet bags, 5 drab coral bags.
posh olive bags contain 3 muted magenta bags, 3 dark plum bags, 1 shiny violet bag.
dull coral bags contain 1 dark gold bag, 2 striped silver bags, 5 vibrant lavender bags, 2 light red bags.
clear bronze bags contain 4 striped cyan bags, 4 dotted chartreuse bags, 4 shiny maroon bags.
bright red bags contain 2 dark violet bags, 4 pale brown bags.
muted silver bags contain 3 bright blue bags, 1 shiny blue bag, 5 muted bronze bags, 1 bright tan bag.
dotted maroon bags contain 5 muted white bags, 4 dull lime bags, 2 dim gold bags, 2 faded fuchsia bags.
clear lime bags contain 4 striped gold bags, 2 vibrant purple bags, 5 dotted green bags, 2 light tomato bags.
shiny tan bags contain 5 dark lavender bags, 1 dull red bag, 4 vibrant turquoise bags, 5 faded fuchsia bags.
dark teal bags contain 2 dotted brown bags, 5 clear salmon bags, 5 wavy coral bags, 3 light fuchsia bags.
shiny cyan bags contain 1 mirrored gold bag, 1 mirrored aqua bag, 1 posh magenta bag.
pale red bags contain 1 vibrant turquoise bag.
drab coral bags contain 2 faded tomato bags, 3 plaid aqua bags.
clear white bags contain 1 dull white bag, 5 shiny tan bags, 1 mirrored yellow bag, 1 wavy chartreuse bag.
clear crimson bags contain 5 muted white bags, 1 vibrant yellow bag.
posh lavender bags contain 2 mirrored aqua bags, 4 faded aqua bags, 2 light red bags.
dim violet bags contain 4 dull orange bags, 5 dull turquoise bags, 5 dark purple bags.
pale beige bags contain 3 wavy indigo bags, 5 dark plum bags, 2 dark purple bags, 2 dim turquoise bags.
striped brown bags contain 4 bright lime bags, 5 wavy coral bags.
shiny blue bags contain 2 wavy coral bags, 2 dotted plum bags.
pale black bags contain 5 clear maroon bags, 4 striped crimson bags, 4 dark gold bags.
drab plum bags contain 3 clear gold bags.
posh beige bags contain 3 faded silver bags, 3 dim gold bags, 5 shiny gold bags.
clear lavender bags contain 1 clear white bag.
light lavender bags contain 4 dotted violet bags, 3 dull violet bags, 4 dark maroon bags, 2 striped violet bags.
plaid brown bags contain 4 dotted yellow bags.
dotted green bags contain 3 dull red bags, 2 faded green bags, 3 muted white bags, 1 dim turquoise bag.
muted olive bags contain 4 vibrant tan bags, 3 dotted black bags.
light turquoise bags contain 3 wavy blue bags, 4 dim plum bags, 4 dim chartreuse bags.
dim salmon bags contain 2 mirrored yellow bags.
shiny white bags contain 1 mirrored violet bag.
drab olive bags contain 3 striped crimson bags, 3 dotted maroon bags.
drab silver bags contain 5 shiny cyan bags, 1 dull teal bag, 4 dark lime bags.
vibrant turquoise bags contain 4 striped crimson bags, 5 dark plum bags, 3 dark lavender bags, 5 dark purple bags.
shiny purple bags contain 1 posh beige bag, 1 dark indigo bag, 4 plaid fuchsia bags, 5 dotted green bags.
bright brown bags contain 1 striped lavender bag, 5 light gold bags, 1 dim maroon bag.
dotted violet bags contain 3 striped blue bags.
bright crimson bags contain 2 muted gold bags, 3 vibrant turquoise bags, 3 wavy green bags, 5 dull white bags.
striped tan bags contain 2 wavy gray bags, 4 bright gray bags, 1 plaid cyan bag, 1 vibrant magenta bag.
dull green bags contain 1 bright brown bag, 5 posh beige bags, 5 mirrored crimson bags, 1 dark silver bag.
mirrored lime bags contain 4 muted tomato bags, 5 wavy chartreuse bags, 5 dotted plum bags.
striped beige bags contain 2 striped bronze bags, 2 shiny yellow bags, 4 pale gray bags, 2 vibrant tomato bags.
vibrant lime bags contain 4 striped crimson bags, 2 pale silver bags, 4 clear purple bags.
pale blue bags contain 1 bright cyan bag, 1 shiny fuchsia bag, 5 wavy turquoise bags, 5 dotted silver bags.
striped maroon bags contain 1 muted lime bag.
faded chartreuse bags contain 2 mirrored white bags.
mirrored crimson bags contain 2 dotted gold bags, 5 shiny red bags, 5 wavy red bags.
dull beige bags contain 2 posh red bags, 1 vibrant turquoise bag, 5 dark plum bags, 5 clear aqua bags.
wavy green bags contain 3 shiny crimson bags.
striped salmon bags contain 2 dim plum bags, 2 mirrored indigo bags.
faded coral bags contain 3 muted tomato bags, 1 light chartreuse bag.
dark blue bags contain 2 shiny violet bags.
shiny gold bags contain 1 dull lime bag, 2 pale coral bags, 1 wavy silver bag, 5 muted black bags.
clear turquoise bags contain 1 posh magenta bag.
dotted salmon bags contain 2 mirrored lime bags, 1 mirrored salmon bag.
pale gray bags contain 3 bright blue bags, 5 muted tan bags.
shiny teal bags contain 5 pale indigo bags.
drab beige bags contain 5 faded indigo bags, 5 vibrant bronze bags, 4 pale lime bags, 3 dark black bags.
vibrant white bags contain 5 striped violet bags, 3 bright blue bags, 2 dim gold bags.
posh aqua bags contain 5 plaid violet bags, 3 drab chartreuse bags.
plaid gray bags contain 5 dotted cyan bags, 2 mirrored silver bags.
clear indigo bags contain 1 bright tan bag, 2 dull yellow bags, 5 mirrored lavender bags, 2 mirrored fuchsia bags.
mirrored turquoise bags contain 3 faded chartreuse bags, 2 drab turquoise bags.
dark chartreuse bags contain 2 mirrored silver bags, 3 vibrant crimson bags, 4 shiny green bags, 1 pale brown bag.
pale tomato bags contain 2 light gold bags.
mirrored purple bags contain 1 light magenta bag, 3 shiny yellow bags, 4 striped lavender bags.
mirrored blue bags contain 3 posh magenta bags, 4 dark lavender bags, 5 striped crimson bags.
dull purple bags contain 4 mirrored indigo bags, 2 wavy bronze bags, 4 muted white bags, 4 shiny crimson bags.
mirrored teal bags contain 5 dim teal bags, 4 dark lime bags, 4 mirrored yellow bags, 3 mirrored turquoise bags.
drab gold bags contain 3 dark maroon bags, 2 plaid beige bags.
dotted gold bags contain 2 striped crimson bags, 3 clear red bags.
posh fuchsia bags contain 4 dim cyan bags, 4 vibrant turquoise bags, 4 dotted plum bags.
dim lime bags contain 4 posh indigo bags.
dim tan bags contain 3 pale indigo bags, 1 striped turquoise bag, 4 plaid coral bags.
plaid red bags contain 5 wavy gold bags, 1 muted plum bag, 2 vibrant plum bags, 1 dim brown bag.
light orange bags contain 4 dotted teal bags, 4 dotted yellow bags.
dark green bags contain 1 dull cyan bag.
posh coral bags contain 3 shiny green bags, 3 dotted red bags, 1 drab silver bag.
striped orange bags contain 3 plaid plum bags.
pale purple bags contain 1 vibrant coral bag, 2 shiny olive bags, 1 clear orange bag.
bright fuchsia bags contain 3 bright yellow bags.
striped red bags contain 2 bright orange bags, 3 mirrored yellow bags, 1 dotted coral bag, 3 clear aqua bags.
faded plum bags contain 2 shiny tan bags, 4 dull tan bags.
striped gold bags contain 1 shiny crimson bag.
faded olive bags contain 2 shiny lavender bags, 5 posh fuchsia bags, 3 pale gray bags.
pale aqua bags contain 3 posh beige bags.
dotted plum bags contain 4 clear red bags.
dotted chartreuse bags contain 1 light white bag, 5 drab turquoise bags.
striped tomato bags contain 4 dim plum bags, 1 striped black bag, 4 drab black bags.
shiny lime bags contain 3 drab coral bags, 1 drab green bag, 4 muted salmon bags.
dim orange bags contain 2 striped chartreuse bags.
plaid tan bags contain 5 light chartreuse bags, 1 dotted maroon bag, 2 clear silver bags.
dull olive bags contain 3 muted gold bags, 5 dotted gold bags, 4 muted white bags, 1 shiny violet bag.
dotted beige bags contain 1 clear tan bag.
dotted silver bags contain 2 faded crimson bags.
muted black bags contain 3 clear red bags, 3 dotted maroon bags.
clear purple bags contain 5 dotted plum bags.
striped indigo bags contain 5 mirrored blue bags, 2 striped violet bags, 3 striped yellow bags.
faded teal bags contain 2 light black bags, 1 vibrant maroon bag.
drab red bags contain 3 dark tan bags, 4 pale red bags, 5 faded salmon bags, 3 dotted tomato bags.
muted aqua bags contain 2 striped purple bags, 3 vibrant orange bags, 3 bright cyan bags.
mirrored black bags contain 4 muted yellow bags, 5 light fuchsia bags.
dark gold bags contain 2 dark indigo bags, 3 muted magenta bags, 3 dull white bags.
dotted lime bags contain 4 shiny blue bags, 3 striped fuchsia bags.
posh brown bags contain 2 muted beige bags.
muted green bags contain 5 bright white bags, 5 dim gold bags.
vibrant salmon bags contain 1 pale green bag, 5 light maroon bags, 4 striped violet bags.
drab white bags contain 2 drab fuchsia bags, 4 dull beige bags, 2 pale coral bags, 1 shiny tan bag.
light lime bags contain 4 dotted salmon bags, 5 dark fuchsia bags, 2 vibrant indigo bags.
shiny tomato bags contain 5 wavy green bags, 2 striped blue bags, 3 faded green bags, 3 muted tomato bags.
mirrored aqua bags contain 2 dark gold bags, 2 shiny green bags.
plaid cyan bags contain 5 shiny brown bags, 2 pale aqua bags, 3 striped turquoise bags, 5 plaid yellow bags.
light crimson bags contain 3 bright silver bags, 2 dark lime bags.
dull cyan bags contain 3 pale gray bags, 5 light beige bags, 3 striped blue bags.
muted plum bags contain 2 muted turquoise bags, 5 wavy lavender bags, 3 striped blue bags, 3 striped gray bags.
posh tan bags contain 4 dark brown bags, 1 drab crimson bag.
clear yellow bags contain 3 striped purple bags, 4 faded blue bags.
wavy fuchsia bags contain 2 light beige bags, 3 faded fuchsia bags.
pale gold bags contain 4 faded green bags, 5 clear bronze bags, 5 vibrant aqua bags, 3 muted cyan bags.
shiny gray bags contain 3 plaid chartreuse bags.
bright indigo bags contain 3 drab fuchsia bags.
drab black bags contain 3 shiny brown bags, 3 posh blue bags.
dark crimson bags contain 5 faded olive bags, 1 mirrored green bag.
vibrant silver bags contain 1 dark black bag, 2 drab tan bags.
shiny green bags contain 4 dark plum bags, 4 drab fuchsia bags, 3 dim plum bags, 3 mirrored gold bags.
plaid crimson bags contain 1 dim olive bag, 5 bright brown bags, 5 dull lavender bags.
dark salmon bags contain 2 light gold bags, 4 shiny blue bags.
faded blue bags contain 4 striped crimson bags, 1 muted tomato bag.
wavy magenta bags contain 5 wavy purple bags, 3 bright yellow bags, 3 shiny maroon bags, 1 wavy orange bag.
striped cyan bags contain 1 dotted plum bag, 1 bright coral bag.
faded crimson bags contain 5 pale aqua bags, 3 light blue bags.
muted gray bags contain 3 shiny tomato bags.
striped aqua bags contain 3 dim crimson bags.
wavy salmon bags contain 5 drab bronze bags, 4 light maroon bags.
drab fuchsia bags contain 3 faded black bags, 4 shiny crimson bags, 5 shiny tan bags.
clear black bags contain 4 dark crimson bags, 5 pale lavender bags.
dotted orange bags contain 1 dotted coral bag, 1 shiny gold bag, 3 wavy coral bags.
plaid tomato bags contain 4 wavy orange bags.
dark white bags contain 3 posh cyan bags.
wavy lime bags contain 4 faded silver bags, 3 vibrant gold bags, 3 vibrant coral bags.
faded tomato bags contain 1 striped bronze bag, 4 dotted green bags.
mirrored salmon bags contain 1 faded crimson bag, 3 muted gold bags, 4 clear aqua bags.
drab maroon bags contain 5 clear silver bags, 4 vibrant cyan bags, 5 faded gold bags.
dull violet bags contain 4 shiny tomato bags.
bright orange bags contain 4 bright tan bags.
plaid magenta bags contain 3 light fuchsia bags.
shiny turquoise bags contain 5 muted bronze bags, 4 bright lavender bags, 4 dark tan bags.
pale fuchsia bags contain 4 dull crimson bags, 3 wavy red bags, 5 dark gold bags.
plaid fuchsia bags contain 2 dim cyan bags, 5 bright coral bags.
dark indigo bags contain 3 dotted teal bags, 3 striped blue bags.
vibrant bronze bags contain 4 mirrored plum bags, 5 faded silver bags.
light tomato bags contain 3 posh fuchsia bags, 4 mirrored magenta bags, 1 muted gold bag, 3 dim green bags.
shiny silver bags contain 2 dim yellow bags, 1 wavy coral bag.
bright bronze bags contain 3 plaid coral bags, 2 wavy coral bags, 2 bright gray bags.
plaid turquoise bags contain 3 dim lime bags.
plaid teal bags contain 1 vibrant teal bag, 3 dark indigo bags, 4 plaid fuchsia bags.
striped purple bags contain 2 striped chartreuse bags, 2 clear chartreuse bags, 4 dark cyan bags, 5 striped salmon bags.
pale orange bags contain 5 muted green bags.
light green bags contain 2 plaid plum bags.
plaid purple bags contain 4 muted lime bags.
dark cyan bags contain no other bags.
wavy teal bags contain 5 dull black bags, 3 striped teal bags, 4 dotted cyan bags, 5 vibrant olive bags.
shiny indigo bags contain 3 dull lavender bags.
bright beige bags contain 1 bright bronze bag.
light white bags contain no other bags.
muted red bags contain 3 light tan bags, 4 clear cyan bags.
light coral bags contain 2 dull aqua bags, 1 bright beige bag, 4 wavy maroon bags, 3 posh tan bags.
bright violet bags contain 2 drab beige bags, 3 shiny fuchsia bags, 2 shiny cyan bags, 5 light gray bags.
striped fuchsia bags contain 1 striped black bag, 4 shiny white bags, 3 dim plum bags.
vibrant teal bags contain 1 faded tomato bag, 3 dim gray bags.
striped turquoise bags contain 3 wavy silver bags, 3 bright orange bags, 5 plaid coral bags, 1 clear red bag.
mirrored fuchsia bags contain 1 dotted green bag, 1 plaid cyan bag.
dim green bags contain 1 posh olive bag, 1 dim silver bag.
faded orange bags contain 4 drab beige bags, 1 vibrant salmon bag, 2 plaid orange bags.
bright tomato bags contain 4 dim aqua bags, 2 posh beige bags, 4 striped purple bags.
faded lime bags contain 1 bright tan bag.
mirrored indigo bags contain 4 shiny tan bags, 3 faded blue bags.
vibrant orange bags contain 3 vibrant olive bags, 2 bright olive bags, 3 wavy violet bags.
plaid beige bags contain 2 shiny violet bags, 3 faded violet bags.
muted purple bags contain 3 light beige bags, 3 bright tan bags.
mirrored orange bags contain 5 plaid lime bags, 4 dotted olive bags.
wavy purple bags contain 3 dim chartreuse bags.
wavy blue bags contain 5 striped blue bags, 5 posh olive bags.
dull black bags contain 3 dotted plum bags.
drab bronze bags contain 5 dim olive bags, 3 vibrant gray bags, 3 pale green bags, 1 dull cyan bag.
pale coral bags contain 5 dim gold bags, 1 vibrant bronze bag.
dull orange bags contain 1 shiny turquoise bag.
mirrored gray bags contain 1 mirrored plum bag, 5 dim silver bags.
drab cyan bags contain 1 dark fuchsia bag, 1 striped salmon bag, 4 plaid beige bags, 5 dim olive bags.
dark bronze bags contain 2 pale salmon bags, 5 dull magenta bags, 5 clear indigo bags, 3 wavy plum bags.
dim tomato bags contain 5 striped lavender bags.
faded white bags contain 3 striped lime bags, 4 dotted orange bags.
dull teal bags contain 4 vibrant yellow bags.
clear teal bags contain 4 wavy gold bags.
muted tan bags contain 3 faded green bags.
dim gold bags contain no other bags.
dim turquoise bags contain 3 mirrored plum bags, 3 bright orange bags, 1 muted tan bag.
striped silver bags contain 4 dull lime bags, 5 striped blue bags.
striped yellow bags contain 2 vibrant crimson bags.
striped violet bags contain 1 clear beige bag, 2 dim indigo bags, 3 muted lime bags.
posh cyan bags contain 4 faded blue bags, 2 vibrant magenta bags, 3 dull lime bags, 3 shiny blue bags.
vibrant brown bags contain 5 shiny violet bags.
pale chartreuse bags contain 1 wavy teal bag, 1 muted maroon bag, 5 clear turquoise bags.
vibrant indigo bags contain 5 drab teal bags, 1 bright aqua bag.
bright green bags contain 4 drab silver bags, 5 shiny gold bags.
dim black bags contain 1 faded violet bag.
muted orange bags contain 3 dull yellow bags, 1 vibrant blue bag, 3 plaid tan bags, 2 dotted teal bags.
muted crimson bags contain 4 muted silver bags, 5 shiny lavender bags, 3 posh beige bags, 2 shiny purple bags.
clear tomato bags contain 4 dotted teal bags, 2 vibrant olive bags, 5 plaid magenta bags, 4 bright chartreuse bags.
vibrant fuchsia bags contain 5 dim cyan bags, 4 light white bags, 1 dull orange bag, 5 dark gold bags.
muted magenta bags contain no other bags.
dim brown bags contain 1 striped red bag, 4 posh fuchsia bags, 3 mirrored gold bags.
dim plum bags contain 1 vibrant turquoise bag, 1 clear chartreuse bag, 3 faded brown bags.
plaid gold bags contain 5 drab tomato bags.
wavy tomato bags contain 3 dark gold bags, 1 light orange bag, 4 muted salmon bags, 2 muted olive bags.
pale olive bags contain 2 plaid cyan bags.
wavy plum bags contain 4 faded aqua bags, 5 dull olive bags, 3 bright lavender bags, 2 drab chartreuse bags.
posh tomato bags contain 5 drab blue bags.
dull gray bags contain 5 dull olive bags, 3 mirrored coral bags, 4 striped lavender bags.
posh plum bags contain 5 dull cyan bags, 2 dotted orange bags, 3 plaid indigo bags, 5 light beige bags.
striped plum bags contain 2 drab white bags, 2 mirrored yellow bags, 3 dim crimson bags, 2 pale salmon bags.
light beige bags contain 3 dark cyan bags, 3 striped crimson bags.
dark maroon bags contain 5 light tan bags, 5 faded green bags, 3 striped gold bags, 4 bright aqua bags.
faded brown bags contain 5 dotted gold bags, 3 striped turquoise bags, 4 bright tan bags, 3 clear chartreuse bags.
striped lime bags contain 4 dim gold bags, 5 pale coral bags, 4 mirrored plum bags.
light olive bags contain 1 shiny white bag, 3 dotted plum bags, 3 clear orange bags, 3 posh turquoise bags.
light magenta bags contain 2 shiny turquoise bags.
dotted turquoise bags contain 5 posh olive bags.
dark violet bags contain 1 faded blue bag, 1 shiny green bag.
shiny plum bags contain 2 dotted blue bags, 1 clear gold bag.
striped bronze bags contain 5 dim chartreuse bags, 1 shiny violet bag.
vibrant lavender bags contain 1 faded fuchsia bag, 2 shiny blue bags, 2 dotted plum bags.
dotted crimson bags contain 2 dark cyan bags, 1 dim chartreuse bag, 4 light red bags.
posh blue bags contain 2 bright silver bags, 4 drab beige bags, 2 dim salmon bags.
plaid orange bags contain 3 dark lime bags.
wavy gold bags contain 1 drab olive bag, 1 shiny cyan bag, 3 drab brown bags.
muted lime bags contain 2 dull teal bags.
vibrant magenta bags contain 3 muted gray bags.
posh silver bags contain 4 bright lavender bags, 5 light gold bags, 2 posh beige bags, 2 dull crimson bags.
shiny bronze bags contain 5 pale lavender bags, 3 plaid bronze bags, 3 mirrored blue bags, 4 bright olive bags.
dotted tomato bags contain 2 drab yellow bags.
posh violet bags contain 4 muted fuchsia bags, 1 dark blue bag, 1 shiny indigo bag.
wavy turquoise bags contain 5 shiny yellow bags.
plaid lavender bags contain 3 dim lavender bags, 3 dotted salmon bags.
striped teal bags contain 5 mirrored crimson bags, 1 mirrored violet bag, 1 dark violet bag, 5 dotted yellow bags.
faded black bags contain 5 posh red bags.
faded tan bags contain 1 mirrored violet bag, 4 dark lime bags, 4 dim green bags, 4 muted green bags.
clear brown bags contain 3 pale coral bags, 1 plaid coral bag, 4 pale gray bags.
light violet bags contain 5 dim plum bags, 4 muted violet bags, 3 drab teal bags.
dotted gray bags contain 4 mirrored white bags, 3 vibrant lavender bags, 4 dark lime bags, 5 vibrant coral bags.
faded yellow bags contain 2 plaid bronze bags, 1 dark purple bag, 5 shiny crimson bags, 3 shiny tan bags.
shiny violet bags contain 4 dull lime bags, 4 muted white bags, 2 dark cyan bags.
faded gold bags contain 5 plaid aqua bags.
bright salmon bags contain 2 shiny lavender bags, 5 plaid red bags.
clear violet bags contain 4 posh turquoise bags.
light silver bags contain 1 light salmon bag, 2 clear aqua bags, 4 mirrored plum bags, 2 striped silver bags.
pale cyan bags contain 4 vibrant orange bags, 3 light salmon bags, 4 striped cyan bags, 4 wavy gray bags.
wavy cyan bags contain 3 light orange bags, 1 bright yellow bag, 2 pale fuchsia bags.
clear maroon bags contain 1 dotted coral bag, 4 plaid yellow bags.
striped blue bags contain 5 light white bags, 2 dull lime bags, 1 shiny maroon bag.
clear red bags contain no other bags.
pale tan bags contain 5 light gold bags, 5 dark brown bags, 1 wavy black bag, 5 drab blue bags.
mirrored magenta bags contain 4 dotted plum bags, 3 posh beige bags.
dull maroon bags contain 1 mirrored fuchsia bag.
dim silver bags contain 5 striped crimson bags, 1 light beige bag.
plaid olive bags contain 3 shiny white bags, 2 bright lavender bags.
shiny magenta bags contain 3 dotted gray bags, 1 shiny blue bag, 3 faded silver bags, 2 dark tomato bags.
mirrored green bags contain 4 dim cyan bags, 2 bright tan bags.
faded silver bags contain 1 dark plum bag, 5 dotted plum bags, 1 dark cyan bag, 5 dull red bags.
vibrant cyan bags contain 5 vibrant lavender bags.
shiny brown bags contain 4 striped blue bags, 1 light beige bag, 1 muted tan bag, 5 bright orange bags.
wavy maroon bags contain 3 vibrant white bags, 1 pale red bag, 5 striped yellow bags, 4 plaid bronze bags.
shiny aqua bags contain 5 dotted salmon bags, 5 bright maroon bags, 1 wavy red bag.
clear cyan bags contain 2 striped red bags, 5 plaid coral bags, 2 dark fuchsia bags.
dotted red bags contain 5 dim orange bags, 4 striped tan bags.
vibrant green bags contain 1 dark plum bag.
striped black bags contain 5 dull white bags.
dotted indigo bags contain 2 vibrant orange bags, 5 vibrant lavender bags, 4 shiny bronze bags.
dark tan bags contain 1 muted tan bag.
dotted yellow bags contain 3 dark cyan bags, 2 shiny maroon bags.
dull chartreuse bags contain 4 vibrant red bags, 4 dim salmon bags, 5 drab salmon bags.
shiny beige bags contain 3 dotted yellow bags, 2 muted tomato bags, 4 wavy red bags.
faded indigo bags contain 4 faded green bags.
light chartreuse bags contain 1 mirrored violet bag, 5 striped lavender bags.
dark red bags contain 5 dark green bags, 3 clear beige bags, 5 wavy tan bags, 4 striped cyan bags.
muted blue bags contain 3 dark beige bags, 2 bright lavender bags, 5 dull teal bags.
mirrored olive bags contain 5 dark lavender bags, 1 clear blue bag.
pale yellow bags contain 2 dark chartreuse bags, 4 posh silver bags, 2 dim crimson bags, 3 wavy gold bags.
dull brown bags contain 1 light aqua bag, 2 pale aqua bags, 1 faded red bag, 1 wavy white bag.
clear chartreuse bags contain 2 wavy coral bags.
bright white bags contain 4 light fuchsia bags, 5 drab turquoise bags, 5 striped lime bags.
light gray bags contain 4 mirrored violet bags, 5 dotted maroon bags, 3 pale lime bags.
mirrored cyan bags contain 4 mirrored salmon bags, 2 drab olive bags.
dark orange bags contain 3 vibrant lavender bags.
drab chartreuse bags contain 2 wavy orange bags.
muted white bags contain no other bags.
dull red bags contain 1 faded fuchsia bag, 2 dark purple bags, 4 clear red bags.
shiny red bags contain 2 bright gray bags, 4 drab blue bags, 2 bright aqua bags.
vibrant gold bags contain 3 shiny tan bags, 5 mirrored gold bags.
wavy red bags contain 1 dark plum bag, 3 striped blue bags, 4 light white bags, 1 wavy silver bag.
mirrored coral bags contain 4 dark indigo bags.
mirrored beige bags contain 1 muted white bag.
faded bronze bags contain 5 bright aqua bags, 2 dotted chartreuse bags, 2 faded tomato bags.
bright plum bags contain 3 drab chartreuse bags.
shiny coral bags contain 2 dark yellow bags, 5 dark blue bags, 4 dotted green bags.
mirrored yellow bags contain 1 dotted plum bag.
faded fuchsia bags contain no other bags.
bright magenta bags contain 4 muted orange bags, 3 striped red bags, 5 light bronze bags.
drab aqua bags contain 5 dotted indigo bags, 3 dim gray bags.
faded violet bags contain 2 shiny gold bags.
dull lavender bags contain 1 drab chartreuse bag, 2 shiny plum bags, 4 vibrant tan bags, 5 dark tomato bags.
shiny lavender bags contain 2 light fuchsia bags.
dotted brown bags contain 5 shiny brown bags, 4 light fuchsia bags, 3 plaid cyan bags.
dark olive bags contain 2 wavy red bags, 5 striped lavender bags, 4 vibrant lavender bags, 2 shiny gold bags.
dotted black bags contain 1 dark lime bag.
faded aqua bags contain 2 dim turquoise bags, 3 muted green bags, 5 clear aqua bags.
plaid yellow bags contain 1 striped turquoise bag, 4 striped lime bags.
pale bronze bags contain 4 muted tan bags, 5 dotted fuchsia bags.
muted coral bags contain 2 striped bronze bags, 1 dark violet bag.
dim indigo bags contain 1 shiny red bag.
drab gray bags contain 3 posh white bags, 2 plaid indigo bags.
pale silver bags contain 1 faded coral bag, 5 shiny lavender bags, 5 wavy lime bags.
wavy silver bags contain 1 vibrant bronze bag.
wavy crimson bags contain 1 mirrored orange bag.
dotted aqua bags contain 4 drab plum bags, 5 faded indigo bags, 3 dark violet bags, 3 pale gray bags.
mirrored violet bags contain 5 mirrored white bags.
dotted white bags contain 3 muted plum bags, 3 bright bronze bags, 2 dark salmon bags.
bright coral bags contain 5 mirrored gray bags.
dim aqua bags contain 3 mirrored plum bags, 3 plaid olive bags, 1 light gold bag.
drab crimson bags contain 5 faded purple bags.
pale crimson bags contain 4 dotted orange bags, 2 faded silver bags.
mirrored tan bags contain 3 posh gray bags, 2 dark silver bags, 3 dim tan bags.
clear olive bags contain 1 dim yellow bag, 1 bright blue bag, 3 bright tomato bags.
dim blue bags contain 3 drab black bags, 1 light blue bag, 5 light orange bags, 5 bright white bags.
mirrored chartreuse bags contain 4 drab beige bags, 1 pale indigo bag.
dark turquoise bags contain 1 vibrant black bag, 1 light turquoise bag, 5 pale aqua bags.
posh yellow bags contain 4 dim teal bags, 2 dark black bags.
clear aqua bags contain 2 drab teal bags, 5 light gold bags, 4 dim crimson bags.
dotted purple bags contain 4 striped salmon bags.
light indigo bags contain 3 faded red bags, 2 shiny crimson bags, 3 wavy green bags, 2 striped coral bags.
vibrant yellow bags contain 1 dotted cyan bag, 3 posh silver bags.
faded lavender bags contain 5 dull cyan bags.
dull magenta bags contain 2 dotted green bags.
posh indigo bags contain 1 dull lime bag, 4 striped lavender bags, 1 faded silver bag.
light aqua bags contain 3 posh maroon bags, 3 dotted black bags, 4 muted tomato bags, 4 mirrored magenta bags.
mirrored maroon bags contain 3 light aqua bags.
dim red bags contain 2 muted green bags, 1 vibrant tan bag.
wavy yellow bags contain 3 dotted cyan bags.
bright aqua bags contain 1 dotted maroon bag, 1 muted white bag, 3 striped turquoise bags.
clear fuchsia bags contain 2 mirrored fuchsia bags, 4 bright white bags, 3 mirrored white bags, 1 bright coral bag.
dotted olive bags contain 3 pale aqua bags, 4 light gold bags, 5 dim yellow bags.
light black bags contain 4 clear tan bags, 5 wavy lime bags, 3 dim fuchsia bags, 3 pale indigo bags.
dark purple bags contain 5 dark cyan bags.
dim purple bags contain 2 wavy crimson bags, 2 dim chartreuse bags, 3 shiny yellow bags, 1 light black bag.
plaid salmon bags contain 1 faded lime bag.
dotted cyan bags contain 2 shiny tomato bags, 1 mirrored plum bag.
posh maroon bags contain 1 light bronze bag, 4 muted tan bags, 5 vibrant plum bags.
dim fuchsia bags contain 3 dim plum bags, 5 dark gray bags.
bright tan bags contain 1 shiny maroon bag, 1 light beige bag, 2 faded fuchsia bags.
plaid green bags contain 3 wavy cyan bags, 5 dark chartreuse bags, 5 dark blue bags.
plaid black bags contain 4 dull olive bags, 4 mirrored white bags, 4 plaid white bags.
clear beige bags contain 1 dull tan bag.
mirrored tomato bags contain 5 drab tomato bags, 1 plaid bronze bag.
dim yellow bags contain 4 dark indigo bags, 4 bright silver bags, 3 muted purple bags.
clear tan bags contain 4 light gold bags, 3 bright lavender bags, 2 mirrored fuchsia bags.
dim lavender bags contain 3 vibrant aqua bags.
striped white bags contain 3 posh tomato bags, 3 dark gold bags, 2 clear olive bags, 1 dotted bronze bag.
wavy bronze bags contain 1 plaid lime bag, 4 plaid yellow bags, 1 bright white bag.
shiny orange bags contain 3 drab chartreuse bags, 1 shiny gold bag.
dim coral bags contain 2 faded silver bags.
bright gold bags contain 5 dim aqua bags, 2 drab bronze bags.
vibrant black bags contain 4 dotted green bags, 2 light brown bags.
bright teal bags contain 1 light gold bag, 2 bright aqua bags.
drab brown bags contain 2 wavy blue bags, 5 wavy orange bags.
dull yellow bags contain 4 striped green bags, 4 bright lime bags, 2 faded tan bags, 5 dotted green bags.
vibrant maroon bags contain 4 mirrored fuchsia bags.
vibrant gray bags contain 3 faded turquoise bags, 5 pale black bags, 3 drab aqua bags.
pale white bags contain 3 shiny beige bags.
dim beige bags contain 1 pale fuchsia bag, 1 muted lime bag, 3 dotted plum bags.
drab blue bags contain 4 dim crimson bags, 4 shiny beige bags, 2 bright silver bags.
dark black bags contain 5 light beige bags, 5 muted gold bags.
plaid bronze bags contain 3 wavy indigo bags.
posh salmon bags contain 3 dark salmon bags, 2 posh purple bags, 5 dim yellow bags.
mirrored lavender bags contain 4 wavy chartreuse bags, 4 plaid bronze bags.
muted brown bags contain 1 drab magenta bag, 2 vibrant plum bags, 4 clear purple bags, 4 dark blue bags.
wavy white bags contain 2 striped red bags.
dark gray bags contain 5 bright blue bags, 2 light brown bags.
mirrored silver bags contain 2 dotted chartreuse bags, 1 dotted fuchsia bag, 4 mirrored lavender bags, 2 mirrored white bags.
wavy brown bags contain 5 posh teal bags, 4 drab white bags, 5 shiny chartreuse bags, 4 light maroon bags.
posh gray bags contain 1 striped turquoise bag, 4 muted crimson bags, 3 clear yellow bags, 3 striped crimson bags.
dull tomato bags contain 5 drab purple bags, 4 faded yellow bags.
dotted blue bags contain 2 dull cyan bags, 3 dim plum bags.
vibrant tomato bags contain 5 plaid coral bags, 5 pale fuchsia bags.
wavy beige bags contain 3 dull magenta bags, 3 dotted beige bags, 3 bright white bags, 2 striped fuchsia bags.
plaid lime bags contain 3 light blue bags, 3 drab brown bags, 1 drab teal bag.
dim white bags contain 5 wavy coral bags, 5 vibrant bronze bags, 2 dark cyan bags, 2 dark plum bags.
bright yellow bags contain 4 pale aqua bags, 2 dim turquoise bags, 4 faded brown bags.
plaid maroon bags contain 1 dark teal bag, 4 vibrant white bags, 5 striped coral bags, 4 shiny white bags.
pale lavender bags contain 2 shiny violet bags.
drab magenta bags contain 5 bright gray bags.
clear salmon bags contain 4 wavy purple bags, 1 bright olive bag, 1 clear yellow bag.
dark yellow bags contain 1 bright bronze bag, 3 striped plum bags.
posh bronze bags contain 1 shiny maroon bag, 4 drab olive bags, 2 mirrored green bags, 5 light silver bags.
drab green bags contain 3 dim orange bags, 5 vibrant chartreuse bags.
light fuchsia bags contain 2 wavy silver bags, 4 muted white bags, 5 muted black bags, 1 faded green bag.
dark plum bags contain 4 bright tan bags, 4 dull lime bags, 2 faded fuchsia bags, 4 shiny maroon bags.
light teal bags contain 4 light lavender bags.
vibrant tan bags contain 1 vibrant bronze bag.
muted teal bags contain 5 wavy green bags, 5 plaid turquoise bags.
bright chartreuse bags contain 2 muted gold bags, 5 posh olive bags, 1 vibrant tan bag, 2 faded salmon bags.
dotted fuchsia bags contain 3 pale lime bags.
pale teal bags contain 5 plaid silver bags, 4 shiny turquoise bags, 3 dim coral bags, 2 vibrant bronze bags.
drab orange bags contain 2 shiny silver bags, 2 vibrant indigo bags, 5 mirrored lavender bags, 5 dark yellow bags.
clear green bags contain 4 vibrant beige bags, 1 bright crimson bag, 5 muted gray bags.
shiny yellow bags contain 4 light fuchsia bags, 2 mirrored plum bags.
plaid blue bags contain 4 mirrored blue bags, 1 plaid olive bag.
mirrored plum bags contain 2 dull red bags, 3 muted magenta bags.
dim bronze bags contain 3 vibrant olive bags.
posh green bags contain 3 mirrored blue bags, 4 vibrant yellow bags, 5 bright yellow bags, 2 wavy fuchsia bags.
clear blue bags contain 5 mirrored yellow bags.
dotted teal bags contain 5 shiny brown bags, 2 faded silver bags, 3 plaid coral bags.
muted cyan bags contain 4 clear aqua bags.
dark fuchsia bags contain 1 shiny blue bag, 1 dull fuchsia bag, 2 dull lime bags, 5 drab salmon bags.
dark silver bags contain 2 dim salmon bags.
muted beige bags contain 1 shiny lavender bag, 1 striped chartreuse bag.
dull indigo bags contain 1 bright beige bag, 2 dark gold bags, 1 mirrored magenta bag.
bright silver bags contain 3 faded violet bags, 4 dim cyan bags, 5 faded indigo bags, 1 clear chartreuse bag.
dim olive bags contain 1 mirrored plum bag, 1 clear indigo bag, 2 striped crimson bags.
pale magenta bags contain 5 vibrant black bags, 3 muted salmon bags, 1 dotted fuchsia bag.
faded turquoise bags contain 2 light lavender bags, 3 clear lavender bags, 3 dull coral bags.
posh gold bags contain 5 clear blue bags.
muted maroon bags contain 5 dark fuchsia bags, 2 muted red bags, 5 dim salmon bags.
muted tomato bags contain 4 striped blue bags, 3 dark plum bags, 5 faded green bags, 4 bright tan bags.
dark lime bags contain 2 posh white bags, 4 dull crimson bags, 2 dark cyan bags, 4 mirrored plum bags.
posh lime bags contain 1 wavy violet bag, 3 dotted teal bags, 5 shiny cyan bags.
light tan bags contain 4 striped turquoise bags, 4 dim white bags, 4 shiny violet bags.
dull bronze bags contain 2 drab teal bags, 5 light red bags, 4 muted indigo bags.
plaid coral bags contain 5 dark purple bags, 5 striped crimson bags, 4 light beige bags.
wavy lavender bags contain 5 muted white bags.
drab indigo bags contain 4 dotted green bags, 1 striped silver bag.
dull silver bags contain 1 dark yellow bag, 2 light beige bags, 3 striped indigo bags, 4 wavy violet bags.
dark aqua bags contain 1 drab violet bag.
muted bronze bags contain 4 clear chartreuse bags, 4 drab turquoise bags, 3 pale coral bags.
striped coral bags contain 1 shiny red bag, 1 dark purple bag.
faded beige bags contain 2 bright fuchsia bags, 2 mirrored turquoise bags.
dull plum bags contain 5 dull aqua bags.
drab lime bags contain 3 clear aqua bags, 4 shiny cyan bags.
pale plum bags contain 5 shiny silver bags, 5 dull coral bags.
pale violet bags contain 1 wavy purple bag, 1 light plum bag, 3 striped silver bags, 3 drab teal bags.
clear magenta bags contain 2 dark plum bags, 2 striped tan bags, 4 posh plum bags, 4 dark turquoise bags.
vibrant plum bags contain 3 dotted teal bags, 5 vibrant gold bags.
bright gray bags contain 3 muted white bags, 2 striped crimson bags, 3 mirrored gray bags, 4 wavy silver bags.
clear coral bags contain 2 vibrant magenta bags, 2 dim orange bags, 3 dark black bags.
vibrant chartreuse bags contain 3 dark lime bags, 1 mirrored turquoise bag, 2 vibrant indigo bags, 1 dull gray bag.
faded purple bags contain 2 mirrored indigo bags, 3 dark indigo bags, 2 pale fuchsia bags, 5 muted olive bags.
drab violet bags contain 4 muted black bags, 1 clear maroon bag, 1 clear gold bag.
dim magenta bags contain 5 wavy tan bags.
clear orange bags contain 5 shiny tomato bags, 1 faded fuchsia bag.
mirrored white bags contain 5 dim plum bags, 3 mirrored magenta bags.
plaid white bags contain 1 pale tomato bag, 2 posh magenta bags, 5 vibrant maroon bags, 5 shiny fuchsia bags.
shiny olive bags contain 4 striped salmon bags, 2 mirrored gray bags, 5 plaid beige bags.
plaid plum bags contain 3 bright bronze bags.
dull salmon bags contain 3 bright white bags, 2 muted cyan bags.
pale maroon bags contain 3 muted tan bags, 1 bright gray bag.
faded salmon bags contain 1 bright silver bag.
striped magenta bags contain 5 dark plum bags, 5 faded bronze bags, 4 striped brown bags.
vibrant crimson bags contain 2 muted lime bags, 5 plaid indigo bags.
wavy tan bags contain 2 shiny yellow bags, 3 clear beige bags, 2 dotted gold bags.
posh teal bags contain 4 striped gold bags, 3 drab salmon bags, 3 shiny plum bags, 2 pale gray bags.
dotted coral bags contain 2 wavy chartreuse bags, 3 wavy blue bags.
light purple bags contain 1 mirrored lime bag.
bright lavender bags contain 5 faded brown bags.
muted turquoise bags contain 2 shiny maroon bags, 3 light purple bags, 2 striped tan bags, 4 plaid cyan bags.
posh red bags contain 2 striped lavender bags, 1 dark black bag, 5 dark purple bags, 3 drab olive bags.
bright black bags contain 3 dark brown bags, 4 clear olive bags, 4 plaid olive bags.
mirrored bronze bags contain 1 wavy turquoise bag.
vibrant violet bags contain 2 plaid indigo bags, 4 faded orange bags.
drab tan bags contain 3 clear crimson bags, 4 mirrored turquoise bags, 2 muted magenta bags.
dim gray bags contain 5 striped black bags, 5 muted silver bags, 1 dotted blue bag, 3 posh gray bags.
dull tan bags contain 1 clear maroon bag, 4 posh beige bags, 2 striped crimson bags, 5 dim gold bags.
vibrant blue bags contain 4 bright beige bags, 5 bright bronze bags, 2 plaid salmon bags.
posh crimson bags contain 2 mirrored purple bags, 1 striped silver bag, 2 bright magenta bags, 5 bright blue bags.
dotted bronze bags contain 2 wavy crimson bags, 5 muted purple bags, 5 light gold bags.
pale brown bags contain 1 drab coral bag, 2 mirrored lavender bags, 4 dark tomato bags, 3 plaid indigo bags.
shiny maroon bags contain 5 light beige bags, 3 light white bags.
dark tomato bags contain 5 shiny gold bags, 5 clear aqua bags, 2 dotted gold bags.
dark beige bags contain 2 bright gray bags, 3 light beige bags, 1 dull lime bag.
light red bags contain 5 mirrored magenta bags, 1 mirrored lime bag, 4 dotted teal bags.
faded magenta bags contain 1 dim maroon bag, 3 mirrored gray bags, 1 dotted beige bag.
drab turquoise bags contain no other bags.
shiny salmon bags contain 5 shiny tan bags, 2 posh magenta bags, 4 clear turquoise bags.
dark magenta bags contain 1 light fuchsia bag, 3 muted yellow bags, 5 dotted olive bags, 4 dark crimson bags.
light gold bags contain 5 clear red bags.
faded red bags contain 4 clear beige bags, 3 dim silver bags, 4 posh gray bags.
pale salmon bags contain 5 mirrored white bags.
striped lavender bags contain 2 striped blue bags.
dull fuchsia bags contain 1 bright orange bag.
dull turquoise bags contain 1 vibrant tomato bag, 3 clear tan bags, 3 bright teal bags, 1 drab maroon bag.
dotted magenta bags contain 5 drab gold bags, 2 muted beige bags.
pale indigo bags contain 4 plaid brown bags, 1 plaid cyan bag, 1 mirrored black bag, 5 drab magenta bags.
drab yellow bags contain 5 dark turquoise bags, 2 dotted beige bags, 5 clear red bags, 2 muted lavender bags.
striped gray bags contain 5 bright orange bags, 5 muted white bags, 2 clear chartreuse bags.
dark lavender bags contain 5 dim gold bags, 2 pale coral bags.
dull gold bags contain 1 dull beige bag.
muted chartreuse bags contain 3 muted bronze bags, 1 faded black bag, 4 bright tan bags.
plaid chartreuse bags contain 4 dim indigo bags, 4 mirrored gold bags, 4 dim lime bags.
muted salmon bags contain 4 faded brown bags, 1 dotted black bag, 5 muted black bags.
bright purple bags contain 5 shiny red bags, 5 vibrant cyan bags, 4 plaid cyan bags, 5 bright silver bags.
dim chartreuse bags contain 1 faded indigo bag.
drab purple bags contain 4 muted cyan bags, 3 wavy lavender bags, 2 dotted blue bags.

82
d07/main.py Executable file
View File

@ -0,0 +1,82 @@
#! /usr/bin/env python3
import itertools
import re
from collections import namedtuple
line_matcher = re.compile(r"(\w+ \w+) bags contain ([\w+ ,]+)+.")
child_matcher = re.compile(r"([0-9]+) (\w+ \w+) bag[s]{0,1}")
BagRule = namedtuple("BagRule", ["parent_bag", "bag_counts"])
def parse_line(line):
result = line_matcher.match(line)
if result is None:
# print(f"{line}: No match")
return None
else:
parent_bag = result.group(1)
bag_counts = {}
# print(result.groups())
for bags in result.group(2).split(","):
if bags == "no other bags":
break
child_result = child_matcher.search(bags.strip())
# print(bags.strip(), child_result.groups())
if child_result is None:
print(f"Invalid child bags: {bags}")
bag_counts[child_result.group(2)] = int(child_result.group(1))
return BagRule(parent_bag, bag_counts)
def get_direct_carriers(contained_in, bags):
return set(itertools.chain.from_iterable((
contained_in.get(bag, [])
for bag in bags
)))
def part1():
contained_in = {}
with open("input.txt") as f:
for line in f:
rule = parse_line(line)
for bag in rule.bag_counts.keys():
contained_in.setdefault(bag, []).append(rule.parent_bag)
my_bag = "shiny gold"
holding_bags = set()
last_level = set((my_bag,))
while last_level:
last_level = get_direct_carriers(contained_in, last_level)
holding_bags |= last_level
print(f"Holding bags: {len(holding_bags)}")
def count_children(contents, bag):
rule = contents.get(bag)
if rule is None:
return 0
return sum(
count * (1 + count_children(contents, child_bag))
for child_bag, count in rule.bag_counts.items()
)
def part2():
contents = {}
with open("input.txt") as f:
for line in f:
rule = parse_line(line)
contents[rule.parent_bag] = rule
children = count_children(contents, "shiny gold")
print(f"Holds {children} bags")
if __name__ == "__main__":
part1()
part2()

596
d08/input.txt Normal file
View File

@ -0,0 +1,596 @@
acc +40
jmp +187
acc +47
acc +20
acc -12
jmp +225
nop +488
acc +13
nop +462
jmp +374
acc +15
acc +42
jmp +116
acc +23
nop +216
acc -15
jmp +398
jmp +103
acc +17
acc +7
jmp +571
jmp +1
jmp +217
acc +7
jmp +1
acc +35
jmp +257
acc +24
nop +20
jmp +309
acc +2
acc -15
acc -13
nop +457
jmp +19
acc +46
acc +45
acc +35
jmp +295
acc -15
acc +49
acc +22
jmp +400
jmp +202
nop -38
jmp +381
acc +0
jmp +137
acc +27
jmp +196
acc +46
acc -15
jmp +348
jmp +457
acc +50
acc +8
jmp +452
acc -14
nop +321
acc +39
jmp +273
acc -9
jmp +413
acc +32
jmp +64
acc +18
jmp +152
acc -4
acc +9
acc +10
acc -1
jmp +433
acc +40
jmp -55
acc +28
nop +279
jmp +145
acc +24
nop +416
acc +45
jmp +45
acc +0
acc +49
acc -14
jmp +44
acc +17
acc +18
nop +224
acc +3
jmp +261
jmp -84
acc -11
acc +29
acc +42
jmp -13
acc -5
jmp +210
acc +26
acc -19
acc -19
jmp -82
acc +29
acc +31
acc -4
jmp +53
acc +46
jmp +139
acc +45
acc +30
jmp +1
jmp +418
jmp +248
acc +24
acc +15
acc +34
acc +17
jmp +52
acc +23
acc +18
jmp +65
jmp +1
acc +37
acc +25
jmp +385
jmp +281
nop +345
jmp -25
jmp +149
acc +21
acc +28
acc +15
jmp -74
jmp +179
jmp +287
acc +14
acc -3
acc -7
jmp -9
acc +17
acc -8
jmp +344
jmp +1
acc +36
acc -16
acc -17
jmp -82
jmp +1
acc +41
acc -8
acc +27
jmp +381
acc -10
nop -71
acc +23
nop +377
jmp -125
jmp +319
nop +119
nop +309
nop +195
jmp +307
acc +8
acc +31
jmp +1
acc -15
jmp +398
jmp +265
jmp -55
nop +143
jmp -36
acc +38
nop -38
jmp +298
acc -17
acc +39
acc -13
jmp -38
acc +23
jmp +133
acc +23
jmp -90
acc +14
jmp +1
jmp +100
nop +230
jmp +346
acc +36
jmp +14
jmp +126
jmp -32
jmp -142
acc +25
jmp +146
nop +118
acc -3
jmp +1
acc -8
jmp +101
nop +277
acc +27
jmp +328
acc -11
acc +17
nop +135
jmp +196
acc -9
jmp +39
nop +110
acc +14
nop +3
jmp +17
jmp +220
acc +17
jmp +5
acc +18
acc +39
acc -12
jmp -204
jmp +317
acc +37
jmp +222
nop +146
nop +248
jmp +182
acc +48
acc -13
jmp +174
jmp +342
nop -189
jmp +324
acc +35
acc +25
acc +21
jmp -152
nop -92
acc -3
acc -15
acc +30
jmp -157
acc -17
acc +37
acc +7
acc +5
jmp -225
jmp -177
acc +21
jmp +244
acc +42
acc -4
jmp -116
nop +225
nop -63
acc +20
jmp +195
acc +20
acc +21
jmp +228
acc +16
acc -8
acc +12
nop +188
jmp +9
acc +6
acc -13
acc +36
jmp -86
jmp -253
nop -60
acc +25
jmp -174
acc +10
nop -114
jmp -65
jmp +1
acc +24
jmp -150
acc +27
jmp -47
acc +50
nop -58
acc -17
acc -16
jmp -170
jmp -104
jmp -177
acc +46
jmp +106
jmp -206
acc +2
acc +10
acc +17
nop -107
jmp -126
jmp +1
acc +50
acc -14
acc +29
jmp -234
nop +144
acc +43
acc +34
jmp +221
jmp +1
nop +97
acc +39
jmp -60
acc +44
jmp -240
acc +11
acc +36
jmp -71
acc -5
jmp +149
jmp +54
acc +38
jmp +44
jmp -165
acc +14
jmp -134
acc +3
acc +22
nop +46
acc -12
jmp -57
acc +49
acc +24
acc +16
jmp +27
acc +6
nop -5
acc +45
acc +34
jmp -175
jmp -76
acc +3
acc +15
acc -19
jmp +1
nop -226
acc -2
jmp -55
jmp -284
acc +2
jmp +1
jmp +15
acc +11
acc +12
acc -1
acc +2
jmp +179
acc +19
acc +17
jmp -329
jmp -272
jmp -104
acc +41
nop +189
acc +47
jmp -88
acc +4
acc +16
acc +43
acc +25
jmp +71
acc -2
acc +45
jmp -173
jmp +1
acc +44
acc +33
jmp -53
acc +45
acc +9
acc +0
acc +12
jmp +178
jmp -100
acc +14
jmp -67
acc +42
jmp +201
acc +30
jmp -319
nop -4
nop -211
acc -3
nop -165
jmp -175
acc +12
acc -10
acc -14
jmp -53
acc -13
nop -143
jmp +159
acc -5
nop +18
nop -5
acc +13
jmp -248
jmp +114
acc +10
nop -396
nop -246
jmp +16
acc -3
acc +33
nop +174
acc +48
jmp -289
nop +98
acc +18
acc -17
jmp -137
jmp +1
acc +34
acc +36
jmp -216
acc +11
jmp -102
acc +10
jmp +10
acc +26
acc +35
acc -9
jmp -83
acc +15
nop -397
jmp -140
nop +111
jmp +139
jmp -165
acc +16
jmp -343
acc +8
acc +35
acc -17
acc -8
jmp +29
acc +50
nop -256
jmp -268
jmp +132
acc +13
acc +38
acc -6
acc -7
jmp -327
acc -8
jmp -256
nop -139
acc +30
jmp -60
acc -1
acc +11
jmp -216
acc -12
nop -390
acc +17
acc +39
jmp +101
acc +28
jmp +1
acc -7
acc -18
jmp -277
jmp -90
acc -10
jmp -326
jmp -368
nop -396
jmp -320
acc +42
acc +3
jmp -430
acc +47
acc +11
acc +19
acc +41
jmp -354
acc +30
acc +7
nop -106
jmp -420
acc +22
acc -15
jmp -296
acc -7
acc +48
jmp -19
jmp -148
acc +10
jmp +1
jmp +17
nop -273
acc +42
acc -4
nop -130
jmp +47
nop -436
acc -7
jmp +1
acc +42
jmp -330
acc +35
jmp +56
acc -19
jmp -440
jmp -335
jmp -279
nop -390
jmp +74
acc -5
jmp -456
acc +38
acc +3
jmp +47
acc +50
acc +26
acc +46
acc -7
jmp -491
acc -4
acc -7
acc +14
nop -105
jmp -487
jmp -326
nop -360
jmp -378
jmp -285
acc +46
jmp -190
acc +10
jmp -346
acc +49
jmp -492
acc -9
acc -17
jmp -147
acc +20
jmp -217
nop -183
acc +35
jmp -268
nop -51
jmp +1
jmp -440
acc +22
acc +24
jmp +1
acc +26
jmp -451
acc -14
acc +48
acc +3
jmp -363
acc +21
acc +24
acc +36
jmp -418
jmp -108
jmp -323
jmp +20
acc +1
acc +21
nop -212
acc -3
jmp -338
acc +36
acc -19
jmp -192
acc +49
jmp -380
acc -12
acc +14
acc +38
acc +4
jmp -228
acc +2
jmp -197
jmp -41
jmp -265
jmp -113
jmp -459
jmp +1
acc +38
jmp -79
acc +16
nop -456
jmp -129
acc +12
acc +29
nop -575
acc -7
jmp +1

94
d08/main.py Executable file
View File

@ -0,0 +1,94 @@
#! /usr/bin/env python3
from copy import copy
sample = [
"nop +0",
"acc +1",
"jmp +4",
"acc +3",
"jmp -3",
"acc -99",
"acc +1",
"jmp -4",
"acc +6",
]
def parse_lines(lines):
def parse_line(line):
inst, _, num = line.partition(" ")
return (inst, int(num))
return [
parse_line(line)
for line in lines
]
def run_line(instructions, index):
inst, num = instructions[index]
if inst == "nop":
return index+1, 0
elif inst == "acc":
return index+1, num
elif inst == "jmp":
return index+num, 0
def part1():
with open("input.txt") as f:
instructions = parse_lines(f)
_, acc = run_until_loop(instructions, 0)
print("Total accumulated:", acc)
def run_until_loop(instructions, line, seen_lines=None):
if seen_lines is None:
seen_lines = set()
acc = 0
while line < len(instructions):
seen_lines.add(line)
# print(f"Inner: {line}:{instructions[line]}")
line, num = run_line(instructions, line)
acc += num
if line in seen_lines:
# print(f"Inner loop, break out")
return True, acc
return False, acc
def part2():
with open("input.txt") as f:
instructions = parse_lines(f)
accum = 0
line = 0
seen_lines = set()
while line < len(instructions):
if line in seen_lines:
print(f"Ugh, looping")
return
# print(f"{line}:{instructions[line]}")
inst, num = instructions[line]
if inst != "acc":
# print(f"Found an alternate, check for loop")
# Possible change
new_inst = copy(instructions)
new_seen = copy(seen_lines)
new_inst[line] = ("nop" if inst == "jmp" else "jmp", num)
has_loop, acc_d = run_until_loop(new_inst, line, new_seen)
if not has_loop:
accum += acc_d
print(f"Found solution! Changing {line}: Total {accum}")
return
seen_lines.add(line)
line, num = run_line(instructions, line)
accum += num
if __name__ == "__main__":
part1()
part2()

1000
d09/input.txt Normal file

File diff suppressed because it is too large Load Diff

273
d09/main.go Normal file
View File

@ -0,0 +1,273 @@
package main
import (
"bufio"
"container/list"
"fmt"
"log"
"os"
"strconv"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
// LimitedList acts as a list with a fixed size
type LimitedList struct {
elements *list.List
maxLength int
}
// Len returns the current length of the fixed list
func (ll *LimitedList) Len() int {
return ll.elements.Len()
}
// Full checks if the fixed list is full
func (ll *LimitedList) Full() bool {
return ll.Len() == ll.maxLength
}
// Front moves the pointer to the front of the list
func (ll *LimitedList) Front() *list.Element {
return ll.elements.Front()
}
// Push adds an item to the back of the fixed list
func (ll *LimitedList) Push(v interface{}) *list.Element {
if ll.Full() {
_ = ll.elements.Remove(ll.Front())
}
return ll.elements.PushBack(v)
}
// NewLimitedList initializes a new list limited to the given length
func NewLimitedList(size int) *LimitedList {
return &LimitedList{
list.New(),
size,
}
}
// Pair of numbers
type Pair struct {
A, B int
}
func searchPairs(l LimitedList, target int) (Pair, error) {
var x, y int
for ex := l.Front(); ex != nil; ex = ex.Next() {
x = ex.Value.(int)
for ey := ex.Next(); ey != nil; ey = ey.Next() {
y = ey.Value.(int)
if x+y == target {
return Pair{x, y}, nil
}
}
}
return Pair{}, fmt.Errorf("could not find pair matching %d in %v", target, l)
}
func searchPairsSlice(numbers []int, target int) (Pair, error) {
for i, x := range numbers {
for _, y := range numbers[i:] {
if x+y == target {
return Pair{x, y}, nil
}
}
}
return Pair{}, fmt.Errorf("could not find pair matching %d in %v", target, numbers)
}
func part1Old() int {
bufferSize := 25
buffer := []int{}
result := -1
err := processLines("input.txt", func(line string) (stop bool, err error) {
v, err := strconv.Atoi(line)
if err != nil {
return
}
if len(buffer) < bufferSize {
buffer = append(buffer, v)
} else {
// Check number
_, err = searchPairsSlice(buffer[len(buffer)-bufferSize:], v)
if err != nil {
stop = true
err = nil
result = v
return
}
buffer = append(buffer, v)
}
return
})
if err != nil {
log.Fatal(err)
}
if result < 0 {
fmt.Println("All valid")
} else {
fmt.Printf("First non matching is %d\n", result)
}
return result
}
func part1() int {
ll := NewLimitedList(25)
result := -1
err := processLines("input.txt", func(line string) (stop bool, err error) {
v, err := strconv.Atoi(line)
if err != nil {
return
}
if !ll.Full() {
ll.Push(v)
} else {
// Check number
_, err = searchPairs(*ll, v)
if err != nil {
stop = true
err = nil
result = v
return
}
ll.Push(v)
}
return
})
if err != nil {
log.Fatal(err)
}
if result < 0 {
fmt.Println("All valid")
} else {
fmt.Printf("First non matching is %d\n", result)
}
return result
}
// SumQueue acts as a list with a fixed size
type SumQueue struct {
elements *list.List
sum int
}
// Len returns the current length of the queue
func (sq *SumQueue) Len() int {
return sq.elements.Len()
}
// Sum returns the sum of the items in the queue
func (sq *SumQueue) Sum() int {
return sq.sum
}
// Front moves the pointer to the front of the list
func (sq *SumQueue) Front() *list.Element {
return sq.elements.Front()
}
// Push adds an item to the back of the queue
func (sq *SumQueue) Push(v int) *list.Element {
sq.sum = sq.sum + v
return sq.elements.PushBack(v)
}
// Pop removes an item from the queue
func (sq *SumQueue) Pop() int {
v := sq.elements.Remove(sq.Front()).(int)
sq.sum = sq.sum - v
return v
}
// NewSumQueue creates a new SumQueue
func NewSumQueue() *SumQueue {
return &SumQueue{
list.New(),
0,
}
}
func part2(target int) {
sq := NewSumQueue()
found := false
err := processLines("input.txt", func(line string) (stop bool, err error) {
v, err := strconv.Atoi(line)
// fmt.Println(v, sq.Len())
if err != nil {
return
}
if v == target {
return
}
sq.Push(v)
if sq.Sum() == target {
// Found it!
stop = true
found = true
return
}
for sq.Sum() > target && sq.Sum() > 0 {
// While too big, pop from the front
_ = sq.Pop()
}
if sq.Sum() == target {
// Found it!
stop = true
found = true
return
}
return
})
if err != nil {
log.Fatal(err)
}
if found {
min := -1
max := -1
for e := sq.Front(); e != nil; e = e.Next() {
if min < 0 || e.Value.(int) < min {
min = e.Value.(int)
}
if e.Value.(int) > max {
max = e.Value.(int)
}
}
fmt.Printf("Found %d numbers matching min %d max %d sum %d", sq.Len(), min, max, min+max)
} else {
fmt.Println("Didn't find anything")
}
}
func main() {
result := part1()
part2(result)
}

20
d09/testinput.txt Normal file
View File

@ -0,0 +1,20 @@
35
20
15
25
47
40
62
55
65
95
102
117
150
182
127
219
299
277
309
576

94
d10/input.txt Normal file
View File

@ -0,0 +1,94 @@
38
23
31
16
141
2
124
25
37
147
86
150
99
75
81
121
93
120
96
55
48
58
108
22
132
62
107
54
69
51
7
134
143
122
28
60
123
82
95
14
6
106
41
131
109
90
112
1
103
44
127
9
83
59
117
8
140
151
89
35
148
76
100
114
130
19
72
36
133
12
34
46
15
45
87
144
80
13
142
149
88
94
61
154
24
66
113
5
73
79
74
65
137
47

217
d10/main.go Normal file
View File

@ -0,0 +1,217 @@
package main
import (
"bufio"
"fmt"
"log"
"math"
"os"
"sort"
"strconv"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func part1() {
values := []int{}
if err := processLines("input.txt", func(line string) (bool, error) {
v, err := strconv.Atoi(line)
values = append(values, v)
return false, err
}); err != nil {
log.Fatal(err)
}
sort.Ints(values)
lastVal := 0
ones := 0
threes := 0
for _, v := range values {
diff := v - lastVal
switch diff {
case 1:
ones++
case 2:
case 3:
threes++
default:
log.Fatalf("unsupported distance: %d-%d=%d", v, lastVal, diff)
return
}
lastVal = v
}
// Final devices is a 3 jolt diff
threes++
fmt.Printf("Total ones %d total threes %d. Product %d\n", ones, threes, ones*threes)
}
var memoized = map[int][][]int{}
func searchSlice(s []int, start int) [][]int {
// Check for memoized results
if memResults, ok := memoized[start]; ok {
fmt.Printf("Cached value for index %d", start)
return memResults
}
// Check for a memoized result
// If at the end, return an empty array
lastVal := s[start]
if start == len(s)-1 {
// fmt.Println("At end! Yay!")
return [][]int{[]int{lastVal}}
}
fmt.Printf("Checking index %d value %d\n", start, lastVal)
results := [][]int{}
for i := 1; i <= 3 && start+i < len(s); i++ {
v := s[start+i]
if v-lastVal > 3 {
// Not valid, skip this
continue
}
subResults := searchSlice(s, start+i)
for _, subResult := range subResults {
subResult = append([]int{lastVal}, subResult...)
results = append(results, subResult)
}
}
// memoize the results
memoized[start] = results
return results
}
var memoizedC = map[int]int{}
func searchSliceC(s *[]int, start int) int {
// Check for memoized results
if memResultsC, ok := memoizedC[start]; ok {
// fmt.Printf("Cached value for index %d", start)
return memResultsC
}
// Check for a memoized result
// If at the end, return an empty array
lastVal := (*s)[start]
if start == len(*s)-1 {
// fmt.Println("At end! Yay!")
return 1
}
fmt.Printf("Checking index %d value %d\n", start, lastVal)
results := 0
for i := 1; i <= 3 && start+i < len(*s); i++ {
v := (*s)[start+i]
if v-lastVal > 3 {
// Not valid, skip this
continue
}
results += searchSliceC(s, start+i)
}
// memoize the results
memoizedC[start] = results
return results
}
func part2() {
values := []int{}
if err := processLines("input.txt", func(line string) (bool, error) {
v, err := strconv.Atoi(line)
values = append(values, v)
return false, err
}); err != nil {
log.Fatal(err)
}
values = append([]int{0}, values...)
sort.Ints(values)
deviceJolts := values[len(values)-1] + 3
values = append(values, deviceJolts)
fmt.Println("Total values", len(values))
/*
* paths := []int{}
* i := 0
* for i < len(values) {
* // look ahead
* for l := 3; l > 1; l-- {
* if i+l < len(values) && values[i+l]-values[i] <= 3 {
* // Look ahead is valid
* paths = append([]int{l}, paths...)
* // We only want max, so break out if we found it
* i = i + l
* break
* }
* }
* i++
* }
* fmt.Println("Paths", paths)
* powTotal := 1.0
* for _, num := range paths {
* if powTotal == 1.0 {
* powTotal = float64(num)
* } else {
* powTotal = math.Pow(float64(powTotal), float64(num))
* }
* }
* fmt.Println("Total pow paths", powTotal)
* productTotal := 1
* for _, num := range paths {
* productTotal = productTotal * num
* }
* fmt.Println("Total product paths", productTotal)
*
* totalOptions := 0
* i = 0
* options := []int{}
* for i < len(values) {
* // look ahead
* for l := 3; l >= 1; l-- {
* if i+l < len(values) && values[i+l]-values[i] <= 3 {
* // Look ahead is valid
* totalOptions++
* options = append(options, l)
* break
* }
* }
* i++
* }
* fmt.Println("Options", options)
* fmt.Println("Total sum options *2=", totalOptions*2)
* totalProdOptions := 1
* for _, num := range options {
* totalProdOptions = totalProdOptions * num
* }
* fmt.Println("Total prod options", totalProdOptions)
*/
fmt.Printf("Looking for device jolts %d\n", deviceJolts)
countResults := searchSliceC(&values, 0)
fmt.Printf("Search found %d results\n", countResults)
/*
* results := searchSlice(values, 0)
* fmt.Printf("Search found %d results\n", len(results))
*/
}
func main() {
part1()
part2()
}

10
d11/input-small.txt Normal file
View File

@ -0,0 +1,10 @@
L.LL.LL.LL
LLLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLLL
L.LLLLLL.L
L.LLLLL.LL

98
d11/input.txt Normal file
View File

@ -0,0 +1,98 @@
LLLLLL.LLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LL
LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.L.LLLLLL.LL.LLLLLL
LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLL.LL.LLLLLLLLLLLLLL.LL.LLLLLLLLL
LLLLLL.LLLLL..LLLLL.LLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.L.LLLLL.L
LLLLLL.LLLLLL.LLL.L.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.LLLLLL..LLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLL.LLL
.LLLLLLLLLLLL.LLL.L.LLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLL.L.L.LLLLLLLLLLLLL.L.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL..LLLLLLLLLL..LLLLLLL.LLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLL.LLLL..LLLLLLLL
..........LL....L..LL..L.....L...L....L............L.LL...L.......L.L.LL...L.L...L....L.L....LLL..
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLL.L.LLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LL..LLLLLLL.LLLLLLLLLL
LLLLLLLLLLLLL.LLLLL.LLLLLLL.LLL.L.LLLLLLLLLLLLLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLL.LLL
.LLLLL..LL.LL..LLL.LLLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL
L.LLLL.LLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLL.LLL.LLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL
LLLLLL.LLLLLLLLLLLLLLLLLLLL.L.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLL.L.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLLL.L.LLLLLLLL.LLLLLLLL.LLLLLLLLL
...LLLLL.......L.LL..L..LL...LL..L.....L...L...LLL.L.L.....L.L....L.L......LL..L.L.L..LL.L.....LL.
LLLLLLLLLLL.L.LLL.LLLLLLLLL.LLLLLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLL.L.LL.LLLLLLLLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLL.LLL.LLL.LLLLLLLL.LLLLLLLL..LLLLLLLLLLLLLL.LL
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLLL.L.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLL..LL.L.LLLLLLL.LLLLLLL.LLLLL.LLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.L.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLLL.LLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.L.LLLLLLLLL
L.LLLL.LLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.LLLL.LL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
.LLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLL.L.LLL.LLLLLLLL.LLL..LLLLLLL.LL.LLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.L.LLLLLL.LLLLLLLLLLLLLLLLL.
L.LL..LLL.L.........L.L....L...LL.L......L..LL.......L.....L.LL.....L..L.L.....L.....L.L...L.L....
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLL..LLLL..LLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL
LLL.L..LLLL.L.LLLLLLLLLLLLL.LLLLL.LLLLL.L.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL..LLLLLLLL
LLLLLL.LLLLLL.LLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLL..LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL
LL.LLLLLLLLLLLLLLL..LLLLLLLLLLLL..LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.L.LLLLLLLLL
LLLLLL..LLLLLLLLLLLLLLLLL.L.LLLLLLLLLLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
..L...L...L..L..LL...L..........L.....L......L....L.L..L.L.L..L.LL....L..L...L...L......L.....L..L
LLLLLLLLLLLL..LLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LL.LLLLLLLLLLLLL.L.LLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.L.LLLLL.LLLLLLLLLLLLLLLLL..LLLLLLL.LLLLLLLLL
LLLLLLLLLLLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLLL
LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLL.LLLLLLLL.LLLLL.LLLLLLLLLL.L
LLLLLLLLLLLLL.L.LLL.LLLLLLL.LLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLL..LLLLLLLLL
LLL..L..LLLL.LLL.L......L...LL.L..L.L...L...LL....L.L.L.L................L....L..L...L......LLL.L.
LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL..LLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLLLLL..LLLLLLL.LLLLLLLLLLLLLLLLLL
LLLLLL.LLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLL.LL.LLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLLL
.LLLLL.LLLLLL.LLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLL
LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLL..LLLLLLLL.LLLLLLLL.LLLLLLLL.L.LLLLLLL
LLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLL.LL.LLLLLLLLLLLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLL.LL.LLLLL.LLLLL.LLLLLLLL..LLL.LLLLL.L.LLLLLLLLLLLLLLLLL.LLL.LLLL.LLLLLLLLL
LL.LLL.LLLLLL.LLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL.LLL.L.LL.LLLLLLLLLLL.LLLLLL
LLLLLLLLLLLLL.LLLLL..LLLLLLLLLLLLLLLLLL.L.LLLLLL.LLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL
.LLLLL..L.L.L...L...L..LL.L.L.LL.L...L.L.L...................LL..L...L......L..L.........L.....LL.
LLLL.LLLLLLLL.LLLLL.LLLLLLL.LLLLLL.LLLLLLLLLLLLL.LLLL.L.LLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLLL.L.LLLL.LLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLL.LLLL.LLL.LL..LLLL.
.LLLLL.LLLLLLLLLLLL.LLLL.LLLLLLLL.LLLLLLLLLLLLLL.L.LLLL.LLLLLLLLLLLLLL.LLLLLLL..LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLL...LLLLL.LLLLLLL.LLLL.LLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLL.LLLLLLLLL.LLLLLLL.LLLLLLLL..L.LLLLL.LLLLLLLL.LLLLLLLLL
LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LL.LLLLLLLLLLLLLL.
LLL.LL.LLLLLL.LLLLL.LLLLLLL.LLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL
LLLLLL.LLLLLL.LLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL
LLLLLL.LLL..L.LLLLL.LLLLLLLLLLLLLLLLL.L.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
L.LL.L.L...L.LL.L.LLL...L.......LLL.L.LL..LLLL.L.L...L..LL.L..LL..L.L..LLLL.L.L..L.L....L....L...L
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLL.LLLL.L.LLLLLLL
LLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL
LLLLLL.L.LLLL.LLLLL.LLL.LLL.LLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLL..LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLL.LLLLLLLL.LLLLL..LLLLLLLLLLLL.LL.LL.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.L.LLLLLL.LLLLLLLLLLLLLLLLLL
LLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLL..LLLLLLL.LL.LLLLLL
LLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL..LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLL.LLLLL
L.L..L................L..LL.....LL...L............L....LL..LL.LLL.L.............L..L...L.....LLL..
LLLLLLLLLLLLLLLL.LL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLL.LLLLLL.LLLLLLL.LLLLL.LLL.LLLLLLLLLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.
LLLLLL.LLLLLLLLLLLLLL.LLLLL.LLLLL.LL.LL.LLLLLLLL.LLLL.LLLLLLL.LL.LLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL
LLLL.LL.LLLLL.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLL..LLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLL.LLL.LLLL.LLLLLL.L.LLLLLLLL.LLLLLLLLL
L.L..L...LL.L.....LL..LL.L.....L.L..L....L..L.L...L.LLLL....L...LL......L..L....LL..L..L........LL
LLLLLLLLLLLLLLLLLLL.LLLL.LL.LLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLL.LLLL.LLLLLLLL.LLLLL.LLL
LLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLL.LL.LLLLLL.LLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL
LLLLLL.LLLLL.LLLLLL.LLLLLLL.LLLLLLLLLLL..LLLLLLL.L.LL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLL..LLLLLLLLL
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLL.LLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLLLLLLLLLLLLL.LL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLL.L.LLLLLLLLLLLLL.LLLLLLLLL.L.LLLLLLLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLL..LLLLLLLL.LLLLLLLLL
LLLLL..LLLL.L.LLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLLL..LLLLLLLL.LLLLLLLLL
L.LLLLLLLLLLLLLLLLL.LLLLLLL.LL.LL.LLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LL.L......L......L...L..LLL.....L.L..L.L...L......L..L..L.....L...LL.L.LL.L.LLL....L.LLL....L..L..
LLLLLLLLLL.LLLLLLLLLL.LL.LL.LLLLLLLLLLL.L..LLLLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLL.LL..LLL.LLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL..LL.LL.LLLLL.LLLLLLL.L.LLLLLLLLL.LLLLLLLL.LLLLLLLL.LLL.LLL.LLLL.LLLLLLLLLLLLLLLL..LLLLLLLLL
LLLLLLLLLLL.LLLLLLL.LLL.LLLLLLLLL.LLLLL.LLLLLLLL.LLLLLL.LLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLLLLLLL.L.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.L.LLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL..LLLL.LLLLLLLLLLLLLLLL.LL.LLLL.LLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.L.L.LLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LL.LLLLLLLLL.LLLLLLL.LLLLLL
L..L.LL......LLL....LLLL.......L.L..L..L....LLLLL..LLLLL..L..L.L.L........LLL...LL.L......LLL.....
LLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLL..LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LL.LLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLL.LLLL.LLLLLLLL..LLLLLL.LLLLL.LLLL...LLLLL.L.LLLL.LLLLLLL..LLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL
LLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLL.LLLLL.LLL
LLLLLLLLLLLLL.LLLLL.L.LLLLL.LLLLLLLLLLL.LLLLLLLLLL.LL.LLLLLLLLLL.LLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLL
LLLLL.LLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLL.LLLLLLLLL
LLLLLL.LLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLL.L.LLLLLL.LLLLLLLLLLLLLLLLL.
LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL

463
d11/main.go Normal file
View File

@ -0,0 +1,463 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
var (
emptySeatCode = 'L'
occupiedSeatCode = '#'
floorCode = '.'
printMaps = false
// Variables for controlling part 1 and part 2.
maxOccupied = 4
lookVisible = false
)
type point struct {
x, y int
}
type square struct {
seat bool
occupied bool
loc point
left *square
right *square
up *square
down *square
tock func() error
}
func (s square) isAvailable() bool {
return s.seat && !s.occupied
}
func (s square) hasPerson() bool {
return s.seat && s.occupied
}
func (s *square) sit() error {
if !s.seat {
return fmt.Errorf("cannot sit on the floor")
}
if s.occupied {
return fmt.Errorf("someone is already sitting here")
}
s.occupied = true
return nil
}
func (s *square) leave() error {
if !s.seat {
return fmt.Errorf("cannot leave from the floor")
}
if !s.occupied {
return fmt.Errorf("nobody is here to leave")
}
s.occupied = false
return nil
}
func (s *square) setLeft(l *square) {
if l.right != nil {
log.Fatalf(
"cannot set square above %v to %v because %v already has %v below it",
s.loc, l.loc, l.loc, l.right.loc,
)
}
s.left = l
l.right = s
}
func (s *square) setUp(u *square) {
if u.down != nil {
log.Fatalf(
"cannot set square above %v to %v because %v already has %v below it",
s.loc, u.loc, u.loc, u.down.loc,
)
}
s.up = u
u.down = s
}
func (s *square) leftUp() *square {
if s.left != nil {
if s.left.up != nil {
return s.left.up
}
}
return nil
}
func (s *square) upRight() *square {
if s.up != nil {
if s.up.right != nil {
return s.up.right
}
}
return nil
}
func (s *square) rightDown() *square {
if s.right != nil {
if s.right.down != nil {
return s.right.down
}
}
return nil
}
func (s *square) downLeft() *square {
if s.down != nil {
if s.down.left != nil {
return s.down.left
}
}
return nil
}
func (s *square) lookLeft() *square {
n := s.left
if n != nil && !n.seat {
return n.lookLeft()
}
return n
}
func (s *square) lookRight() *square {
n := s.right
if n != nil && !n.seat {
return n.lookRight()
}
return n
}
func (s *square) lookUp() *square {
n := s.up
if n != nil && !n.seat {
return n.lookUp()
}
return n
}
func (s *square) lookDown() *square {
n := s.down
if n != nil && !n.seat {
return n.lookDown()
}
return n
}
func (s *square) lookLeftUp() *square {
n := s.leftUp()
if n != nil && !n.seat {
return n.lookLeftUp()
}
return n
}
func (s *square) lookUpRight() *square {
n := s.upRight()
if n != nil && !n.seat {
return n.lookUpRight()
}
return n
}
func (s *square) lookRightDown() *square {
n := s.rightDown()
if n != nil && !n.seat {
return n.lookRightDown()
}
return n
}
func (s *square) lookDownLeft() *square {
n := s.downLeft()
if n != nil && !n.seat {
return n.lookDownLeft()
}
return n
}
func appendNonNil(s []*square, e *square) []*square {
if e != nil {
return append(s, e)
}
return s
}
func (s *square) visibleSeats() []*square {
result := []*square{}
result = appendNonNil(result, s.lookLeft())
result = appendNonNil(result, s.lookRight())
result = appendNonNil(result, s.lookUp())
result = appendNonNil(result, s.lookDown())
result = appendNonNil(result, s.lookLeftUp())
result = appendNonNil(result, s.lookUpRight())
result = appendNonNil(result, s.lookRightDown())
result = appendNonNil(result, s.lookDownLeft())
return result
}
func (s *square) adjacentSeats() []*square {
result := []*square{}
result = appendNonNil(result, s.left)
result = appendNonNil(result, s.right)
result = appendNonNil(result, s.up)
result = appendNonNil(result, s.down)
result = appendNonNil(result, s.leftUp())
result = appendNonNil(result, s.upRight())
result = appendNonNil(result, s.rightDown())
result = appendNonNil(result, s.downLeft())
return result
}
func (s *square) tick() bool {
// Noop tock function
s.tock = func() error { return nil }
if !s.seat {
return false
}
var seats []*square
if lookVisible {
seats = s.visibleSeats()
} else {
seats = s.adjacentSeats()
}
if s.isAvailable() {
// Check adjacent seats
for _, adj := range seats {
if adj.hasPerson() {
// If any adjacent seat is occupied, do nothing
return false
}
}
// Nothing is occupied? Sit!
s.tock = s.sit
return true
}
if s.hasPerson() {
numOccupied := 0
for _, adj := range seats {
if adj.hasPerson() {
numOccupied++
}
}
if numOccupied >= maxOccupied {
s.tock = s.leave
return true
}
}
return false
}
func (s square) String() string {
// return fmt.Sprintf("%v", s.loc)
if !s.seat {
return "."
}
if s.occupied {
return "#"
}
return "L"
}
func readMap() *[][]*square {
worldMap := [][]*square{}
rowIndex := 0
if err := processLines("input.txt", func(line string) (bool, error) {
// fmt.Printf("New line! %d\n", rowIndex)
row := []*square{}
var leftSeat *square
for i, c := range line {
var s square
switch c {
case emptySeatCode:
s = square{loc: point{i, rowIndex}, seat: true}
case occupiedSeatCode:
s = square{loc: point{i, rowIndex}, seat: true, occupied: true}
case floorCode:
s = square{loc: point{i, rowIndex}, seat: false}
default:
return false, fmt.Errorf("unknown square value %x", c)
}
// fmt.Printf("%v", s.loc)
if leftSeat != nil {
s.setLeft(leftSeat)
}
if rowIndex > 0 {
up := worldMap[rowIndex-1][i]
// fmt.Printf("\nTry set above %d,%d to %d,%d ", i, rowIndex, up.loc.x, up.loc.y)
s.setUp(up)
}
leftSeat = &s
row = append(row, &s)
}
// fmt.Println(row)
worldMap = append(worldMap, row)
// fmt.Printf("\n")
rowIndex++
return false, nil
}); err != nil {
log.Fatal("could not parse map", err)
}
return &worldMap
}
func printMap(worldMap *[][]*square) {
for _, row := range *worldMap {
for _, s := range row {
fmt.Print(s.String())
}
fmt.Print("\n")
}
}
func tickMap(worldMap *[][]*square) bool {
worldChanged := false
for _, row := range *worldMap {
for _, s := range row {
worldChanged = s.tick() || worldChanged
}
}
return worldChanged
}
func tockMap(worldMap *[][]*square) error {
for _, row := range *worldMap {
for _, s := range row {
err := s.tock()
if err != nil {
return err
}
}
}
return nil
}
func countOccupied(worldMap *[][]*square) int {
occupied := 0
for _, row := range *worldMap {
for _, s := range row {
if s.hasPerson() {
occupied++
}
}
}
return occupied
}
func run() {
worldMap := readMap()
if printMaps {
fmt.Println("Time 0")
printMap(worldMap)
}
var err error
t := 1
changed := true
for changed {
changed = tickMap(worldMap)
err = tockMap(worldMap)
if err != nil {
log.Fatal(err)
}
if printMaps {
fmt.Printf("\nTime %d (%t)\n", t, changed)
printMap(worldMap)
}
t++
}
fmt.Printf("\nTotal %d occupied seats after %d iterations\n", countOccupied(worldMap), t)
}
func main() {
// Part 1
run()
// Part 2
maxOccupied = 5
lookVisible = true
run()
}

779
d12/input.txt Normal file
View File

@ -0,0 +1,779 @@
S3
W3
F47
L90
W1
F42
N1
R90
F7
R90
E2
S1
W2
F11
E4
N1
F77
W1
S3
W4
F64
W3
R180
N5
E1
F8
N1
F54
N2
L180
N1
F44
E2
N2
L90
W3
F5
W2
L180
F100
N3
E1
W4
N5
F40
R180
W5
R90
N1
W3
R270
N1
R90
S5
F10
E4
N4
F56
E3
N4
W4
R90
N3
F24
F58
R90
N2
R90
W5
S2
R90
W3
R90
W1
N3
R90
N4
E2
F25
N5
N4
L90
E5
N4
R90
N1
R90
F73
W1
S3
W4
W1
F28
W3
E2
S3
F28
S3
R270
E1
S2
W3
S3
L90
F56
E5
L180
R90
F48
N2
F75
S2
E5
F21
F57
N5
L90
E4
N4
F14
S3
F75
W5
L90
E3
R90
N1
W4
F4
W5
S3
E3
F68
N3
R90
W4
N5
S3
F4
R90
F48
R90
F93
R90
S3
F90
R90
F41
N2
S1
E5
F19
E3
F71
R180
F16
W3
N4
W3
F12
L180
L90
R180
W4
R90
F26
W1
E4
F65
L90
F90
W5
S4
W1
E3
L90
W3
N2
F77
W2
L90
E4
S2
W5
F60
R90
F45
R90
S3
F56
W2
S3
W5
F58
L90
N1
F94
S4
F17
W5
R180
S2
R90
N4
W1
S3
R180
F93
R90
F45
E4
R90
S1
F81
E2
L90
S1
F63
E2
R90
E2
N1
W1
L90
F91
S5
L270
E3
S1
F29
N4
R180
F44
L90
E3
L90
F90
R90
F93
N2
S2
F28
E1
F58
N1
F9
L90
S1
F74
N2
F19
L180
S3
E1
R90
F55
S3
L90
F58
S1
R90
E4
F42
S5
R90
S4
L90
S1
E3
F75
L90
F44
E2
F50
S2
N4
W2
F14
W2
N2
F14
S1
W4
F74
L90
F52
W3
S5
L90
W5
N3
L90
F54
S1
R90
E3
R90
F23
S4
F75
N5
R90
F79
R90
F70
N2
F89
W1
S5
E2
F44
L180
W5
R90
F72
R90
N3
W4
N4
F90
R270
E4
F43
W4
F44
N5
F55
S4
F68
S1
E1
F39
W2
N4
F46
W5
F62
E1
R270
F97
W4
L180
F41
R90
W3
R270
S1
E1
R90
E2
F18
E2
F12
R90
W5
L90
E2
F82
N3
E5
F45
N5
F69
N5
W1
R90
F15
W1
S2
R90
F50
S4
S5
W2
S4
F21
E5
L90
F47
E1
F73
L90
F4
R90
F65
E2
S4
F52
E1
N1
L90
S1
F41
R180
S2
F5
E1
R90
N3
F29
L90
F69
E4
F92
R90
N4
L180
W5
N3
R180
W1
N5
E5
F1
N3
F19
W4
F33
N2
R90
E2
N3
F68
E3
S1
R90
N3
R180
E5
R90
W1
R90
S2
L90
F67
W2
S4
R270
W1
R90
F11
L180
F83
R90
N3
L90
W1
N1
L90
F41
N4
F45
S2
W4
S4
F92
E3
F21
R180
W4
S1
N3
R90
N2
L90
F97
N4
F99
F78
E2
S3
W1
N4
N1
E1
L180
F32
S1
F84
L90
S3
L90
E3
R90
F62
N4
L90
E2
R90
F68
S4
F29
E5
S5
R180
S1
F15
W1
S3
F65
L180
F54
L90
W2
S3
W2
F22
L180
W5
R90
E4
L90
F65
W5
F82
S3
W5
L90
F83
W4
L90
E1
F92
W4
N2
F99
L90
E5
R180
N5
W5
R90
N3
F74
R90
N1
F26
S3
W2
N2
E3
L90
F75
R90
F12
W3
S5
L90
N2
E4
F13
E1
F44
N3
R90
E5
R90
W4
F4
W5
N3
W3
F40
L180
W3
N2
E3
F57
W1
F16
S2
W3
R90
W3
F24
R90
F84
R90
W2
R270
S1
L180
F62
W1
R180
F71
E2
S2
R90
F84
E2
F64
R90
S5
F42
S4
F37
E5
R90
S2
R90
S4
W1
R180
F71
W3
F19
W5
R180
F98
S5
R90
N2
W5
N5
F14
L270
F29
L90
F94
W4
F92
W5
N4
F78
N1
S3
F10
L90
F72
R90
S2
L180
N3
R180
W3
F83
N4
E5
N2
E3
L90
E2
F84
S4
R90
E3
S4
F59
R90
W1
R90
F29
S4
W1
S5
L90
F77
R90
N4
F69
L90
W5
F15
N3
N1
L180
N2
N4
W4
N1
L180
W4
F5
R180
E2
R90
S2
R90
N2
F49
L180
F32
N5
R90
W5
L90
E1
F46
E1
L90
W3
F69
N5
E1
S3
L90
F98
W2
L90
F17
W3
N2
F78
E5
W1
S1
F73
S2
F36
N5
E3
F61
R90
E4
F88
L90
E4
R180
W4
S2
R180
N2
F17
E5
S5
E1
R90
S3
L90
R90
S4
F1
W2
N1
W5
F35
S2
F78
S2
L90
W1
L180
N4
F99
F34
L90
N5
R90
S4
L90
N2
F72
E5
S4
R180
S4
F18
W1
L90
E1
S4
E2
R90
F62
L90
F71
S1
F18
F6
N1
F28
L90
N1
F24
E1
R90
S2
F51

180
d12/main.go Normal file
View File

@ -0,0 +1,180 @@
package main
import (
"bufio"
"fmt"
"log"
"math"
"os"
"strconv"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
type ship struct {
// Ship position and heading
e, n, heading int
// Waypoint positions
pe, pn int
}
func (s *ship) part2(inst string) error {
fmt.Println("Read inst", inst)
c := inst[0]
amt, err := strconv.Atoi(inst[1:])
if err != nil {
return err
}
switch c {
case 'N':
s.pn += amt
case 'S':
s.pn -= amt
case 'W':
s.pe -= amt
case 'E':
s.pe += amt
case 'R':
err = s.rotateWaypoint(amt)
case 'L':
err = s.rotateWaypoint(-amt)
case 'F':
err = s.moveToWaypoint(amt)
default:
err = fmt.Errorf("unknown instruction %s", inst)
}
fmt.Printf("After move %+v\n", s)
return err
}
func (s *ship) moveToWaypoint(amt int) error {
s.n += amt * s.pn
s.e += amt * s.pe
return nil
}
func (s *ship) rotateWaypoint(amt int) error {
if amt < 0 {
amt = 360 + amt
}
for i := 0; i < amt/90; i++ {
s.pe, s.pn = s.pn, -s.pe
}
return nil
}
func (s *ship) forward(amt int) error {
switch s.heading {
case 0:
s.n += amt
case 90:
s.e += amt
case 180:
s.n -= amt
case 270:
s.e -= amt
default:
return fmt.Errorf("unable to move in heading %d", s.heading)
}
return nil
}
func (s *ship) changeHeading(amt int) error {
// Add to heading
for amt < 0 {
amt = 360 + amt
}
s.heading = (s.heading + amt) % 360
return nil
}
func (s *ship) move(inst string) error {
c := inst[0]
amt, err := strconv.Atoi(inst[1:])
if err != nil {
return err
}
switch c {
case 'N':
s.n += amt
case 'S':
s.n -= amt
case 'W':
s.e -= amt
case 'E':
s.e += amt
case 'R':
return s.changeHeading(amt)
case 'L':
return s.changeHeading(-amt)
case 'F':
return s.forward(amt)
default:
return fmt.Errorf("unknown instruction %s", inst)
}
return nil
}
func part1() {
s := ship{0, 0, 90, 0, 0}
if err := processLines("input.txt", func(line string) (bool, error) {
return false, s.move(line)
}); err != nil {
log.Fatal(err)
}
dist := int(math.Abs(float64(s.e)) + math.Abs(float64(s.n)))
fmt.Printf("Resulting position %d,%d Distance: %d\n", s.e, s.n, dist)
}
func part2() {
s := ship{0, 0, 90, 10, 1}
if err := processLines("input.txt", func(line string) (bool, error) {
return false, s.part2(line)
}); err != nil {
log.Fatal(err)
}
dist := int(math.Abs(float64(s.e)) + math.Abs(float64(s.n)))
fmt.Printf("Resulting position %d,%d Distance: %d\n", s.e, s.n, dist)
}
func main() {
part1()
part2()
}

2
d13/input.txt Normal file
View File

@ -0,0 +1,2 @@
1000066
13,x,x,41,x,x,x,37,x,x,x,x,x,659,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,19,x,x,x,23,x,x,x,x,x,29,x,409,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,17

132
d13/main.py Executable file
View File

@ -0,0 +1,132 @@
#! /usr/bin/env python3
import sys
import math
from typing import List
from typing import Tuple
def read_file(filename: str) -> Tuple[int, List[int]]:
with open(filename) as f:
ts = int(next(f).strip())
busses = [
int(bus) if bus != "x" else -1
for bus in next(f).strip().split(",")
]
return ts, busses
def read_cli(arg: str) -> List[int]:
busses = [
int(bus) if bus != "x" else -1
for bus in arg.strip().split(",")
]
return busses
def wait_time(ts: int, bus_id: int) -> int:
return (bus_id - (ts % bus_id) % bus_id)
def part1():
ts, busses = read_file("input.txt")
min_wait = -1
min_bus_id = 0
for bus_id in busses:
if bus_id < 0:
continue
w = wait_time(ts, bus_id)
if min_wait < 0 or w < min_wait:
min_wait = w
min_bus_id = bus_id
print(f"Wait {min_wait} for bus {min_bus_id}. Answer {min_wait * min_bus_id}")
def part2(busses=None, start=0):
if busses is None:
_, busses = read_file("input.txt")
# busses = [7, 13, -1, -1, 59, -1, 31, 19]
t = start
# t = 100000000000000
# t = t - (t%7)
# if t%7 != 0:
# print("Not starting with multiple of 7")
# return
while True:
# print(f"Checking time {t}")
for i, bus_id in enumerate(busses):
if bus_id < 0:
continue
if i == 0:
w = t % bus_id
else:
w = wait_time(t, bus_id)
# print(f"Wait for bus {bus_id} is {w} expect {i}")
if w != i:
if i > 0:
t += busses[0]
else:
t += 1
break
else:
print(f"All busses match for time {t}")
break
def part2_calc(busses=None, start=0):
if busses is None:
_, busses = read_file("input.txt")
# busses = [7, 13, -1, -1, 59, -1, 31, 19]
t = start
last_index = 0
product = -1
while True:
print(f"Checking time {t}")
for i, bus_id in enumerate(busses[last_index:], last_index):
if bus_id < 0:
continue
if i == 0:
w = t % bus_id
else:
w = wait_time(t, bus_id)
print(f"Wait for bus {bus_id} is {w} expect {i}")
if w == i % bus_id:
last_index = i+1
if product < 0:
product = bus_id
else:
product = product * bus_id
print(f"New index {last_index}, new product {product}")
else:
if i > 0:
t += product
else:
t += 1
break
else:
print(f"All busses match for time {t}")
break
if __name__ == "__main__":
if len(sys.argv) == 1:
part1()
part2_calc()
else:
busses = read_cli(sys.argv[1])
b1, b2 = busses[0], busses[1]
t = b1 * math.floor(b2/b1)
print(f"Maybe t = {t}")
start = 0
if len(sys.argv) > 2:
start = int(sys.argv[2])
print("brute")
part2(busses, start)
print("")
print("calc")
part2_calc(busses, start)

572
d14/input.txt Normal file
View File

@ -0,0 +1,572 @@
mask = 01X11X10X10110110X111X11010X1X101010
mem[19409] = 3025
mem[40104] = 798480382
mem[25359] = 905
mask = 01011X111100XX1100X1X10X110000000000
mem[55479] = 930785
mem[25548] = 130263864
mem[60518] = 202648
mem[11955] = 1138
mem[45248] = 753
mask = 00XX10001XXX00101X1XX1101000010X0010
mem[2050] = 27965
mem[5662] = 110507779
mem[60807] = 1608
mask = 000110101100XX10X01000X010X000010100
mem[28713] = 1039
mem[22733] = 182274602
mem[21460] = 12248397
mem[60257] = 103
mem[13722] = 137279
mem[2117] = 208446548
mask = 100110111X011X1X10110X11010001X11XX0
mem[29709] = 6606
mem[27812] = 143567051
mem[3595] = 478522065
mem[13123] = 7445318
mem[37070] = 32452
mem[60140] = 47608
mem[21316] = 69201021
mask = X10X0010110000111111X0X11X10X1000111
mem[29528] = 3980
mem[41054] = 274606
mem[34884] = 265241899
mem[7496] = 228368
mem[35014] = 109110
mem[40696] = 172101503
mask = 010X011010X0001X11101011X1X100010100
mem[23210] = 3864280
mem[53761] = 5046
mem[6853] = 1214
mem[45297] = 219
mem[33797] = 1843462
mask = 01011011110011110X0X01110110010XX000
mem[15509] = 16472647
mem[19332] = 526724681
mask = 0101X0101100X01X111X1X11X000X1X1X110
mem[16393] = 122368236
mem[18852] = 4351408
mem[56526] = 780
mem[46701] = 31085562
mem[53459] = 47134
mem[19409] = 7629114
mem[47891] = 76573711
mask = 000110X0010010X0X010XX110000X0X1000X
mem[35342] = 1095
mem[56466] = 3462270
mem[31124] = 204698678
mem[104] = 2115
mem[22733] = 154721
mask = 00X100X01XX000101X1001110000010XX110
mem[44047] = 6823624
mem[11955] = 242152
mem[41039] = 515174779
mask = 0101101X110X10110X11101011X00110XXXX
mem[46716] = 52535895
mem[20578] = 851818
mem[7307] = 1658
mem[59777] = 7566837
mem[38136] = 6
mem[18835] = 95379
mem[37574] = 28195477
mask = 010XXX101X0X0011X1100X1001110X01X100
mem[17831] = 4467
mem[45439] = 61064
mem[43070] = 291981105
mem[9562] = 725
mem[18574] = 82455219
mem[53761] = 2223
mask = 0001X010X1001010XX10011110000011000X
mem[24954] = 229575
mem[49643] = 118597
mem[40891] = 218656479
mem[6549] = 655
mem[16413] = 105021
mask = 01X0X01010010X111X1001X0X1X1X0000110
mem[24722] = 3306225
mem[18574] = 2046331
mem[51991] = 2879
mask = 010X10001X00XX10000000101100000X0000
mem[64694] = 69415191
mem[42979] = 1589
mem[49282] = 199
mem[3987] = 2386
mem[64631] = 17661
mask = 011XXX1010010111101X0000100100X10XX0
mem[21201] = 341993
mem[61134] = 328
mem[19716] = 463044
mem[53800] = 23668576
mem[46317] = 368717
mem[3978] = 2699
mask = X10X01X011001011X111101010X0XX111111
mem[5567] = 9644235
mem[50029] = 4717
mem[34043] = 119207
mem[35949] = 665131137
mem[58233] = 98752
mask = 0X00001011X0001111X000100X0000XX0110
mem[28818] = 809
mem[20113] = 604
mem[58178] = 11229
mem[9389] = 38294680
mem[34657] = 8016112
mem[10161] = 1585984
mem[8020] = 1403857
mask = 01011011110XX0110111111101100X000X01
mem[47451] = 201798
mem[62498] = 61888
mem[49564] = 16728
mem[60513] = 23392513
mem[36774] = 56575
mem[22431] = 70709
mask = 011X100011000X1X10X0101100X10X011111
mem[41938] = 34906
mem[62853] = 221817
mem[50173] = 471027372
mem[55286] = 4561108
mask = 1X010X0011010000X1100X000101X101X000
mem[22998] = 62382
mem[18574] = 57889052
mem[57700] = 1018
mask = X1XX0X1011001011111X101X111001111111
mem[34453] = 6483
mem[49122] = 391290
mask = 01010000000100110XX000011X00X01XX10X
mem[23870] = 19517
mem[24291] = 616878
mem[12134] = 1990123
mem[26637] = 55962054
mem[47968] = 712481177
mem[20878] = 242502
mem[30722] = 1568
mask = 11X11111X100XX1000100111100000000010
mem[35335] = 59630
mem[63185] = 11256526
mem[30722] = 266092278
mem[9776] = 63532545
mask = 10010010010X1010111X11001000X110101X
mem[12312] = 4029860
mem[27593] = 42705942
mem[46156] = 27895
mem[64088] = 1408576
mem[50342] = 15980145
mem[46315] = 29427
mem[47451] = 18865
mask = 011111001X0XX01010100110X11000X01100
mem[1293] = 837
mem[29000] = 10697
mask = XX0X0010X1001010XX11X01110X101101100
mem[42918] = 1028
mem[2608] = 3093
mem[21904] = 6098595
mem[41278] = 1039294
mem[53102] = 858102784
mask = 0X0110X01100X010X0X0001X10X00XX00000
mem[20578] = 860568571
mem[52466] = 143792
mem[10261] = 182
mask = 0X0110101100X011XX111X111110111X11XX
mem[5752] = 37841428
mem[31368] = 1094581
mask = 000X11101X01001110100001000X0100100X
mem[56372] = 1046359
mem[19541] = 315663570
mem[37436] = 437380
mem[54334] = 241690746
mem[16559] = 3127549
mem[59609] = 176914004
mask = 110101X01XX1000X0XX0100000X0000XX101
mem[1033] = 8174
mem[49587] = 107787
mem[1572] = 430
mem[49873] = 115828687
mem[24389] = 2707208
mem[30170] = 91827506
mask = 01XX01001XX10010X0101001000000011101
mem[26015] = 198698
mem[50136] = 19382
mem[16413] = 103882
mem[8340] = 2066093
mask = XX01101X1101101XX01111X01X1100X00100
mem[42378] = 518494
mem[13927] = 94055
mem[48225] = 15652034
mask = 000100X0110X101X0X1XXX1X10110011101X
mem[65006] = 6769
mem[46625] = 5473325
mem[22440] = 617624684
mem[24954] = 719974
mem[53626] = 62067
mask = 00011XX01101X01X1010X11X10000X00X0X0
mem[43072] = 106139234
mem[53459] = 26813614
mem[31162] = 184146764
mask = 0X01X0101X00001XXX10X11X000001000010
mem[5467] = 121320
mem[63724] = 11067492
mem[57246] = 315
mem[16413] = 2008242
mem[10240] = 11073
mem[24282] = 618660016
mask = 1101111011000010101X1101X0X0001X1011
mem[61598] = 627237127
mem[16057] = 235475116
mem[5662] = 6226
mem[61721] = 26023344
mem[58178] = 209547
mem[59687] = 141941
mem[9548] = 1392254
mask = 00011X1000X01010011X01111X0110X10100
mem[13185] = 300556
mem[51203] = 17097
mem[59687] = 8787507
mem[12337] = 124607
mem[46043] = 4378256
mask = 1100X100110100100110X10X000X01111101
mem[17458] = 420459
mem[46315] = 142385
mem[7273] = 58415
mem[49604] = 57549
mem[33375] = 12460422
mem[61540] = 7752
mask = X1X11XXX1100X010X0100100000000X00010
mem[28889] = 13691764
mem[27546] = 355436
mem[45337] = 10614
mem[64088] = 960
mem[39291] = 3019
mem[30722] = 1976602
mem[18725] = 299
mask = 0X111X1011000X101010X0X001X100XX1010
mem[5532] = 413573
mem[7707] = 78463710
mem[46156] = 25164851
mem[17354] = 15295191
mask = 000110100X0X10100X100011XX0010010000
mem[18725] = 7003
mem[49536] = 49752
mem[33519] = 116272721
mem[46701] = 253380665
mask = 000X001001001XXX101XX00X0101X1010000
mem[57459] = 792510
mem[10350] = 217210394
mem[43612] = 178868
mem[2374] = 42534899
mem[40891] = 621
mem[7270] = 1014999
mem[49038] = 1657373
mask = 00XX10100001100X01000110001001010X10
mem[7270] = 1904
mem[33267] = 171621958
mem[42531] = 623
mask = 011111001100001X00X0010X10010010001X
mem[59756] = 19646
mem[45248] = 182118
mem[49395] = 186
mem[46043] = 1875998
mem[42378] = 2150393
mem[16423] = 449813446
mask = 00X10X1001001010111X0X11100XX0101X01
mem[42378] = 11316
mem[6217] = 448726
mem[56349] = 105698
mem[18523] = 6560236
mask = 0X01101011000X101111X1110010X1110111
mem[57685] = 1052364113
mem[42200] = 1624
mem[64281] = 162750
mem[53459] = 900417618
mem[44010] = 311326
mem[38385] = 168338
mem[64234] = 715
mask = 0110001010X1001X111000XX01X110X1000X
mem[46270] = 413222
mem[20358] = 301418973
mask = 0101X01010000X1X111001000X010000X100
mem[25549] = 9478586
mem[27938] = 186993583
mem[10014] = 630139
mem[50316] = 22183454
mask = 00X10XX0110010100X10XX11X01000100010
mem[51762] = 575
mem[39895] = 33305
mem[19768] = 31036515
mem[30918] = 522221
mem[26371] = 790132
mem[43705] = 13814
mask = 00XXX010X1100010100101110101X0001110
mem[12495] = 2801000
mem[43811] = 35764
mem[59173] = 235362
mem[50677] = 13747007
mem[47458] = 49520
mask = 00X1101X1100X010X010001010000000010X
mem[19737] = 309
mem[10289] = 1391
mem[44222] = 202053013
mem[32818] = 57015
mask = XX111010X10XX0101010XX00000X00100X01
mem[25062] = 92115406
mem[40507] = 8539848
mem[6853] = 1555113
mem[59566] = 55734
mem[29440] = 3860
mem[2339] = 1687
mask = X0X100100100X000X0011000100100110001
mem[62983] = 496942
mem[55239] = 31959819
mem[23037] = 185
mem[14426] = 11052660
mem[59756] = 11483028
mask = 0X1X101011X0101X0X100110100110X101XX
mem[9761] = 26687118
mem[152] = 1818
mask = 01X110X01010001X1110XXX0000100X100X0
mem[46327] = 780262
mem[11424] = 1003003
mask = 010011XX100X0011X1XX000X01X10X011110
mem[40928] = 10697
mem[989] = 22449916
mem[9034] = 107225
mask = 010100X0X001001101100XX110X0000X10X0
mem[50403] = 60110
mem[1465] = 9126
mem[4598] = 348452
mem[26661] = 17672110
mask = 00X110101XX00010100X0010010011X10010
mem[38295] = 20183
mem[61069] = 22691
mem[51394] = 7278100
mem[18711] = 34474
mem[52888] = 1962576
mask = 1001001X0X001010101X0110XXX001XX100X
mem[33226] = 3641501
mem[2376] = 72068973
mem[57257] = 11382653
mem[22489] = 47282
mem[45359] = 38362
mask = 010X1X10010X101X01111010111110111011
mem[26980] = 755824
mem[47763] = 385
mem[23332] = 30083831
mem[32975] = 61896119
mask = XX0110111101X011X011X0XXX10000011100
mem[29709] = 711754376
mem[36513] = 71516
mem[7293] = 5061813
mem[60256] = 419151
mask = 0101101011000XX1111111X001100100XX00
mem[19475] = 35852
mem[57183] = 6494332
mem[1327] = 872346
mem[2543] = 943
mem[2188] = 868813
mem[29387] = 209125695
mask = 00X1X0101X1000X01X010X1X01100X0X1101
mem[51955] = 196066365
mem[38207] = 15671526
mem[26980] = 75520251
mem[11077] = 161630247
mem[26456] = 30666501
mem[19737] = 9386
mask = 1101011010110X0X01101XX001X0X001X001
mem[49292] = 858273
mem[11497] = 884831
mem[49282] = 93065
mem[54031] = 862594
mask = 0X01011010X1X01111X0X0X00X11X1010100
mem[58536] = 4031842
mem[11621] = 155458283
mem[8786] = 12859
mask = 00010010XXX000X010010X1XX001X0X01100
mem[45429] = 122467
mem[57256] = 759
mem[3687] = 384128816
mem[56464] = 10758724
mem[11869] = 652805159
mem[50173] = 75914445
mask = 0001001001001010111XX10X1X0XX0111101
mem[5809] = 743780
mem[52067] = 806
mem[12750] = 22132
mem[13019] = 654
mask = 00X110X01100101X00100X1X00XX00100001
mem[2117] = 4067660
mem[2068] = 9851885
mem[48662] = 52185630
mem[24246] = 72048
mem[25978] = 5182633
mask = 010X1010X0X0001111100X001101X01X0XX0
mem[10242] = 1118
mem[57601] = 525
mem[38099] = 930509
mask = 10111101110X0X10001001X00001001000X1
mem[50741] = 59787235
mem[1588] = 218533
mem[33080] = 182579
mem[3978] = 1591079
mem[62070] = 15472
mask = 0101100X1100X0X10110X010000X000X00X1
mem[3814] = 788124
mem[63265] = 215577374
mem[57364] = 1311024
mem[36364] = 3985
mem[18564] = 4526
mem[23647] = 376609
mask = 001XX00011010010111000101X100X0011X0
mem[61429] = 6896
mem[22094] = 1966698
mask = X00110111101XX111011101X011010100X01
mem[36214] = 310642
mem[59733] = 1160
mem[10909] = 1820
mem[25225] = 51102962
mem[35074] = 514484736
mem[21460] = 3630
mask = 1001001X01001010XX10111001XX1X1X1000
mem[53608] = 6145
mem[44618] = 302105
mem[50955] = 12609449
mem[48282] = 22035626
mask = 01X1XX001XXX001XX0100111000000001100
mem[47458] = 4534
mem[26444] = 4150059
mem[10366] = 1061
mem[51657] = 2817023
mem[35995] = 1064419
mem[38295] = 148703436
mask = 01X0001010010X1110X0000010111X001000
mem[26046] = 2672378
mem[1080] = 682
mem[2151] = 737
mask = 110X0100110100X001X0X1XXX100011101X0
mem[56044] = 527135884
mem[39296] = 107094645
mem[61785] = 1261
mask = 01001X00100X0011010000000101000XX101
mem[54752] = 16579540
mem[36330] = 1696582
mem[1435] = 240113842
mem[49758] = 7811
mem[51729] = 2543212
mem[10909] = 13139
mask = 0X0XXX100001101X011010101000011001XX
mem[58487] = 9986
mem[7175] = 3371969
mem[14294] = 10275
mem[36225] = 13168
mem[7934] = 48879
mem[47891] = 1571293
mem[18711] = 399
mask = X1010XX01X01001X01101010X1X00001X010
mem[62247] = 18380710
mem[20715] = 15548870
mem[61924] = 28821546
mem[40119] = 181518508
mem[50251] = 59934
mask = XXX1011X11X100X1X110001011X001100001
mem[13627] = 4734
mem[36208] = 48295
mem[37672] = 184327969
mem[60518] = 9137
mem[46168] = 105126453
mask = 1X111101110X0010001000XX000100XXX011
mem[4455] = 17333982
mem[58592] = 931411
mem[61752] = 198443
mem[183] = 808
mask = XX010010010XX0101011111111010011X100
mem[6221] = 256009562
mem[3528] = 422478
mem[16002] = 6328770
mask = 0X01X00011001010XX000010100000100010
mem[31570] = 32237
mem[14971] = 846258186
mem[18978] = 1202
mem[15368] = 120674
mem[13185] = 22420
mask = 010110111101101XX011X11XX11X00X00X00
mem[59330] = 628
mem[9283] = 58883
mem[44010] = 387833048
mask = 010010101001X1111010111X000X00X0X110
mem[50633] = 751888
mem[11056] = 31979
mem[50741] = 4724
mem[40028] = 7336181
mem[42263] = 6863
mask = 0001X010110000X00010010X10000XX10100
mem[20546] = 8708
mem[36908] = 234294
mem[63185] = 1408
mem[57531] = 1054
mem[13722] = 1045167819
mem[4617] = 3519205
mask = 00111000X10010X10010X01010X00010010X
mem[46693] = 4740
mem[17824] = 884
mem[54997] = 339096
mem[2117] = 26803
mem[20] = 84635057
mask = 0101XXX01100X011011X010000000X00X100
mem[40142] = 140297
mem[53459] = 5575659
mem[57435] = 69641959
mem[28563] = 433881
mem[59188] = 230341
mem[26483] = 151116806
mask = 110101X01XX100X10110001XX1X0X01000X1
mem[37526] = 454911
mem[35793] = 3340
mem[54537] = 630806
mem[58456] = 115228
mem[59172] = 13363
mask = 010110X0110000101010X001111X0X010010
mem[45969] = 1736711
mem[2487] = 610736260
mem[54173] = 453
mem[55144] = 2748104
mem[52466] = 6109568
mem[31890] = 3977366
mask = 01011001110000X101100X00X00X10010000
mem[64336] = 3971537
mem[60265] = 85267
mem[24597] = 7455656
mem[34924] = 703390248
mem[40391] = 328312
mem[49255] = 1117186
mask = 110X0100101100X1011010101X0X11X11010
mem[31313] = 789405
mem[7934] = 1803
mem[36190] = 1836611
mask = X0010010010010101X1X1X1010X111X010XX
mem[4017] = 64210
mem[40696] = 58930789
mem[18166] = 195479433
mem[41257] = 40207
mem[40948] = 1058796
mem[30803] = 486
mem[29709] = 72337
mask = 000X101000X110X001X00110X1X0011X0XX1
mem[11077] = 1653
mem[2376] = 77389
mem[19561] = 4876923
mem[32851] = 538156
mem[38532] = 1110
mask = X101101011X010111110X0111001X101010X
mem[44618] = 13980
mem[10366] = 711247
mem[4942] = 74171
mem[25306] = 350133
mem[21409] = 27748
mask = 00011010X1001010XXX0001110000001011X
mem[5809] = 1082
mem[36908] = 180
mem[59172] = 196430412
mem[60137] = 1388
mem[49643] = 1887
mask = 01011010X10000X1111111111XX00101111X
mem[56344] = 1237
mem[23638] = 37922654
mem[20307] = 593227321

200
d14/main.go Normal file
View File

@ -0,0 +1,200 @@
package main
import (
"bufio"
"fmt"
"log"
"math"
"os"
"regexp"
"strconv"
"strings"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
var memExtractor = regexp.MustCompile(`^mem\[([0-9]+)] = ([0-9]+)`)
func powInt(x, y int) int {
return int(math.Pow(float64(x), float64(y)))
}
func applyMask(mask string, v int) (int, error) {
for i := 0; i < len(mask); i++ {
m := mask[len(mask)-i-1]
switch m {
case 'X':
case '1':
v |= powInt(2, i)
case '0':
v &^= powInt(2, i)
default:
return 0, fmt.Errorf("could not apply mask %v in position %d", m, i)
}
}
return v, nil
}
func sprintBinArray(a []int, z int) string {
r := " "
for _, v := range a {
f := fmt.Sprintf("%%%db(%%d)", z)
r += fmt.Sprintf(f, v, v)
}
return fmt.Sprintf("[%s]", r)
}
func applyFloatingMask(mask string, v int) ([]int, error) {
base2 := 2
results := []int{v}
// fmt.Printf("Applying %s to %8b\n", mask, v)
for i := 0; i < len(mask); i++ {
m := mask[len(mask)-i-1]
// fmt.Printf("Apply %s at %d ", string(m), i)
resultLen := len(results)
for j := 0; j < resultLen; j++ {
switch m {
case 'X':
// Add a 0 mask to end of results
results = append(results, results[j]|powInt(base2, i))
// Apply a 1 mask in place
results[j] &^= powInt(base2, i)
case '1':
results[j] |= powInt(base2, i)
case '0':
// results[j] &^= powInt(base2, i)
default:
return results, fmt.Errorf("could not apply mask %v in position %d", m, i)
}
}
// fmt.Printf("Result %s\n", sprintBinArray(results, 8))
}
return results, nil
}
func parseMemValues(line string) (loc int, val int, err error) {
match := memExtractor.FindStringSubmatch(line)
if match == nil {
err = fmt.Errorf("could not extract mem val in %s", line)
return
}
loc, err = strconv.Atoi(match[1])
if err != nil {
err = fmt.Errorf("error parsing int from %s: %w", line, err)
return
}
val, err = strconv.Atoi(match[2])
if err != nil {
err = fmt.Errorf("error parsing int from %s: %w", line, err)
return
}
return
}
func part1() {
var mask string
mem := map[int]int{}
if err := processLines("input.txt", func(line string) (bool, error) {
if strings.HasPrefix(line, "mask") {
mask = strings.TrimPrefix(line, "mask = ")
} else {
loc, val, err := parseMemValues(line)
if err != nil {
return false, err
}
val, err = applyMask(mask, val)
if err != nil {
return false, fmt.Errorf("error applying mask to value on line %s: %w", line, err)
}
// fmt.Printf("mem[%d] = %d\n", loc, val)
mem[loc] = val
}
return false, nil
}); err != nil {
log.Fatal(err)
}
sum := 0
for _, v := range mem {
sum += v
}
fmt.Printf("Total value in memory %d\n", sum)
}
func part2() {
var mask string
mem := map[int]int{}
if err := processLines("input.txt", func(line string) (bool, error) {
if strings.HasPrefix(line, "mask") {
mask = strings.TrimPrefix(line, "mask = ")
} else {
loc, val, err := parseMemValues(line)
if err != nil {
return false, err
}
locs, err := applyFloatingMask(mask, loc)
if err != nil {
return false, fmt.Errorf("error applying mask to value on line %s: %w", line, err)
}
for _, l := range locs {
mem[l] = val
}
}
return false, nil
}); err != nil {
log.Fatal(err)
}
sum := 0
for _, v := range mem {
sum += v
}
fmt.Printf("Total value in memory %d\n", sum)
}
func main() {
part1()
part2()
}

94
d15/main.go Normal file
View File

@ -0,0 +1,94 @@
package main
import "fmt"
type game struct {
turn, lastNumber int
history map[int]int
}
func newGame(startingNumbers []int) *game {
g := game{0, 0, map[int]int{}}
for _, n := range startingNumbers {
g.history[g.lastNumber] = g.turn
g.turn++
g.lastNumber = n
}
return &g
}
func (g *game) takeTurn() (int, int) {
// fmt.Printf("> Starting turn %d. last: %d\n", g.turn+1, g.lastNumber)
// fmt.Printf(">> state %+v\n", g)
var number int
// Get the new number
if t, ok := g.history[g.lastNumber]; ok {
// fmt.Printf(">> We've seen %d before!\n", g.lastNumber)
// Last number was seen
number = g.turn - t
} else {
// Otherwise the number is zero
number = 0
}
// Store the last turn in history
g.history[g.lastNumber] = g.turn
// Go to the next turn
g.turn++
g.lastNumber = number
// fmt.Printf(">> Incrementing turn and updating state %+v\n", g)
// fmt.Printf("Turn %d spoke \"%d\"\n", g.turn, g.lastNumber)
return g.turn, g.lastNumber
}
func (g *game) turnTo(targetTurn int) int {
var n int
for g.turn < targetTurn {
_, n = g.takeTurn()
}
return n
}
func part1() {
numbers := []int{16, 12, 1, 0, 15, 7, 11}
// numbers := []int{0, 3, 6}
g := newGame(numbers)
fmt.Println(g)
t, n := g.takeTurn()
for t < 2020 {
t, n = g.takeTurn()
}
fmt.Printf("Part 1: Number on turn %d is %d\n", t, n)
}
func part2() {
numbers := []int{16, 12, 1, 0, 15, 7, 11}
// numbers := []int{0, 3, 6}
g := newGame(numbers)
fmt.Println(g)
t, n := g.takeTurn()
for t < 30000000 {
t, n = g.takeTurn()
}
fmt.Printf("Part 2: Number on turn %d is %d\n", t, n)
}
func main() {
fmt.Println(newGame([]int{16, 12, 1, 0, 15, 7, 11}).turnTo(2020))
fmt.Println(newGame([]int{16, 12, 1, 0, 15, 7, 11}).turnTo(30000000))
part1()
part2()
}

12
d16/input-small.txt Normal file
View File

@ -0,0 +1,12 @@
class: 1-3 or 5-7
row: 6-11 or 33-44
seat: 13-40 or 45-50
your ticket:
7,1,14
nearby tickets:
7,3,47
40,4,50
55,2,20
38,6,12

11
d16/input-small2.txt Normal file
View File

@ -0,0 +1,11 @@
class: 0-1 or 4-19
row: 0-5 or 8-19
seat: 0-13 or 16-19
your ticket:
11,12,13
nearby tickets:
3,9,18
15,1,5
5,14,9

261
d16/input.txt Normal file
View File

@ -0,0 +1,261 @@
departure location: 29-766 or 786-950
departure station: 40-480 or 491-949
departure platform: 46-373 or 397-957
departure track: 33-657 or 673-970
departure date: 31-433 or 445-961
departure time: 33-231 or 250-966
arrival location: 48-533 or 556-974
arrival station: 42-597 or 620-957
arrival platform: 32-119 or 140-967
arrival track: 28-750 or 762-973
class: 26-88 or 101-950
duration: 30-271 or 293-974
price: 33-712 or 718-966
route: 49-153 or 159-953
row: 36-842 or 851-972
seat: 43-181 or 194-955
train: 29-500 or 513-964
type: 32-59 or 73-974
wagon: 47-809 or 816-957
zone: 44-451 or 464-955
your ticket:
151,103,173,199,211,107,167,59,113,179,53,197,83,163,101,149,109,79,181,73
nearby tickets:
339,870,872,222,255,276,706,890,583,718,924,118,201,141,59,581,931,143,221,919
400,418,807,726,84,142,820,112,228,687,335,855,761,740,627,532,369,313,147,620
474,926,741,424,632,982,876,926,738,936,300,726,400,321,348,160,421,464,78,258
337,683,885,368,214,215,620,650,321,311,200,696,838,880,526,812,821,891,829,204
678,69,480,939,219,736,628,948,178,296,204,890,199,526,736,210,170,923,228,726
574,55,871,945,347,207,840,707,442,791,159,216,427,312,947,326,738,801,264,54
811,259,417,932,870,634,945,408,706,766,303,402,942,50,415,150,839,674,904,836
670,358,701,172,231,914,875,205,586,517,576,206,796,400,363,303,295,932,73,308
319,949,312,803,217,6,719,870,202,883,111,532,467,801,83,202,331,637,930,412
580,262,196,529,401,806,446,104,326,657,589,789,876,817,470,653,167,191,634,678
720,217,118,422,190,115,684,827,317,228,524,569,531,471,322,408,896,566,875,302
678,683,218,820,896,303,296,316,229,758,114,261,825,750,901,428,479,556,373,404
502,259,577,77,260,588,340,199,626,575,171,422,372,83,111,902,300,863,800,886
577,216,195,804,298,948,83,807,878,656,740,743,854,740,219,331,714,176,683,199
492,187,259,528,853,80,808,887,149,723,324,922,170,323,884,825,710,562,416,471
702,55,141,261,743,256,632,693,787,581,363,851,578,74,164,146,413,224,829,282
370,161,470,207,876,57,564,103,195,216,468,632,161,734,487,150,570,251,311,196
242,430,115,575,806,258,109,85,433,794,85,258,647,596,84,339,215,879,203,74
912,449,174,371,857,556,743,537,521,643,903,745,764,207,295,896,431,901,592,332
687,361,855,683,298,828,421,894,163,214,308,110,643,495,106,198,613,205,322,582
318,578,83,318,150,182,298,740,424,306,411,895,50,265,887,465,912,262,294,428
320,948,74,114,643,801,928,280,868,930,822,140,620,696,627,520,692,820,526,764
622,477,314,253,419,73,333,924,750,432,705,894,114,827,364,946,577,269,789,463
639,742,840,541,656,787,222,637,728,734,558,744,173,801,80,629,634,572,151,326
830,468,597,75,259,762,331,315,151,369,308,419,447,207,523,268,118,719,501,839
496,312,525,343,559,77,114,404,362,595,656,301,622,337,741,818,816,352,1,449
432,512,627,739,729,627,218,829,595,471,641,447,639,350,220,718,573,319,859,363
646,368,258,320,916,520,328,327,180,357,646,620,530,208,269,84,264,53,184,163
904,657,329,897,327,339,674,803,110,327,308,78,883,353,150,446,296,645,539,932
472,726,685,676,406,419,594,419,699,364,416,868,106,53,662,856,859,571,674,571
301,741,900,869,259,727,557,975,334,913,496,948,929,79,165,680,838,465,591,902
939,201,586,897,948,725,625,224,923,801,910,723,361,338,55,217,721,300,674,777
362,211,592,573,711,831,170,949,171,408,647,578,228,349,629,780,582,567,84,349
317,874,623,704,934,526,898,797,447,485,400,589,679,109,827,107,353,807,859,513
519,108,304,162,888,88,742,637,789,923,749,404,171,175,708,432,559,200,557,444
787,589,518,397,762,200,734,222,468,252,306,560,558,701,905,656,155,689,51,258
354,159,938,734,932,636,478,162,562,718,315,712,933,862,530,877,118,535,366,797
189,338,517,302,414,401,167,905,947,500,895,940,405,222,864,706,835,352,269,825
757,404,212,426,628,113,945,480,398,271,353,364,225,804,643,84,416,728,936,223
337,529,631,589,909,314,174,820,257,199,822,359,344,445,929,20,513,450,212,928
254,927,865,202,851,733,897,329,433,224,319,674,857,722,837,207,419,84,728,375
416,464,822,368,920,175,0,213,799,200,648,529,398,889,678,407,180,870,496,786
712,335,80,824,826,416,261,400,904,630,255,691,259,723,344,354,786,857,774,195
945,257,57,260,642,817,934,909,574,358,269,683,764,176,365,427,549,878,500,791
807,140,308,885,866,623,80,111,648,848,572,643,853,854,560,934,699,52,580,164
895,590,647,730,540,874,255,115,304,117,224,399,168,819,420,525,306,160,580,595
594,265,401,920,855,62,352,706,908,835,925,908,829,620,476,51,251,73,875,696
261,748,411,706,409,53,470,202,227,918,653,398,516,518,416,187,917,836,649,222
288,690,877,468,620,451,147,919,251,408,836,584,319,729,640,445,673,87,650,856
308,806,477,875,329,928,948,800,417,574,220,991,355,51,693,838,747,794,498,913
706,582,499,834,887,109,677,857,280,407,651,517,468,407,403,303,515,881,656,523
256,597,344,577,636,702,561,738,683,884,268,858,73,201,421,721,646,739,424,992
903,211,920,623,160,152,567,786,852,423,179,258,690,493,110,505,823,303,721,373
397,893,747,819,729,88,651,893,699,229,744,948,712,104,741,643,511,854,876,706
929,880,820,532,259,621,307,480,900,59,915,188,863,624,119,252,928,935,451,885
335,893,475,733,787,850,629,839,530,231,451,942,260,718,654,473,255,495,406,464
451,822,629,745,226,595,295,862,408,592,498,474,77,110,845,354,906,424,913,936
75,891,446,347,468,521,312,320,346,579,900,205,528,307,370,890,8,269,826,566
566,353,58,360,629,793,649,567,259,736,261,531,118,880,244,145,581,172,885,471
107,371,947,936,250,468,624,888,334,622,947,327,837,941,360,521,754,199,688,905
313,163,370,367,8,174,341,792,153,736,725,581,313,203,872,225,590,720,841,475
210,823,329,556,763,691,371,202,807,902,741,413,303,832,651,802,473,358,990,897
718,652,891,367,702,640,645,883,817,231,590,842,350,820,291,681,422,859,691,338
349,408,890,915,116,719,872,589,586,620,116,206,683,353,317,81,319,86,849,797
84,520,856,641,254,206,209,356,178,476,728,114,559,802,579,377,298,112,941,853
518,741,500,466,796,676,833,235,330,854,494,762,58,923,908,228,335,433,85,565
418,697,943,513,854,907,824,872,479,81,372,324,688,216,299,407,621,492,63,685
559,652,645,107,685,577,870,370,509,58,371,85,445,800,174,255,412,475,640,837
85,366,789,597,625,701,275,166,632,82,854,422,628,863,855,213,448,213,517,263
447,373,853,469,912,545,712,695,749,673,299,647,744,826,893,367,865,448,116,943
570,520,859,919,742,221,577,316,946,358,82,910,892,595,584,559,644,593,665,879
645,345,399,430,697,86,641,642,239,764,325,253,728,82,891,372,402,270,400,153
144,533,735,296,806,648,521,747,115,194,405,764,188,861,838,584,872,373,738,744
446,180,652,85,429,330,172,517,629,566,167,922,177,884,751,868,919,102,494,930
306,946,257,637,886,231,836,566,108,210,357,720,791,819,826,489,346,159,420,883
360,622,764,398,398,82,323,165,403,185,557,447,635,171,493,211,736,570,766,79
840,174,102,911,424,821,878,311,498,785,798,572,211,268,59,177,732,853,475,165
109,228,693,210,300,882,184,419,872,939,706,693,596,635,625,905,566,351,202,727
686,414,806,638,869,737,407,506,912,465,448,738,913,118,514,321,363,180,905,345
928,348,305,110,916,827,222,681,197,313,827,903,148,761,498,523,643,297,430,897
317,816,623,799,152,518,491,801,934,762,694,708,583,257,818,400,931,358,899,755
418,943,493,888,559,252,826,222,680,726,426,639,104,579,886,732,844,111,856,817
478,728,865,930,591,340,734,401,900,399,116,839,78,106,315,111,667,631,302,478
744,691,703,984,901,301,75,432,687,336,630,421,527,116,944,111,930,641,497,729
529,930,589,712,588,59,817,76,566,704,319,253,935,423,692,753,626,217,299,142
911,403,257,196,179,178,55,627,468,546,684,327,255,923,912,252,646,266,206,207
889,638,475,473,866,227,789,148,72,57,50,366,269,743,878,901,627,227,586,199
833,976,570,51,335,212,173,110,652,424,446,858,677,73,787,107,877,159,587,165
333,831,361,52,165,59,145,528,935,57,262,366,884,198,354,223,985,808,170,521
928,301,762,573,572,832,728,708,933,150,689,308,680,579,603,313,354,582,368,477
437,686,400,937,162,594,878,414,170,209,259,886,432,208,348,228,399,519,708,574
85,633,54,353,886,917,161,499,496,78,804,119,652,496,511,919,476,306,728,51
451,718,399,578,639,651,293,940,364,75,450,364,799,341,851,295,465,335,754,266
371,268,852,750,706,735,113,752,863,795,467,572,794,497,838,310,160,367,251,471
883,269,624,268,268,557,68,197,590,330,678,316,429,266,877,414,896,733,899,746
991,521,595,300,422,471,686,620,159,341,448,730,694,513,342,575,743,213,790,684
178,252,643,595,697,59,703,328,424,76,567,173,254,880,805,728,519,798,332,157
297,373,312,687,566,491,571,109,448,581,720,873,552,695,806,446,351,854,594,150
260,216,58,789,676,180,708,785,115,252,331,344,498,334,570,935,200,105,208,687
207,484,171,323,466,722,794,833,323,50,763,347,729,252,710,176,910,328,74,649
938,293,838,840,341,429,702,483,259,852,900,112,143,180,881,526,519,58,466,750
700,172,253,365,871,563,643,520,945,587,253,852,492,731,493,281,310,112,573,220
425,941,103,586,871,801,807,918,843,898,522,251,799,177,763,144,195,228,408,84
149,256,792,82,711,419,533,946,835,271,76,681,172,141,120,451,178,633,358,297
595,79,203,762,856,988,556,562,791,528,635,678,865,205,449,870,823,341,260,817
407,24,904,411,818,365,859,654,491,817,297,86,674,218,360,840,620,54,806,708
466,210,258,641,199,766,76,256,651,267,824,343,940,405,198,701,431,259,205,536
561,164,326,563,765,897,177,805,207,571,425,572,349,734,907,233,255,310,54,88
934,866,361,699,709,861,140,680,217,699,172,647,572,923,56,319,164,475,136,255
689,587,52,885,751,517,624,915,790,347,172,366,162,941,893,916,358,419,421,226
562,516,58,626,940,802,840,212,473,230,887,875,180,893,332,942,274,896,718,170
863,557,196,692,263,53,145,340,211,61,117,816,417,108,171,111,683,312,559,75
250,808,732,474,174,261,312,587,349,167,573,934,790,334,819,643,784,212,564,500
480,103,319,230,477,428,119,563,896,421,568,712,923,519,737,672,882,398,496,625
424,787,54,256,917,880,415,466,309,410,59,836,230,189,594,927,620,730,561,168
584,104,415,451,747,808,349,742,54,410,315,711,531,277,705,521,368,259,144,708
365,467,337,75,993,147,223,519,150,206,864,946,763,51,596,105,736,310,695,146
79,365,85,309,649,676,324,597,938,310,733,942,223,693,316,904,413,229,833,484
946,921,52,450,229,180,700,268,16,701,919,885,730,682,494,836,786,852,171,220
295,750,718,149,626,497,335,819,518,624,199,705,631,825,418,897,468,19,698,866
556,584,807,269,721,213,420,721,870,812,88,359,180,829,738,789,295,877,151,360
940,333,838,622,637,173,325,923,547,866,304,398,943,789,822,916,639,679,261,340
480,266,711,197,322,112,362,169,705,828,84,862,719,17,593,864,142,561,916,356
337,675,859,872,586,689,329,949,771,573,267,932,200,526,333,161,350,115,300,697
562,362,942,150,924,215,330,162,753,565,498,321,307,709,641,697,863,578,205,868
655,464,886,153,318,402,818,733,490,73,354,853,936,858,637,473,203,301,177,312
705,429,402,348,882,471,644,193,427,687,804,841,414,270,332,720,228,633,787,880
265,927,325,889,345,403,88,168,219,696,230,570,733,521,833,217,482,711,522,742
335,702,271,178,592,569,845,913,176,649,299,916,788,253,205,860,146,113,710,168
264,219,87,368,798,852,470,224,646,367,355,710,655,17,649,219,942,169,314,118
54,710,880,343,270,468,269,850,167,50,675,303,688,750,419,870,324,674,728,914
528,423,153,101,939,471,418,21,414,926,656,446,211,826,681,863,897,530,839,347
909,298,338,890,335,216,693,171,584,480,228,987,198,252,582,657,641,218,824,791
254,578,837,816,936,271,368,268,167,101,685,516,743,399,465,542,495,626,888,319
268,140,857,844,79,763,115,322,735,159,409,519,857,699,317,917,520,910,75,728
628,2,410,568,299,252,168,683,587,303,743,141,702,723,498,911,766,165,465,800
431,583,212,933,253,358,981,114,766,764,942,361,524,586,203,730,562,627,449,926
631,337,858,720,866,567,723,828,731,926,145,204,640,653,231,724,688,371,482,144
83,571,836,361,797,349,834,809,704,293,839,301,271,219,797,743,803,637,719,811
844,59,356,851,692,180,786,476,703,801,323,797,943,86,432,329,943,596,868,745
230,922,302,180,118,241,231,867,469,639,161,207,807,325,825,74,338,526,722,855
628,0,416,116,143,467,262,937,269,590,80,926,176,523,519,674,523,911,651,366
873,934,81,406,163,945,905,216,359,795,819,554,314,583,722,568,597,317,204,880
433,683,181,426,583,631,826,873,894,938,588,854,308,267,885,222,861,843,719,144
905,825,294,143,203,465,794,674,346,364,180,88,865,168,905,947,897,943,252,717
492,416,629,719,827,108,921,163,745,930,500,343,426,740,777,326,574,149,250,589
940,340,584,722,251,520,880,532,151,398,795,886,869,253,185,304,468,311,852,877
833,371,112,810,56,516,829,352,641,466,295,528,476,718,413,725,559,917,818,533
677,355,203,373,356,398,573,831,750,410,697,809,53,597,435,946,173,890,905,152
588,465,475,201,523,521,340,897,427,834,875,718,635,407,733,323,908,341,440,595
478,496,748,82,890,210,623,809,315,273,58,681,655,101,640,325,621,337,494,299
216,761,834,342,766,808,466,325,51,480,221,721,433,411,403,342,267,620,218,255
301,58,310,355,891,149,474,681,76,677,518,734,532,745,908,333,519,418,278,446
842,527,339,354,940,828,198,478,413,181,695,84,637,988,712,938,165,147,696,211
795,712,522,698,402,310,813,465,910,630,263,331,731,706,936,686,226,829,199,828
575,786,691,828,447,512,730,270,56,722,794,108,175,346,639,174,217,347,652,822
530,732,51,688,74,696,416,309,264,521,209,727,710,259,361,401,559,909,260,510
368,590,119,906,200,725,329,696,942,140,118,933,474,847,657,557,652,823,162,332
107,940,194,558,335,798,926,366,528,918,880,867,695,491,268,226,70,765,150,732
161,684,179,184,732,749,265,529,349,87,934,467,723,111,216,201,861,795,449,801
649,141,914,636,468,196,656,703,813,897,852,472,347,56,337,809,736,901,707,747
594,141,425,316,174,573,885,357,873,595,726,334,59,745,717,887,207,200,310,357
732,368,862,346,795,657,531,464,721,356,732,422,114,735,328,421,741,332,394,164
264,261,806,898,471,170,763,819,642,690,500,267,847,592,73,906,171,175,909,532
77,852,267,578,219,913,795,839,85,920,645,560,303,871,404,804,595,206,727,138
264,323,50,338,301,417,702,817,791,666,172,674,597,721,876,705,576,449,786,945
880,633,356,366,197,692,209,426,261,940,643,634,926,160,269,590,191,293,928,529
295,700,113,627,643,557,141,820,379,140,430,677,791,450,686,118,322,479,495,423
467,749,178,367,520,566,938,114,176,226,894,470,908,824,806,373,436,596,497,575
816,233,748,518,829,424,901,643,56,565,333,570,561,948,114,430,632,901,301,708
208,268,409,297,571,838,722,62,889,885,256,725,166,869,168,150,647,406,498,762
646,695,359,76,710,363,748,887,416,515,696,227,166,86,742,308,140,721,311,663
635,479,734,830,338,224,563,359,88,587,676,370,582,871,840,476,247,790,856,584
226,101,270,301,423,103,264,674,724,361,349,620,646,337,801,830,445,688,746,64
821,112,882,887,295,764,760,789,623,198,655,922,109,809,922,88,399,419,925,305
891,308,685,214,106,147,228,903,114,497,309,743,175,399,416,416,354,935,747,990
642,449,852,913,621,752,318,255,331,478,229,680,630,871,865,922,253,422,151,201
115,732,583,361,316,500,210,77,319,737,448,625,371,651,202,949,403,228,263,999
711,280,169,354,364,255,176,633,560,225,194,214,252,229,168,117,329,348,344,681
168,471,181,476,368,691,918,19,910,325,629,793,298,340,880,570,201,686,795,398
763,206,648,686,679,163,250,167,178,917,301,205,69,372,175,201,802,629,258,513
340,304,195,422,220,450,942,500,620,505,88,924,266,566,832,50,647,480,222,840
643,560,923,526,880,942,411,945,184,527,630,725,258,118,908,868,205,422,416,523
376,639,418,938,425,905,650,891,317,269,495,940,113,582,728,178,176,589,802,78
775,312,631,797,931,103,109,588,109,464,680,293,655,149,167,821,415,816,260,881
478,655,496,170,419,806,582,115,908,639,110,153,644,571,543,164,103,210,175,228
206,211,889,225,703,901,857,530,648,144,81,934,110,923,305,846,433,745,529,646
493,763,224,310,921,644,355,479,81,115,269,265,886,9,110,625,694,675,350,636
836,518,345,917,78,445,478,892,945,476,417,107,862,744,380,327,872,935,884,691
928,475,349,927,404,801,203,924,667,915,143,932,119,197,864,513,646,802,359,592
194,369,582,115,422,531,675,373,166,640,311,268,703,710,826,699,722,114,795,847
179,257,525,695,324,197,745,719,171,450,707,576,814,478,888,426,828,749,268,916
654,520,898,640,929,586,425,828,862,861,861,266,743,297,0,689,884,116,414,366
318,365,189,651,586,294,326,429,735,569,934,109,447,914,675,701,701,803,106,634
145,229,170,364,581,722,918,875,866,410,566,982,635,321,750,164,741,335,403,918
890,497,731,81,432,417,919,338,355,297,153,640,675,799,620,684,518,4,209,301
197,733,109,834,889,207,898,400,140,525,424,583,416,448,902,201,902,688,472,14
0,809,569,206,625,431,56,448,913,800,476,344,882,269,166,314,908,202,373,570
206,201,414,688,166,718,677,696,978,431,594,263,628,449,868,360,807,305,346,499
217,513,429,924,143,167,526,348,268,101,260,654,917,866,812,748,59,816,589,655
788,52,203,270,361,796,895,466,596,149,864,929,895,325,351,702,883,316,892,239
831,500,911,524,820,498,547,315,737,103,494,406,220,358,467,414,725,415,466,472
577,821,171,9,863,807,398,354,266,268,339,724,932,691,334,679,450,264,228,654
116,497,360,294,166,469,919,870,321,592,566,206,883,214,736,309,806,762,810,748
839,525,166,295,269,203,892,578,740,645,305,583,874,634,681,499,998,912,365,638
419,692,496,597,297,945,929,410,911,699,733,868,831,709,932,680,890,199,728,615
944,820,324,693,736,874,637,872,528,249,681,149,339,151,464,591,225,314,315,313
270,639,345,944,690,150,201,822,851,468,876,830,511,303,57,923,762,869,472,316
641,793,104,944,23,870,307,788,877,591,860,328,492,899,472,328,419,361,903,820
799,992,500,116,516,142,903,451,177,477,931,560,744,77,570,52,344,695,816,50
691,227,707,202,302,813,149,623,261,116,575,564,704,824,653,890,937,101,174,256
257,112,339,420,261,834,492,907,912,649,874,838,729,826,271,345,361,470,637,193
339,812,319,906,401,575,867,586,207,351,697,497,855,740,407,347,945,736,152,896
925,845,88,477,58,216,885,565,623,259,142,307,621,304,115,476,939,700,202,469
808,786,83,651,174,623,579,224,224,789,208,161,7,722,116,350,698,733,883,199
682,421,887,432,847,336,524,654,361,371,161,480,59,880,797,348,407,308,681,403
686,571,408,941,788,705,480,365,678,728,631,591,152,555,119,725,595,936,143,142
825,331,993,830,876,399,142,880,741,140,694,947,293,532,445,855,78,912,357,412
898,315,491,897,927,807,165,596,695,563,877,700,56,307,480,253,139,77,117,762
299,690,341,493,500,152,351,810,631,339,828,87,205,565,725,696,207,828,270,404
484,260,809,639,52,620,910,223,499,706,465,348,85,698,116,622,579,707,826,571
621,655,13,445,733,686,411,449,467,898,491,75,344,805,148,356,195,79,449,653
988,891,824,632,229,909,571,176,928,586,708,117,471,560,864,805,725,161,114,934
741,165,570,908,632,728,938,570,516,220,86,301,655,882,581,637,877,475,234,320
67,801,766,731,254,827,916,572,449,621,628,596,478,175,166,696,323,533,416,701
720,58,837,307,695,306,629,215,522,706,856,591,281,110,175,872,532,524,181,167
525,841,651,174,940,530,165,869,423,250,920,705,724,742,112,144,378,259,467,360
740,648,791,679,674,404,165,265,151,256,348,162,880,150,66,353,80,636,258,115
886,575,150,754,365,562,362,522,498,571,639,364,834,169,55,562,470,446,466,366
552,361,412,118,318,724,652,828,450,627,469,594,424,620,519,108,884,884,53,349
519,587,585,341,892,56,175,316,312,472,874,496,267,358,946,874,812,218,943,228
927,307,867,229,597,448,929,557,688,886,269,331,718,345,471,651,369,838,619,469
203,796,199,515,424,212,572,529,220,786,170,889,198,359,596,65,626,569,933,687
208,105,266,278,269,653,531,627,881,253,81,632,836,445,574,788,348,209,166,586
425,543,702,474,424,673,918,747,628,762,175,931,832,863,79,213,109,557,881,494
606,789,514,465,893,339,315,494,314,921,944,477,724,920,856,150,733,932,897,415

399
d16/main.go Normal file
View File

@ -0,0 +1,399 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"sort"
"strconv"
"strings"
)
func processLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func processGroups(path string, f func([]string) (stop bool, err error)) error {
group := []string{}
if err := processLines(path, func(line string) (stop bool, err error) {
if line == "" {
stop, err = f(group)
if stop || err != nil {
return
}
group = []string{}
} else {
group = append(group, line)
}
return
}); err != nil {
return err
}
_, err := f(group)
return err
}
// StringSet is a set of strings.
type StringSet map[string]bool
// Add an item to a StringSet.
func (s *StringSet) Add(v string) {
(*s)[v] = true
}
// AddAll adds all items in a list to the set.
func (s *StringSet) AddAll(l []string) {
for _, v := range l {
s.Add(v)
}
}
// Values returns all values in the set as a list.
func (s StringSet) Values() []string {
values := []string{}
for k := range s {
values = append(values, k)
}
return values
}
// NewStringSet creates an empty string set.
func NewStringSet() StringSet {
return StringSet{}
}
// Union returns the union of two SringSets.
func Union(s1, s2 StringSet) StringSet {
union := NewStringSet()
for v := range s1 {
union.Add(v)
}
for v := range s2 {
union.Add(v)
}
return union
}
// Intersection returns the union of two SringSets.
func Intersection(s1, s2 StringSet) StringSet {
intersect := NewStringSet()
for v := range s1 {
if _, ok := s2[v]; ok {
intersect.Add(v)
}
}
return intersect
}
// Difference returns the value of s1 with values of s2 removed.
func Difference(s1, s2 StringSet) StringSet {
difference := NewStringSet()
for v := range s1 {
if _, ok := s2[v]; !ok {
difference.Add(v)
}
}
return difference
}
type numRange struct {
lower, upper int
}
func (r numRange) validate(n int) bool {
return r.lower <= n && n <= r.upper
}
type fieldRule struct {
name string
ranges []numRange
}
func (f fieldRule) validate(n int) bool {
for _, r := range f.ranges {
if r.validate(n) {
return true
}
}
return false
}
var ruleMatcher = regexp.MustCompile(`([a-z ]+): ([0-9]+)-([0-9]+) or ([0-9]+)-([0-9]+)`)
func parseFieldRule(line string) (fieldRule, error) {
res := ruleMatcher.FindStringSubmatch(line)
if res == nil {
return fieldRule{}, fmt.Errorf("failed parsing rule line: %s", line)
}
name := res[1]
l1, err := strconv.Atoi(res[2])
if err != nil {
return fieldRule{}, fmt.Errorf("failed parsing int in rule %w", err)
}
u1, err := strconv.Atoi(res[3])
if err != nil {
return fieldRule{}, fmt.Errorf("failed parsing int in rule %w", err)
}
l2, err := strconv.Atoi(res[4])
if err != nil {
return fieldRule{}, fmt.Errorf("failed parsing int in rule %w", err)
}
u2, err := strconv.Atoi(res[5])
if err != nil {
return fieldRule{}, fmt.Errorf("failed parsing int in rule %w", err)
}
return fieldRule{
name: name,
ranges: []numRange{
numRange{
lower: l1,
upper: u1,
},
numRange{
lower: l2,
upper: u2,
},
},
}, nil
}
type fieldRules []fieldRule
func (f fieldRules) validFields(n int) []string {
validFields := []string{}
for _, r := range f {
if r.validate(n) {
validFields = append(validFields, r.name)
}
}
return validFields
}
type ticket []int
func parseTicket(line string) (ticket, error) {
t := ticket{}
for _, n := range strings.Split(line, ",") {
i, err := strconv.Atoi(n)
if err != nil {
return nil, err
}
t = append(t, i)
}
return t, nil
}
func parseInput() (fieldRules, ticket, []ticket) {
rules := fieldRules{}
nearby := []ticket{}
var t ticket
if err := processGroups("input.txt", func(group []string) (bool, error) {
if len(rules) == 0 {
for _, line := range group {
rule, err := parseFieldRule(line)
if err != nil {
log.Fatal(err)
}
rules = append(rules, rule)
}
} else if group[0] == "your ticket:" {
var err error
t, err = parseTicket(group[1])
if err != nil {
log.Fatal(err)
}
} else if group[0] == "nearby tickets:" {
for _, line := range group[1:] {
nt, err := parseTicket(line)
if err != nil {
log.Fatal(err)
}
nearby = append(nearby, nt)
}
} else {
log.Fatal(fmt.Errorf("unknown section %v", group))
}
return false, nil
}); err != nil {
log.Fatal(err)
}
return rules, t, nearby
}
func part1() {
rules, _, nearby := parseInput()
invalid := 0
for _, t := range nearby {
for _, v := range t {
if len(rules.validFields(v)) == 0 {
invalid += v
}
}
}
fmt.Printf("Total scanning error rate is %d\n", invalid)
}
func reduceFields(fieldOptions []StringSet) ([]string, error) {
type fieldOption struct {
options StringSet
position int
}
workingFields := []fieldOption{}
for i, o := range fieldOptions {
workingFields = append(
workingFields,
fieldOption{o, i},
)
}
// Sort slice by number of options
sort.Slice(workingFields, func(i, j int) bool {
return len(workingFields[i].options) < len(workingFields[j].options)
})
for i, o1 := range workingFields {
if len(o1.options) == 1 {
// Remove this option from everywhere else
for j, o2 := range workingFields {
if i == j {
// Skip current outer index
continue
}
workingFields[j].options = Difference(o2.options, o1.options)
}
}
}
// fmt.Printf("All options? %+v", workingFields)
// Sort slice by number of options
sort.Slice(workingFields, func(i, j int) bool {
return workingFields[i].position < workingFields[j].position
})
results := []string{}
for _, o := range workingFields {
if len(o.options) != 1 {
return []string{}, fmt.Errorf("some options have multiple values")
}
results = append(results, o.options.Values()[0])
}
return results, nil
}
func part2() {
rules, myTicket, nearby := parseInput()
fieldOptions := []StringSet{}
// Get all possible field names
allFields := []string{}
for _, rule := range rules {
allFields = append(allFields, rule.name)
}
// Add them to every field in ticket
for range myTicket {
s := StringSet{}
s.AddAll(allFields)
fieldOptions = append(fieldOptions, s)
}
var ticketOptions []StringSet
for _, nearbyTicket := range nearby {
ticketOptions = []StringSet{}
for _, ticketValue := range nearbyTicket {
validFields := StringSet{}
validFields.AddAll(rules.validFields(ticketValue))
if len(validFields) == 0 {
// This ticket is invalid
ticketOptions = nil
break
}
ticketOptions = append(ticketOptions, validFields)
}
// Done checking ticket
if ticketOptions != nil {
// Ticket is valid
for i := range fieldOptions {
fieldOptions[i] = Intersection(fieldOptions[i], ticketOptions[i])
}
}
}
// fmt.Printf("Final fieldOptions %+v\n", fieldOptions)
fieldLabels, err := reduceFields(fieldOptions)
if err != nil {
log.Fatal(err)
}
// fmt.Println("Values: ", fieldLabels)
product := 1
for i, label := range fieldLabels {
if strings.HasPrefix(label, "departure") {
product *= myTicket[i]
}
}
fmt.Printf("Product of all departures %d\n", product)
}
func main() {
part1()
part2()
}

8
d17/input.txt Normal file
View File

@ -0,0 +1,8 @@
#...#.#.
..#.#.##
..#..#..
.....###
...#.#.#
#.#.##..
#####...
.#.#.##.

113
d17/main.go Normal file
View File

@ -0,0 +1,113 @@
package main
import "fmt"
var (
activeRune = '#'
inactiveRune = '.'
)
type point3 [3]int
func addPoint(p1, p2 point3) point3 {
p := point3{}
for i := range p {
p[i] = p1[i] + p2[i]
}
return p
}
type cube struct {
loc point3
active bool
tock func() error
world *grid
}
func (c cube) neighbors() []cube {
directions := []point3{
// 1 pt
point3{0, 0, 1},
point3{0, 0, -1},
point3{0, 1, 0},
point3{0, -1, 0},
point3{1, 0, 0},
point3{-1, 0, 0},
// 2pt
point3{0, 1, 1},
point3{0, 1, -1},
point3{0, -1, 1},
point3{0, -1, -1},
point3{1, 1, 0},
point3{1, -1, 0},
point3{-1, 1, 0},
point3{-1, -1, 0},
point3{1, 0, 1},
point3{-1, 0, 1},
point3{1, 0, -1},
point3{-1, 0, -1},
// 3pt
point3{1, 1, 1},
point3{-1, 1, 1},
point3{1, -1, 1},
point3{1, 1, -1},
point3{-1, -1, 1},
point3{1, -1, -1},
point3{-1, 1, -1},
point3{-1, -1, -1},
}
}
func (c *cube) tick() error {
}
type world [][][]*cube
func (w world) getCube(p point) *cube {
x := point[0]
y := point[1]
z := point[2]
if z >= len(w) {
return nil
}
slice := world[z]
if y >= len(slice) {
return nil
}
row := slice[y]
if x >= len(row) {
return nil
}
return row[x]
}
func (w *world) tick() error {
for z, slice := range w {
for y, row := range slice {
for x, cube := range row {
err := cube.tick()
if err != nil {
return err
}
}
}
}
return nil
}
func main() {
p := point3{}
p[0] = 1
fmt.Println(p)
}

703
d17/main.py Executable file
View File

@ -0,0 +1,703 @@
#! /usr/bin/env python3
from collections import namedtuple
from itertools import product
from typing import Any
from typing import Callable
from typing import Iterable
from typing import List
from typing import Optional
from typing import Tuple
from typing import Set
Point = namedtuple("Point", "x y z w", defaults=(0,))
back_refs = {
"left": "right",
"right": "left",
"up": "down",
"down": "up",
"front": "back",
"back": "front",
}
ACTIVE = "#"
INACTIVE = "."
def add_points(p1, p2) -> Point:
return Point(
p1.x + p2.x,
p1.y + p2.y,
p1.z + p2.z,
p1.w + p2.w,
)
class Cube(object):
def __init__(self, loc: Point, world: "World", active=False):
self._loc = loc
self._world = world
self.active = active
self._ticked = False
def _tock():
# print("Default tock")
pass
self.tock = _tock
# def __init__(self, left=None, up=None, right=None,
# down=None, front=None, back=None):
# # self.set_neighbor("left", left)
# # self.set_neighbor("up", up)
# # self.set_neighbor("right", right)
# # self.set_neighbor("down", down)
# # self.set_neighbor("front", front)
# # self.set_neighbor("back", back)
#
# # tock func
# self.tock = None
# def set_neighbor(self, direction: str, value: "Cube"):
# backref = back_refs[direction]
# setattr(self, direction, value)
# if value is not None:
# setattr(value, backref, self)
def neighbors(self, expand=False) -> Iterable["Cube"]:
seen_points: Set[Point] = set()
for diff in product((0, 1, -1), repeat=4):
# from pdb import set_trace; set_trace()
neighbor_point = add_points(
self._loc,
Point(
diff[0],
diff[1],
diff[2],
diff[3],
),
)
if self._loc == neighbor_point:
# skip self
continue
if neighbor_point in seen_points:
# skip points we've already visited
# print("Already seen, skipping")
continue
seen_points.add(neighbor_point)
# print(f"Getting point {neighbor_point}")
neighbor = self._world.get_point(neighbor_point, expand=expand)
if neighbor is not None:
# print("FOUND!")
yield neighbor
def tick(self):
active_neighbors = 0
for neighbor in self.neighbors():
# print(f"Neighbor is active: {neighbor.active}")
if neighbor.active:
# print(f"Neighbor is active {neighbor}")
active_neighbors += 1
# if self._loc == Point(1, 3, 0):
# import pdb; pdb.set_trace()
if self.active and active_neighbors not in (2, 3):
# print("Should go inactive")
def _tock():
# print("go inactive")
self.active = False
self.tock = _tock
elif not self.active and active_neighbors == 3:
# print("Should go active")
def _tock():
# print("go active")
self.active = True
self.tock = _tock
else:
# print("Should do nothing")
def _tock():
# print("Empty tock")
pass
self.tock = _tock
def __repr__(self) -> str:
return f"({self._loc.x}, {self._loc.y}, {self._loc.z})"
def to_str(self) -> str:
return ACTIVE if self.active else INACTIVE
class AutoExpanding(object):
_l: List[Any]
_zero: int
_item_factory: Callable[[int], Any]
def __init__(self):
self._l = [self._item_factory(0)]
self._zero = 0
def get(self, i, expand=True):
if not expand:
if self._zero+i < 0:
raise IndexError(f"index {i} is out of bounds")
return self._l[self._zero+i]
if self._zero is None:
self._l = [self._item_factory(0)]
self._zero = 0
if i > 0 and i >= len(self._l) - self._zero - 1:
# print(f"resize pos to {i} with {self._l} zero={self._zero}")
self._l = self._l + [
self._item_factory(j)
for j in range(len(self._l)-self._zero, i+1)
]
# print(f"> done {self._l} zero={self._zero}")
elif i < 0 and abs(i) > self._zero:
# print(f"resize neg to {i} with {self._l} zero={self._zero}")
self._l = [
self._item_factory(j)
for j in range(i, -1 * self._zero)
] + self._l
self._zero = abs(i)
# print(f"> done {self._l} zero={self._zero}")
# print(f"Now getting item at index {i} from {self._l}")
return self._l[self._zero+i]
def __getitem__(self, i):
if isinstance(i, slice):
return [
self[j]
for j in range(
i.start if i.start is not None else self.min_index(),
(i.stop if i.stop is not None else self.max_index()) + 1,
i.step or 1,
)
]
return self.get(i, expand=False)
def __setitem__(self, i, value):
self.get(i, expand=True)
self._l[self._zero+i] = value
def __len__(self) -> int:
return len(self._l)
def __iter__(self):
return iter(self._l)
def min_index(self) -> int:
return -1 * self._zero
def max_index(self) -> int:
return len(self._l) - self._zero - 1
def get_bounds(self) -> Tuple[int, int]:
return self.min_index(), self.max_index()
def resize(self, min_index: int, max_index: int):
if min_index < self.min_index():
self.get(min_index, expand=True)
else:
if min_index > 0:
raise IndexError("Cannot resize to exclude zero")
self._l = self[min_index:]
self._zero = abs(min_index)
if max_index > self.max_index():
self.get(max_index, expand=True)
else:
if max_index < 0:
raise IndexError("Cannot resize to exclude zero")
self._l = self[:max_index]
def __repr__(self) -> str:
return f"<AutoExpanding {self._l}>"
class World(AutoExpanding):
def iter_cubes(self) -> Iterable[Cube]:
raise NotImplementedError()
def tick(self):
for c in self.iter_cubes():
c.tick()
def tock(self):
for c in self.iter_cubes():
c.tock()
def get_point(self, p: Point, expand=True) -> Optional[Cube]:
raise NotImplementedError()
def trim(self):
raise NotImplementedError()
def get_all_bounds(self) -> Tuple[Point, Point]:
raise NotImplementedError()
def true_up(self):
raise NotImplementedError()
def expand_all(self, i: int):
raise NotImplementedError()
def count_active(self) -> int:
total = 0
for c in self.iter_cubes():
if c.active:
total += 1
return total
class GridRow(AutoExpanding):
def __init__(self, y: int, z: int, world: World, w: Optional[int] = 0):
self._y = y
self._z = z
self._w = w
self._world = world
super().__init__()
def _item_factory(self, x: int) -> Cube:
return Cube(Point(x, self._y, self._z, self._w), self._world)
def __repr__(self) -> str:
return "[" + " ".join((str(c) for c in self._l)) + "]"
def to_str(self) -> str:
return "".join((c.to_str() for c in self._l))
class GridSlice(AutoExpanding):
def __init__(self, z: int, world: World, w: Optional[int] = 0):
self._z = z
self._w = w
self._world = world
super().__init__()
def _item_factory(self, y: int) -> GridRow:
return GridRow(y, self._z, self._world, w=self._w)
def __repr__(self) -> str:
return f"z={self._z}\n" + "\n".join((
str(r) for r in self._l
))
def to_str(self) -> str:
return f"z={self._z}\n" + "\n".join([r.to_str() for r in self._l])
class Grid(World):
def __init__(self, world: Optional[World] = None, w: Optional[int] = 0):
if world is not None:
self._world = world
else:
self._world = self
self._w = w
super().__init__()
def _item_factory(self, z: int) -> GridSlice:
return GridSlice(z, self._world, w=self._w)
def __repr__(self) -> str:
return "\n\n".join((
str(s) for s in self._l
))
def to_str(self) -> str:
return "\n\n".join((
s.to_str() for s in self._l
))
def iter_cubes(self) -> Iterable[Cube]:
for s in self:
for r in s:
for c in r:
yield c
def get_point(self, p: Point, expand=True) -> Optional[Cube]:
try:
# print(f"expand world z to {p.z}")
c = self.get(
p.z,
expand=expand,
).get(
p.y,
expand=expand,
).get(
p.x,
expand=expand,
)
# from pdb import set_trace; set_trace()
return c
except IndexError:
return None
def trim(self):
for s in self:
for r in s:
first, last = None, None
min_index, max_index = r.get_bounds()
for i in range(min_index, max_index+1):
if r[i].active:
if first is None:
first = i
last = i
if first is None or first > 0:
first = 0
if last is None or last < 0:
last = 0
r.resize(first, last)
first, last = None, None
min_index, max_index = s.get_bounds()
for i in range(min_index, max_index+1):
if len(s[i]) > 1 or (len(s[i]) == 1 and s[i][0].active):
if first is None:
first = i
last = i
if first is None or first > 0:
first = 0
if last is None or last < 0:
last = 0
s.resize(first, last)
def get_all_bounds(self) -> Tuple[Point, Point]:
min_z, max_z = self.get_bounds()
min_y, max_y = 0, 0
min_x, max_x = 0, 0
for s in self:
if s.min_index() < min_y:
min_y = s.min_index()
if s.max_index() > max_y:
max_y = s.max_index()
for r in s:
if r.min_index() < min_x:
min_x = r.min_index()
if r.max_index() > max_x:
max_x = r.max_index()
return Point(min_x, min_y, min_z), Point(max_x, max_y, max_z)
def true_up(self):
min_point, max_point = self.get_all_bounds()
for s in self:
s.resize(min_point.y, max_point.y)
for r in s:
r.resize(min_point.x, max_point.x)
def expand_all(self, i: int):
min_point, max_point = self.get_all_bounds()
# print(f"expand {i} cell")
# print("expsting min, max:", min_point, max_point)
min_point = add_points(min_point, Point(-i, -i, -i))
max_point = add_points(max_point, Point(i, i, i))
# print("new min, max:", min_point, max_point)
self.get_point(min_point, expand=True)
self.get_point(max_point, expand=True)
class HyperGrid(World):
def __init__(self):
super().__init__()
def _item_factory(self, w: int) -> Grid:
return Grid(world=self, w=w)
def __repr__(self) -> str:
return "\n\n".join((
str(s) for s in self._l
))
def to_str(self) -> str:
return "\n\n".join((
f"w = {s._w}, " + s.to_str() for s in self._l
))
def iter_cubes(self) -> Iterable[Cube]:
for g in self:
for s in g:
for r in s:
for c in r:
yield c
def get_point(self, p: Point, expand=True) -> Optional[Cube]:
try:
# print(f"expand world z to {p.z}")
c = self.get(
p.w,
expand=expand,
).get(
p.z,
expand=expand,
).get(
p.y,
expand=expand,
).get(
p.x,
expand=expand,
)
# from pdb import set_trace; set_trace()
return c
except IndexError:
return None
def get_all_bounds(self) -> Tuple[Point, Point]:
min_w, max_w = self.get_bounds()
min_z, max_z = 0, 0
min_y, max_y = 0, 0
min_x, max_x = 0, 0
for g in self:
if g.min_index() < min_z:
min_z = g.min_index()
if g.max_index() > max_z:
max_z = g.max_index()
for s in g:
if s.min_index() < min_y:
min_y = s.min_index()
if s.max_index() > max_y:
max_y = s.max_index()
for r in s:
if r.min_index() < min_x:
min_x = r.min_index()
if r.max_index() > max_x:
max_x = r.max_index()
return (
Point(min_x, min_y, min_z, min_w),
Point(max_x, max_y, max_z, max_w),
)
def true_up(self):
min_point, max_point = self.get_all_bounds()
for g in self:
g.resize(min_point.z, max_point.z),
for s in g:
s.resize(min_point.y, max_point.y)
for r in s:
r.resize(min_point.x, max_point.x)
def expand_all(self, i: int):
min_point, max_point = self.get_all_bounds()
# print(f"expand {i} cell")
# print("existing min, max:", min_point, max_point)
min_point = add_points(min_point, Point(-i, -i, -i, -i))
max_point = add_points(max_point, Point(i, i, i, i))
# print("new min, max:", min_point, max_point)
self.get_point(min_point, expand=True)
self.get_point(max_point, expand=True)
def part1():
# Load world
g = Grid()
with open("input.txt") as f:
for y, row in enumerate(f):
row.strip()
for x, c in enumerate(row):
g.get(0).get(y).get(x).active = c == ACTIVE
g.true_up()
print("time = 0\n_____________")
print(g.to_str())
for t in range(6):
g.expand_all(1)
g.true_up()
g.tick()
g.tock()
# g.trim()
g.true_up()
print(f"time = {t+1}\n_____________")
print(g.to_str())
# print(g)
total = g.count_active()
print(f"Total active: {total}")
def part2():
# Load world
g = HyperGrid()
with open("input.txt") as f:
for y, row in enumerate(f):
row.strip()
for x, c in enumerate(row):
g.get(0).get(0).get(y).get(x).active = c == ACTIVE
g.true_up()
print("time = 0\n_____________")
print(g.to_str())
# g.expand_all(1)
# g.true_up()
# print("EXPANDED\ntime = 0\n_____________")
# print(g.to_str())
# return
for t in range(6):
g.expand_all(1)
g.true_up()
g.tick()
g.tock()
# g.trim()
g.true_up()
# print(f"time = {t+1}\n_____________")
# print(g.to_str())
# print(g)
total = g.count_active()
print(f"Total active: {total}")
def test():
g = Grid()
# print("test")
# s = [
# "...",
# "###",
# "...",
# ]
# for y, row in enumerate(s):
# row.strip()
# for x, c in enumerate(row):
# g.get(0).get(y).get(x).active = c == ACTIVE
#
# g.true_up()
#
# print("time = 0")
# print(g.to_str())
# print(g)
#
# p = g.get(0).get(0).get(1)
# from pdb import set_trace; set_trace()
# p.tick()
# p.tock()
# print(g.to_str())
#
# p = g.get(0).get(2).get(1)
# from pdb import set_trace; set_trace()
# p.tick()
# p.tock()
# print(g.to_str())
# print(list(g[0][0][0].neighbors()))
#
# print(g.to_str())
#
#
# return
# g.get(1).get(1).get(1)
# g.get_point(Point(1, 1, 1))
# g.expand_all(1)
# g.true_up()
# print(g)
# r = GridRow(0, 0, None)
# print(r)
# r.get(1)
# print(r)
# print(r[:3])
# r.get(-3)
# # print(r[0:3])
# print(r[-2:])
#
# print("Resize")
# print(r)
# r.resize(0, 3)
# print(r)
# return
# c = g.get(0).get(0).get(0)
# print(g)
# from pdb import set_trace; set_trace()
# neigh = list(c.neighbors())
# print(neigh)
#
# return
print("test")
s = [
".#.",
"..#",
"###",
]
for y, row in enumerate(s):
row.strip()
for x, c in enumerate(row):
g.get(0).get(y).get(x).active = c == ACTIVE
g.true_up()
print("time = 0\n_____________")
print(g.to_str())
# print(g)
# g.expand_all(1)
# g.true_up()
# print(g.to_str())
# print(g)
# return
for t in range(6):
g.expand_all(1)
g.true_up()
# print(g.to_str())
# p = g.get(0).get(3).get(1)
# from pdb import set_trace; set_trace()
g.tick()
g.tock()
# g.trim()
g.true_up()
print(f"time = {t+1}\n_____________")
print(g.to_str())
# print(g)
total = g.count_active()
print(f"Total active: {total}")
if __name__ == "__main__":
# part1()
part2()

300
d17/util.go Normal file
View File

@ -0,0 +1,300 @@
package main
import (
"bufio"
"errors"
"fmt"
"math"
"os"
)
var (
errItemAlreadySet = errors.New("cannot set item in direction as one is already set")
)
// ProcessLines maps a function on lines parsed from a file.
func ProcessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
// ProcessGroups maps a function on groups of lines parsed from a file separated by some string.
func ProcessGroups(path, separator string, f func([]string) (stop bool, err error)) error {
group := []string{}
if err := ProcessLines(path, func(line string) (stop bool, err error) {
if line == separator {
stop, err = f(group)
if stop || err != nil {
return
}
group = []string{}
} else {
group = append(group, line)
}
return
}); err != nil {
return err
}
_, err := f(group)
return err
}
// StringSet is a set of strings..
type StringSet map[string]bool
// Add an item to a StringSet.
func (s *StringSet) Add(v string) {
(*s)[v] = true
}
// AddAll adds all items in a list to the set.
func (s *StringSet) AddAll(l []string) {
for _, v := range l {
s.Add(v)
}
}
// Items returns all values in the set as a list.
func (s StringSet) Items() []string {
values := []string{}
for k := range s {
values = append(values, k)
}
return values
}
// NewStringSet creates an empty string set.
func NewStringSet(values []string) StringSet {
v := StringSet{}
v.AddAll(values)
return v
}
// Union returns the union of two SringSets.
func Union(s1, s2 StringSet) StringSet {
union := NewStringSet(s1.Items())
union.AddAll(s2.Items())
return union
}
// Intersection returns the union of two SringSets.
func Intersection(s1, s2 StringSet) StringSet {
intersect := StringSet{}
for v := range s1 {
if _, ok := s2[v]; ok {
intersect.Add(v)
}
}
return intersect
}
// Difference returns the value of s1 with values of s2 removed.
func Difference(s1, s2 StringSet) StringSet {
difference := StringSet{}
for v := range s1 {
if _, ok := s2[v]; !ok {
difference.Add(v)
}
}
return difference
}
// Point represents a point on a coordinate system.
type Point struct {
x, y int
}
// AddPoints adds two points together.
func AddPoints(p1, p2 Point) Point {
return Point{
p1.x + p2.x,
p1.y + p2.y,
}
}
// PowInt is equivalent to math.Pow but for integers.
func PowInt(x, y int) int {
return int(math.Pow(float64(x), float64(y)))
}
// LinkedGridItem is a single item in a linked grid.
type LinkedGridItem struct {
location Point
left, right, up, down *LinkedGridItem
grid *LinkedGrid
}
func (item LinkedGridItem) String() string {
return fmt.Sprintf("%v", item.location)
}
// Location of the item.
func (item LinkedGridItem) Location() Point {
return item.location
}
// Left gives a pointer to the item on the left.
func (item LinkedGridItem) Left() *LinkedGridItem {
return item.left
}
// Up gives a pointer to the item above.
func (item LinkedGridItem) Up() *LinkedGridItem {
return item.up
}
// Right gives a pointer to the item on the right.
func (item LinkedGridItem) Right() *LinkedGridItem {
return item.right
}
// Down gives a pointer to the item below.
func (item LinkedGridItem) Down() *LinkedGridItem {
return item.down
}
// SetLeft gives a pointer to the item on the left.
func (item *LinkedGridItem) SetLeft(other *LinkedGridItem) error {
if item.left != nil || other.right != nil {
return errItemAlreadySet
}
item.left = other
other.right = item
return nil
}
// SetUp gives a pointer to the item on the up.
func (item *LinkedGridItem) SetUp(other *LinkedGridItem) error {
if item.up != nil || other.down != nil {
return errItemAlreadySet
}
item.up = other
other.down = item
return nil
}
// SetRight gives a pointer to the item on the right.
func (item *LinkedGridItem) SetRight(other *LinkedGridItem) error {
if item.right != nil || other.left != nil {
return errItemAlreadySet
}
item.right = other
other.left = item
return nil
}
// SetDown gives a pointer to the item on the down.
func (item *LinkedGridItem) SetDown(other *LinkedGridItem) error {
if item.down != nil || other.up != nil {
return errItemAlreadySet
}
item.down = other
other.up = item
return nil
}
// LinkedGrid is a 2d array of grid square.
type LinkedGrid [][]*LinkedGridItem
// Print a linked grid.
func (grid LinkedGrid) Print() {
for _, row := range grid {
for _, item := range row {
fmt.Print(item.String())
}
fmt.Print("\n")
}
}
// NewLinkedGrid initializes a new linked grid of a given size.
func NewLinkedGrid(width, height int) *LinkedGrid {
var w = make(LinkedGrid, height)
for y := 0; y < height; y++ {
w[y] = make([]*LinkedGridItem, width)
for x := 0; x < height; x++ {
item := LinkedGridItem{location: Point{x, y}}
if x != 0 {
_ = item.SetLeft(w[y][x-1])
}
if y != 0 {
_ = item.SetUp(w[y-1][x])
}
w[y][x] = &item
}
}
return &w
}
// MapInt maps a function onto a list of ints.
func MapInt(a []int, f func(int) (int, error)) error {
var err error
for i, v := range a {
a[i], err = f(v)
if err != nil {
return err
}
}
return nil
}
// ReduceInt maps a function onto a list of ints.
func ReduceInt(a []int, start int, f func(int, int) (int, error)) (int, error) {
var err error
result := start
for _, v := range a {
result, err = f(result, v)
if err != nil {
return 0, err
}
}
return result, nil
}

4
d18/input-small.txt Normal file
View File

@ -0,0 +1,4 @@
2 * 3 + (4 * 5)
5 + (8 * 3 + 9 + 3 * 4 * 3)
5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))
((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2

373
d18/input.txt Normal file
View File

@ -0,0 +1,373 @@
(4 + (2 * 7) * 4) + (6 * 9 + 8 * 4 + 7 * 3) * 3 * 5
5 * 9 + (5 * 9) * (6 + 2) + 3 + 7
8 + 5 * 9 * 9 + 9 + 5
(7 + 9 * 8 + 4 * 6) + 6 * ((9 + 9 + 5 * 7 + 4) * 8 * 2 + 5 * 6 + 2) + 2 * 6
(6 * (5 + 8 * 7 * 8 + 4) * (7 + 7 * 3 * 5)) + 5 * (8 + (8 + 3 + 5 + 5) + (3 + 2 + 7 * 2 * 9) + 6 * 5 + (2 * 6)) * ((4 * 3) + 3) + 9 * (3 + 6 * 2 + 3 * 8)
2 * 9 + (6 * 2 + 6 + (9 + 6 + 8 + 5 + 5) + (8 + 7 * 4 + 3) + 8) * (4 + 4 * 2 + 6)
5 + 4 + 5 + (7 + (9 + 7 + 4 + 4 + 4 + 5) + 2 * 4) + 4 * 9
9 + (7 * 8 + (6 + 3 + 4)) + (5 * 9)
2 * 4 + 8 + (5 + 8) * 9 * (9 + (5 + 3) + 3)
8 * 6 * 5 + 8 + (8 * (2 + 8 * 7 * 5 + 3 + 5)) * 2
6 * ((3 + 4 * 3 * 7 * 8) * 8 + (9 + 5 + 2 * 3) * 3 * 2) + 7 + 8 * 8 + 4
9 + 3 + 7 * 8
(9 + (4 + 9 + 3 + 5 * 5 + 5) * 5 + 9 * 6) * 3 * 2 * 6 * 5
7 * 9 * 6
(5 + 2 * 8) * 8 + 3 + 8
9 * 5 * (5 + (5 * 4 + 8 + 6 * 5) * (9 * 7 + 5)) * 3 * 9
(6 * (8 * 3 * 7 + 2) * (3 + 9 + 5 + 5) + 3) + 7 * 3
7 + 9 + (4 + 9 * (4 * 6 + 3 * 8 * 5) + 8 + 9 + 3) + 6 * (6 + 8 + 7 * 9 * 6 + 6) + 7
2 * (5 * 5 + 6 + (5 + 5 * 5 + 6)) * 4 + 5 + 2
8 + 2 * (8 * 7 * 4 + 8) * 9
9 + 5 * (4 * 8 + 9 * 6 + (3 * 3) + 2) + 5 + (4 * 5 + 2 * 2)
(5 * 7 + 2) + 3 + 9
7 * 9 + 8
3 * 7 * (7 + 5 + 8 * 5 * 8)
(7 + (3 * 6 + 6 * 9 + 2) * 8 * 6 + 6 + 2) * 6
4 * (7 * 5 * (6 + 8) * 7 * (5 * 3 * 2 * 9 + 2 * 4) * 6) * 2 + 2 * 5
((3 * 3 * 9 + 8) + 2 + 5 + 8) + 6 * (6 + 9 * 2) + 7 * 9 * ((9 + 4 + 4) * 4 + 4 + 9)
7 * (4 * 2 + 3 + 7 + 5) * (8 + 2 + (5 * 9) * 2 + 3 * 5)
7 + (8 + 3 + 8 * 4 * 2 * 2) + 7 * 2 + ((3 + 5 * 3 + 5) * 8 + 3) + 8
7 + 2 + 9 * 9 + 5
((6 + 4 + 2) * 2 + 9) + 3 * 6 * (6 + 4 + 9 + 2 + 6) * 9
6 + 6 * (9 * 9 + 6 + 6) + 2 * 6
2 + 5 * ((4 * 4) * 6) + (3 * 3 + 2) * 9 + 5
9 * 4 + 8 * 5 * ((6 * 5 * 4) + (3 + 8 * 7 + 6 * 7) * (6 * 6 + 7) * 8 + 4 + 7)
3 * 8 + (4 + (7 * 7 + 9 * 8 * 6 + 7) * (8 * 4 + 4 * 6 * 4 + 4) + 2 * 9)
3 + 6 * 2 * 3 * (4 + 7 + (3 * 6 + 7 * 8) * 7 + 9 * 8)
2 + 8 + (5 * 4 * 2 * 5 + 5) * 4 + 3 * 4
6 + 4 + (5 + 5)
6 * 3 + 8 + (8 + 2 + 9 * 3) * ((6 * 8 + 6) + 6 + (7 * 4 * 3) * 4 + 9 + 3)
((9 + 7 + 9 + 2 * 7 * 7) + 8 * 6) + 2 + 7
6 * (6 + 9 * 2 + 4 * 7 + 8) + 5 * 9
((2 + 5 + 6 * 3) + 7 + (7 * 6 * 8 * 3 + 8 * 3)) + (8 * 6 * 8 * 9 * 5)
6 * 7 * 5 + 5 * (2 * 9) * 4
(8 * 7) * (2 * (7 + 3) + 3) + 8
(7 * 9 + 7 + 7 + 7 + 7) + (7 * 5 * 8 + 4 * 5) + 6
5 * (6 * 7 * 8 * 5) * 6
5 * (2 + (6 * 7) * 8 * 3 + 6 * 2) + 2 * 4 + 8 + 3
3 * 5 + 6 + 6
((9 * 9) * 6) + (4 + 9 * 6 + 4 * 9 + 7)
(3 + 9 + 2) * (3 * 7 * 7 * 7 * (8 * 8 * 4 + 3 + 8)) + 2
6 * 6 + 8
((9 + 5 + 8) + 9) + 7 + ((9 * 5) * 3 * (3 * 4 * 4 + 3) * 7) + ((5 + 6 + 2) * (7 * 2 * 9 * 8) * 5)
6 + (8 * 7 * 6 + 5) + 9 * 7 * 7 * 7
2 + (4 * 9 * 3 * 9 + 8) + 2 * 7 * 3 + 4
7 + 3 + (5 + 7 * (4 + 4 * 8) + 2 + 8 * 6) * 2
(2 * 5 * (4 * 7) * 9 * (3 + 7)) + 3 * 4 * (2 * 3 * 8 * 4) * ((6 + 2 * 2) + (6 * 5 * 7 * 6) + 9 * (8 + 4))
((9 + 3 + 5) + 8) * 2
2 + 4 + 7 + 5 * (6 * 7 + 8 * (4 * 3 + 6 * 4 + 7) * (7 + 3 + 7 + 3 * 2) + 8)
5 + (9 * 8 + 5)
(2 + (9 + 7 * 8) + (6 + 7) + 6) * 5 + 3 * 2
7 + (9 + (8 * 7 * 9)) * 8 + 3
9 * (9 + 4 * 2 * 3 + (6 + 7 * 8 + 9)) + 6 * ((7 * 4 + 7 * 4) + 2 * 6 * 5 + 6 * 6)
((3 * 3 + 4 * 9) + 7 + 7 + 3) * 8
9 + 8 * (2 + 6 + 8 * 6 + 3 + (8 * 6 * 6 * 4 * 6))
3 * (9 + 2 * (9 + 2 * 8) + 3 + 8 * 5) + (9 + 8 + (6 * 9 + 2 + 8 * 5 + 7) * 7) * 2
((2 + 9) + 3) * 6 * 2 * 2 * 4 + 7
2 * 3 + 4 + (7 + (7 * 5 * 5 + 5) * 9 + (3 + 3 * 5) + 3 * 8)
4 * (8 + 2 + (3 * 7 + 4 + 2 * 6 + 2) * 8 + 7)
4 + (5 * 9 * (8 + 3 * 9 + 9 + 5) * (3 * 8 + 9 * 8)) * 8 + 9
4 * 5 * (2 + 2 + 7 + (3 * 7 * 4 * 2) + 3) * 6
((8 * 8 * 4 + 4 + 5) + 6) + 9 * (3 * 3) * 4
9 * (8 + (6 + 2 * 7 + 3 + 8 * 8) * 3 * (9 + 3) * (3 + 7 * 3) + 5)
9 * 3
6 * (7 + 8 * 8 * 4) * 6 * 9 + (4 * 7) * 4
4 * (3 * (4 * 9 * 6) + 5 + 5) * 4 * 6 * 6 * ((9 + 3 * 6 + 5 + 8) + 4)
5 * 2 * (4 * 3 + (8 * 4 + 2 + 2) * 6 * (8 * 8 * 2 + 7 + 9) + 3) * 5 + (4 + 6)
3 + (5 + 6 * 5 * 9) * 9 + 7
((3 + 6 + 8) * 7 * 3 + 4 + 4 * 8) * 2 * 2
2 + ((9 + 9 * 4 + 2 + 3) * 4 + 9 + 5 + (7 + 3 * 9)) + 8 + 7 * 3
5 * 5 * (5 * 6 * 6 + (3 + 4 * 8 + 7) * 2) * 6 + 4 + 3
4 + 3 * (5 + (6 * 5 + 6 * 2) * 4) + 9 + 7 * (5 * 5 + 9 * 5)
2 + (6 * 7) + 7 + 3 * 7
5 * 7 * (6 + (9 * 5)) * 4 + 2
((7 * 7 * 3) + 2 + 2 + (9 + 8 + 3)) * (3 * 8 + 6) + ((6 + 2 * 6) * (2 * 4 + 3 + 8 + 2)) * 8
((8 + 3 + 8 + 5 + 8 * 3) * 2 + 4 * (6 + 4)) * 8 * 2 * 5 + 9
7 + 6 * 3 + 3 + (5 * 7 + 3 + 3 + 8) * 6
8 + 7 + ((5 * 9 * 3 + 3 + 4 + 6) + (6 * 6 + 2 + 6) + 8)
5 + 5
6 + (6 * 5 * 7 + 8)
(8 + (9 + 2 + 8 + 2 + 2) * 4 + 7 * 6) * 9 * 6 * (6 * 6 * 5 + 5 * 4) + 7 + 9
3 + 8 + (3 + (6 * 9 + 9 * 2 * 3 * 4) * 3 + 9 * (4 * 2) + (3 * 2 * 9 + 2))
(5 * 8 + 7 * 8 + (2 + 3 * 8) * (8 + 4 * 7)) * 3
8 + 2 * (2 + (6 * 6 + 9 * 3 + 6) + (9 * 2 * 4) + 6 * 4 * (6 * 3 + 2 + 6 + 3 + 5)) + 8 + 4 * 9
8 + 8 + (4 * 9 + 9)
5 + 5 * (5 + 8 + (3 * 9 * 9 + 8 + 8 * 2) * 5) * (8 + 7 + 7 + 8 + (2 + 7 * 4 * 8))
6 * 3 + 6 + ((9 * 5 * 4 + 6 + 5 + 5) * 6) * 2 + (6 * 5 + 5 * 7 * 8 * (3 + 7 * 7 * 9))
4 + (3 + 4 + 5 * (4 * 2 + 7 * 9 + 6 + 6)) + (7 + 7)
2 * (6 + 2 + 6 * 3 + 4) + (6 + 5 * 4 * 8 + 3 + 7) + 8 + 3 * 5
((5 + 3 + 7 * 2 + 9 * 5) + 7 * 7 * (4 + 7 + 9) + 8 + 6) + 3
((9 * 9 + 2 * 7 * 5 * 6) + 8 * 7 * 4 * 2 + 6) * 5 * 9
((3 * 3 * 2 + 5 + 6) * 7 + (3 * 6 * 2) * 3 + 3) + 9 * 7 + 5
(7 + (4 + 7 + 6 * 8 + 9 * 9) + 7 * 2 * 2) * 7
(9 * 3 * 9) + ((2 * 6 * 6 + 9 * 7) * 3) + 3 + 8 + 8
2 + (3 * 5) * (2 + 8 + 8 * 3 * 6 + 6) * 6 * 9
(4 * 7 * 7 + 3 + 4) * 3 * 9 + 6 * (2 + 5 * 4)
(8 * 4 + 3 * 8) * 4 * 5
(7 + 5 + (4 + 2) + 4) + (2 * 5 * 9 * 2 * 6)
9 * 4 + 3 + 8 * (2 * 4 + 7 * 2 * 2) * (2 + 6 + 5 + 9 + 5)
8 + 3 * (6 * 8) + (2 * 4 + 7 * 8)
(9 + 6 + 3) * 5 + (9 * 8) * 5 + 6 * 5
((6 * 2 + 6 * 2) + 3 + 7 + 5 * 8) * 2 + 2
2 + (9 * 3 * 9) * (4 + (6 + 4 + 7) + 5) + 9
(3 + 4) + 5 + 7 + 7
9 + 8 + 8 + 7 + 5 + ((2 + 7 * 9 * 7 * 6 * 9) * 8 * 8 + 7 * 3 + 9)
(8 * 7 * (8 * 7)) * 9 + (4 * (4 + 9) * (7 * 9 + 9 + 6 * 5 + 5) + 7)
(6 + 7 * 9 + 5 + 5) * 5 * (2 + 6 + (3 * 6) + (7 + 3 + 5 * 5) + 9)
2 + ((7 + 8 * 2 + 8) * 4 + 2) * 9 * 9 + 8
8 * 8 * 7 * 2 + 2
7 * 2 + 9 + ((5 * 2 + 6 * 9 + 8 + 7) + 6 * 2 + 8 + 4 * (3 * 2 * 3 * 2))
5 * (7 * 5 + (7 * 9) * 4 * 6 * (8 + 7 + 3 + 9 + 9)) * 4
8 * ((3 + 7 + 5) + 7) + 5 + (6 + 4 + 6 + 4 * 4) + ((2 * 6) * 3) + 9
3 * 3
4 * (5 + 5 + 6 + 2 + 7) + 7 * 6
(7 + 4 + 5 * 9 + 5 + 8) * 8 * (7 * 9 * 9) + 4
3 + (9 * (7 * 7 + 3 * 4 + 8 + 5) * 7 * (2 * 4) + 9 + 5) * (4 + 7)
6 * (5 * (6 * 2) + 6 + (4 * 8 + 9) + 3 * (2 * 4 + 4)) * 6 * 5 + 6 + 3
(9 * 3 * 9) * 8 * 5 * (8 + 3 + 2 + 9)
(8 + 8 * (8 * 9) + 2 + 7) + 8 * (5 * 7 + 6 + 2 * 4 * 2) + 6 * (3 * 8 + 6) * 2
2 * (8 * 5 + 7) * 8 + 7 * 9
4 * 4 * (5 + (5 * 4 + 2 * 9 + 5 + 7)) * 8 * ((4 * 9 + 4) + 6 * (7 + 2 + 4 * 8 * 9))
4 * 6 + (4 * 8 * 3 * (9 + 8) * 7 * 9)
(6 + 9 + 3 * 2 + 8 * 8) * 6
(8 + (3 + 3 + 2 * 3) + (6 + 7 * 6) + 7 * 4 + (9 * 5 * 4 * 6 + 2)) * 2 + 5
4 * 6 + 2 * 5 * 2 + (5 + 3 + 2 + (5 * 3 * 3 + 7 * 6 + 2) + 8)
9 + 2 + (7 * 7 + 7 + 9)
5 + 8 + (8 + (5 + 9 + 6 * 2 * 4 * 4)) * 9
(2 + 4 + 8 + 7 * 8 * 5) + 3 + 3 + (9 + 9 + (9 * 2 + 6 + 4 + 4) + 6 * 2) + 2
7 + (6 + 5 * 2 * 9 + 7 + (9 + 7)) * (3 + 6 + 2 * 5 * 3)
8 + (9 + (4 * 3 * 7 * 7) * 7) + 9 * 6
6 * 9 * ((8 + 5) + 9) * 7 * 8
(2 * 9 + 2) + (6 * 3 * 3 + 6 * 7 + 9)
7 * 5 * (4 * 4 + 7 * 4 + 8 + 3)
3 * (6 + (5 + 3) + 5) * 3
(7 * (9 * 5 * 9 + 2 + 4) + 3 * 8 + (9 + 7) + (2 * 9 + 5)) * (6 + 3 * 9 + 3 + (7 + 4 * 9 + 5) + 9) * (8 * 2 + (2 * 9 + 7 + 5 * 4) * 4)
4 + 7 + 5 + 6 * 8
5 + 4 + 3
9 * (6 * 2 + 7 + 5) * 3 * 2 * 2
7 * 4 + ((6 * 7 * 6 * 8 + 6 * 9) * 7 * 3) + 8
9 * 5 + 4 + 8 + 8 * 8
(3 + 6) * 2 * 7 * (2 * 7 + 2 + 6 + 3)
5 * 2 + 8 * 7 + (4 + 8 + (3 * 6 + 7 * 2 + 4 + 7))
6 + (8 + 6 * (9 * 7 + 2 + 2 + 3 + 4) * (4 * 7 + 2 + 4 * 3) * 3)
(8 + 5 * 2) * (9 * 4) + 5
3 * (4 * 5 * (4 + 3 + 4) + 5 * (3 + 6 + 3 * 7 * 7)) * 3
2 + 7 + (8 + 3) + 8
8 * (9 * 8 * 3) + 4
(2 * 6) * 3
((9 * 6 + 3 + 3 * 9 + 7) + 2 * (2 + 9 * 8 + 2 * 4) + 9 * 8 + 6) + (5 * 9 * (2 + 7) + 7 * 9) + 7
4 + 7 * ((3 * 7 + 2) * 9 * 7 * 2 + 4 + 3) * 4 * (3 + 8 * 9) + 6
9 * (9 + (9 * 6 + 2 * 7 + 6) + 7 * 2 + 2)
(9 * 2 + 4 + 8 + 6 * 8) * (4 + 8 + 7) * 5 + (4 * 2 + 2) * ((4 * 5) * 8) * 2
(5 * 9 + 9 + 2) * 3 + ((7 * 5 + 9 * 3) + 2 + 3 + 6 + 7) + 4 * 6 * 6
9 * 8 + 3 * 4 * (9 + 5 + 7 + 5) * (6 * (7 + 4 * 6 * 7) + 6 * (6 * 5 * 3 + 9 + 4) + (2 * 3 + 3 + 6))
7 * 6 * 2 + (8 * 9 + (6 * 7 * 8 + 6 + 9 * 8) * 3 + 6)
5 + 7 * 8 + 2 + ((2 + 4) * 7)
2 * 5 + 6 * 6 * (3 * 6)
6 * 6 * 6 * (6 * (4 * 4 + 5) * 4 + 3 + 9) + 4
((3 * 4 * 7) * 5 * 9 + 7 * 6 + 5) + 2 * 2 * 6 + 4 * 8
7 * 2 * (3 + (6 * 9 * 9) * 4) * (5 * 8 * 7 * 6 + 2 * 9) * 7
9 + (6 + 6 + (8 + 8 * 3 + 6 + 6))
5 * 2 + 7 + 3 * (9 + 9 * 9 * 9 * (4 * 4)) * 2
4 + 6 + 3 + (2 + 2 * 7 * 2) + 5 + 7
7 * 9 * 9 * 2 * 4 + 7
6 + (6 + 5 + 5) + 7 + 4
9 + (9 * (7 * 3 + 9 + 7 + 8 * 8) * 6 * 5) + 2 * 5
8 + 6 * 8
8 * (9 * 6 + 4 + 8 + 8)
((8 + 3) + 8 * 2) + (3 * 6 * 7 + 7 + 4 + 2) * 9 * 5
6 * (4 * 5 + 6 * 7 * 4) + (2 * 8 + 4 + 7 + 7 + 6) + 9 + 5
9 * 8 * (2 + 7 + 9 + 4 + 5) + (8 * (3 * 8 + 3 * 6)) + ((7 * 2) * 7) + 2
9 + 4 + 9 * 2 * (5 * 2 + 6 + (9 * 5 + 8 + 2 * 5) + 6 + 6) + 7
9 + 9 * ((3 * 6) + (5 + 5 + 7 * 9 * 4 + 9) + 2 * 6 * 6) * 5
(9 * (3 * 2) + 8 * 2) * (6 * (8 + 3 * 8 + 5 * 5 * 9) + 4 + 9 * 6) * 5 + 9 * 6
7 * 9 * (2 * 9 + 4 * (3 * 2 * 6 * 9 + 5 + 6) + 2) + 7 * 6 + 3
9 + (5 * (3 * 9) + 4 * 6 + 6) + 9 + 8 * 5
8 + 8 * 8 + (9 + 4 * (5 + 3 * 8 * 3 * 4 * 4) + 2 * 8 * (9 * 6 * 4 * 6 + 9))
(6 + 6 * 3 + (5 + 8 * 4 + 4) + 3) * (3 + 7) * (6 + 5 * 4 * 6 + 6 + (5 * 7))
(9 + 7 + 6 + (8 * 8) * 4 * 6) + 3 * 5
5 * 2 * 3 + (3 + (6 + 9 * 2) * 3 * 3)
2 + (8 * 7 * (4 * 8 * 2 + 6 * 7)) * 5 + 5 + (8 * 5)
9 * 6 * 4 * 2 * ((6 * 3 + 9 * 8) * 5) * 3
((8 + 6) + 6 * (8 * 5 * 5 * 7) + (2 + 9 + 6 * 7) * 7 * (2 + 9 * 7 * 3)) * ((7 * 5 + 2 * 5) + (8 * 7))
(7 + 8) * 6 * 9 + 6 + 6 * 8
7 * 8 + (8 * 2) * 7 * 8 * 9
9 * ((8 + 6 * 9 + 2 + 3 * 2) * 2 + 4 + 3 + 7) * 2 * 6
2 + (8 + (2 + 9) * 7 * 4 + (8 * 6 + 8 * 6 * 4 + 5) + 6) + 4 * (9 + (3 + 4) * (3 * 9 * 7 * 6 + 9 + 7) + 9 * 6 * 3)
2 + (8 + (8 * 2 + 3 * 8 * 4 + 2)) + 3 * 6
(5 * 5 + (3 + 5 * 6 * 9 + 4 * 4)) * 8 * (7 * 7 + 3 * 7)
9 + 6 * (9 * 2 + 2 * (9 + 6 * 8 + 5 + 3))
5 * 5 + 5 * (7 * 3 * 3 * 5) + 6
7 * 5 * 7 * ((6 * 3 + 5 * 8 * 6) * 7 + 4 * 5) + 7
(5 * 4 + 8) * 3 + 6 + 9 + 6
(7 + 7 + 4 + 8) * (2 * 7 + 9) * 2 * 4
2 + ((7 + 2 + 9 * 4 + 2) * 6 + 9)
9 + 2 + (7 + 6 + 4) * 3 * 8
5 + 7 * 2 + 2 * (3 * 4 + 4 * 6) + 2
2 + (7 + 2 + (9 * 3 * 5 + 7 + 7) + 5 * (7 + 7 * 2 * 4 * 7 * 4) + 5) * (6 + 2 * 5 + (4 * 6 + 4 * 8 * 4) + 7) * 2 * 5
((5 * 9) * 9) * 2 + 4 + ((3 + 6) + (9 + 3 + 6 + 3) * 3 * 5 + (9 + 9 + 6 * 7) + 7) * 2 + 9
4 + (4 + 4 + 6) + 6 + 5 * 9 + 8
(3 * 8 * (7 * 5 * 7 * 5 * 7 + 2)) * 7 * 4 + 3 + 2 + 4
(4 * 8 + 7 + 8 * 5 * 9) + 2 * (5 * 2 * 3 * 9) + 7 + 7 * 2
6 * 3 * (4 + 6) + 7 + 2
(5 + 4 + 4 * 8 + (4 * 6 * 5 + 7 * 4 * 2)) * 9 * 6 * 6 * (3 + 5 + 9 * 7)
4 * (5 * 2 + 8 * 9 * 3) + 3
7 * 3 + 7 + 5 + ((6 * 8 * 8 + 8 + 2 * 4) * 8 * 2 * 9)
4 * 2 + 6 + 2
(2 * 2 + 2 * 9 * 6) + (5 + 9) * 3 * 9 * 5
(5 + 5 * (3 + 3 + 7) * (3 * 7 * 7)) + 4
9 + 7 + 9 + 5 * 6
(6 + 9 + (4 + 7 * 7 * 4) + (9 * 2 + 9 + 5 + 6)) + 7 * 8
5 + (5 * (6 * 5 + 8 + 2) + (4 * 7 * 4 * 7 * 7 * 8) * 8)
4 + (6 + 6 * 2 + 9) + 7 * ((3 + 8) * (3 * 5 + 5 * 3 * 3 * 6) + (4 + 9 * 3 + 3 * 2 + 9))
(7 * (7 + 7 + 5) * 8 * 2 * 8 + 3) + (2 * 4 + 8 * 7 + 3 + 2) + 7 * (7 + 2 + 2)
(3 * 7 * 4) * 5 + 4 * 7 * 8 * 4
7 * 3 * (2 * 7 * 9 * 7 * (8 + 4 + 2) * 3) + 7
7 * (9 + 2 + 5 + 5 + 7 * 5)
5 + 2 * 9 * (8 * 6 * 8 + 2 * 7)
4 + (2 + (2 * 5 * 7 * 5) + 3 + 6) + 8 * ((3 + 4 * 4 + 5 * 3 + 6) + 2 + (5 * 8)) + 8 + 3
2 * (9 * 7 * 3) + (8 + 7 + 8 + 2 * 3 + 9) + 8 + 9
8 * (7 + 5 * 3 + (2 * 6 * 6 * 4) + 9) + 3 * 4
3 + 4 * 8 * 9 + (6 + (5 + 7 * 7 * 4)) + 7
(5 + 6 + 8 + 5 * 7) * 2 + 5 * (9 * (9 * 9 + 8 + 5) + 7 * 4)
8 + (8 * 2 * 4 * 2 + 3 * 2) * (3 * 3) * 6 + 8
(6 * 2 * (6 + 5 * 9 * 3) * 6 * 2 + 7) + 7 * 8 + 2 * 4
5 + (2 + 4 + 5 * 4 + 6) + 9 * (5 * (5 + 9) * 9 * 9 * 2 + 8) * 5
7 * 4 + 9 * (9 + (5 * 7 + 8 * 7 * 5) + 9 + 2 + 2 + (2 * 4 * 7 + 5))
7 + 2 + (4 + (8 + 8 + 5 * 9)) + 9
(8 * 3 * 9 + 6) * 8 + 8 + 7
(2 + 3 * 9 * 4) * 7 + (8 * 6 * 9) * (8 + 6 + 9 + 4)
((7 * 6 + 4) + 6 + 6) + 5 * 4 + 3 * 4
5 * (2 + (3 * 9 + 9 * 6) + (7 + 3 + 2 * 4 + 9)) + 7 + 8 * 5 * 5
7 * 9 * (5 + 6 + (7 * 6) + 4 + 4 + 3) * 2 + 9
(3 * 2 + 5) * 8 * (2 + 4 + 2 + 8 + 7 * (8 * 9))
((2 + 7 * 8 * 9) * 4 * 3 + 6 * 7) + 9 * 8 + 5 + 9
5 + 4 + 9 + 8
7 + 7 + 9 + 2 + 5 + ((6 * 3 + 3 + 6) * 4 * (4 + 4))
(9 * 4) + 8 * 4
3 * 9 * (9 + 5 * 4) + 8 + 9 * 3
3 + (9 * 8 * (6 + 4 + 6 + 5 * 2) + 9 + (4 * 7 * 7) + (3 + 4 + 6 * 8 + 9)) * (2 + 8) + 7 * 5 * 6
9 + 6
6 * 8 * 8 + 6 * 6 * ((9 + 3) + (4 + 2 * 8 + 8 * 2 + 5) * 2)
4 + (4 * (2 + 2)) + 7 + 4 + (4 * (8 + 8 + 4 + 4 + 2) + (3 + 2) * 9 + 8) + (4 + 9 * 9)
(2 * (3 * 7 + 6 + 2)) + (4 * 6) + 6 + (6 + 9 + (2 * 2 * 2 + 6 + 4) * 4) * 5 + (4 + 2 * 5 * 8 + 6 * 2)
4 * ((5 + 5 + 9 + 3 * 5) * 7 * (7 + 9 * 5 * 7 + 2) + 5 * (4 + 7)) + 7 * 9 * 6 * 4
4 * 7 + 4 + ((4 + 8 * 6 * 3 + 2) + 3 + 8 * (6 * 7 * 2 * 8) * 7) * 9 + 6
4 * 6 * ((3 * 6) + 4 + (2 * 2 * 2 * 7) + 9 + 8) * (3 + 8 * 2 * 4 * 2 * 3) + (4 + 3 * (7 + 5) + 6 + 9) + 5
(7 + 2 + (8 + 6 * 4)) + 8 + (7 + 5 + (2 * 5 + 9) * 5)
(7 * 8 + 5 + 8 + 8 * 2) * 6 + (5 + (8 + 3 + 4 * 5) * 9)
8 * (4 + 5 * 9 + 6 + 8 * 7) * 3 * 6 + 4 * 5
6 + ((6 * 3 * 4) + (8 * 8 * 2 * 5 * 8 + 2)) + 3
9 * 3 + 6 + 5 + ((5 * 2 + 9 * 5 + 6) + (4 * 9)) + (4 * 2 * 3 + 7)
6 + 8 + (6 + 2 + 8 + 2) * (5 + 8 + 5 * 5 + (4 + 9 + 3))
(2 * 7) + (6 + 4 + (8 + 6 + 5 + 9 * 4 + 7))
8 * 3 + 3 * (3 * 5) * 6 + 2
9 + 4 + ((5 * 4 + 2 + 6) + 5) * 5 + 6 + 4
(9 * 9 * 3 + 5 * 3 * 4) * 3 + (2 + 3 * 5 + (3 + 6 * 6 + 2) * 8 + 3)
(6 + 9 * 9 + 7 * 6) + 7
4 + 6 * (3 * 3 * 7 * 7 * 5 + 2) * (7 + 7 * 2 * 5 + 4 + 9) + (8 * 2 + (8 + 8 * 4 + 7 + 3 + 5) * 7) + 9
4 + 8 + 6 * 7 * 7 + (2 * 8 + 3 + 5)
4 * 8 * 4 * (9 * 9 * 5) + 9
8 * 5 + (2 + 3 + 2 + 8 * (3 + 5 + 8 + 7 * 9))
3 * ((8 * 6 + 9 * 8 * 5) + 9 * 6 + 6) * 6
5 * 8 + 6 * (5 * 2 * 8)
8 + (6 + 7 + 7 * (6 + 7 + 3) * (5 + 2 * 7) + 7) + (2 * 8)
6 + 5 + 4 + 2 + ((3 + 8) * (5 + 4 * 9) * (4 + 9 + 3 + 9 + 9 * 7) + (5 + 2 + 9 + 3) + (6 + 6) + 3)
3 * (2 + 5 * (5 * 6 * 5 + 9) + 9 * 5) * 8 * 5 + 4
2 * 4 + 6 + (9 * 4 * 3 * 4)
(4 * 6 * (3 + 9) + (3 * 5 + 8 * 5 * 9) + 6) + 9 + 8
(3 * 5 + 8) + 8 * 8 * 7 + 8 * (9 + 6)
(5 * 4 * 6 + 3 + 3) * (3 * 8 * (7 + 2 * 9 * 6)) + ((9 * 9 * 4 + 8 * 7 * 7) + 4 * 4) + 8 * 6
3 + 5 * 5 * 6 * ((3 + 3) * 8 + (6 + 9 + 2 + 6 * 7)) * 4
9 + ((4 * 7 + 2 + 2 * 6) + 8 * (4 * 6 + 7 * 5) * 7 + 4) + 6 + 6
(9 + 9 * (8 * 2 + 9 + 5) * 3 * 4 * 4) + 5 * ((3 + 6 * 3 * 7) + 6 * 4) * (3 + 8 * 9 + 6 + (4 + 3 * 4 + 2) + 6)
5 * 5 * (9 + 8 * 3 * 3 + 3) * 4 + 8
3 + (6 * 9 * 8) + 9 + (3 + 3 + 2 + 5 + 2)
3 + 4 * (4 * 8 + 2 * (3 + 3 + 4 + 9 * 7) + 4 + (6 + 9 + 4 * 6 + 9))
6 * 5 * 9 * ((6 + 9 * 6 + 7) + (6 * 4 + 2 * 4 * 6 * 6) + 9 + 6 + 8)
7 + 7 * 2 * 4 + 7 * 2
2 + 8 * (7 + 3 * 3 + 2) + 6 + 3 * 7
2 * 2 * 9 + 8 + 8
9 + 5 + 4 * (6 * 7 * 5 * 7 * 4 * 3) * 3
7 * 5 * 7 * 6 + 4 * 9
((9 + 7 + 9 + 7 * 7 * 4) * 6 * 5) + 5 + (8 + (2 + 6 * 9 * 7 * 9 + 9) * (9 * 3 * 8 + 9 * 6 * 2) + 6 * 7) * (2 + 6 + (3 * 4 + 4) * 6 * 5) * 9 * 5
(7 * 5 * (3 + 2 + 6 * 5 + 9) + 5 + (2 + 9) + 2) + 2 * 6 + (5 * (7 * 2 + 3 + 8 * 9) * 7 + 6 + 6 * (5 + 3 + 9)) * (4 * 6 + (9 + 7 + 4))
((3 + 5) + 7 + 3) + 6
3 * 4 + 4 * 6 + (5 + 8 * 2)
7 + (7 * (4 + 4)) * 3 + 7 * 4
(5 + 4 * 6 + 3 * 9 + 7) * (7 * 3 * 5) + 6
3 + 4 * (8 + 2) + ((6 * 7) + 8 + 8 * (9 * 3 + 2) * 9)
7 + (7 + 9 * 2 * 9 * 2 * (2 + 5 + 9 * 6)) * 4
(7 + 6 + 3 + 5 * 2) + 2 * 3 + 4 * (3 + 4 * 5 * (3 + 7) + (7 + 2 * 7 * 6) + 8) * 8
4 + (9 * 2 * 6 * (6 + 6 * 7 * 7 + 5) * 9) * 9 + (4 + 8 * 7) * 4 + 4
6 * 6 * 2 + (4 * 2 + 7 + 4 + (2 + 2 * 5)) + 2
8 + 2 + 3 + 3 + 8 + (6 + 4)
8 + 9 + 2 + ((3 * 9 * 3 * 5) * 3 + (2 + 2 + 8 + 6 + 9 + 7)) + 9
6 * (3 * (5 * 4 + 4 * 4 * 4 + 4)) * 8 * (5 + (5 + 2 * 7 + 8) * 3)
3 + ((3 + 7) + 2 + (5 * 3 + 4 * 9))
4 + 5 * 6 * (7 * 5 + 6 * 5 * 5 + (4 * 6 * 9 * 6)) + 7 + 3
7 * 4 * 7 * 5 * (3 + (5 + 6 + 9 * 9 * 3 * 7) * 2 * 8 + 2 + 6)
5 * 4 + (4 * 7 * (3 + 8 + 9)) + 4
(7 + (3 * 5 * 7 + 5 * 8) * (6 + 9 * 6 * 7) * (3 + 9 * 8 + 4) + 8 + 7) * 2 + 4
8 + 7 + (9 + 6 + 7 + 9 + 6 + 4) + (7 * 8 * 6 * 5 * 3) + (3 * 4 * 3 * 8)
7 * ((4 + 4 + 9 + 3 * 3) + (9 * 6 * 8 * 7 * 3 + 6) * 7 + (7 + 2 * 3 + 6 * 2)) + 3 + (5 * 8) + (4 + 9 * 6 * (2 * 5 + 7 * 3 * 5) * 3 * 8)
8 + (3 + (8 + 3 * 4 + 4)) * 2 * 4 * (3 + 4)
(4 + 9 + 4 + (4 + 7 * 3 * 2 * 5 + 7)) * 2
2 * 8
6 * (7 * 5 + (4 * 5 * 2))
(3 + 3 * 4 * 3 + 7 + 4) + 8 + 2 + 4 * 4 * 5
7 * 2 * 5 + (2 * (9 + 6) * (3 * 8 + 4) + 3) * 9
(6 * 9 * (6 + 6 + 7 + 7) * (5 * 7 + 8 * 5 + 2 * 8) + 5 + 8) * 9 * 9 + 3 * 2 + 7
(2 * 3 + 8 + (4 * 2 + 7 * 2 + 7 + 7) + 3 + 6) * 3 * (6 + (9 + 7 * 2 + 2) + 6) + (4 + 3) * 3
4 * (6 * (8 * 8 + 7) + 7) * 6 * 9 * (4 * (6 * 4 * 3 * 2 + 6) + (8 * 9) + (9 + 3) * 4)
5 * 7 * 2 * (2 * 2 * 5 * (8 + 6))
(8 * (7 + 7 + 8)) + 2 + 9 * 9 + 9 * 4
6 + 6 + 5 + (2 * (8 * 7 + 3 * 6) + 9) * 7 + 6
8 + 6 + (8 * 4 * 8 * 2 + (6 * 6 + 9 * 3 + 6)) + 3
9 * 5 * 4 * (5 + (3 + 7) + (4 + 4 * 5 + 5 * 8 * 9) * 5)
5 + 4 * 9 * ((2 * 4 + 8 * 2 * 7 + 2) + 4) * 9 * 3
3 + 6 * (6 + 2 + 3 * 2) + (3 + 5) + ((3 * 6 + 5 + 7 + 8 * 8) * 9 + (5 + 8 * 7 + 6 * 8 + 7) + 7 + 8 + 5)
7 * ((7 + 5 * 3 * 5 + 4) + 7 + (6 * 3 * 6 * 6 * 7 * 7))
((5 + 7 * 9 * 2 + 3) * 2 + 9 * 3) * (4 + 6) * (4 * 7 * (9 + 6 * 8 + 5) * (3 + 8 + 9) + 9 * (8 + 6 * 9 + 6)) * 6 + 4
2 * (6 * 3 + 4 + 4 * 2) + 6 + 7 + 5
2 + 7 + 5 + 5 * ((7 * 6 + 2) * 8 * 8) + (2 * 5 * 4 * 5)
3 + (7 * 8 * 5) + 5 + (5 + (4 * 4 + 7 + 2) + 6 + (8 + 3) * 9 + 4)
6 * (9 + 5 + 6) * 5 + 5 * (7 * (3 * 5 + 6 + 2 * 5) * 2)
(9 + 6 + (9 + 7 * 5 + 6 * 7) * 7 * 3) + 3 + 4 + 6
7 * ((5 + 4 + 6) + 7) + 2 * 3 + (6 + 9 * (6 * 4 * 8 * 3 + 4 * 2) + 7) + 3
7 * (8 + 9 + 5 * (9 * 7 * 9) + 2) + (7 + 7 + (7 + 3 + 2 * 2) + 4 * 2)
3 * (2 * (4 + 6) * 8)
8 + ((6 * 4 * 8 + 4) + 7) * 7
(7 + (2 + 8 * 8 * 6 * 2)) + 7 * 2
(4 * 2 + 4 * 8 + 4) + (3 * 9 + (2 * 4 + 2 * 7) * 9 + 7) * (5 + 9) * (7 + (3 * 4 * 4 * 6) + 8 * 7) + 8 + 8
8 + (2 + 2 * 8 * 7 + 7) + 2 + 4 * 3 + (8 + 9 * 9)
3 + 2 + 8 + (9 + 3 * (3 + 2 + 9 + 7) + 4 * 4 * 7) * 3
5 * 4 * 7 * 3 + (9 * (6 * 6 + 2 * 4) * 8 + 2 * 9)
4 * 7 * (3 + 6 * 6 + 4 + 8) + 5
(8 + (8 + 2 * 9 + 3 * 3) * 8 * 8 * (9 * 6 + 2 * 6)) * 9 + 5 * 2 + 5
5 + 6 + 3 + 4 * 9 + (4 + (4 + 3 + 9 * 2) + 4)
3 * (5 + 3) * 7 + 6
((3 * 2 + 2 * 6 + 5 + 3) + 4) + (4 * (8 + 2 + 9 * 2) * 8 + (8 * 3 + 6 + 2 + 6) * 2) + 7 + 2 * 9
6 * 8 * ((8 * 8 + 3 * 7 + 8 * 4) * 4 + 9) + (8 * 7 * (6 * 8 * 3 * 2) * 3) * 2 * 8
(2 * 7 + 4) * 2 * (5 * 4 + 2 + 5 + (7 + 5) * (4 * 3 + 6 * 8 * 5 + 9)) * 5
(6 * 8) * (7 * 7 + 8 * 3 * 3) * (5 * 8 + 2)
(6 + 6 * 2) * 5 + ((7 * 6 * 8) * 8 * 9 * 4)
(8 * 4 * 9) + ((5 * 3 + 6 * 3) + (9 + 9 + 9 * 2 * 2) * (4 + 9 * 7 + 2 * 2 + 3) + 6) * 7 * 6 * 6
((4 + 3) * (2 * 5 + 8 * 2 * 4) * 9) + 6 + (6 + (5 * 4 * 5 * 3 + 3) * 6 * (5 * 3 + 7 * 2 + 4 + 8)) + 4 + 7
(6 * 9 + 9 + 7) * (6 * 2 * (4 * 7 * 4 + 4 * 5 + 7) + (7 + 5 * 8 * 4 + 9 + 6)) * 7 + 8 * 5 + (9 * 5 * 2 + 7)
6 * 6 + ((2 + 9) * 5 + 2 * 3 + 3 * 3) + 9 * ((4 * 7) + 5 + 8 + 4)
5 + (4 * 5 + 5 * 3 + 7) * 6 * 5 + (2 + (9 + 7 + 8 + 4))
(2 * 4 + 5 + 8 + 6 * 9) + 3 + 6
9 + (9 + 8 * 3) * (3 + 8 + 6 + 5) * 5
(3 + 9 * 5 + 7) + 2
((9 + 5 * 2) * 5 + (4 + 2 * 7) + 9) * 8
(4 + 4) * 9 + 3 + 2 * 8
(3 + 4 * 8 + 9 * 6 + 6) * 5 + 8 + 9
3 * 8 + 9 * (3 * 4)
6 + 7 * 6 * 7
3 * 3 + (8 * 8 * 9 + 3 * 8 + 2) * 3 + 8 * 2
5 + ((6 + 2 * 6) * 8 + 6 * 5) + ((7 + 3) + 2 * 5 + 7 + 6 + 5) + (8 + 2 * 7 + 4 + 2 * 3) * 2 * 5
(6 * (6 * 7) * 7 + 3) * 9 + 6 * 3
(5 * 9 + 7) + 8
(3 + 9 * 3 * 9 * 2) * 9 * 5
5 + (6 * 3)

88
d18/main.py Executable file
View File

@ -0,0 +1,88 @@
#! /usr/bin/env python3
operators = {
"+": lambda x, y: x + y,
"-": lambda x, y: x - y,
"*": lambda x, y: x * y,
"/": lambda x, y: x / y,
}
def evaluate(s):
num_s = ""
num = None
left_num = None
op = None
s = s+" "
inner = None
level = 0
for c in s:
# print(f"reading {c} level {level} left: {left_num} inner: {inner}")
if c == ")":
# print("close paren")
level -= 1
if level == 0:
# print("eval inner", inner)
num = evaluate(inner)
# print(f"finished evaluating {inner}, Result was: {num}")
inner = None
else:
inner += c
elif c == "(":
# Start to read innner
# print("start reading inner paren")
if inner is None:
inner = ""
else:
inner += c
level += 1
pass
elif inner is not None:
inner += c
# print("append to inner paren", inner)
elif c.isnumeric():
num_s += c
elif c == " " and num_s:
# print("got number")
num = int(num_s)
num_s = ""
elif c in operators:
op = operators[c]
if num is not None and left_num is None:
# print(f"putting {num} on left")
left_num = num
num = None
# Evaluate
if left_num is not None and num is not None:
# print(f"evaluating {left_num} {op} {num}")
left_num = op(left_num, num)
# print(f"new left is {left_num}")
num = None
op = None
return left_num or 0
def part1():
# r = evaluate("1 + (2 * 3)")
# r = evaluate("1 + (2 * 3) + (4 * (5 + 6))")
# r = evaluate("1 + 2 * 3 + 4 * 5 + 6")
# r = evaluate("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2")
# print(r)
# return
total = 0
with open("input.txt") as f:
for line in f:
line.strip()
v = evaluate(line)
print(v)
total += v
print("sum: ", total)
if __name__ == "__main__":
part1()

96
d18/main2.py Executable file
View File

@ -0,0 +1,96 @@
#! /usr/bin/env python3
from typing import List
operators = {
"+": lambda x, y: x + y,
"-": lambda x, y: x - y,
"*": lambda x, y: x * y,
"/": lambda x, y: x / y,
}
class SynNode(object):
def __init__(self, nodes, ops):
self.nodes = nodes
self.ops = ops
def evaluate(self) -> int:
assert len(self.nodes) == len(self.ops) + 1
# Eval sub nodes
node_values = [node.evaluate() for node in self.nodes]
total_value = node_values[0]
for i, op in enumerate(self.ops, 1):
total_value = operators[op](total_value, node_values[i])
return total_value
class ValueNode(SynNode):
def __init__(self, val: int):
self.value = val
def evaluate(self) -> int:
return self.value
def find_high_level_ops(s: str):
balance = 0
indicies = []
for i, ch in enumerate(s):
if ch == ')':
balance += 1
elif ch == '(':
balance -= 1
elif ch in operators and balance == 0:
indicies.append(i)
return indicies
def parse(s: str) -> SynNode:
s = s.strip()
if s.isnumeric():
return ValueNode(int(s))
hl_op_indicies = find_high_level_ops(s)
if not hl_op_indicies:
# Must be like "(1 + 2)", remove parent and try parse sub operation
return parse(s[1:-1])
ops = [s[i] for i in hl_op_indicies]
nodes: List[SynNode] = []
start = 0
for i in hl_op_indicies:
nodes.append(parse(s[start:i]))
start = i + 1
# Parse remaining
nodes.append(parse(s[start:]))
while '+' in ops:
add_index = ops.index('+')
# Remove op and neighbor nodes and replace with a syn node instead
op = ops.pop(add_index)
right = nodes.pop(add_index+1)
left = nodes.pop(add_index)
nodes.insert(add_index, SynNode([left, right], [op]))
return SynNode(nodes, ops)
def part2():
# print(parse("1 + (2 * 3) + (4 * (5 + 6))").evaluate())
# print(parse("5 + (8 * 3 + 9 + 3 * 4 * 3)").evaluate())
total = 0
with open("input.txt") as f:
for line in f:
r = parse(line).evaluate()
total += r
print(f"Total: {total}")
if __name__ == "__main__":
part2()

538
d19/input.txt Normal file
View File

@ -0,0 +1,538 @@
2: 12 16 | 41 26
55: 92 16 | 84 26
107: 48 26 | 29 16
91: 16 86 | 26 120
56: 19 16 | 30 26
33: 69 16 | 127 26
65: 112 16 | 76 26
23: 16 16 | 44 26
102: 16 116 | 26 132
39: 16 26 | 26 26
40: 23 26 | 76 16
108: 16 53 | 26 51
22: 110 26 | 55 16
42: 1 16 | 47 26
14: 112 26 | 46 16
117: 115 26 | 76 16
120: 26 6 | 16 59
72: 26 130 | 16 66
131: 102 26 | 20 16
93: 16 16 | 26 16
58: 97 26 | 104 16
69: 26 88 | 16 46
54: 76 16 | 116 26
1: 26 64 | 16 28
48: 13 26 | 61 16
92: 85 26 | 117 16
49: 124 26 | 98 16
6: 44 44
24: 112 26
17: 112 16 | 116 26
115: 44 16 | 16 26
113: 16 128 | 26 89
106: 26 132 | 16 6
16: "b"
67: 44 16 | 26 26
104: 44 88
41: 26 132 | 16 76
38: 16 59 | 26 46
89: 16 24 | 26 62
80: 18 26 | 35 16
98: 46 26
101: 16 132 | 26 46
85: 16 59
126: 16 67 | 26 59
9: 26 49 | 16 80
10: 26 67 | 16 59
34: 26 93 | 16 23
4: 70 26 | 107 16
100: 123 26 | 63 16
109: 118 16 | 54 26
77: 16 50 | 26 99
88: 26 26 | 16 16
81: 67 26
18: 16 115 | 26 88
123: 57 16 | 103 26
60: 26 18 | 16 43
94: 26 23 | 16 59
0: 8 11
57: 46 16 | 125 26
110: 26 58 | 16 60
20: 44 76
15: 56 26 | 33 16
114: 26 132 | 16 23
7: 16 6 | 26 115
28: 16 3 | 26 25
51: 112 16 | 23 26
43: 88 16 | 116 26
111: 26 6 | 16 93
62: 26 132 | 16 112
76: 16 26 | 26 16
27: 96 26 | 45 16
50: 26 93 | 16 76
132: 16 26
35: 16 115 | 26 132
53: 16 46 | 26 116
75: 104 26 | 81 16
82: 26 9 | 16 100
78: 26 116 | 16 125
19: 16 39 | 26 132
37: 26 41 | 16 127
45: 91 16 | 108 26
59: 26 26 | 26 16
116: 26 16
84: 7 16 | 94 26
86: 16 6 | 26 88
63: 94 26 | 17 16
103: 115 26 | 59 16
130: 16 34 | 26 20
99: 39 26 | 6 16
26: "a"
64: 16 15 | 26 21
97: 67 16 | 23 26
83: 105 26 | 27 16
21: 75 16 | 52 26
30: 26 125 | 16 112
3: 16 121 | 26 74
105: 26 73 | 16 113
125: 16 16
13: 16 88 | 26 39
32: 72 26 | 122 16
122: 16 77 | 26 2
90: 4 26 | 32 16
12: 26 6 | 16 39
29: 68 26 | 101 16
79: 106 26 | 111 16
61: 132 16 | 46 26
31: 83 26 | 90 16
96: 16 87 | 26 5
118: 26 93 | 16 116
44: 26 | 16
25: 37 16 | 71 26
52: 10 26 | 7 16
124: 125 16 | 6 26
66: 26 36 | 16 14
127: 16 116 | 26 39
68: 26 46 | 16 6
70: 79 26 | 109 16
128: 126 16 | 40 26
8: 42
71: 26 114 | 16 78
73: 129 16 | 131 26
5: 16 65 | 26 118
11: 42 31
119: 16 112 | 26 6
95: 16 88 | 26 59
87: 119 16 | 14 26
121: 35 26 | 95 16
47: 22 26 | 82 16
46: 16 16 | 16 26
129: 12 16 | 17 26
112: 26 26
36: 67 26 | 125 16
74: 16 10 | 26 38
aaaaaababbaaababaaaabbbb
aabbabbabbbbbaaaababbbbbaaabbaabababbaaabababbab
baabaabaaabbaaaaaaabaabb
aabaaababababbbaabababaaaaaaabba
babbaabaaaabbabbabbaabba
aabbabbbaaaaaaabaabaabaa
aaabaabbaaabaabbaaaaababaabaabbabbabaaababaabaabbaabaabbaabaaaabbabababa
abbabaabbbaabbbbaabaababaabbaabbbabbbabbaabbabbaabaabbbbbaaabaababbabbba
abaaabaababaaabbbaaabbbb
baabbabbaaababbbabaabaab
abababbabbabbbaabaaaaaab
bbabbaababbbbbbbbaababba
abaaaaaaabbaaaaabbaabbba
abbbbaabbabbbaabbabbbbbbaaababbaabaaaababaaabbbabaaaaabbbababaabbbaababb
aabaaabbaaabbbaababbbaaaaabbaaababbbababbbabaabbabbaabbbbbabbbbbaaaababbabbabaaa
aaabbbababbbabababbaabba
babbbbabbbaabaabbbbaabba
ababbbbbbbbaaabababbaaaabbaabaaabbbabbab
bbabaaaaabababaababaabaaabababbb
bbabbabbabbaaaabbbaababbbaaaabaabbaaaaaa
baaaabaabbabbabbabbbbbbaabbbbbbbbbaababbbbabbaabaabababb
babbaaaabaababaabaababab
bbbababaababaabbbabaabbb
baaababbbbbbbababbabbabaaaaabbaa
baababaababbabbbabbababaabbaaabababbaaab
bbbaaabbbabbbaaaaaabaabaabbbbaabbaaabbba
aabbabaaaaaabaabababaabbbbbaabbaaababbbb
aaababbbaabaabbababaababbbaaabbabaaaabab
bbbbbbbbabbbaaaabbbbaaaa
abbbbaaaaabaababbbbaabba
abbbbaaaaabbbabbbbbaabbbaaabbabbabbababaababbaaa
bababbabaaabbaaaaabaabaababababa
aabaabbabbabaabaaaabbaaabbbbbbbabbbbbabbabbbbabb
abbaaabaaaaaaaaabaaabbbaabbbaaabbaaaaabaaaabbbbaaaabbaab
aabaaababbaaabbbaabbbaaabaabbbbabbbaaabaabbaababababaaba
aaaaaabaabbaaaababbaabba
aaaaaaaabaaabbaabaabaaabbbababaaabbabbab
bbabbabaaabbababaabababb
aabbbbabbaaabbbabaababaaaaabbbba
baaaaaaabbbababbabbaaabaaabababbaababaaaababaaabaababaaa
bbbaabbbabaaaabaaaabbbaa
baaaabaabbababaabaabaaaa
bbbbbaabbaaaaaaabbaaabaa
aabbbbabbbbaaabbabbbbaab
babaababbabbabbabbababbbaaabbbbb
babbbbabbbaabaaabbbaabaa
abbbbaaaabbaaaaabbabbbaaabbbaababaababbbaaaababbaaabbbbbaabaaaaa
baabbbbabbbbbaabbbaabbba
aabbabbbaaabaaaabbaabbbb
babaabaabaaaabbaabababbb
aabbabbbbabbaababbaaaaaa
bbaababbababbbbbbbbbaaab
bbbbbbabaaabbabbabaababbbbbbbbaa
baabbaaabbabaabbbbbababb
abbbbbbaaabaaabbaababbbb
bababbbabbabaabbbabbaabaaabbbabaababbababbababab
aababbababbbbbaabaababab
babbbaaaaaaaaaabbbabaaba
abbbaaabbaaaabaaababaabbaabaaaaaabbaabbaabaabababbabaaaa
aababaabaabbaaaabababaab
babababbaaaaaabaabababababbbabbbbbababaabaababba
bbbbbabbbbaababaabaabbbbbababababaabbaba
baabbbbabbabaabbbaababbb
abbbbbabbababbbbbbaaabbabababbabaabbaabbabaaabbaaaaabababaabbaababbbabbaaaabaaaa
aababababaaaabbbaaaabbbaaaaabbbb
ababbaabbbaaaabaaaabaaab
abbbbbbaaababaabbabbabbababbbaaabbaababa
bbaabaabbbbaabbbbbaaabbbabbababbbbbbaabb
abbababbabababbbaabaaaaa
abbbaaaaaaaaabaabababbab
bbaababbabababbaababaabbabbbbbabbbabbbbb
babbabbabaabbaabaababbbb
bbbbbaaaaabbabbabbaaaaab
aaababababbbabaababbabab
baababbbaaabbaababaaaabbabbaabbb
aababaabaabaaaabbbbabaabbbbbbbabaabbbbaa
aaaaaaaabbbbaabbbbbababaabbaabbbaaababba
bbbababbbbaabbabbbababbaabababababbaaabaababaaab
baababaaaabbbabbabbbabbababbababbabbaaab
baabbbbaaabbbababbaaaabb
bbababbbabbbbaaaabbabbab
babbabbbabbbabaabaabbbbb
aabaabbabbababaabbbbaaaa
aabbbabbbbababaabaaaaaab
aaabaaaabbbabaabaabbabaabbbabbbb
aababaabbbbbabaaaaaaabba
babaabbabbababbbbaabbbaabbbbbaababbbbabbbbabbbab
abaaabbbbbababbbbabbbbba
abbbbaaaaabbbabaaababbaa
ababbbaaabbbabbbbabbaabb
aaaaaaabaaaaabaababbbbabbabbbbababaabbaa
aaaabbabbaaababbbbbabababbabaabaaabbbabbbbbbbabbaaabbbbbbabbabab
bbbaaabbbbbbaabbaaabbbba
bbbaaababbabbabbbaabaabb
abbbbbbbaababbbbbbbbabbaabaabbaababbbaba
aaaaaabbbbbbbababbaababbbaabbbba
baaaabaaabbababaabaabaaaababbbbbbababaaabbbbbabb
bbabbbaabbbaabbbbabaaabbbabaaabaabbbbbbbaaaaabba
aaaaaabaabababbabbbbabba
ababbaababababbaaaaabbba
aabaababbabbbbabbbbaabbbabaaaaaaaabaaababaabbbbb
baabbabbbbaaabbabababbaaaaaababb
aaabbaabababbabaababaaab
abbaaaabaaaaaabbaaabbbaa
ababbababbabbabababbaaaababbabbabbbabaabbababaabbbabbbbaabbbbabbabbabbbb
baaaaaaabbababbababaabbabaaaabbaaabababaabaaaaabaabbbbaa
aabbaaaabbaaababbbaaabbaabbbababababaaaa
aaaaabbbaaabababbaabbaabbaaaaaba
bbababaabaaabaabbbbbabbb
aababaabaaaaabbbabaaabaaabababbb
bbbabababbaaaabbabaaabbabbabaaba
bababbaaabaaaaaababbaabb
aaaaaabbaaabaaaabaababab
baaabaabbabaababaabbbbabaabaabbbbbbabbbabbaabbaa
aaaaabaaaaabbabbbbbbbabb
babbabaaaaabaaaaabbbbabb
bbbbbaababbbbbbabbbaaabbabbbabbbbabbaabbbababbbb
aaabababbbabbabbaaaabaababbaabbbaabababb
bbaaababaaaaabaabaabbbbabbabbabbbabbbbbabaaabbba
aabaaabbababbbbbbbbbaaaa
aababbabbbaabaaabbabbaabaabbababbabbbbbb
bababaaabbbbbaabbbbabaabbaabaaba
aaaabaaaaaaaaababbaaaaabbbbababbbabbbaab
aabaaaabbaaabaabaababbaa
aabaababbbbabaabbaaabbba
bbbbababbbabaaabbabbaabbababaaabbbbbabba
aabbaaaaabbaaaababbbaabb
aaabaaaaaaaaaaaabaaababaabbbabbbaababaabbaabaabbbbaabbabbbbabbaa
abaaaaaaabbbabbbababbbaabaabaabb
abbaaaaaaabbaaaababbbaab
bbabaabbaaaaaabbabaabbba
bbabaabbabbbabaababbbbba
baabbbbaaaabaabaaabaabaa
bbabbbbbbbaabbbaaabbaabbbbaabbabbabbbabbbbabbbab
aaabababbbabbaababababababbbbabaabababaaaaaaabba
aabbbaaaaababbabbbaaabbabbaaaabaabbbbaaaabbaabba
ababaabbaabbbabaabaaaabbbbabbbbbbaaabbbb
baababbbabbbabbbaababaaa
bbbbbaaaabababababbabaab
bbbbbaabbbabbaabbaaaaaba
abaaabbbbabaababbabaaababbaababa
aabbbbabbabaaabbbbababaaabaaaabbbabaabaa
babbabbbababbbbbbaabbbbaabbabbab
abababababbaaaaaaaabbbba
aabbbabbbbabaaabbabbbbabaabaaaabbbbabaaaaaabbbba
aabbbabbbbaababbbbbbbaab
bbaaaababbbababaaaabbbbaabbbaaabbababbbb
abbabbaabaaaabababaabababaaabbaaababbbbaababbabbaaabbabaababbaab
aaabababaaaabaabaaaaaaabbbababbababbabbababbaaab
babaabbabaabbabbbbbaabaa
babbabbbbbaabaaabbbbbabaabbbabbabbaaaabbabbbabaabbbaaaaa
bbbababaaabaaabbabababaabaaababbbabaaaaaabbaabba
baabbabbababbbaaaaaabbaa
aabaabababbbbbaabaababba
ababbbaaababbbaaaaabbbaa
abbabbbabbaababbaababbbb
aababaababaabaaabbabaaababaabababbabbbab
aaaabaaaaabbbbabaabbbabbbbaababbbbbbaaab
bbbbababbbbbababaaaabbaa
abbbaaaabbbaaabaabbbaaab
bbabaaabbbbbabaababbaaaabbbaaabbbaaaaabaabbbabbbbbabbbbbbaaaaabbaaabbbabbbbaabababaaabaa
aaabbaabaabbababaaaaabba
bbabaaaaabbbaabaaabbabaaaabbabbbaaabaabbbbaabbab
bbaabaaaaabbbaaababaabaaabbabaab
bbbbababababaabbbaaababa
baabaaaaabbababaaababaabaabbbabaabbabababbababbaabaaaabaabbbbaaaabaabbbbbaabbbbb
bbababaaababababbababaaabbbabbbaaaaababa
bbaabaaaabbbbbbbaaaabbbb
aabaabbaababbbbbbaaababb
abbbaaaaaabbabbababaaabaabbabaabababaaaabababbbb
abbbbbaaaaaabbabbbabaaabbaaaaaaabbbabbab
bbabbabbbbabbabbaabbaabb
aabbabbababbaababbbabbba
abababbabaababaababbbbaababbabab
bbababbabbaabbbbbbbaaaaabababaabaaaaabba
abaaaabbbaabbaabbaabaabb
ababbaababbabbbaabaababa
abaaaabaaabbbabbbaabbaaaababaaaabbbabbbabbaaaaaa
aabbababbbabbbaaabaabbba
abbabbbaaaaaabbbaabbabaabbaaabbbababbabbabaaabba
aabbbabaaaabbbabbabbbbbabbabaabbabaababa
babaabbaabaabaaababbabbaababababaabababa
abbaaaaaaaabbbabbbaaabbbbaaaaaba
bbaaabbbbbaaabbabababbab
aabbababbbbaabbbaababbba
abaaabbaaabaabbbbaaaabab
babbaabaaabbbbabbaaabbaabbaaaabb
bbabbabbababbbaabbaababa
babbbababbabbbbabbbaabbbbbaaaabaabbbababaabbabbabbabbaaababbbbaaaabaaaabbbaabaabaaabbabb
bbabbabbbbbbbbabbabbbbbb
bbbaaabbabaaabaaabbababbbabababbbbabaaabaaaababb
babaaababbaababbababbababbbabaabbbbbbabbabbaaababbabaabaaababbaa
aabbbbabbaaaabbaaabaabbabaabbabbabbbaaabaaaababa
abbaaaaaabbababbbbbbbabb
baabbbaaabbaababbbbabbaa
ababbabababbbaabbbaabbbb
abababbabaabbbabbaababaaababaabbbbbabbaabbaabbababbabbababbbbabbaabbbaaaaabbaababaabbaba
aabaababababbbaabbaabbab
babaabbabbbbaabbaababbaa
baabbaabbbbbbababaabbaaaabababaabaabbbabbbbbabaa
abbabababbaabaabbbaababa
baababbbaabaaabaabaaabbbaabababa
bbabaabbbbbbbaabbabaabbb
babaabbaabaabbbaaabaabbbbabbabaababbabbb
babaababbbaababbbbaabaaaabbbbabaabbabbbbaaaabbba
ababaabaababbbbaaaaabbba
aabbbabbaabbbbabaabbabbbabbbaababaaaaaaaabbabbbb
aaabaaaaaabaabbaaabaaaaa
abbababbabbbaababbbaabba
abababbababbbbabbaaaaaab
aaaabaabaaabbbabbbaabbab
abbbbbbbbaababbbbabbabab
ababaabbbbbbbbababbbbaab
aaaaaaabaabbabababaaaaaaaaabababbabbbbaa
bbaabaaaaabbbabbbaaabbba
baabbaaababbabaabbbbaaba
bbbaabbbabbabbbabaaaaaab
aaaaababbbbabbaababbabababaabbab
aaabbbababbbabbaabaabbbb
abababaaabababababbaabba
ababbbaaabbaabaaabbabbbb
bbabaabbbaabbbbabaaabaaa
ababbaabaaaabaabbbbbbbab
baabaaabbbaabaaaaabaaaabbaabbbabbbbabbbbaabababb
abbaabbbabaababaabaabaaaabbbaaaababbaabbbabaabaa
aababbabbababaaaababbbba
bbabbabaabaaaaaaabaaaaaabbaababbaaaabbaababbbbaabbabbbbaaabbabaa
aaaaaaabbbaababbababbbaabbabbabaaababbaabbabbbbbaabababa
aaabaaaabaaabaababaabbab
baaaaaaabaabaaababaaaabaaabbaabb
bbaabaabaabaaaabbbbbaaab
abaabbbaaaabaaaaabbbababaaabaaaaaaaabaaaababbbabbbababbaaabbabbb
abaaabbbabbbbbabbabaaaaa
ababbababbbabaababbbbabb
babaababaaaaaaaaaaabbbabaaaababa
aabaaabbaaaaabbbaaabbaba
baaabbaaaabaaababaababaaaabaaabaaaabaaaaabbbaaba
aaaaabbbbabbaabaaaabbaabbbbbbabb
aabbbbababbbaaaabbaaaaab
bbbabaabaabaaaabbabaaaaa
abbbbaaaabbbaabaabaabbbb
abbaaaaababbaaaaabbbabbabaaaaaba
abbbaabaabbbaababbababab
bbbaaabbbaabaababaaabbab
aabaabababbbaaaabbbbaaba
baababbbbaababbbbabbbbabbbbababbabbbbaab
bbbbababaababaabbbbbbaaabbaaaabaabbbbaaabbbabbba
baaabbaabaabbbabaaaaabaaaabbaabb
aabaaababbbabababbbabbbb
aabbaababaabbbbabaaaaaba
aaaabbababbaababbabbbabb
ababababaaaabbababaaabab
aaabaabababbbbababbabbbbaabbaaabaabaaabbbbbababbabbabbabaaabbbba
aabaaabbaabaaabbbbbaaabbbbbabaaa
bbbaabbbbabaaababbbbbbabababbbbbaaabbabbabbabbaa
abbaaaabbaabaababbbaaaab
baaaabaaabaaaabbbbabbbab
bbabbababbbbbbbbbabaabbb
babaaabaaabbabbabbababab
bbabbabaabbbababbbbabbba
abaaaabababbbaaabbabbabaaabaaabb
aaaabbabaaaaaaabbabbbaba
abaaaaaabaabbaaababbbbabaabbabbabbbaaaaaaaabbbba
ababbabaabbbbbaaaabaabaa
abbbaababaaababbaabaaaaa
bbbabaabbbaabbbbbaaabaaa
bbabbabbbaaabbaabaaabbba
babbabaabbabbaababaabbba
abbababaababababaabbbbaa
baabbbabaaaaabbbbabbbbbb
aabbabaaaabbabbaabbbaaab
abbbbbaaaabaaaabbbbabbbb
bbbaabbbbbbbabaaababaaaa
ababbaabbbaababbbbaaababbaaabaabbbaababbbbbbbbaa
bbbabbababbbbbaaaabbbabbbbbaabbabbaaaaabbaabbaaaabbbbabaaababaaa
aababaaababbbaababaabbbaaababbbabbbbbbaa
babbabbbaaaabbabaaabaaab
aabbbaaaaaabaabaababaaab
babaaabaaabbbaaaabaabbba
aabaaaababbbabbaabaababa
bbbbbbaaabbabbaaabaabaabaaabbabaaaababbbabbbabbb
aababaababbaaaabbabbaabb
abbbaaaabaaabbaabbabababbaabaabb
aaaaaabbabbaaaaababababa
bbbbabaabbbaaabaaababbbb
babaabababbbabbabbbabaaa
bbbaaabbbaabbbbaaaabbbaa
abbabbbababbbaaabaabbabbababbabbababbbbaaaabbabababbbbabaabbaaba
abababbabbbaaababaabbaba
aabbababaaabbbbbbbaaaabbbbbbbbababbbabaabbabbbbb
abaabaaabbababbbbaaaabababaabbaaaaaabbbbbbbbaaaabbbbbbaabbaababa
aabbabbaababbbbbbbbbaaaa
aaaaaabbaabbababbbaaaaaa
bbbaaababbbbbbabaaabbaabbbbaabba
bbabbabbabbbabbabbabbbab
bbaabaaabbaabbbbabbbaabb
babbbaaaaababaabbbbbbabb
abaaabaaabaaaabaaabbbbbb
bbababaaabbbabbaabbbabbbbabbbbbaababaaba
abababaabbabaabbbbaaabbabaabbbababbaabbb
babbaabaabbbabbaabaabbbb
baabbbbabbababbabaababba
bbaaabbbaabbaaaabaaababbbabbabaabaabbbbb
aaaabbabbbbbbbbbaaaabbabbaaaabbb
bbbbabaaabbaababbbaabbab
baaaabbaabaaaaaababbabaabaaababa
aabaabbabbaaaababababbaababbabab
abaaaaaabaaababbabbaaabb
abbbabbabbbbabaabbbbaaba
babababbbbabbbaaaabbbabbaaaaaabbbabbabbbaabaaaabababaaaa
aaaabaababbbbbbaabaabbaa
ababbbaaababababababbaaa
ababbbaabababaaabbbbbabb
abbababbaabaaabbbbbaabab
babaababbababbbabbbbabbb
abbbbabbabbbaabbabaaaaabbaaabbbbbabbaaababaababa
baabbbbaaaabbabbbbbababb
aaaaabaaabbabbbababbbbaabaaabbaabbbabbba
baabaaabaabbbaaaabaaabba
aabaabbabbbbbababaababbb
aabbbabaabaaaaaaabaabbaa
abaabababaabaababbbbbbaabbabaabbaabaabbb
aabaaabbbbabbabaabaaaababbaababaaabbbaab
abaaaaaabababbbaabbbaabb
bbabaabbaaabaaaababbbabaabbaabba
bbbbabababbbabababaababb
babbaaabababbabaabbabababaaababbbbabbbbbbbabbabbbaaaabaaabbbbbba
abbbbbbbbbbbabababbabbaaabbaaaababbbbabaaabbaaaaaababbbbbbaababbbbaabaabababaabbababaabbbbbbbbba
bbbaaababaaaabbabaaababbababbaabbbbbbbba
babbabbaaaabbbabababbabb
ababaabbabbabbbabbabbbba
aaabbaabababbbaaababaaab
ababbbabaababbaaababbaaa
baaaabaaaabbaaaaabaababa
baaababbababababbbabbaaa
ababbabababaabababaabaabaaaabbbbbbaaaaababaabbaabbaaaabb
abbbbbaaaaaaabbbabbabaab
aaaaaaabbbaaababbbbaaababaababaaababbaaa
aaabbbabbabaabaaaabbbaab
abbbabbabbababaaaaabbbbb
abbbbabaaaaabbbaabbabaab
bbabaabbaabbbaaabaabbbbb
ababbaababbabbbabbabbaabbbaaaaabbbbbbbba
aabaaabababbbbaabaabaabb
aabbbaaabaabaaabbbbabbaa
babbbaaababbaabaabbbabbbababbaabababaaba
aababaabbabbabbababbbbabaabbbbabbbbbaaaaaabaabaa
aabaaaabbbaabbbabaabaaababaaabababbbabbbabbaaababbaabaababbabbbbabbabaaa
abbbabbbbabbbbaaaabbbabbaabaaabaabaababbbbbabaaa
babababbaababbababbabaaa
aaaaabbbabbbabbabbbaabba
bbaabaaaabaabbabababaaab
babbabaaaaaaaababaaababbbaabbbaaabaabaab
abbbbbbbabbaabaabbbbbbaa
aabaaaaabaaaaaabaaaaabbaaabababa
abababbabbabbabbaabaabbb
aabbbaaaabababbaabbaaaabbbababab
baababaababbabaaaabaaabaaabbbababbbbabbabbabbaaababbbbba
bbababaabaaaabbaababbababbabaaaaabbabbab
abbbbbbbabbbbbaaaaaabbba
bababbbabbbaaabaaabbbabbabaaabaaaabbabbbababbbbbababbbab
abababaaaaaaaababbbaabaa
babbabbbaabbabbbaababaaa
abbaabaababaaaabbbbbabbaaaabbabbbbbababaabbbbbabbaaaaabbbbaaaabaaabbaaab
aaababababbaaaabbaaaabbb
aaaaaabaaaaabaabaaaabbaa
bbaaabbbabbbbbbaaabbaaaaababbabbbaaabbba
bbbaabbbbbabbbaaabbbbbab
aabbaabaabbbababbaaabbbb
bbabbbabbbaabbaaabbbbbbababaaabaabbababbaabbaabbbaabaaaabaababbb
aaaabaaaabbbabaababbbbaabaaaaaba
abbbabbaabaaabbbabbababaaaaabbabbaabbaaaababbbab
baaabaabaabbaaaabbababbbabbaaaababbbbbab
bbbbbbababaaabaabbaaaaaa
baaabbaaaabaaabaaaabaaab
bbbaaabaaabbabbaabbabaab
babaabababbbbbbaaaaabbba
aaabbbabaaaaaaaabababbab
bbbbababaabbabbababbbbbb
aaaaabaaaaaaaababaaaaabb
aaaaaaaababbbbababbbabbaabababbb
abbbbbbaaababaababbbbaab
aaaaaabababaababaaaaabba
aabbaaaabababbabaabaababbbaabbbbabbbaaaaaabbabaaabaabbbb
ababbbbaabbabbbabbbbbaaababababbaababaaabaaaaaab
bbabbabbbabaaabaaabbbbaa
baaaabbaaabbbabaabaabaaabbabbababbbbbbbbaaabaaaababbbbbabaaabbabbabbbbbaaaababaa
abbababaaaabababbbabbaaa
babaabbabbbaabbbaaaabbaa
abbbbbaaaabaabbaaabbabbaabbabaaaabbabaaa
abababbababaaabaabbababaaaaabbababaaaaaaabababbaabaabbbabbaaaabb
bbbaabbbababaabbabaaaaab
aabaabaaabbabaabbbaaabaa
abababaabaabbaababbabbbb
babaabbaaaaaaaabaaaaabba
bbaabbbaababaaaaaaaababa
bbabaaaaabaaaaaaaaabaaaabbbabababaabbbababaaabba
abaaabaaabaaaabbbaaaabab
aabbabaaaaaaabbbababbbba
abababaabbbbaabbaabbaaabbbbbaaaabababababababaaaabbbbaaaaaaaabbbbabbbaaa
abbbabbabababbaaabaabbaa
aaabaaaaaabbaaaabbaabbba
aabaabbababbabbaaabbabbbababbaab
bbbbbaabaaabaaabaabbaabbbbaababa

381
d19/main.py Executable file
View File

@ -0,0 +1,381 @@
#! /usr/bin/env python3
from itertools import product
from typing import Dict
from typing import List
from typing import Optional
from typing import Tuple
MAX_DEPTH = 10
class Rule(object):
_rule_body: str
key: int
_values: List[str]
_depth: int
def __init__(self, key: int, rule_body: str):
self.key = key
self._rule_body = rule_body
self._values = []
self._depth = 0
def validate(self, s: str) -> bool:
return s in self.values()
def values(self) -> List[str]:
if not self._values:
if self._depth >= MAX_DEPTH:
# Break out of recursion
return []
self._depth += 1
values: List[str] = []
for sub_rule in self._rule_body.split(" | "):
rule_combo: "Rule" = ValueRule(-1, [""])
for rule_key in sub_rule.split(" "):
rule_combo += RULE_INDEX[int(rule_key)]
values += rule_combo.values()
self._values = values
return self._values
def __add__(self, other) -> "Rule":
values = [
"".join(v)
for v in product(self.values(), other.values())
]
return ValueRule(
-1,
values,
)
def __mul__(self, other) -> List[str]:
raise NotImplementedError()
def __repr__(self) -> str:
return f"<Rule key={self.key} rule={self._rule_body}>"
class ValueRule(Rule):
key: int
def __init__(self, key: int, values: List[str]):
self.key = key
self._values = values
def values(self) -> List[str]:
return self._values
def __repr__(self) -> str:
return f"<ValueRule key={self.key} values={self.values()}>"
def parse_rule(line) -> Tuple[int, Rule]:
rule_index = line.find(":")
if rule_index <= 0:
raise ValueError(f"Could not find rule number in {line}")
rule_key = int(line[:rule_index])
rule_body = line[rule_index+2:]
rule: Optional[Rule] = None
if rule_body[0] == '"':
rule = ValueRule(rule_key, [rule_body[1:-1]])
else:
rule = Rule(rule_key, rule_body)
return rule_key, rule
RULE_INDEX: Dict[int, Rule] = {}
def test():
test_input = (
"0: 4 1 5",
"1: 2 3 | 3 2",
"2: 4 4 | 5 5",
"3: 4 5 | 5 4",
'4: "a"',
'5: "b"',
)
RULE_INDEX.update({
parse_rule(line)
for line in test_input
})
print(RULE_INDEX)
for rule in RULE_INDEX.values():
print(rule.key, rule.values())
test_eval = (
"ababbb",
"bababa",
"abbbab",
"aaabbb",
"aaaabbb",
)
rule_0 = RULE_INDEX[0]
matched = 0
for t in test_eval:
if rule_0.validate(t):
matched += 1
print(f"Total matched is {matched}")
def part1():
rules_parsed = False
matched = 0
with open("input.txt") as f:
for line in f:
line = line.strip()
print(line, end="")
if line == "":
rules_parsed = True
print("DONE PARSING RULES")
elif not rules_parsed:
key, rule = parse_rule(line)
RULE_INDEX[key] = rule
print(" Parsed")
elif RULE_INDEX[0].validate(line):
matched += 1
print(" OK")
else:
print(" Not OK")
print(f"Total matched is {matched}")
def chunk(a, n):
return (a[i:i+n] for i in range(0, len(a), n))
def count_prefix(value: str, prefix: str) -> int:
count = 0
for c in chunk(value, len(prefix)):
if c == prefix:
count += 1
else:
break
return count
class Rule0(Rule):
def __init__(self):
super().__init__(0, "")
def validate(self, value: str) -> bool:
r42 = RULE_INDEX[42]
r31 = RULE_INDEX[31]
# print(42, "\n".join(r42.values()))
# print(31, "\n".join(r31.values()))
size = None
for v in r42.values():
if size is None:
size = len(v)
assert len(v) == size
for v in r31.values():
assert len(v) == size
match42, match31 = 0, 0
for c in chunk(value, size):
if match31 == 0 and r42.validate(c):
match42 += 1
elif match42 != 0 and r31.validate(c):
match31 += 1
else:
return False
# if value == "abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa":
# from pdb import set_trace; set_trace()
if match42 > match31 and match31 > 0:
return True
return False
# if RULE_INDEX[0].validate(value):
# from pdb import set_trace; set_trace()
# Check beginning starts with "8"
for prefix1 in r42.values():
prefix_count = count_prefix(value, prefix1)
if prefix_count == 0:
# Not even one chunk was matched, this is a bust
continue
# Trim first prefix out
back_half = value[len(prefix1) * prefix_count:]
# Check following "11" match
for prefix2, suffix in product(r42.values(), r31.values()):
remain = back_half
if RULE_INDEX[0].validate(value) and prefix1 == "bbabb" and prefix2 == "bbaab" and suffix == "aabba":
from pdb import set_trace; set_trace()
# If prefixes aren't the same, look for the new one
if prefix1 != prefix2:
prefix_count = count_prefix(remain, prefix2)
# Trim the new prefix
remain = remain[len(prefix2) * prefix_count:]
if prefix_count == 0:
# No valid prefix
continue
suffix_count = count_prefix(remain, suffix)
if suffix_count == 0:
# No valid suffix
continue
# Trim the suffix
remain = remain[len(suffix) * suffix_count:]
if len(remain) > 0:
# There is something after the suffix
continue
# Make sure we've seen at least the same number of prefixes
if prefix_count >= suffix_count:
return True
return False
def part2():
# Update two changed rules
# 0: 8 11
# Test short circuits
# RULE_INDEX[42] = parse_rule('42: "a"')[1]
# RULE_INDEX[31] = parse_rule('31: "b"')[1]
# rule8 = parse_rule("8: 42 | 42 8")[1]
# rule11 = parse_rule("11: 42 31 | 42 11 31")[1]
# print(RULE_INDEX[8].values())
# print(RULE_INDEX[11].values())
rules_parsed = False
matched = 0
# Empty rules
RULE_INDEX.clear()
with open("input.txt") as f:
for line in f:
line = line.strip()
print(line, end="")
if line == "":
rules_parsed = True
# All rules parsed, replace values
# RULE_INDEX[8] = rule8
# RULE_INDEX[11] = rule11
print("DONE PARSING RULES")
r42 = RULE_INDEX[42]
print("prefixes", r42.values())
r31 = RULE_INDEX[31]
print("suffixes", r31.values())
elif not rules_parsed:
key, rule = parse_rule(line)
RULE_INDEX[key] = rule
print(" Parsed")
elif Rule0().validate(line):
matched += 1
print(" OK")
else:
print(" Not OK")
print(f"Total matched is {matched}")
def test2():
r0 = Rule0()
# RULE_INDEX[42] = ValueRule(42, ["prefixa", "prefixb"])
# RULE_INDEX[31] = ValueRule(31, ["sa", "sb"])
test_input = (
"42: 9 14 | 10 1",
"9: 14 27 | 1 26",
"10: 23 14 | 28 1",
'1: "a"',
"11: 42 31",
"5: 1 14 | 15 1",
"19: 14 1 | 14 14",
"12: 24 14 | 19 1",
"16: 15 1 | 14 14",
"31: 14 17 | 1 13",
"6: 14 14 | 1 14",
"2: 1 24 | 14 4",
"0: 8 11",
"13: 14 3 | 1 12",
"15: 1 | 14",
"17: 14 2 | 1 7",
"23: 25 1 | 22 14",
"28: 16 1",
"4: 1 1",
"20: 14 14 | 1 15",
"3: 5 14 | 16 1",
"27: 1 6 | 14 18",
'14: "b"',
"21: 14 1 | 1 14",
"25: 1 1 | 1 14",
"22: 14 14",
"8: 42",
"26: 14 22 | 1 20",
"18: 15 15",
"7: 14 5 | 1 21",
"24: 14 1",
)
RULE_INDEX.update({
parse_rule(line)
for line in test_input
})
og_valid = 0
new_valid = 0
for v in (
"abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa",
"bbabbbbaabaabba",
"babbbbaabbbbbabbbbbbaabaaabaaa",
"aaabbbbbbaaaabaababaabababbabaaabbababababaaa",
"bbbbbbbaaaabbbbaaabbabaaa",
"bbbababbbbaaaaaaaabbababaaababaabab",
"ababaaaaaabaaab",
"ababaaaaabbbaba",
"baabbaaaabbaaaababbaababb",
"abbbbabbbbaaaababbbbbbaaaababb",
"aaaaabbaabaaaaababaa",
"aaaabbaaaabbaaa",
"aaaabbaabbaaaaaaabbbabbbaaabbaabaaa",
"babaaabbbaaabaababbaabababaaab",
"aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba",
):
og = RULE_INDEX[0].validate(v)
n = r0.validate(v)
print(v, "og", og, "new", n)
if og:
og_valid += 1
if n:
new_valid += 1
print("og valid:", og_valid, "new valid:", new_valid)
if __name__ == "__main__":
# part1()
part2()
# test2()

1727
d20/input.txt Normal file

File diff suppressed because it is too large Load Diff

400
d20/main.py Executable file
View File

@ -0,0 +1,400 @@
#! /usr/bin/env python3
from itertools import chain
from functools import reduce
from typing import List
from typing import Optional
from typing import Set
from typing import Tuple
class Tile(object):
def __init__(self, tile_num: int, content: List[List[str]]):
self.num = tile_num
self.content = content
# Neighboring tiles
self.top: Optional["Tile"] = None
self.bottom: Optional["Tile"] = None
self.left: Optional["Tile"] = None
self.right: Optional["Tile"] = None
# All edges for quick match
self.edges: Set[str] = set()
self.edges.add(self.top_edge)
self.edges.add(self.top_edge[::-1])
self.edges.add(self.bottom_edge)
self.edges.add(self.bottom_edge[::-1])
self.edges.add(self.left_edge)
self.edges.add(self.left_edge[::-1])
self.edges.add(self.right_edge)
self.edges.add(self.right_edge[::-1])
@property
def left_edge(self) -> str:
return "".join(
[self.content[y][0] for y in range(0, len(self.content))]
)
@property
def right_edge(self) -> str:
return "".join(
[self.content[y][-1] for y in range(0, len(self.content))]
)
@property
def top_edge(self) -> str:
return "".join(self.content[0])
@property
def bottom_edge(self) -> str:
return "".join(self.content[-1])
def flip_lr(self):
for i, row in enumerate(self.content):
self.content[i] = row[::-1]
def flip_tb(self):
self.content = self.content[::-1]
def rotate_cw(self):
self.content = [
[self.content[j][i] for j in range(len(self.content)-1, -1, -1)]
for i in range(len(self.content[0]))
]
def rotate_ccw(self):
self.content = [
[self.content[j][i] for j in range(len(self.content))]
for i in range(len(self.content[0])-1, -1, -1)
]
def align_edge(self, edge: str, direction: str):
assert edge in self.edges
if direction in ("top", "bottom"):
while getattr(self, direction+"_edge") != edge:
if getattr(self, direction+"_edge")[::-1] == edge:
self.flip_lr()
return
self.rotate_cw()
elif direction in ("left", "right"):
while getattr(self, direction+"_edge") != edge:
if getattr(self, direction+"_edge")[::-1] == edge:
self.flip_tb()
return
self.rotate_cw()
else:
raise ValueError(f"Unknown direction {direction}")
def count_neighbors(self, other_tiles: List["Tile"]) -> int:
num_neighbors = 0
for tile in other_tiles:
if self.num == tile.num:
continue
if self.edges & tile.edges:
num_neighbors += 1
return num_neighbors
def find_bottom(
self,
other_tiles: List["Tile"],
assign: Optional[bool] = True,
) -> Optional["Tile"]:
bottom_tile: Optional[Tile] = None
for tile in other_tiles:
if self.num == tile.num:
continue
if self.bottom_edge in tile.edges:
tile.align_edge(self.bottom_edge, "top")
if bottom_tile is None:
bottom_tile = tile
else:
raise ValueError("Multiple match error")
if assign:
self.bottom = tile
tile.top = self
return bottom_tile
def find_right(
self,
other_tiles: List["Tile"],
assign: Optional[bool] = True,
) -> Optional["Tile"]:
right_tile: Optional[Tile] = None
for tile in other_tiles:
if self.num == tile.num:
continue
if self.right_edge in tile.edges:
tile.align_edge(self.right_edge, "left")
if right_tile is None:
right_tile = tile
else:
raise ValueError("Multiple match error")
if assign:
self.right = tile
tile.left = self
return right_tile
def remove_edges(self):
self.content = [
row[1:-1]
for row in self.content[1:-1]
]
def __add__(self, other) -> "Tile":
new_content = [
s + o
for s, o in zip(self.content, other.content)
]
return Tile(self.num * other.num, new_content)
def __truediv__(self, other) -> "Tile":
new_content = [
row for row in chain(self.content, other.content)
]
return Tile(self.num * other.num, new_content)
def __eq__(self, other) -> bool:
return self.num == other.num
def __hash__(self) -> int:
return self.num
def __repr__(self) -> str:
return f"<Tile no={self.num}>"
def to_str(self) -> str:
return "\n".join(
"".join(row)
for row in self.content
)
def total_turbulance(self) -> int:
total = 0
for row in self.content:
for c in row:
if c == "#":
total += 1
return total
SEAMONSTER = [
" # ",
"# ## ## ###",
" # # # # # # ",
]
IN_THE_SEA: Set[Tuple[int, int]] = set()
def search_seamonster(
content: List[List[str]],
x: int,
y: int,
) -> Tuple[bool, int]:
found = True
turbulance = 0
in_the_sea: Set[Tuple[int, int]] = set()
for yi in range(len(SEAMONSTER)):
if y+yi >= len(content):
return False, 0
row = content[y+yi]
for xi in range(len(SEAMONSTER[yi])):
p = (x+xi, y+yi)
if p in IN_THE_SEA:
return False, 0
if x+xi >= len(row):
return False, 0
c = row[x+xi]
sea = SEAMONSTER[yi][xi]
if sea == "#" and c == "#":
in_the_sea.add(p)
# Not a seamonster match
elif sea == "#" and c != "#":
return False, 0
elif sea == " " and c == "#":
turbulance += 1
elif sea == " " and c == ".":
continue
else:
raise ValueError(f"Uncharted waters: {sea}, {c}")
if found:
for p in in_the_sea:
IN_THE_SEA.add(p)
return found, turbulance
def read_tiles(filename: str) -> List[Tile]:
results: List[Tile] = []
with open(filename) as f:
tile_num = -1
content: List[List[str]] = []
for line in f:
line = line.strip()
if line.startswith("Tile "):
tile_num = int(line[5:line.index(":")])
elif line == "":
results.append(Tile(tile_num, content))
tile_num = -1
content = []
else:
content.append([c for c in line])
results.append(Tile(tile_num, content))
return results
def test():
tiles = read_tiles("test-input.txt")
corners: List[Tile] = []
for tile in tiles:
num_neighbors = tile.count_neighbors(tiles)
print(f"Tile: {tile.num}: {num_neighbors}")
if num_neighbors == 2:
corners.append(tile)
product = 1
for t in corners:
product *= t.num
print("Corner product:", product)
def part1():
tiles = read_tiles("input.txt")
corners: List[Tile] = []
for tile in tiles:
num_neighbors = tile.count_neighbors(tiles)
print(f"Tile: {tile.num}: {num_neighbors}")
if num_neighbors == 2:
corners.append(tile)
product = 1
for t in corners:
product *= t.num
print("Corner product:", product)
def part2():
tiles = set(read_tiles("input.txt"))
corners: List[Tile] = []
for tile in tiles:
num_neighbors = tile.count_neighbors(tiles)
print(f"Tile: {tile.num}: {num_neighbors}")
if num_neighbors == 2:
corners.append(tile)
product = 1
for t in corners:
product *= t.num
top_left: Optional[Tile] = None
print("Corner product:", product)
for corner in corners:
right = corner.find_right(tiles, False)
if not right:
continue
bottom = corner.find_bottom(tiles, False)
if not bottom:
continue
top_left = corner
# print(corner.to_str(), corner.right.to_str())
# print(corner.bottom.to_str())
break
else:
print("no perfect corner")
# Init grid
g = [[top_left]]
print("removing", top_left)
tiles.remove(top_left)
tile = top_left
tile.find_bottom(tiles)
# Build rows
while tile.bottom:
tile = tile.bottom
g.append([tile])
print("removing bottom", tile)
tiles.remove(tile)
tile.find_bottom(tiles)
for row in g:
tile = row[0]
tile.find_right(tiles)
while tile.right:
print(f"removing right {tile}->{tile.right}")
tile = tile.right
row.append(tile)
tiles.remove(tile)
tile.find_right(tiles)
v_split = Tile(0, [[" "] for _ in range(len(top_left.content))])
h_split = Tile(0, [[" " for _ in range(len(top_left.content[0]))]])
m = reduce(lambda x, y: x/h_split/y, (
reduce(lambda x, y: x+v_split+y, (tile for tile in row))
for row in g
))
m.flip_tb()
print(m.to_str())
# Trim all edges
for row in g:
for t in row:
t.remove_edges()
m = reduce(lambda x, y: x/y, (
reduce(lambda x, y: x+y, (tile for tile in row))
for row in g
))
turbulance = m.total_turbulance()
seamonsters = 0
while seamonsters == 0:
m.rotate_cw()
content = m.content
for y in range(len(content)):
for x in range(len(content[y])):
found, _ = search_seamonster(content, x, y)
if found:
print("found a seamonster at", x, y)
seamonsters += 1
sea_turb = 0
for row in SEAMONSTER:
for c in row:
if c == "#":
sea_turb += 1
turbulance -= sea_turb * seamonsters
for p in IN_THE_SEA:
m.content[p[1]][p[0]] = "O"
print(m.to_str())
print(f"Found {seamonsters} seamonsters with {turbulance} turbulance")
if __name__ == "__main__":
# part1()
part2()

142
d20/output.txt Normal file
View File

@ -0,0 +1,142 @@
...###...##...#...#..###
.#.###..##..##..####.##.
#.##..#..#...#..####...#
#####..#####...###....##
#..####...#.#.#.###.###.
..#.#..#..#.#.#.####.###
.####.###.#...###.#..#.#
.#.#.###.##.##.#..#.##..
###.#...#..#.##.######..
.#.#....#.##.#...###.##.
...#..#..#.#.##..###.###
##..##.#...#...#.#.#.#..
#.####....##..########.#
###.#.#...#.######.#..##
#.####..#.####.#.#.###..
#..#.##..#..###.#.##....
.####...#..#....#..#####
....#..#...##..#.#......
...########.#...#####...
##.#....#.##.######.#..#
###.#####...#.###...#.##
##.##.###.#.#..#.#####.#
###....#.#....#..#.###..
.#.#..#.##...#.#.#......
.####...#####..#...###..
#####..#..#.#.####..#.#.
.#.#...#.###...#.##.O#..
#.O.##.OO#.#.OO.##.OOO##
..#O.#O#.O##O..O.#O##.##
...#.#..##.##...#..#..##
#.##.#..#.#..#..##.#.#..
.###.##.....#...###.#...
#.####.#.#....##.#..#.#.
##...#..#....#..#...####
..#.##...###..#.#####..#
....#.##.#.#####....#...
..##.##.###.....#.##..#.
#...#...###..####....##.
.#.##...#.##.#.#.###...#
#.###.#..####...##..#...
...###.##.##...#.######.
###.###..#######..#####.
..#.##..#..#.#######.###
.##..#.#########..#..##.
.#####.#.#.#...##..#....
.##....#.#.#########..##
...#...#..#..##...###.##
..###..#..##.#...##.##.#
.####...#####..#...###..
#####..#..#.#.####..#.#.
.#.#...#.###...#.##.O#..
#.O.##.OO#.#.OO.##.OOO##
..#O.#O#.O##O..O.#O##.##
...#.#..##.##...#..#..##
#.##.#..#.#..#..##.#.#..
.###.##.....#...###.#...
#.####.#.#....##.#..#.#.
##...#..#....#..#...####
..#.##...###..#.#####..#
....#.##.#.#####....#...
..##.##.###.....#.##..#.
#...#...###..####....##.
.#.##...#.##.#.#.###...#
#.###.#..####...##..#...
#.###...#.##...#.##O###.
.O##.#OO.###OO##..OOO##.
..O#.O..O..O.#O##O##.###
#.#..##.########..#..##.
#.#####..#.#...##..#....
#....##..#.#########..##
#...#.....#..##...###.##
#..###....##.#...##.##.#
..#.#....# ##.#.#.... ...##.....
#...###... ..##...#.. ...#..####
#.#.###... .##..##... .####.##.#
##.##..#.. ..#...#... .####...#.
.#####..## #####...#. .##....##.
.#..####.# #..#.#.#.# ####.###..
#..#.#..#. ...#.#.#.. .####.###.
..####.### ##.#...##. .#.#..#.##
..#.#.###. ..##.##.## #..#.##..#
...#.#.#.# ###.##.#.. .##...####
...#.#.#.# ###.##.#.. .##...####
####.#.... .#..#.##.. .######...
..#.#..... .#.##.#..# #.###.##..
....#..#.# #.#.#.##.# #.###.###.
.##..##.#. ....#...## #.#.#.#...
.#.####... ...##..##. .######.##
####.#.#.. ...#.##### ###.#..###
##.####... .#.####.#. ..#.###..#
##..#.##.. ..#..###.# ##.##....#
#.##...##. ..##.#..#. ..#.###...
#.##...##. ..##.#..#. #.#.#####.
#.####...# ##..#..... .#..######
.....#..## #...##..#. ..#.......
#...###### ####.#...# ######....
.##.#....# ##.##.###. ####.#..#.
.###.##### ##...#.### .#...#.##.
###.##.##. .#.#.#..## #.#####.##
.###....#. ..#....#.. ..#.###...
..#.#..#.# ###...#.#. ..#.......
#...##.#.. ..###..### ..#.###...
#...##.#.. ..###..### #.#.#####.
..#.#..#.# ###...#.#. .#..######
.###....#. ..#....#.. ..#.......
###.##.##. .#.#.#..## ######....
.###.##### ##...#.### ####.#..#.
.##.#....# ##.##.###. .#...#.##.
#...###### ####.#...# #.#####.##
.....#..## #...##..#. ..#.###...
#.####...# ##..#..... ..#.......
#.##...##. ..##.#..#. ..#.###...
#.##...##. ..##.#..#. ..#.###...
##..#.##.. ..#..###.# ##.##....#
##.####... .#.####.#. ..#.###..#
####.#.#.. ...#.##### ###.#..###
.#.####... ...##..##. .######.##
.##..##.#. ....#...## #.#.#.#...
....#..#.# #.#.#.##.# #.###.###.
..#.#..... .#.##.#..# #.###.##..
####.#.... .#..#.##.. .######...
...#.#.#.# ###.##.#.. .##...####
...#.#.#.# ###.##.#.. .##...####
..#.#.###. ..##.##.## #..#.##..#
..####.### ##.#...##. .#.#..#.##
#..#.#..#. ...#.#.#.. .####.###.
.#..####.# #..#.#.#.# ####.###..
.#####..## #####...#. .##....##.
##.##..#.. ..#...#... .####...#.
#.#.###... .##..##... .####.##.#
#...###... ..##...#.. ...#..####
..#.#....# ##.#.#.... ...##.....

107
d20/test-input.txt Normal file
View File

@ -0,0 +1,107 @@
Tile 2311:
..##.#..#.
##..#.....
#...##..#.
####.#...#
##.##.###.
##...#.###
.#.#.#..##
..#....#..
###...#.#.
..###..###
Tile 1951:
#.##...##.
#.####...#
.....#..##
#...######
.##.#....#
.###.#####
###.##.##.
.###....#.
..#.#..#.#
#...##.#..
Tile 1171:
####...##.
#..##.#..#
##.#..#.#.
.###.####.
..###.####
.##....##.
.#...####.
#.##.####.
####..#...
.....##...
Tile 1427:
###.##.#..
.#..#.##..
.#.##.#..#
#.#.#.##.#
....#...##
...##..##.
...#.#####
.#.####.#.
..#..###.#
..##.#..#.
Tile 1489:
##.#.#....
..##...#..
.##..##...
..#...#...
#####...#.
#..#.#.#.#
...#.#.#..
##.#...##.
..##.##.##
###.##.#..
Tile 2473:
#....####.
#..#.##...
#.##..#...
######.#.#
.#...#.#.#
.#########
.###.#..#.
########.#
##...##.#.
..###.#.#.
Tile 2971:
..#.#....#
#...###...
#.#.###...
##.##..#..
.#####..##
.#..####.#
#..#.#..#.
..####.###
..#.#.###.
...#.#.#.#
Tile 2729:
...#.#.#.#
####.#....
..#.#.....
....#..#.#
.##..##.#.
.#.####...
####.#.#..
##.####...
##..#.##..
#.##...##.
Tile 3079:
#.#.#####.
.#..######
..#.......
######....
####.#..#.
.#...#.##.
#.#####.##
..#.###...
..#.......
..#.###...

46
d21/input.txt Normal file
View File

@ -0,0 +1,46 @@
pnglkx nfnzx tjsdp jkbqk rpmqq gzgvdh rgdx szsbj xjdhk zfml ddbmq thvm mvnqdh gsgmdn dtlhh rqqfnlc bxv nthhxn hnmjfl ckqq qrsczjv fkh hkxcb rpcdfph flhfddq qspfqb zmb rpmmv zrgzf jfqqgtl xxfgvz kltcm xjrpr vnfmc xhmmt zkzdrn jmdg xgbvk ngqh hlmvqh djpsmd bnzq rbvdt tfmgl pjln (contains sesame, nuts)
qchnn dnpgcd zfml thvm gsgmdn frld nfnzx nqfc xbpb kltcm ljmvpp mrfxh zntrfp gzgvdh rrbndl pptgt rknm qsgb mstc ckqq zzldmh nggcjr bkd zfsks hlmvqh cxzkmr zmb tzjnvp npbnj lh pfqxsxd clqk rpmmv szsbj mnvq cnghsg jdtzr kfsfn jxjqp knqzf lvjpp qdpbx qrsczjv xxfgvz ngqh zrgzf jvvmcq zmcj dsmc xhmmt (contains sesame)
hlmvqh klmjmz clqk qrsczjv pjln lvjpp tbm thvm rqqfnlc gzgvdh klx sfk bnzq mhrm vht pjqdmpm tfmgl cxzkmr ghr rxrgtvs rfh rhrc vnfmc ljhn fbcds rkzhxmh htllnq zrgzf xhmmt rcr dgrrm xlzqfb xlnn ckqq vpgvm zntrfp jmdg pgqxp xjrpr vnmfg vqrjn thcs mnvq rczbvg bkd zqsc ngqh rpmqq zmcj cbbkfx rpcdfph mrfxh jfqqgtl mszc tzjnvp sdccxkt rcvd pcf xzcdnr jgtrnm zfcvnj dsmc gjqfj gtgrcf nthhxn jngghk hnmjfl qspfqb bxv (contains eggs)
nthhxn htllnq pbn qsgb mrfxh zrgzf dvcfx mstc jngghk xddkbd dpfphd zhghprj rfh ljmvpp vtljml pmtfmv zmb xxfgvz crnfzr xbpb jmdg tshn nqfc kmsh rknm hkqp pjqdmpm pjln ddbmq bjvcg zntrfp vnfmc qszmzsh fhtsl tjsdp kfsfn jkbqk thvm mnvq dnpgcd xzcdnr xjrpr rbvdt vht jxjqp zzldmh cnghsg pzxj jfqqgtl ckqq kqzcj lxr glrc dgrrm cxzkmr clqk xjdhk hlmvqh vpvj lbfgp klmjmz (contains dairy, peanuts, eggs)
rqqfnlc vgp tbm tjsdp tshn zzldmh zrgzf vgjbgj pptgt xnfhq pbn rpmmv dnpgcd qszmzsh rbvdt nzlks xddkbd thvm npbnj lxr szsbj dtlhh mrfxh ljmvpp xjzc zmb pjqdmpm rknm rrbndl xhmmt hlmvqh jmdg pjln pfqxsxd jdtzr jnr jkbqk vht vhcnpg ckqq ddgdhg pzxj ljhn xgbvk qfkjsq zhghprj gzgvdh xzcdnr ddbmq rcvd lbfgp mvnqdh rfh nggcjr gjqfj hrfmdk (contains dairy)
cmnb cnghsg cxzkmr vfkpj pgb xddkbd qfvfzg gzgvdh bxv zfml clqk pbn nthhxn jmdg ckqq rvchbn xbpb sfk dtlhh rqqfnlc rhrc djpsmd qrftr gjqfj bjvcg zntrfp qrsczjv thvm zlgztsbd lbfgp vnmfg jkbqk lvjpp pfqxsxd ljmvpp mrfxh mnvq ljhn fkh ddrd hlmvqh qmmt rcr vht xgbvk ddbmq tbm vhcnpg srgnx zrgzf ngqh mhrm pptgt glrc rpmmv kx htllnq (contains soy, shellfish)
fdf tshn zhghprj xjzc xxfgvz nggcjr hkqp vgjbgj ckqq hnmjfl mstc dmxhhd rpmmv jdtzr klx ngqh gtgrcf bjvcg vgp jgtrnm ttxx bcvmz pgqxp nfnzx sjgx zfcvnj tzjnvp qmmt jmdg qdpbx zmb rhrc gmc zfsks ljmvpp gjqfj fjgxv zttx lbskg vnfmc vfkpj lxr hkxcb dln xbpb sfk vpgvm thvm ljhn rknm rfh mgxzl thcs jfqqgtl bkd sdccxkt zzldmh mrfxh rcvd qchnn xhmmt rkzhxmh xgbvk csfmx zrgzf qrsczjv gzgvdh ncqdr rxr vtljml lbfgp pzxj djpsmd dpfphd rczbvg knnmm xmjlsn (contains nuts, dairy, sesame)
klx hkqp lqmfgp mstc mgxzl cxfzhj xxfgvz qrsczjv jxjqp ljhn pcf mrxg jmdg bjvcg vht lbskg tphtz nldzpc tjsdp mszc hlmvqh sfk dln ghr mppf lbfgp zkzdrn qdpbx bnzq qsgb rrbndl nggcjr zttx qjsbk llgsg srgnx dbx stcsp rcr zfml jvvmcq pptgt gmc fkh xjdhk pzxj zntrfp flhfddq knqzf ddrd jmgt fdf thcs lh mrfxh xmjlsn kglr pjqdmpm kx dpfphd vqrjn vhcnpg rxrgtvs pfqxsxd nqfc ckqq cbbkfx dtlhh thvm zmb qmmt xlzqfb rpmmv jfqqgtl gsgmdn bcvmz mnvq fbcds xjzc gtgrcf (contains nuts, sesame)
gzgvdh vbqbkt fjgxv nggcjr jvvmcq pptgt fmvvb zqsc hlmvqh rbvdt llgsg xddkbd rfh pjln tzjnvp glrc zmb rqqfnlc zttx qrsczjv rrbndl qfkjsq mppf rxrgtvs lvjpp dtlhh zfml stcsp zkzdrn vtljml qdpbx zrgzf fstgc xlnn sdccxkt hkxcb kltcm xlzqfb jfqqgtl npbnj bcvmz rknm ngqh xbpb rcr thvm kglr dbx xxfgvz bjvcg rpmmv srgnx ckqq gjqfj tshn gmc vgp dgrrm ljhn knnmm qkgqv mstc pnglkx flhfddq tjsdp jmdg zntrfp vgjbgj bkd (contains soy)
qjsbk fkh xddkbd fjgxv lbfgp rxr ckqq tphtz vhcnpg klmjmz pmtfmv jmdg hrfmdk dbx fbcds jnr xxfgvz pfqxsxd qfvfzg bxv flhfddq rknm rpmqq pjln sdccxkt pgb klx jdtzr zmb thvm hlmvqh lxr zrgzf nthhxn vnmfg jgtrnm nfnzx zzldmh ddbmq nldzpc tvqbhv dznd dnpgcd cmnb vpvj sjgx xjzc hkxcb szsbj dcbk pmvl pjqdmpm mhrm rgdx jfqqgtl zttx vtljml mrfxh cbbkfx knqzf mszc jkbqk xbpb vgjbgj pptgt vfkpj vqrjn zhghprj xnfhq tshn rcvd xjdhk djpsmd rfh glrc rkzhxmh (contains wheat, dairy)
mvnqdh nqfc bjvcg ckqq zfcvnj jmdg ljhn hkqp srgnx zfsks bxv xbpb rkzhxmh cxfzhj rpmqq zdntns dnpgcd thcs lvjpp klx jngghk flhfddq gmc pjln dcbk cbbkfx vbqbkt qchnn tshn fhtsl qmthj jvvmcq ncqdr jmgt csfmx qrsczjv tzjnvp rczbvg rcr hlmvqh rbvdt gtgrcf thvm cnghsg zrgzf rxrgtvs zmb (contains peanuts, soy)
ckqq frld mvnqdh tphtz bjvcg xzcdnr djpsmd ttxx dcbk qdpbx tshn rczbvg vpvj qmmt ddrd dln bxv zrgzf jxjqp lh mgxzl qrsczjv ltvr pbn nggcjr dsmc llgsg knnmm pzxj cnghsg thvm vnmfg mhrm xlnn gjqfj pptgt jkbqk htllnq jmdg xnfhq klx jmgt mrfxh rxr hnmjfl lqmfgp qrftr mppf sjgx rvchbn lvjpp mstc zqsc gmc kmsh rpmmv crnfzr hrfmdk kglr hlmvqh cxzkmr dvcfx (contains shellfish, eggs, dairy)
xjrpr mjpt cbbkfx rpmqq ljhn jmdg vht sdccxkt ngqh bnzq jgtrnm fmvvb mrfxh xxfgvz jfqqgtl tfmgl bcvmz pgqxp thvm crnfzr xddkbd zfsks qrsczjv pzxj tshn fbcds lbfgp thcs hkqp gsgmdn dvcfx zmb cnghsg csfmx vhqfz rxr bxv xjdhk zhghprj dtlhh ckqq qmthj jxjqp rczbvg gmc sfk ttxx ltvr pnglkx dnpgcd qsgb clqk klmjmz lh rvchbn pjln knqzf vnfmc qspfqb nthhxn zqsc mhrm gzgvdh ncqdr zrgzf ddrd vqrjn (contains nuts, shellfish)
rvchbn vhcnpg mstc zrgzf hkqp bnzq xbpb qrsczjv fhtsl fjgxv ddgdhg jfqqgtl rpmqq dpfphd pcf qrftr ngqh vht dvcfx dfrg tphtz mnvq qjsbk mvnqdh zntrfp xjzc jmgt xzcdnr vnfmc xddkbd fkh kmsh xmjlsn ckqq zfsks bcvmz ljhn gmc rrbndl fmvvb cxzkmr lh zdntns pgb thvm xxfgvz hrfmdk dln mrfxh tvqbhv cnghsg vpgvm hlmvqh mjpt jdtzr dgrrm kglr pgqxp kqzcj hkxcb xgbvk djpsmd tshn klmjmz rfh xlnn bjvcg qfkjsq rkzhxmh glrc clqk gjqfj jmdg knqzf ljmvpp csfmx rbvdt zfcvnj dsmc fstgc (contains dairy)
nthhxn vnfmc dsmc vpvj rhrc zfcvnj zdntns qmthj knnmm rpmmv dtlhh qdpbx zhghprj xddkbd mrfxh rqqfnlc dpfphd xhmmt dgrrm pgqxp zmb gmc flhfddq zkzdrn hlmvqh qrsczjv vhcnpg mjpt fbcds thvm ncqdr pjln zttx hrfmdk xlnn dvcfx fkh mszc klx cmnb zfml zrgzf mnvq rcr bjvcg csfmx xlzqfb ckqq (contains sesame, shellfish)
xnfhq hlmvqh lh qdpbx rpcdfph qsgb rpmqq tjsdp ljhn gsgmdn vfkpj jmdg xlzqfb ckqq qmmt jmgt dvcfx zrgzf bkd pmvl ngqh sjgx dpfphd kfsfn mrfxh bjvcg jkbqk qrftr mjpt vnmfg nldzpc ncqdr jvvmcq pptgt pjqdmpm thvm pjln ddrd csfmx kglr xgbvk tzjnvp bxv htllnq fstgc zfcvnj jxjqp pbn dsmc kbtx vqrjn rqqfnlc rxrgtvs hnmjfl qrsczjv (contains eggs)
mvnqdh klx rbvdt kx qmthj hrfmdk bcvmz fhtsl zrgzf xxfgvz pmvl csfmx hkxcb rpmqq vpvj jmgt vbqbkt lxr hlmvqh zhghprj kglr dpfphd xzcdnr mszc vgp dvcfx gzgvdh ncqdr mppf nldzpc djpsmd pnglkx mrfxh lqmfgp sjgx jfqqgtl dln vhcnpg npbnj cmnb hnmjfl kfsfn vtljml qspfqb xlzqfb dcbk jngghk lh jxjqp rxr jdtzr qrftr fbcds thvm mrxg zzldmh qfvfzg dtlhh hkqp dsmc qdpbx cxzkmr tfmgl xjrpr pjqdmpm rczbvg rcvd lbfgp jmdg qszmzsh glrc qkgqv tvqbhv qrsczjv fkh rknm ckqq zntrfp cbbkfx (contains shellfish, dairy)
zqsc zmb sfk thvm lvjpp ddgdhg qrsczjv qspfqb dmxhhd zzldmh xzcdnr xjdhk dznd qfvfzg ljhn ghr zrgzf bcvmz frld pnglkx fhtsl srgnx jfqqgtl fdf vhqfz qsgb jkbqk ckqq xxfgvz pjqdmpm rpmqq jmdg fkh crnfzr mjpt cnghsg qrftr xddkbd rkzhxmh pfqxsxd mhrm gtgrcf hlmvqh fmvvb tvqbhv dgrrm xbpb qmthj gjqfj kqzcj tshn qkgqv vfkpj kmsh pgqxp ddrd glrc xgbvk hrfmdk rgdx bnzq knnmm qchnn vnmfg ncqdr qfkjsq pmtfmv xnfhq sjgx cbbkfx stcsp rbvdt mstc gzgvdh kglr dsmc rrbndl xjzc rpcdfph (contains nuts)
rbvdt jmdg zkzdrn zmb hnmjfl gmc pgqxp lqmfgp knqzf xbpb fmvvb bkd dgrrm vgjbgj dcbk ttxx dtlhh vpgvm xlnn hlmvqh jgtrnm dpfphd qrsczjv xzcdnr jngghk qmmt thvm flhfddq gzgvdh crnfzr qszmzsh xlzqfb dfrg qspfqb qmthj rpcdfph frld zqsc xjdhk dmxhhd ljhn qchnn bnzq kltcm gtgrcf mszc zhghprj rhrc csfmx mrxg klmjmz lbskg ckqq pzxj nggcjr nthhxn nldzpc rpmqq dbx mhrm zrgzf xjzc (contains dairy, wheat, eggs)
lh sfk jvvmcq szsbj fmvvb xxfgvz sjgx jnr vqrjn gmc cnghsg qsgb jmdg mppf jfqqgtl fjgxv vbqbkt zqsc xgbvk pgqxp nqfc jmgt rfh xlnn rhrc nfnzx rpcdfph qszmzsh kglr zmb xnfhq thvm tbm zzldmh rcvd pmvl kqzcj hnmjfl nggcjr qrsczjv qchnn zmcj rvchbn fdf xmjlsn mnvq mgxzl rkzhxmh bxv ngqh xlzqfb gjqfj sdccxkt clqk cmnb rbvdt jkbqk dpfphd mrfxh hlmvqh kltcm ckqq jngghk mszc (contains sesame)
zfcvnj mvnqdh gjqfj htllnq nggcjr vtljml qrftr fstgc xjrpr dvcfx klmjmz thvm qjsbk rcvd hrfmdk rczbvg mjpt ncqdr kbtx nqfc xxfgvz xlzqfb mrfxh zmb jkbqk jmgt rxrgtvs qspfqb rhrc qmthj mszc ghr fmvvb cxfzhj lqmfgp ckqq zrgzf vfkpj tzjnvp mhrm vpvj pgqxp ngqh xlnn hlmvqh xnfhq tbm zqsc jvvmcq rvchbn lxr qrsczjv vgp cmnb pjqdmpm (contains dairy)
qfvfzg ngqh rhrc nthhxn mvnqdh rcr knnmm zmcj nfnzx stcsp nzlks qdpbx kfsfn nldzpc mrfxh cxzkmr fkh vpvj llgsg pgb cmnb ncqdr qchnn zrgzf rknm xjzc zntrfp mstc clqk gsgmdn jnr ljhn mppf hkqp jmdg xlnn xgbvk csfmx rpmmv fmvvb mjpt thvm zlgztsbd dtlhh dln bnzq klmjmz tfmgl vgp qmmt kglr dbx gzgvdh rcvd kmsh rgdx kqzcj ttxx tzjnvp qmthj hlmvqh zfsks qrsczjv lh vhcnpg pgqxp zmb zhghprj vht rxr vbqbkt pcf gtgrcf zzldmh dvcfx (contains wheat)
vfkpj kbtx qkgqv bkd srgnx rcr zdntns tjsdp kfsfn rhrc mstc vtljml zlgztsbd rbvdt zrgzf glrc qfvfzg rkzhxmh ddbmq pbn flhfddq dfrg kglr clqk rxrgtvs cxzkmr mrfxh ddgdhg cmnb hlmvqh rpmmv dln zttx pjln zmb pjqdmpm jmgt ckqq qdpbx rcvd thvm rrbndl vbqbkt xmjlsn lh xhmmt qmthj nzlks pgb xzcdnr mrxg xgbvk fkh vgp rqqfnlc gjqfj gsgmdn tbm szsbj bxv lxr cnghsg jfqqgtl dbx pmtfmv lvjpp xjzc xlnn dtlhh dsmc vnfmc qrsczjv zkzdrn ghr fhtsl (contains dairy, wheat, peanuts)
nldzpc pbn rxr vgp zmb pgqxp zfsks vfkpj tvqbhv qmmt pjln jmdg qfkjsq hnmjfl mrxg hlmvqh dln nqfc lbfgp rcr kfsfn vtljml rxrgtvs tbm dsmc hkqp lh jngghk vbqbkt thvm fbcds clqk pjqdmpm ckqq mppf tzjnvp xhmmt csfmx rpcdfph sdccxkt kbtx knqzf rkzhxmh qrsczjv mszc ttxx klx mrfxh mnvq (contains dairy, sesame)
rgdx tfmgl gmc fstgc ltvr ckqq pnglkx kglr hkqp ddgdhg qfkjsq xzcdnr jnr xxfgvz hlmvqh zhghprj ghr pfqxsxd ljmvpp zmb cmnb nldzpc dznd xlnn zrgzf lh zfcvnj dcbk kmsh xjrpr qjsbk nzlks gtgrcf kfsfn dpfphd rqqfnlc mppf zzldmh thcs cbbkfx jmgt rcr pjln mrfxh jxjqp fmvvb pmvl mgxzl knqzf rbvdt gzgvdh jmdg qrsczjv nqfc vnmfg qszmzsh tjsdp ljhn qrftr ddbmq bkd fbcds (contains wheat, peanuts)
clqk rpmmv rkzhxmh pbn mrfxh pmvl hkxcb mvnqdh kbtx tzjnvp ncqdr kmsh dcbk zrgzf qchnn bkd kqzcj hlmvqh thvm cmnb mjpt knnmm pzxj frld gsgmdn pfqxsxd ltvr lqmfgp fkh rbvdt vgjbgj nldzpc jgtrnm dbx qrftr zdntns lbskg rpcdfph djpsmd vbqbkt dsmc jdtzr qmthj zmb hnmjfl sfk mppf fmvvb rcr xmjlsn qrsczjv csfmx dln vqrjn xbpb stcsp fdf rxrgtvs mstc jmdg ljhn npbnj thcs ddbmq knqzf dgrrm rqqfnlc mszc jnr lbfgp qsgb dtlhh pgb bcvmz qszmzsh rfh gjqfj xlzqfb rxr (contains peanuts)
clqk csfmx lvjpp kqzcj thvm zntrfp dcbk ghr vtljml pfqxsxd pjqdmpm jgtrnm flhfddq zzldmh llgsg nthhxn mjpt zrgzf pjln dznd mnvq bjvcg nfnzx tzjnvp vgp dtlhh qmmt rpmmv jmdg zfcvnj xzcdnr zmb tbm dbx bxv cxzkmr tfmgl mszc ttxx qkgqv qjsbk ckqq pgqxp zfml mhrm vpvj jdtzr mgxzl tvqbhv qfvfzg vhcnpg lbskg lqmfgp cnghsg rcvd hnmjfl zhghprj hlmvqh xjrpr xxfgvz dln gtgrcf sdccxkt kx qspfqb jfqqgtl pptgt dmxhhd rpcdfph fstgc rcr fmvvb ljmvpp mrxg gmc pgb mrfxh kmsh cmnb (contains soy, wheat, eggs)
klx nggcjr xjrpr zdntns kltcm vhcnpg xlnn kqzcj hlmvqh dnpgcd vht rpmmv bnzq hnmjfl lbskg fdf bkd dgrrm rvchbn mgxzl pgb jdtzr dcbk qszmzsh rpmqq hrfmdk qrftr dpfphd lxr ngqh xddkbd qrsczjv tbm vqrjn qchnn vpvj mstc ckqq pbn zrgzf jxjqp jgtrnm tfmgl zmb rqqfnlc xmjlsn rxr pmtfmv zmcj zfsks zqsc crnfzr jmdg fbcds mrfxh xgbvk hkxcb gmc nldzpc nfnzx xnfhq (contains peanuts, eggs, nuts)
csfmx zzldmh dcbk fdf rhrc fjgxv qchnn cxzkmr qmthj crnfzr nqfc zmcj mhrm ltvr sdccxkt flhfddq cbbkfx cmnb qdpbx thvm xmjlsn fhtsl knqzf bxv nggcjr vnmfg zmb cxfzhj jdtzr pnglkx jmdg lxr kmsh vgjbgj mrfxh dln mppf gzgvdh rpmmv zntrfp zrgzf pgqxp ckqq zfml vnfmc vht pmvl xlzqfb rxrgtvs kltcm pzxj dsmc dtlhh hrfmdk qmmt dnpgcd bjvcg gsgmdn cnghsg xhmmt gmc ttxx qjsbk hlmvqh fkh vhqfz xxfgvz (contains dairy, sesame, eggs)
jmgt mppf ttxx dsmc xnfhq bxv kglr bcvmz ckqq jmdg dfrg jnr mnvq ngqh sfk fdf xhmmt fjgxv zfcvnj rczbvg cmnb xjrpr szsbj dvcfx gtgrcf knqzf pjln mrfxh lbfgp vnmfg jdtzr mhrm fstgc tbm djpsmd pnglkx qkgqv zmb vfkpj hkxcb qfkjsq pgqxp xzcdnr nfnzx npbnj rbvdt jfqqgtl hlmvqh qfvfzg jvvmcq hnmjfl thvm rgdx gjqfj zhghprj kqzcj rcr zrgzf tvqbhv tshn (contains peanuts)
rknm lvjpp cnghsg qrsczjv sdccxkt zrgzf rcvd rxrgtvs stcsp thvm fstgc ttxx pmvl rpcdfph dznd ckqq pptgt mstc rpmmv fdf knnmm jnr bjvcg mnvq qdpbx zfml rqqfnlc zqsc zhghprj mgxzl qmmt fkh rxr dsmc lbskg sfk xhmmt kqzcj vfkpj mhrm hlmvqh mrfxh pcf zmb jmgt ljmvpp jfqqgtl szsbj xjrpr vnfmc qszmzsh dbx mszc xlnn qrftr qchnn mjpt zttx ddgdhg gmc djpsmd zfcvnj dln qkgqv rcr dnpgcd tzjnvp hkxcb zmcj lxr bcvmz fhtsl vnmfg vpgvm (contains dairy, sesame)
rgdx jmdg cmnb thvm fstgc pfqxsxd ncqdr dmxhhd glrc xjrpr rkzhxmh fhtsl mrfxh hkxcb pmtfmv zfsks knnmm pgb vnmfg thcs dfrg ddbmq clqk zntrfp nthhxn xjzc dgrrm lvjpp rpmmv vht lh jfqqgtl vgp mszc rczbvg jnr jngghk xhmmt vhqfz bcvmz zmb ckqq tjsdp bkd xlzqfb xddkbd pmvl qrsczjv ddgdhg djpsmd ttxx zfcvnj mjpt nldzpc qrftr kx xnfhq fjgxv jmgt ljhn mrxg pbn sdccxkt rxrgtvs dln dpfphd zrgzf tbm rfh tvqbhv (contains sesame, dairy, shellfish)
rczbvg cxfzhj lxr mgxzl hkxcb kbtx zmb jvvmcq pmtfmv jfqqgtl jxjqp mszc thvm rknm jmdg vfkpj qmmt hlmvqh ltvr cnghsg pjln mrfxh gzgvdh szsbj pgb dcbk lvjpp qchnn bcvmz sdccxkt llgsg xgbvk mrxg ghr zhghprj hkqp thcs zrgzf zzldmh ckqq frld gtgrcf pnglkx clqk kglr xhmmt hnmjfl qjsbk qfvfzg dnpgcd dbx djpsmd qrftr rgdx tvqbhv ncqdr (contains eggs)
pmvl zmb zrgzf rxrgtvs mvnqdh dznd srgnx qmmt pgb jmdg hlmvqh dgrrm xjdhk klx rcvd qrsczjv cnghsg ttxx hrfmdk qspfqb pfqxsxd fmvvb pzxj sfk rbvdt nggcjr zqsc npbnj kglr xddkbd lbskg lqmfgp mrxg mrfxh zfml rkzhxmh jfqqgtl vgjbgj rpmmv tphtz mszc dln zfcvnj vpgvm tzjnvp rhrc nldzpc rknm tshn jgtrnm mppf fjgxv ckqq ddgdhg vpvj fbcds (contains shellfish)
xlzqfb nthhxn dln rczbvg jmdg vgp cbbkfx gsgmdn jvvmcq glrc klmjmz stcsp bcvmz dbx vpvj cmnb sjgx rfh rrbndl mgxzl jnr rhrc thvm xlnn mhrm mrfxh bxv qrftr lvjpp fjgxv kglr cxfzhj zmb pptgt ghr kbtx pnglkx qjsbk ckqq jfqqgtl fstgc dznd qszmzsh jgtrnm zrgzf tjsdp klx pjln vgjbgj vbqbkt zkzdrn sfk qrsczjv vhqfz hrfmdk kltcm vnfmc zqsc xhmmt knnmm qfvfzg xjrpr nqfc jkbqk (contains nuts, sesame)
jgtrnm bxv fbcds dznd bkd ttxx rpmqq ckqq pmvl dtlhh xjdhk zdntns knnmm vqrjn dsmc lqmfgp ltvr jfqqgtl mszc xhmmt szsbj crnfzr fkh rbvdt pjqdmpm nggcjr qrftr bcvmz qmmt srgnx xddkbd rvchbn zmb cmnb pptgt xjzc llgsg rxr bnzq gsgmdn thvm zzldmh rcvd mrfxh dgrrm zfsks qsgb tvqbhv zkzdrn nzlks lh klmjmz rxrgtvs kqzcj mnvq ngqh rczbvg tshn tjsdp hlmvqh pcf fdf rfh pnglkx hkqp zrgzf jkbqk sdccxkt fstgc vpvj ddbmq zttx xlzqfb qfvfzg frld qrsczjv zlgztsbd xnfhq pfqxsxd cxfzhj cxzkmr tphtz clqk (contains shellfish, peanuts)
hrfmdk nthhxn lh zrgzf thvm rbvdt qdpbx mhrm vhqfz lqmfgp qjsbk vgp qfvfzg szsbj nldzpc vpgvm sdccxkt dgrrm tfmgl zdntns ddgdhg zfsks hlmvqh zmcj pnglkx ncqdr qrsczjv sfk mrfxh rqqfnlc vht mstc pmvl cmnb gmc ckqq jmdg thcs bjvcg nzlks klx jfqqgtl fkh ghr ddbmq htllnq xlnn kglr (contains nuts)
fkh knqzf tvqbhv mrfxh hkqp nqfc mvnqdh xxfgvz gzgvdh vnfmc qrftr qrsczjv ngqh cxzkmr mjpt dvcfx zmcj xddkbd clqk rvchbn dsmc xjzc pfqxsxd dfrg qmmt mhrm flhfddq rrbndl xnfhq hlmvqh jmdg dznd frld jnr djpsmd thvm qjsbk ddbmq qchnn pnglkx dtlhh zhghprj fhtsl vtljml nzlks qszmzsh lqmfgp pbn cmnb rpcdfph kx qkgqv zrgzf tshn zmb zlgztsbd xlnn (contains eggs, nuts, dairy)
gsgmdn zqsc cxzkmr xlnn htllnq vbqbkt pgb pnglkx tphtz jmgt mrfxh qkgqv pjqdmpm glrc sdccxkt rbvdt vht pzxj fstgc bcvmz mjpt dvcfx vpvj ljmvpp pfqxsxd tshn zmcj zrgzf qmmt pcf dpfphd xxfgvz jxjqp rczbvg mgxzl thvm fjgxv hnmjfl rkzhxmh qrsczjv jmdg cnghsg zfml gjqfj tbm lh mppf dcbk zntrfp dbx jvvmcq szsbj pjln xhmmt rcr nthhxn kx fmvvb xzcdnr klx rpcdfph zmb djpsmd jdtzr mnvq hlmvqh bjvcg mrxg (contains eggs)
vqrjn rhrc pzxj pjqdmpm tshn pjln nggcjr ljhn fkh qchnn kfsfn vgjbgj jmgt qkgqv stcsp knnmm dznd pgb csfmx fmvvb ltvr rknm rpcdfph thvm mrfxh qfvfzg zfcvnj zmb clqk kx ghr rpmmv vbqbkt tfmgl dfrg lxr hrfmdk vpgvm zlgztsbd rczbvg tvqbhv jnr qjsbk qfkjsq xxfgvz hlmvqh klx dnpgcd kbtx flhfddq jfqqgtl jmdg ddrd xgbvk rqqfnlc ckqq bnzq mnvq ncqdr dln qdpbx kltcm mppf zttx dbx pmtfmv klmjmz vnmfg pgqxp nthhxn crnfzr dmxhhd xhmmt rgdx mvnqdh gsgmdn nzlks xzcdnr fbcds djpsmd zfsks dpfphd lh ddbmq vfkpj vgp qrsczjv (contains peanuts, eggs, soy)
dsmc hlmvqh rqqfnlc dgrrm lbskg xxfgvz klmjmz jmgt jnr dznd npbnj rrbndl fkh vfkpj dvcfx hnmjfl qrftr pmtfmv kltcm xzcdnr gtgrcf lbfgp bcvmz xddkbd vgjbgj gjqfj kglr qchnn zlgztsbd rcvd xmjlsn bnzq kbtx vnfmc zmb srgnx pptgt llgsg thvm ckqq qrsczjv cbbkfx cnghsg xjzc rbvdt mnvq mrfxh mppf rknm jmdg tzjnvp rfh vgp vpvj nfnzx hkxcb zqsc lqmfgp kmsh dnpgcd sjgx sfk gmc jfqqgtl ltvr vpgvm pmvl qmthj klx tbm rvchbn pfqxsxd xjdhk glrc rczbvg knqzf (contains shellfish, dairy, nuts)
ngqh lxr qrftr nldzpc cbbkfx zdntns xxfgvz srgnx qspfqb zfsks tzjnvp tphtz qrsczjv lbfgp gjqfj xjrpr qfkjsq rfh xgbvk dtlhh mrfxh xjdhk qkgqv hkqp dsmc rczbvg klmjmz ckqq xlzqfb ddgdhg kltcm vhqfz kglr jxjqp xddkbd htllnq gtgrcf zrgzf lbskg gmc szsbj thvm zmb zfcvnj hlmvqh pjqdmpm (contains peanuts, shellfish)
xlzqfb vpgvm flhfddq kbtx zmcj jmdg vhqfz tphtz vqrjn stcsp ckqq rgdx nfnzx nggcjr qrsczjv xmjlsn pgb ngqh pjqdmpm qsgb nldzpc hkxcb klmjmz rpmmv xjrpr zlgztsbd ncqdr zmb rpcdfph qjsbk gzgvdh xnfhq hlmvqh cbbkfx knnmm qfkjsq xddkbd vgp pmtfmv qdpbx cnghsg hrfmdk fjgxv xlnn xjzc mszc ljmvpp zntrfp fdf pcf mnvq thvm bkd fbcds dbx fstgc dln pfqxsxd zrgzf mhrm pbn zttx zhghprj (contains peanuts, eggs, dairy)
nldzpc gmc mjpt knqzf rbvdt zntrfp nthhxn jmdg rxr xzcdnr kx ljmvpp kltcm jmgt gjqfj pgqxp xjrpr zmb qrsczjv hlmvqh dbx dmxhhd pnglkx gsgmdn vhcnpg zrgzf xjzc pjqdmpm rpcdfph lbfgp xgbvk jvvmcq qdpbx nqfc dvcfx thvm rknm kbtx npbnj mrxg klmjmz rrbndl xbpb ncqdr fdf vpvj kglr pptgt mrfxh (contains sesame)
tshn dmxhhd qmthj kqzcj rqqfnlc pcf dgrrm hkqp ckqq flhfddq qmmt thcs vqrjn vht tbm lqmfgp bcvmz fbcds jmdg rbvdt xzcdnr xlzqfb vfkpj mrfxh sdccxkt fstgc fhtsl qfvfzg kmsh dznd zrgzf bxv glrc thvm pmtfmv rkzhxmh zqsc xjzc fmvvb ddbmq qspfqb tjsdp rcvd xgbvk gzgvdh cmnb pptgt ngqh xlnn sjgx mrxg qdpbx rknm hnmjfl szsbj zntrfp gtgrcf fdf kltcm vhcnpg zmb pjln mppf dnpgcd ttxx qrsczjv srgnx qszmzsh (contains shellfish, nuts)

105
d21/main.py Executable file
View File

@ -0,0 +1,105 @@
#! /usr/bin/env python3
import re
from functools import reduce
from dataclasses import dataclass
from typing import Any
from typing import Dict
from typing import Iterable
from typing import Set
food_parser = re.compile(r"([a-z ]+) \(contains ([a-z, ]+)\)")
@dataclass
class Food:
items: Set[str]
alergens: Set[str]
def read_input(filename: str) -> Iterable[Food]:
with open(filename) as f:
for line in f:
line = line.strip()
if line == "":
continue
match = food_parser.match(line)
if not match:
raise ValueError(f"cannot parse line {line}")
items = match.group(1).split(" ")
alergens = match.group(2).split(", ")
yield Food(set(items), set(alergens))
def extract_alergen_info(foods: Iterable[Food]) -> Dict[str, Set[str]]:
alergen_defs: Dict[str, Set[str]] = {}
for food in foods:
for alergen in food.alergens:
if alergen not in alergen_defs:
alergen_defs[alergen] = food.items.copy()
else:
alergen_defs[alergen] &= food.items
return alergen_defs
def reduce_union(items: Iterable[Set[Any]]) -> Set[Any]:
return reduce(lambda x, y: x | y, items)
def reduce_intersecion(items: Iterable[Set[Any]]) -> Set[Any]:
return reduce(lambda x, y: x & y, items)
def narrow_results(alergen_defs: Dict[str, Set[str]]):
sorted_alergens = sorted(alergen_defs.items(), key=lambda x: len(x[1]))
for i, alergen_info in enumerate(sorted_alergens):
if len(alergen_info[1]) == 1:
# Remove from others
if i+1 < len(sorted_alergens):
for other_info in sorted_alergens[i+1:]:
other_info[1].difference_update(alergen_info[1])
def part1():
all_foods = list(read_input("input.txt"))
alergen_defs = extract_alergen_info(all_foods)
print("Alergen defs", alergen_defs)
safe_items = reduce_union((food.items for food in all_foods))
all_possible_alergens = reduce_union(alergen_defs.values())
print("All possible alergens", all_possible_alergens)
safe_items -= all_possible_alergens
print("All safe items", safe_items)
count_safe = sum(
map(
lambda food: len(food.items & safe_items),
(food for food in all_foods),
),
)
print("Count of safe items appeared is", count_safe)
print("Part 2")
narrow_results(alergen_defs)
narrow_results(alergen_defs)
narrow_results(alergen_defs)
print("Narrowed alergen list", alergen_defs)
canon_list = ",".join((
a[1].pop() for a in sorted(alergen_defs.items(), key=lambda x: x[0])
))
print("Canon list of ingredients", canon_list)
if __name__ == "__main__":
part1()

4
d21/sample-input.txt Normal file
View File

@ -0,0 +1,4 @@
mxmxvkd kfcds sqjhc nhms (contains dairy, fish)
trh fvjkl sbzzf mxmxvkd (contains dairy)
sqjhc fvjkl (contains soy)
sqjhc mxmxvkd sbzzf (contains fish)

54
d22/input.txt Normal file
View File

@ -0,0 +1,54 @@
Player 1:
14
6
21
10
1
33
7
13
25
8
17
11
28
27
50
2
35
49
19
46
3
38
23
5
43
Player 2:
18
9
12
39
48
24
32
45
47
41
40
15
22
36
30
26
42
34
20
16
4
31
37
44
29

8
d22/loop-input.txt Normal file
View File

@ -0,0 +1,8 @@
Player 1:
43
19
Player 2:
2
29
14

174
d22/main.py Executable file
View File

@ -0,0 +1,174 @@
#! /usr/bin/env python3
from copy import copy
from enum import Enum
from typing import Set, Tuple, List, Optional
class Player(Enum):
UNKNOWN = 0
ONE = 1
TWO = 2
def read_decks(filename: str):
deck1, deck2 = None, None
cur_deck: List[int] = []
with open(filename) as f:
for line in f:
line = line.strip()
if line.startswith("Player 1"):
continue
if line == "":
continue
if line.startswith("Player 2"):
deck1 = cur_deck
cur_deck = []
continue
cur_deck.append(int(line))
deck2 = cur_deck
return deck1, deck2
def play_round(deck1, deck2):
c1 = deck1.pop(0)
c2 = deck2.pop(0)
print(f"{c1} vs {c2} ", end="", flush=True)
if c1 > c2:
print("Player 1 wins!")
deck1 += [c1, c2]
elif c2 > c1:
print("Player 2 wins!")
deck2 += [c2, c1]
else:
print("Nobody wins?")
# raise ValueError("Nobody wins")
RoundHistory = Set[Tuple[Tuple[int, ...], Tuple[int, ...]]]
def recursive_combat(
deck1: List[int],
deck2: List[int],
game: int = 1,
past_games: Optional[RoundHistory] = None
) -> Player:
if past_games is None:
past_games = set()
print(f"{game}: Starting p2 {deck1} p2 {deck2}")
# Play until there is an empty deck
game_round = 0
winner = Player.UNKNOWN
while deck1 and deck2:
game_round += 1
# Check for looping...
this_round = (tuple(deck1), tuple(deck2))
if this_round in past_games:
print(
f"{game}:{game_round} Loop detected. Player 1 wins the game!",
)
return Player.ONE
past_games.add(this_round)
print(f"{game}:{game_round} p1 {deck1} p2 {deck2} ")
# Draw
c1 = deck1.pop(0)
c2 = deck2.pop(0)
print(f"{game}:{game_round} {c1} vs {c2} ", end="", flush=True)
winner = Player.UNKNOWN
if c1 <= len(deck1) and c2 <= len(deck2):
print("RECURSIVE COMBAT!!!!")
winner = recursive_combat(
copy(deck1[:c1]),
copy(deck2[:c2]),
game=game+1,
past_games=past_games.copy(),
)
else:
if c1 > c2:
winner = Player.ONE
elif c2 > c1:
winner = Player.TWO
else:
raise ValueError("cards are equal? No way!")
if winner == Player.ONE:
print("Player 1 wins!")
deck1 += [c1, c2]
elif winner == Player.TWO:
print("Player 2 wins!")
deck2 += [c2, c1]
else:
print("Nobody wins?")
raise ValueError("Nobody wins")
print(f"{game}: Game finished p1 {deck1} p2 {deck2}")
# Deck is empty!
if deck1:
winner = Player.ONE
elif deck2:
winner = Player.TWO
else:
raise ValueError("unknown winner")
return winner
def part1():
deck1, deck2 = read_decks("input.txt")
print("Initial decks")
print("Player 1", deck1)
print("Player 2", deck2)
while deck1 and deck2:
play_round(deck1, deck2)
winning_deck: List[int] = None
if deck1:
winning_deck = deck1
print("Winner! Player 1!")
elif deck2:
winning_deck = deck2
print("Winner! Player 2!")
score = sum((i*v for i, v in enumerate(reversed(winning_deck), 1)))
print("Score:", score)
def part2():
deck1, deck2 = read_decks("input.txt")
print("Initial decks")
print("Player 1", deck1)
print("Player 2", deck2)
_ = recursive_combat(deck1, deck2)
winning_deck: List[int] = None
if deck1:
winning_deck = deck1
print("Winner! Player 1!")
elif deck2:
winning_deck = deck2
print("Winner! Player 2!")
score = sum((i*v for i, v in enumerate(reversed(winning_deck), 1)))
print("Score:", score)
if __name__ == "__main__":
part1()
part2()

13
d22/sample-input.txt Normal file
View File

@ -0,0 +1,13 @@
Player 1:
9
2
6
3
1
Player 2:
5
8
4
7
10

171
d23/main.py Executable file
View File

@ -0,0 +1,171 @@
#! /usr/bin/env python3
from typing import List
from typing import Tuple
def cups_str(cups: List[int], current: int) -> str:
return " ".join(
("(" if c == current else "") + str(c) + (")" if c == current else "")
for c in cups
)
def get_result(cups: List[int], part2: bool = False) -> str:
# Rotate 1 to the front
index_1 = cups.index(1)
if not part2:
result = cups[index_1:] + cups[:index_1]
# Remove 1 from the front
result = result[1:]
return "".join((str(c) for c in result))
else:
cup1 = cups[index_1+1 % len(cups)]
cup2 = cups[index_1+2 % len(cups)]
print(f"cup1: {cup1} cup2: {cup2}")
return str(cup1 * cup2)
def str_to_cups(opening: str, part2: bool = False) -> List[int]:
cups = [int(c) for c in opening]
if part2:
max_cup = max(cups)
cup_limit = 1000000
cups += [c for c in range(max_cup+1, cup_limit+1)]
return cups
def play_round(
cups: List[int],
current: int,
debug: bool = True,
) -> Tuple[List[int], int]:
if debug:
print(f"cups: {cups_str(cups, current)}")
cur_i = cups.index(current)
# Pick up cups
picked_up: List[int] = []
while len(picked_up) < 3:
if cur_i+1 < len(cups):
picked_up.append(cups.pop(cur_i+1))
else:
picked_up.append(cups.pop(0))
cur_i -= 1
if debug:
print(f"pick up: {', '.join((str(c) for c in picked_up))}")
# Find destination
dest = 0
max_cup = 0
for c in cups:
if c < current and c > dest:
dest = c
if dest == current-1:
break
if c > max_cup:
max_cup = c
if dest <= 0:
dest = max_cup
dest_i = cups.index(dest)
# Other guy
# dest = max((c for c in cups if c < current), default=max(cups))
# dest_i = cups.index(dest)
# My attempt 1
# dest = current - 1
# dest_i = None
# while dest_i is None:
# if dest <= 0:
# # Wrap around to the highest value instead
# dest = max(cups)
# try:
# dest_i = cups.index(dest)
# except ValueError:
# # Try the next cup down
# dest -= 1
if debug:
print(f"destination: {dest}")
# Add cups back
# cups[dest_i+1:dest_i+1] = picked_up
if dest_i+1 >= len(cups):
cups += picked_up
else:
for cup in reversed(picked_up):
cups.insert(dest_i+1, cup)
# If inserted before the current, move that index up
if dest_i < cur_i:
cur_i += 3
# Get the new current to the right of old
cur_i += 1
cur_i = cur_i % len(cups)
current = cups[cur_i]
return cups, current
def play_game(cups: List[int], rounds: int, debug: bool = True) -> List[int]:
current = cups[0]
if debug:
print(f"game: {cups_str(cups, current)} {rounds} rounds")
ten_percent = int(rounds / 10)
for move in range(rounds):
if move % ten_percent == 0:
print(f"{move/ten_percent*10}%")
if debug:
print(f"-- move {move+1} --")
cups, current = play_round(cups, current, debug=debug)
if debug:
print("")
if debug:
print("-- final --")
print(f"cups: {cups_str(cups, current)}")
print(f"result {get_result(cups)}")
return cups
def sample():
# cups = str_to_cups("389125467")
# cups = play_game(cups, 10, debug=False)
# print(f"result {get_result(cups)}")
#
cups = str_to_cups("389125467")
cups = play_game(cups, 100, debug=False)
print(f"result {get_result(cups)}")
# cups = str_to_cups("389125467", part2=True)
# cups = play_game(cups, 10000000, debug=False)
# print(f"result {get_result(cups, part2=True)}")
def part1():
cups = str_to_cups("853192647")
cups = play_game(cups, 100, debug=False)
print(f"result {get_result(cups)}")
def part2():
cups = str_to_cups("853192647", part2=True)
cups = play_game(cups, 10000000, debug=False)
print(f"result {get_result(cups, part2=True)}")
if __name__ == "__main__":
# sample()
# part1()
part2()

157
d23/main2.py Executable file
View File

@ -0,0 +1,157 @@
#! /usr/bin/env python3
from typing import List
from typing import Iterable
from typing import Dict
from typing import Tuple
def listify(cups: Dict[int, int]) -> Iterable[int]:
yield 1
next_cup = cups[1]
while next_cup != 1:
yield next_cup
next_cup = cups[next_cup]
def cups_str(cups: Dict[int, int], current: int) -> str:
return " ".join(
("(" if c == current else "") + str(c) + (")" if c == current else "")
for c in listify(cups)
)
def get_result(cups: Dict[int, int]) -> str:
# Rotate 1 to the front
cup1 = cups[1]
cup2 = cups[cup1]
print(f"cup1: {cup1} cup2: {cup2}")
return str(cup1 * cup2)
def str_to_cups(opening: str, max_cups: int = 0) -> Dict[int, int]:
cups_list = [int(c) for c in opening]
max_cup = max(cups_list)
if max_cups:
cup_limit = max_cups
cups_list += [c for c in range(max_cup+1, cup_limit+1)]
cups = dict(zip(cups_list, cups_list[1:]+cups_list[0:1]))
return cups
def play_round(
cups: Dict[int, int],
current: int,
max_cup: int,
debug: bool = False,
) -> Tuple[Dict[int, int], int]:
if debug:
print(f"cups: {cups_str(cups, current)}")
# Pick up cups
first_cup = cups[current]
second_cup = cups[first_cup]
third_cup = cups[second_cup]
following_cup = cups[third_cup]
# Seal
cups[current] = following_cup
if debug:
print(f"pick up: {first_cup}, {second_cup}, {third_cup}")
# Find destination
dest = current - 1
if dest < 1:
dest = max_cup
while dest in (first_cup, second_cup, third_cup):
dest -= 1
if dest < 1:
dest = max_cup
if debug:
print(f"destination: {dest}")
# Add cups back
following_cup = cups[dest]
cups[dest] = first_cup
cups[third_cup] = following_cup
# Get the new current to the right of old
current = cups[current]
return cups, current
def play_game(
cups: Dict[int, int],
start: int,
max_cup: int,
rounds: int,
debug: bool = False,
) -> Dict[int, int]:
current = start
if debug:
print(f"game: {cups_str(cups, current)} {rounds} rounds")
ten_percent = int(rounds / 10)
for move in range(rounds):
if move % ten_percent == 0:
print(f"{move/ten_percent*10}%")
if debug:
print(f"-- move {move+1} --")
cups, current = play_round(cups, current, max_cup, debug)
if debug:
print("")
if debug:
print("-- final --")
print(f"cups: {cups_str(cups, current)}")
# print(f"result {get_result(cups)}")
return cups
def sample():
# cups = str_to_cups("389125467")
# cups = play_game(cups, 10, debug=False)
# print(f"result {get_result(cups)}")
# cups = str_to_cups("389125467")
# start = 3
# max_cups = 9
# cups = play_game(cups, start, max_cups, 100, debug=True)
# print(f"result {get_result(cups)}")
start = 3
rounds = 10000000
max_cups = 1000000
cups = str_to_cups("389125467", max_cups=max_cups)
cups = play_game(cups, start, max_cups, rounds, debug=False)
print(f"result {get_result(cups)}")
def part1():
cups = str_to_cups("853192647")
cups = play_game(cups, 100, debug=False)
print(f"result {get_result(cups)}")
def part2():
start = 8
rounds = 10000000
max_cups = 1000000
cups = str_to_cups("853192647", max_cups=max_cups)
cups = play_game(cups, start, max_cups, rounds, debug=False)
print(f"result {get_result(cups)}")
if __name__ == "__main__":
# sample()
# part1()
part2()

0
d24/__init__.py Normal file
View File

662
d24/expanding.py Normal file
View File

@ -0,0 +1,662 @@
#! /usr/bin/env python3
from collections import namedtuple
from itertools import product
from typing import Any
from typing import Callable
from typing import Iterable
from typing import List
from typing import Optional
from typing import Tuple
from typing import Set
Point = namedtuple("Point", "x y z w", defaults=(0, 0))
def add_points(p1, p2) -> Point:
return Point(
p1.x + p2.x,
p1.y + p2.y,
p1.z + p2.z,
p1.w + p2.w,
)
class GridItem(object):
def __init__(self, loc: Point, world: "World"):
self._loc = loc
self._world = world
self._ticked = False
def _tock():
# print("Default tock")
pass
self.tock = _tock
def neighbors(self, expand=False) -> Iterable["GridItem"]:
seen_points: Set[Point] = set()
for diff in product((0, 1, -1), repeat=4):
# from pdb import set_trace; set_trace()
neighbor_point = add_points(
self._loc,
Point(
diff[0],
diff[1],
diff[2],
diff[3],
),
)
if self._loc == neighbor_point:
# skip self
continue
if neighbor_point in seen_points:
# skip points we've already visited
# print("Already seen, skipping")
continue
seen_points.add(neighbor_point)
# print(f"Getting point {neighbor_point}")
neighbor = self._world.get_point(neighbor_point, expand=expand)
if neighbor is not None:
# print("FOUND!")
yield neighbor
def tick(self):
active_neighbors = 0
for neighbor in self.neighbors():
# print(f"Neighbor is active: {neighbor.active}")
if neighbor.active:
# print(f"Neighbor is active {neighbor}")
active_neighbors += 1
if self.active and active_neighbors not in (2, 3):
# print("Should go inactive")
def _tock():
# print("go inactive")
self.active = False
self.tock = _tock
elif not self.active and active_neighbors == 3:
# print("Should go active")
def _tock():
# print("go active")
self.active = True
self.tock = _tock
else:
# print("Should do nothing")
def _tock():
# print("Empty tock")
pass
self.tock = _tock
def __repr__(self) -> str:
return f"({self._loc.x}, {self._loc.y}, {self._loc.z})"
def to_str(self) -> str:
raise NotImplementedError()
class AutoExpanding(object):
_l: List[Any]
_zero: int
_item_factory: Callable[[int], Any]
def __init__(self):
self._l = [self._item_factory(0)]
self._zero = 0
def get(self, i, expand=True):
if not expand:
if self._zero+i < 0:
raise IndexError(f"index {i} is out of bounds")
return self._l[self._zero+i]
if self._zero is None:
self._l = [self._item_factory(0)]
self._zero = 0
if i > 0 and i >= len(self._l) - self._zero - 1:
# print(f"resize pos to {i} with {self._l} zero={self._zero}")
self._l = self._l + [
self._item_factory(j)
for j in range(len(self._l)-self._zero, i+1)
]
# print(f"> done {self._l} zero={self._zero}")
elif i < 0 and abs(i) > self._zero:
# print(f"resize neg to {i} with {self._l} zero={self._zero}")
self._l = [
self._item_factory(j)
for j in range(i, -1 * self._zero)
] + self._l
self._zero = abs(i)
# print(f"> done {self._l} zero={self._zero}")
# print(f"Now getting item at index {i} from {self._l}")
return self._l[self._zero+i]
def __getitem__(self, i):
if isinstance(i, slice):
return [
self[j]
for j in range(
i.start if i.start is not None else self.min_index(),
(i.stop if i.stop is not None else self.max_index()) + 1,
i.step or 1,
)
]
return self.get(i, expand=False)
def __setitem__(self, i, value):
self.get(i, expand=True)
self._l[self._zero+i] = value
def __len__(self) -> int:
return len(self._l)
def __iter__(self):
return iter(self._l)
def min_index(self) -> int:
return -1 * self._zero
def max_index(self) -> int:
return len(self._l) - self._zero - 1
def get_bounds(self) -> Tuple[int, int]:
return self.min_index(), self.max_index()
def resize(self, min_index: int, max_index: int):
if min_index < self.min_index():
self.get(min_index, expand=True)
else:
if min_index > 0:
raise IndexError("Cannot resize to exclude zero")
self._l = self[min_index:]
self._zero = abs(min_index)
if max_index > self.max_index():
self.get(max_index, expand=True)
else:
if max_index < 0:
raise IndexError("Cannot resize to exclude zero")
self._l = self[:max_index]
def __repr__(self) -> str:
return f"<AutoExpanding {self._l}>"
class World(AutoExpanding):
def iter_items(self) -> Iterable[GridItem]:
raise NotImplementedError()
def tick(self):
for c in self.iter_items():
c.tick()
def tock(self):
for c in self.iter_items():
c.tock()
def get_point(self, p: Point, expand=True) -> Optional[GridItem]:
raise NotImplementedError()
def trim(self):
raise NotImplementedError()
def get_all_bounds(self) -> Tuple[Point, Point]:
raise NotImplementedError()
def true_up(self):
raise NotImplementedError()
def expand_all(self, i: int):
raise NotImplementedError()
class GridRow(AutoExpanding):
def __init__(self, y: int, z: int, world: World, w: Optional[int] = 0):
self._y = y
self._z = z
self._w = w
self._world = world
super().__init__()
def _item_factory(self, x: int) -> GridItem:
return GridItem(Point(x, self._y, self._z, self._w), self._world)
def __repr__(self) -> str:
return "[" + " ".join((str(c) for c in self._l)) + "]"
def to_str(self) -> str:
return "".join((c.to_str() for c in self._l))
class GridSlice(AutoExpanding):
def __init__(self, z: int, world: World, w: Optional[int] = 0):
self._z = z
self._w = w
self._world = world
super().__init__()
def _item_factory(self, y: int) -> GridRow:
return GridRow(y, self._z, self._world, w=self._w)
def __repr__(self) -> str:
return f"z={self._z}\n" + "\n".join((
str(r) for r in self._l
))
def to_str(self) -> str:
return f"z={self._z}\n" + "\n".join([r.to_str() for r in self._l])
class Grid(World):
def __init__(self, world: Optional[World] = None, w: Optional[int] = 0):
if world is not None:
self._world = world
else:
self._world = self
self._w = w
super().__init__()
def _item_factory(self, z: int) -> GridSlice:
return GridSlice(z, self._world, w=self._w)
def __repr__(self) -> str:
return "\n\n".join((
str(s) for s in self._l
))
def to_str(self) -> str:
return "\n\n".join((
s.to_str() for s in self._l
))
def iter_cubes(self) -> Iterable[GridItem]:
for s in self:
for r in s:
for c in r:
yield c
def get_point(self, p: Point, expand=True) -> Optional[GridItem]:
try:
# print(f"expand world z to {p.z}")
c = self.get(
p.z,
expand=expand,
).get(
p.y,
expand=expand,
).get(
p.x,
expand=expand,
)
# from pdb import set_trace; set_trace()
return c
except IndexError:
return None
def trim(self):
for s in self:
for r in s:
first, last = None, None
min_index, max_index = r.get_bounds()
for i in range(min_index, max_index+1):
if r[i].active:
if first is None:
first = i
last = i
if first is None or first > 0:
first = 0
if last is None or last < 0:
last = 0
r.resize(first, last)
first, last = None, None
min_index, max_index = s.get_bounds()
for i in range(min_index, max_index+1):
if len(s[i]) > 1 or (len(s[i]) == 1 and s[i][0].active):
if first is None:
first = i
last = i
if first is None or first > 0:
first = 0
if last is None or last < 0:
last = 0
s.resize(first, last)
def get_all_bounds(self) -> Tuple[Point, Point]:
min_z, max_z = self.get_bounds()
min_y, max_y = 0, 0
min_x, max_x = 0, 0
for s in self:
if s.min_index() < min_y:
min_y = s.min_index()
if s.max_index() > max_y:
max_y = s.max_index()
for r in s:
if r.min_index() < min_x:
min_x = r.min_index()
if r.max_index() > max_x:
max_x = r.max_index()
return Point(min_x, min_y, min_z), Point(max_x, max_y, max_z)
def true_up(self):
min_point, max_point = self.get_all_bounds()
for s in self:
s.resize(min_point.y, max_point.y)
for r in s:
r.resize(min_point.x, max_point.x)
def expand_all(self, i: int):
min_point, max_point = self.get_all_bounds()
# print(f"expand {i} cell")
# print("expsting min, max:", min_point, max_point)
min_point = add_points(min_point, Point(-i, -i, -i))
max_point = add_points(max_point, Point(i, i, i))
# print("new min, max:", min_point, max_point)
self.get_point(min_point, expand=True)
self.get_point(max_point, expand=True)
class HyperGrid(World):
def __init__(self):
super().__init__()
def _item_factory(self, w: int) -> Grid:
return Grid(world=self, w=w)
def __repr__(self) -> str:
return "\n\n".join((
str(s) for s in self._l
))
def to_str(self) -> str:
return "\n\n".join((
f"w = {s._w}, " + s.to_str() for s in self._l
))
def iter_cubes(self) -> Iterable[GridItem]:
for g in self:
for s in g:
for r in s:
for c in r:
yield c
def get_point(self, p: Point, expand=True) -> Optional[GridItem]:
try:
# print(f"expand world z to {p.z}")
c = self.get(
p.w,
expand=expand,
).get(
p.z,
expand=expand,
).get(
p.y,
expand=expand,
).get(
p.x,
expand=expand,
)
# from pdb import set_trace; set_trace()
return c
except IndexError:
return None
def get_all_bounds(self) -> Tuple[Point, Point]:
min_w, max_w = self.get_bounds()
min_z, max_z = 0, 0
min_y, max_y = 0, 0
min_x, max_x = 0, 0
for g in self:
if g.min_index() < min_z:
min_z = g.min_index()
if g.max_index() > max_z:
max_z = g.max_index()
for s in g:
if s.min_index() < min_y:
min_y = s.min_index()
if s.max_index() > max_y:
max_y = s.max_index()
for r in s:
if r.min_index() < min_x:
min_x = r.min_index()
if r.max_index() > max_x:
max_x = r.max_index()
return (
Point(min_x, min_y, min_z, min_w),
Point(max_x, max_y, max_z, max_w),
)
def true_up(self):
min_point, max_point = self.get_all_bounds()
for g in self:
g.resize(min_point.z, max_point.z),
for s in g:
s.resize(min_point.y, max_point.y)
for r in s:
r.resize(min_point.x, max_point.x)
def expand_all(self, i: int):
min_point, max_point = self.get_all_bounds()
# print(f"expand {i} cell")
# print("existing min, max:", min_point, max_point)
min_point = add_points(min_point, Point(-i, -i, -i, -i))
max_point = add_points(max_point, Point(i, i, i, i))
# print("new min, max:", min_point, max_point)
self.get_point(min_point, expand=True)
self.get_point(max_point, expand=True)
def part1():
# Load world
g = Grid()
with open("input.txt") as f:
for y, row in enumerate(f):
row.strip()
for x, c in enumerate(row):
# g.get(0).get(y).get(x).active = c == ACTIVE
pass
g.true_up()
print("time = 0\n_____________")
print(g.to_str())
for t in range(6):
g.expand_all(1)
g.true_up()
g.tick()
g.tock()
# g.trim()
g.true_up()
print(f"time = {t+1}\n_____________")
print(g.to_str())
# print(g)
total = g.count_active()
print(f"Total active: {total}")
def part2():
# Load world
g = HyperGrid()
with open("input.txt") as f:
for y, row in enumerate(f):
row.strip()
for x, c in enumerate(row):
# g.get(0).get(0).get(y).get(x).active = c == ACTIVE
pass
g.true_up()
print("time = 0\n_____________")
print(g.to_str())
# g.expand_all(1)
# g.true_up()
# print("EXPANDED\ntime = 0\n_____________")
# print(g.to_str())
# return
for t in range(6):
g.expand_all(1)
g.true_up()
g.tick()
g.tock()
# g.trim()
g.true_up()
# print(f"time = {t+1}\n_____________")
# print(g.to_str())
# print(g)
total = g.count_active()
print(f"Total active: {total}")
def test():
g = Grid()
# print("test")
# s = [
# "...",
# "###",
# "...",
# ]
# for y, row in enumerate(s):
# row.strip()
# for x, c in enumerate(row):
# g.get(0).get(y).get(x).active = c == ACTIVE
#
# g.true_up()
#
# print("time = 0")
# print(g.to_str())
# print(g)
#
# p = g.get(0).get(0).get(1)
# from pdb import set_trace; set_trace()
# p.tick()
# p.tock()
# print(g.to_str())
#
# p = g.get(0).get(2).get(1)
# from pdb import set_trace; set_trace()
# p.tick()
# p.tock()
# print(g.to_str())
# print(list(g[0][0][0].neighbors()))
#
# print(g.to_str())
#
#
# return
# g.get(1).get(1).get(1)
# g.get_point(Point(1, 1, 1))
# g.expand_all(1)
# g.true_up()
# print(g)
# r = GridRow(0, 0, None)
# print(r)
# r.get(1)
# print(r)
# print(r[:3])
# r.get(-3)
# # print(r[0:3])
# print(r[-2:])
#
# print("Resize")
# print(r)
# r.resize(0, 3)
# print(r)
# return
# c = g.get(0).get(0).get(0)
# print(g)
# from pdb import set_trace; set_trace()
# neigh = list(c.neighbors())
# print(neigh)
#
# return
print("test")
s = [
".#.",
"..#",
"###",
]
for y, row in enumerate(s):
row.strip()
for x, c in enumerate(row):
# g.get(0).get(y).get(x).active = c == ACTIVE
pass
g.true_up()
print("time = 0\n_____________")
print(g.to_str())
# print(g)
# g.expand_all(1)
# g.true_up()
# print(g.to_str())
# print(g)
# return
for t in range(6):
g.expand_all(1)
g.true_up()
# print(g.to_str())
# p = g.get(0).get(3).get(1)
# from pdb import set_trace; set_trace()
g.tick()
g.tock()
# g.trim()
g.true_up()
print(f"time = {t+1}\n_____________")
print(g.to_str())
# print(g)
total = g.count_active()
print(f"Total active: {total}")
if __name__ == "__main__":
# part1()
part2()

547
d24/input.txt Normal file
View File

@ -0,0 +1,547 @@
neeneneneswneneee
eeeswneseseeseeeseeeeesesee
swswsweswwswswswnw
neseewwswwneswnewnewwswswwswwse
wswsweenweesenweeeeeenweeee
neswwwswwwnewwwwwwwwsewwswsww
neseeeswesweenweeeeeeeeee
neeeneneeneeswneeneneneene
ewwsenwwenwnwswnwswwnewwwsewne
sesesesesesewseseweeeeneweseeww
neeeswnwneswneneneweeneeneswnwnesw
neseswnwnenenewneneesenenenenenenenenenene
eneeeeseseeseesewseseseeeseee
enenewseeenewnweseewnwneseweesw
sesesesesenwseseseseseseseswseseee
nenenenenwneeesweseneeeeeenenenwe
neeenenwseswsenewseswenwewsww
neeenesweswwneeneeeeeeeeenwe
swseneswewwsewsweeeseeswwsesww
nenwwnwnwswwnwwnwnwnwnwnweswswnenww
swswseseswnwswswswseswseeswswswswnwswsesenw
nwnewwswnwesewnwwwsenwwnewewe
newwsewwsenwswwswswswswseswwnwwwsw
swswsweswseswswwswswnwseswswswswswswswsw
nenwnwnwnenwnwnwnenenwnenwneswnesenwenw
nwswnwwnwnwwnwnenwwse
neesweeeesewewneese
nwneweswwwswswwswwswswsewsw
wwwwsenwwnwneswsewsewnenewnwwseswne
eeeeeneneneneweneeeeeweswnene
enenwneneeneswnewnweewseswneswnew
swsesesesesenweswseseseswswseswswsesese
nweeeneweewsw
nwswswneswswswneswsewswswswswsesw
swenwwnenwnwnwswnwsesenenw
swswswnwneswswswseswswswswswswswseswse
sweseseseeseseweenese
wnwnwnwnwnenwnwswnwnwenwsenwenwnwnene
eeenweeeeeeeeeeesweeee
nesenwswnwseswneewnenwenwsenwenwewnw
eeeeeewesenweeseeeeswe
swwwswneswsewwswsw
nwnenwnenwnenwnenesenenwnwnwnwnwnwwnw
newnesewnwnenwneneenwnenenwnenenenenesw
eeeeeeeeeeenweeeseeeesw
swnwnwwnwwwnwwewnwwsewwwwnwnew
nwnwnwenenwswnwnwnwnwwnwnenwswewnwnw
swseenwnwswnwnenesenenwnwneeswneenwwnw
enwwseeswwenwswswesw
enwseseeeeeeenweeeseeseswseee
eseswseseswseneenwwneeswwwse
swswswwesenwswswswswswswswswswsenesesw
neswenwswswswnwnwsweswnweswswsweswsw
newsenenwswesewenesewwseeesenwesew
seswswswswswswneseseswweswseswsewseswnw
wnwwwwnwnwnwwnenwwewnwnwswnwnww
newwwwwwsenwwwewwwnwwwww
seseseeeswseseswseswswwsewseseswswse
eenenwswnenwneswnesenwnenenenwnwnenenewsw
swnwewswwewnwnwswwwnwnwewwwse
nwenewneneneewnene
wwwwwswwswenwwsewwwwwwswsww
enenewswnwneneneneseneneneeneneeneene
wnwswswnewwwswnewwwsewwseswnew
nenenwwsenweswnwswswnwswnwnenwnwne
seeenwesesesewseseeseseeesesesese
eeneeeeeeeneenwenweswsweeene
wneneneswseneneneneneneeneenenwsenwnene
seseseswsenewesesesenwneseseeseseesese
wsesenesenwsesweseswnwsesweseseesenwsese
wwwwnwwnewewwswsenwseseewnwnenwnw
wnenenenenenenenenwnenenwnenenesenenene
neeewnwwneneesweneeweseswnwneswsw
neesewwneenwnwwwwseswwnwwwwswww
esweeeeeeneneenwe
eseeseeeeenwswseeseneeseseseswee
neneenewnweneseswnenenwneneenwwseswne
senwwnesenwswnwneeewswnenwnwwnwnwsene
eeeeseeeeeneewwneeweneeenene
nwnenesenwwwseswseswnwwesesenwwnene
swseneswswswswswsewswnwneseswseneeswsesw
nwnwwnwswnwnwwnwnwenenwswwnwnwnwnwenw
seswswseeesesenwnweeseeeneeenewese
nwsenenesenwwnenenwnwneswnenenenenenene
swsewnwwwseswwwsewneneswneenene
nwenenwnwnenwsenwnenwnwswnwnenenenwnenwnw
swwneneneneneenweeeneenesweenesenesw
swnwnwswnwwwswsenewsewswsewswswseswsww
enenenenesenenenenenenenenenenwswnenewne
newewesesewseseseseeeseseeesesese
nenwwwnwsewswwwwewsewwwwwsew
enwewnwwwwnwwnwnwnwnwnwnwwwnwnwswnw
neweeswesweeswewneseewnw
swswswswsewesewswswswswneseswswswseswse
swneeewseneeeeeswneewwneseenwe
wwwwwwwwwneewwsewwwwweww
eeeesweneenweeeneneeweeenee
wnenwneseeenwseeneneewneseswwnene
wwwnwewnwnwnwnwnwewneenwnwnwswswswnw
enenenenwesesewnwneeeswneneeneenenene
nwnewseneseenwwwseswneswseneeeswnew
swsewwsweseswneseseeseswneseneswswse
swswswwswswnewsesesweswswswswseneswnesww
enwwnwwnwwnewnwswswseeswnenwwnwwnwse
sesenwnenwnwnenwnwnwswnwnenwnwnenenwnwnwsw
seeneswswwswwswswwwwswwwswnenesw
swwwwswneseswwwwswwnwswswswswwswsew
swseeenenwnwswenwneneenwnwnenwnwsewsw
wswswswwwswwwswswswneswswswseswswsw
neswnewnenenwnenewenenwneneeenenenw
eswneneneneneenenwneneeeneenenewe
enenenenenenwneneeneeeeeeenese
seeseewswwseseneesenwneseseswsewswsw
ewwewswwswwswswwewwnwswwsww
swwswswswswswswswswswne
nwnenwnenenenwnwnwswnwne
nwnenwnwswnwwewnwnwswnwsenwwnwnwnwnw
nwnwnenwnwnwnwwnwnwnwswnwswnwnwewnwnw
eseneseeswenwneeneneneneewnenwnenene
swwnwwswwswswwswwswswswsewwwwswne
swsewsenenweseesweee
nwnwnwnwsenwnwnwnenenwnewnwnwnenwnwnwnw
nwsweeeseseeeeseeeeseneeswene
neenwneneswnwnesewewswneswnwnwneneswe
esenenwnwnewseneswnwsewswwnwsenwsewswse
nwwwweneeewwwesesenwneneswswswnw
nwnwsenwnewseswnwesenewnenenwnenenenwe
wnwwnwnenwnwsenwnewwnwwsewwnwwwwe
wwwewwswwswwwswwwwswsw
swswwswswseswswswswseswswswswnesw
wwwwwwwwwwswwewwnwwwww
nwnenwnwnwnwnwsenenwnwnwnwnwnw
swnwswswswswwseeeswswswswswswsewnwnwsw
nenwnenwnenewnwnenwnwnenwnwseenenwnenwne
seewseeseeeeseseeeweneseseseese
seenesesesesesesesewseseseseesesesese
nenenenenwneneneenweneneneesenenenesene
swswneneeseswwswnwseswswwswswseswsesw
nwswsenwneenwnwnwnwsenwnwwsenwenewnwsw
nweseseseswswswswswswswswswsw
seseswseseseswsenwseseseseesesesesesese
wwwwwwsenwwnewewnwwsewswnesww
nwseswswnwseswswsewseseeseswswesesesesw
seswseseenwswseseseenwswseswseesewswse
nwwnwnwswnwwnwnwnwnwesenwnwnwwwwnww
neneswseneneneswwnenweneeneneenesenww
swswswswneseswswseswswswwswswsesweswswse
swneswseswswswswswswswswswseswswseseswsene
swswneneswswwneswwwswswswwswnweswsene
nenwnwnwwnwnwnwnwnwnwnwnwnwenwnwnwswnwnw
wwneswwwwwwwwewwwnwwwsewww
neneeswnwneneeneeee
swesweswswnesweswsesewwnenwnwnewnwnee
nwwwwewwwwwwwnwwseswwwswwe
sweenwseeseneweseseeewnwseeseenenw
eeeeeenweseeneeeeeeeenesw
nwnwnwswnwnwnwswnwnwnwnweeenwnwswnenw
eneeneeeeweeeeeneeeeneewsee
swnenwnweneneenwnwnwnwswnwnenenenwnwnwnw
nenwnenwnwnenwnenesenenwnwnwnenw
neeswnweswswseewwnwwweswwwwwne
nwseeeeeeweseeeeseeeeeeee
sweseneneseeseeseeneeeeeewsweew
wnwwnewswwwswwwwewwwwnwww
wswnwsweswwneseswnwswswwseswsweswnwwsw
nweswneeweeeeswsenwew
neeswneneenenweeneneneeneseenesenwe
nwnwnwnwnwnwnwnwnwnwnenenwnwnwnwsenwnwse
seswseseswseseswseseseseswsesenw
nwnenwewnesenwnwnwnwnewnenwnenwne
swswswswesweswswswwswswswswswswwswsw
nwnweeeeeeeeeseeeeeeeese
wswnwnwswswswwwwswswswswswwwseswswse
seneswwseswsesewsenwsenenesenwseseese
neneneswneswenenweeneenenenenwnwswnene
newwwnwwwwnwsewwwwseswwwwse
swsenwenwnwnwnwnewnwswenwwesw
newwnwnwnewsewwswwwwnwnwnwswww
eseswsenenesesenwwseswseseseeseesese
nwwenwenwsenwnewnenenwnwwnweneswnwne
neswneneseswseeseseswswsenesenwswswsww
neneeeswseneswnwnwwenenenwseswwwe
nwswseseseeeseseseseesesesesese
wswwnwswswnenwneswnweswseenwewwwse
swseseswseneswswseswswseseswswnwswseswswsw
sesesenwseswseseseseseeesesesesesesese
nenenenenenenewwneeeneneseneeneneene
wnwswwewswnwnwsenenwesesweeswsene
enenenwneneneeneeeneeseswneenenenene
seenwseseeneeswwneseeeseswwesenww
seseswnwwsewnewswnwseswneswswswesweenw
nenenenenwnwnenenwwnwenwnenw
nwwwwnwneeeeneneneseswsenewesenw
swswswneneseswwwwswswswswswnwswswswsw
nesesenwswswseswnenwsewswseseseseswnese
neeeenenweswenweneneeneeneeeeese
seeweneseeneseseseswseewsenenwe
seseseseseseseseseseseseseseswsenwsw
wswswswswsweswwwwseweswwwswswne
nwseeswneswneswwnenwseswenewseswwsw
neeweenweeeeneeeeeesweeeee
swwswwswwneweswwswswwwswsewwsw
sesweswwswenwweswswesenwnwnwnweswse
nwneenenwnewenesw
wnwseewwenwwwwesewwwnwewwnw
eeeneesenenenweswene
seenwseseseeseseewsweesesesewsese
wswsweswswseseseseseseseseswswsesesenwse
wweeeeeneeseeeeeeeeesese
swseswseseseeswsenenwseswseseseseseswsw
wwwewwwwwnwswwwnwnwnwwwewnw
wwnwnenwseneeswswswewewswswswwenw
neswswswswswseseswseseseseswseesenwswsw
neeswnewnwwswsenwnwnenwnwsenesewene
nenwseeswwswseswsesesweseswswswswseswsw
nwwwwseneneswseseneeseswswnwnwseene
seesesesesenwseweseeseseeseseswseese
ewwwswswwsewnwwwwswnewneeswsw
eeneneneneneneeneenenewnenenenesewne
enweeswnwsweseneeneenwsenewnwswswne
sesenwseewsesenweseeeseseeeseeenee
nwnwnwnenwnwnwswnwnwnwnenwnwenwnenwswnwnwnw
seswnwsenwnenwnwnenwnenwnwnenw
nenwnwnwsenwnwnwnwnwnwnwnesenwswnwnwnwnwne
swnwnenwnenenwnwnwnwnenwweenwwenwnwnwnw
senwnwnwwnwwwwnwwnwnwnwswnenwnwnwnewnw
neswnenwswsesewnwnewsewwnewnesenewnwnw
wwwsenwnewwwwewwnwwwwwsww
enwneeneneswswnesw
enweesesewsenesesw
eeswewneesenenweneneneneneeseee
nwnwseneswnwnwwewwwwsenwwwnwww
swwneswneswwwswsweeswswswwswswseswnw
ewwwwwsewswwwwwwenwwwneww
swneswseeswswswwswnwsewwswswswswwswwsw
sweswwswseneseeewswwnenwnwneewwsw
swwswswseswswswwswswswswswswswwswswne
nwwwswwwwwwswwweweswneswwew
neneneswsenenenwnenenwneswnweweenwsww
senwswnewwseseeseenewseseneeeswene
nenwsewwsenewswseenesewsenenewnwe
swswswswwwwwewswwnewwswwwwww
swsweswsenwnweenenwe
wnwsesesesewseswnesenesenwswsesesesesesese
eeewseeeseeweeeseeewwenee
eeeeeneeeeeeeweseeewwe
neneneneenenwneneneneneneneneneneneswne
seeseeseesesesenweseeeswneenwnwee
seeeseenwswneeeewswewneseeew
nwseenwnwnwnwnwswnwnewwseenwnwnwsenw
esweeeweweneeseeneseee
ewswnwswswwnewswwsweseswweswswww
sweseeneswwwwnwnenwsenwwsweseswe
eweeseseeswnwneneeeneew
swnweseeeeeneweeeeeeweene
wwnwwweswwnenwwnwnwswwwewwsw
neneeeweenewneneeeeneeeneswe
swwwesewnwsenenwnewnwneseenwwswnew
senwnwnenwnwnewnwneneswwneeneneenewse
nwwwnwwwwwnwwwwnwsewnwwwsew
wwwswwswwwswwwwseneneeswwwww
neswswseswswnwseswseseswswwseswsesesesese
nwsewnwnwwnewnwnwnenwneenwnwseneenw
seseseseseseseesenewsesesesenesewsese
newwnwnwnwwnwwwnwsenwnwnwwwsenww
swswenwnewswswswneweweswswswswnwsesese
seeseswseseseseesesesesesewseseswnwse
nenewneneneswnenwsenenenenewneenenenee
sewseneseswneseneseeewswnwswsewswwsw
eeswwswswswswswswswswswsenwswswnwwswsw
seneenwswseseeeneeeeeswswsenewe
nenenwnwnenwenenenwnewnwwsenenenwnwne
nenwenwswenwnenwnwsenwwnwenwnwswnwnw
wwwsenwwswnwwwewenewwwwwnwnw
nwnwnwnesenwnwnwsenwnwnwswnwnwnwnwnwnwnw
swswswswseswsweswswnwswwswseswneswswswwsw
eswnenwneenwewnwnwnww
seseseseeseneseseseseseseweeseseseswnw
enwwnwnwswnwnwnwnwwwnwnwnwwnw
swsewseneswneewwwwnwnwnwnwwseswsesww
nenesenwnenenenenenenenenenewneneswnee
nwweswwsweswswswneswswnwswswswswww
neeneeneneneeneenenenenenenewsenene
nwswswswsweswwswswswwswewwwswswsw
swwswwwwwswwseswswswnwweneswswsw
wswnwneeneswnwwswwnwwsenenewwnwww
nenenenenwwenwnwnenwenenww
seseneseseswwneseeseewseseesesenwse
nwenwsenwnewneswnwnenwnwnwneenwnwnwnenw
nwnwnenwnwnwnwnweswnenwsenenwnwnwnenwnwwne
nwnenwenwswnwenwwswnenwnenwnwnwnwewnee
wwnwenwnwwnwwwnenwnwwnwnwnwesww
neseeneeeneeeeewneneneneeenee
swseseswnwneeseseneswswwswswnwswse
swnwswseswswwswswswneswsw
swwweeeeswnwneneeewnweeeeee
enenwnenwsenwswnwnwnenenwnewnesenwnwsenwnw
swewswwneneseeeenwneenenwnenwseee
seseseseseenwseneseseeseswseeseswnwse
seneeeseseeeseswnwswsesesenwwwseenw
wwnewwwwwwwsenewwwwwwswwnww
nwswwwswswwnwsweswswsweswswsesweswsw
swswnwnwnwnwwenwnwnwenenwnenw
seeseseseseweseseeeseseesee
wnwnwnwsewnwnwnwnw
nwnenenwnwneswnwnwnwnwnwnwnwneenwnwwnw
sweeseneweseneswenwsesenweswsenwnee
wswnwnweseseewenenenwenenesweene
nwnesenwnwseesewneswwnesweswnwnwsenww
sewneswwwnwewnenwnwnwwwswnwwnwswe
eeesweseneeweenweeswenweneewe
neneneeneeeeneneeesweeenwenene
eeneneeeneeeenwneeswweneenenee
sesweeneeseeeweeeenweeeese
swnwswneewwwnwwsewwnwnwwnwnwwenwnw
eeeeesweseeeseswenwnwenwnwee
sewwnewwswwwwswnesewswsw
nesewseewseswsesewwswweseseneswswe
newneenwsewnenenenenenwne
sewsenwseeseesewneswwwnwsenweswnene
swswswwwwwswwwswneww
wnewwwwwwwwwwwwwwwswsw
swwwnewwwwswsenwnwwwnenwseenww
neeenenwweneeneeneneneneneeneneswse
nwsenwnwnwnwnwswwnenenwsewnwswnwenwse
nwesenwnewwnwwwnwwwwnwwswnwnww
neswwsenwswnwwwswswseswswwsw
neneeneswneneneenewnewseenenenenene
seswseswsesesenesesesesesese
wwwnwwwwweswewswnw
seneseswsesewseseneesewwseswwswsenese
enenwnwnwwnwswnwnwnwswnwenwnwswenwnw
neswwsenwswsweneswswnwswseswnesenwnesw
senwwnweswseswneswneewneseesesesesene
nwenwwnesenwnwwswenwnenwswnenwnenwse
weneeseeneeswweswnweswenwewswnw
eswnwewwnwnwswwswwswene
swwnwneseseseneneseswewswwsenewseee
seswwnwwwswseeswwswnwwsewwenene
neeneneneneneenenenenewsenenenwswnene
eesesweeeeeeeneenweeweseww
seswswswnwswswsweswswnwswswswseswswswsesw
nenwnwnwnenenwnwnwnwwnwsenesenwnenwnew
neneswneneneenesenwnenenwnenwwnewnesene
wnwnwewnwwswsenewenenwnwswwwwwwnw
weneswnenwnenwnenenenenwnenesewnwnene
eneneewswneenenwswnenweeeeneesee
neswseseswseswwseseseseswnwnwnwswnwsesw
nenenenenenwenenewnwnwwsenwnenenenene
weseswnewnenwwenwnwnwewnenenwsenw
swenwnewewwwnwneswewwsewnwsewnw
seseseseneswseseswseswseseseseswnesewsesese
nwnwnwnenwnwnwnwnenwnwenwnwnwnwnwnwnwsww
nwesweeeneeeeseeeeeneeeeee
esweseswnenwsenwnw
swneswwswswswewswwnwnewswsenenenwsw
enenwnwswnwnwnwsenenwnwnenenwnwnenwnwsenw
neswneswswswsenwseseneswseseneswseswswse
ewneneenwnenwneneswnwnw
swsenwsenesweswwnwsenesewswswwseswswsesw
swwswwswwwswwswswwswnwswswswe
nwwnewwewwwwswneswwswswseswswsw
seeseswwnesesenwsenwswweseswenwnese
nwnenwneneswswwnenesenenwnenenwnwnenenene
nenwnenwnwswnwnenwnewneneneneneneneenwne
eeeenenenenwneneeeeeeneewsese
neseswsesesesewsenewsesenwseneswnesesw
eswnwswsweeswnwnwnwwswwwswwesesesw
wnwwsenwwwenwswswswsewwenewnwwnw
seweeeeeeeneeeeseenwswnenwee
nwsenwwwwwwwwwwwwnwwwneww
swneswswswswwswsweswwwswnenwwswseswsw
swneeeeeeesweenwneneeeeeee
neewsewswseswswsenwswswneswwswenesw
wnwnwsewwswnwwwwnwnwnwnenw
neseseeseswsesesewswsenwswseseswseswswnw
nwenenwnwnwnwnwnwnwwswnwnwnwnwnwsenwe
neneeewnewnweseenenwswwnesewsee
sesewseswneswswseseswnwswswneswneswswe
seseseswseswsesesesesesesesenesesewsesenwse
enwwwswswwwnwsesewwewwwnwew
nwsenwnweseswnwnenwnwnwnwnwnwwwswnwnw
nwseseeneseesweseseseseseseseeswnwsese
seswswseswneseswswneswswswseswswswswswswnw
swswsenwseswswseswswswseseneseseseswneswsw
seseeseswswswswswseswnwswswnwsweswsesw
wneseswseseneseesenenwwnesewseswswese
neneswnenwnenenenenwneesenwnenenenwnwnene
sweneseweseeeeeseeeeeenweeee
enwnwnwnwnwnewenwsenenenwnenenwnwswne
weeeeneeeseseeeeseseesewewee
wsenwnwsewwwwwwwnwwnwnewnwww
nwnwewnwnewnwsewnwwnwnwnwnwwwwwse
swswswwwwswwswswsewnewwwswwneww
nenwswewwswneswwswswwweswswwww
neneneswenenenwneneweewnwnenenenene
swswseneseseseseswseswsese
nwnesenwnenenewneseswwwnwenenwseene
wsesewseseseseseseesesesesesenesesese
seseweswsesesesesesesese
nwnwnwnenwsenwnwnwneswnenwnenwenwnenwnw
seseswewseneseseseseseseswswsesewnese
seswseswsesenesesesesesenwswseseseswsese
sweenwseeeeeeeeenweeeeeeswe
eenwwnewswsesewewswswseneswnewww
wwwwwwwwwnwwsewww
wnwnenwswenwnwnwnwse
swneseneneswneneesewwnenene
wwswewwwwwwwwnwwnwwwswwswwse
sesesewseeseswsewseswnesesesesesesene
swwwwwwwwwswwwwnewwwsenesw
swswseswswnwswswswseseeswsw
newwswsenwnewwsewseseswenwneeswwnw
nwsweswswswswswswnwswswswseswswswswsesw
nwswneseswseswsenewenewwneseewsenw
sewseneseneseseseseesewseseneswsesesese
wnwnwenwnwnwnwnwnwnwnwsenwnwneswnwnwne
sewneewwsesenwnwnewwswwwwneswwsw
wwwnwsewwwwswwwwwnwwwwwe
ewneenwseneneewswneswneenenwenee
swwswswswswswswneswswseswswweswswswswswsw
nwswnwswnenenwswneneneneeneene
esenenenwneneneswenenewneneneenenenenene
swswsweseewweswwsesw
enwewwnwnwsenwneseswwesewnewenew
eeeseseseeneesweeeeeee
ewenwwwswwseswnwswnwwswsweswwww
wnwweeneenewnenenwnewswneeesew
nenwnenwnenenwswnenwnewnwnenwenwnwnene
neneneseneeeneneesewneneeew
neneneneneneneenenwneneneneswneenesenene
nenwnenenwnwnwenenwnwneneneenewswnenenw
swwwswwwwewswswswwwswnwseneswswww
neenenewneneseneneesenewenenenenwnwnese
wnwwweswswswwswweswswwswwswwwwnw
wswwwewwswwswwwwwwnwwwsw
senwesewenwseseswesesesenwswnwsesee
nwnwnwnwnwneneswnwsenenwnenwsenenwnwnw
seewwwwwnwnwwwwnwneswwwnwswnww
seeweseeeseeeeseneeswseeseene
enesweeweeeneesweneseeeeneee
senwseweswneeesweeneseweeesenesew
swswseswseswswsweneswswswwenwwneswsw
swswswwewnwswswswswewwswswswswswswsw
swswswseswsesewseswseenwseswseswnwnesese
ewswswswswswneswswnwwenwsesenwswwsee
swnenwweesenwswnewneneneswnwnwnwswnenw
nwnwnwnwnenwswnenwnenwenwnwwnwnenenwnwne
neneseenewnenenenewnenenenesenenenenenee
nwnwnwswnenwnwenwsenenwnwnenwnwnenenwnwnene
nenenenenewnenewsenenenenesenenenenene
swswswswseseesesesenwswswsesenwseseseese
neneneweeeenesesewneweneeeneene
wwnwewswsewwnewwnewwwww
seseeeeseeeeeesewseee
senesesesweseswenwnesesweseneeseswe
wweeswswnwswwsesesewesenwseewee
nwwnwwnwnwnwnwwwnwnwswenwwnwnw
wwswnewwwwwwwwwwsewwwww
neneeneneneneneneeneenenesenenenewne
neweseeeeseeeeeeeswseeseesee
nweneneswnwnwnwnenesenesewnwnwneenwnwnw
neneseswnenenwnwswwnwnenwnewseneseneneenw
nenenewesewseweeeswswneswneseee
swswseseeseseeeseesesesenwsesesesenwsese
seneeneenweeneneenesweeewneee
wwwewsenewwswneeneeswseswswenw
nwnwwnewsenewswnesenwwwnwenwwsenwnw
seeenwneewnweswnweewseewseese
sewnwswwwwnewwnewnwwwsewwww
swsenwnwewnwnwnwnwnwnwwnwnw
enwesweeseeneswneeseewsewwnee
wnwweneswswwsenwwwnwwwwnwnwww
wwwswwwwwwnewswwwweswwww
swswnewswswsweswswwwswseswswwwsw
wwwnwwewnwwwwnwwwwnwwwnwsew
nwnwnwnwnwsenwwnwsewnwnwnwnwnwnenwnwnw
nesenweswnenenesenenenwneneeeneenwne
sweeeseeeeesenweseeseseeese
eseswwswseswseswneseseseseseswswseswwswsw
nwenwnwsenwnwnenwnwnwnwnwnwsenwnwnwwne
wewwwwwnewwwwewwnwwswww
wnwwwswswneeswswswswswseseseesenwesw
seweeeenweeeeesweeeeee
nenenenenwsewnenenwneneswnenenenenenenene
neesewneswneeeneneneneeenwwwneene
swseswneswseswwesesweswswswnwseswnwswswe
newnwwwseswswwswwswnwswwwsewswwne
swswswwswswswswswsenwseswnenewswwswsw
neeneenenewneeweeeswneseeeeee
newsewnenwnewsenesewnwee
nwnwswswseseneswswnweseswsenwneseweswsw
seswswwwwwswwneswswwenewswne
eneeenwwnwwwwwswnwnwswnwnwwww
nwnwnwnwnwnwnwwewnwsww
seeswneseseseeseesesesewenwseenwwse
nwnwwswnwwwwewnwnwwwnwnwwewnwew
eeseseseeeseneseeeseseeneseseswwsese
swwswswweswwwnwswneswwswswswwww
wnwswwwwwnwnwwwsenenwewswwwnenw
sewswseseswnwnwsweenweswwseswswswnenwne
wwnwwwnwnwwwwwnenwwnewswnwwnwwse
seweswwneeswsenwswnwwswswswnwseswwsw
nwnenenwnwnwneswnenenenenwenwnenwnenwneswne
sewsenwnenwnwwwnenwnewwsenwwnwwnwse
seseeseseenweneseweseswswswnesesenw
swwneswwwwswwnewwswwseswswwsww
seesweswnwseseseswnwnwswswnwse
eesesweseeeseeeeeeenwsweene
swseswswswseswswswswswswswwswswenwswsesw
swwswswsweswwwnwswswswnwswwsewswsw
nwnwwwnwwnwnwwnwwneenwwwwnwsesee
weeenwseseseseeseenesesee
nwnwwseenwwwwnwwnwwnwnenwsenwnww
eeeeseseeeeswseeseseswneseeseeenw
eeeeeneesweeeesweeenenweeee
eweeseneeseesesenesweeseewsewne
neneneswswenenwwnenewsweneswenwswsenw
wwswnwsewneseswswneesenewswwwsenwsw
seswswsweswnweswesweswswwnwnwsesese
weneeeneeeeewseeeeeeeneee
nwwnewwswwswswswwwswswwewswwwe
seseesewseneeseesesweswsenwwsenwsese
wenwseeswwnwewwneswnwenwwnwnwse
wwwewswwwwwwwewnwwwwwnww
seseswsesweweeesenweeseeeeseesenw
swseneswneseswwswswswswseneseswswswswsesww
esenwseseeeseseseesesesesenwwnwseene
neeneneneeneeenenenwwswe
wnewwswswswwwswswswswsewswwswwsw
eswnwesenesweeeneesweeneseeesw
nenwneneneeswneneneswnwnenene
swswswswswswswneseswswenwwnweswswswsw
eeeeneeeneeewneneeeeeeenwesw
neneeesweseneneenwseenwnee
nwnenenenwswewnwnwnwnwnwnweswseswnenw
wneseseseseseseswseneswseseswsesesesese
wswsweseseswswneswwswneswneswswnwswsw
swnwnweneneswsewnenwnw
nwnwnwnwnewnwnenwnenwnwnwnwnwnesenenesene
nenenenenenwnenenwneenwswnenwsenenenenw
swnwswnweesenwswswswsenwswseseeswswsesw
ewswnwseswsenweenwsenesesewsee
nwnewseewsewnwnwnesewwnwsesenwwswnw
nwnwnenwnenwneneneenwwnenenenwswnwenenw
nwwwswwwwwwnwwwswwenwnwwwe
wnwsenesenwswsewswneswswnwsewswwwwsw

231
d24/main.py Executable file
View File

@ -0,0 +1,231 @@
#! /usr/bin/env python3
from typing import Iterable
from typing import Tuple
from typing import Optional
from expanding import AutoExpanding
from expanding import GridItem
from expanding import Point
from expanding import World
from expanding import add_points
D2P = {
"se": Point(1, -1),
"sw": Point(-1, -1),
"ne": Point(1, 1),
"nw": Point(-1, 1),
"w": Point(-2, 0),
"e": Point(2, 0),
}
def directions_to_point(s: str) -> Point:
point = Point(0, 0)
direction = ""
for c in s:
direction += c
if direction in D2P:
point = add_points(point, D2P[direction])
direction = ""
if direction != "":
raise ValueError("Something left over unexpectedly")
return point
class Tile(GridItem):
def __init__(self, loc: Point, world: World, is_black: bool = False):
# Give this tile a unique id for tracking later
self.is_black = is_black
def _tock():
# print("Default tock")
pass
self.tock = _tock
super().__init__(loc, world)
def flip(self):
self.is_black = not self.is_black
def neighbors(self, expand=False) -> Iterable["Tile"]:
for diff in D2P.values():
neighbor_point = add_points(self._loc, diff)
neighbor = self._world.get_point(neighbor_point, expand=expand)
if neighbor:
yield neighbor
def tick(self):
num_black = count_black(self.neighbors(expand=True))
if self.is_black and (num_black == 0 or num_black > 2):
self.tock = self.flip
if not self.is_black and num_black == 2:
self.tock = self.flip
def count_black(tiles: Iterable[Tile]) -> int:
return sum(map(lambda x: 1 if x.is_black else 0, tiles))
class TileRow(AutoExpanding):
def __init__(self, y: int, world: World):
self._y = y
self._world = world
super().__init__()
def _item_factory(self, x: int) -> GridItem:
return Tile(Point(x, self._y), self._world)
def __repr__(self) -> str:
return "[" + " ".join((str(c) for c in self._l)) + "]"
def to_str(self) -> str:
return "".join((c.to_str() for c in self._l))
class Floor(World):
def __init__(self):
super().__init__()
def _item_factory(self, y: int) -> TileRow:
return TileRow(y, self)
def iter_items(self) -> Iterable[GridItem]:
for r in self:
for t in r:
yield t
def get_point(self, p: Point, expand=True) -> Optional[GridItem]:
try:
return self.get(
p.y,
expand=expand,
).get(
p.x,
expand=expand,
)
except IndexError:
return None
def get_all_bounds(self) -> Tuple[Point, Point]:
min_y, max_y = self.get_bounds()
min_x, max_x = 0, 0
for r in self:
if r.min_index() < min_x:
min_x = r.min_index()
if r.max_index() > max_x:
max_x = r.max_index()
return Point(min_x, min_y, 0), Point(max_x, max_y, 0)
def true_up(self):
min_point, max_point = self.get_all_bounds()
for r in self:
r.resize(min_point.x, max_point.x)
def expand_all(self, i: int):
min_point, max_point = self.get_all_bounds()
min_point = add_points(min_point, Point(-i, -i))
max_point = add_points(max_point, Point(i, i))
self.get_point(min_point, expand=True)
self.get_point(max_point, expand=True)
def tick(self):
for t in self.iter_items():
t.tick()
def tock(self):
for t in self.iter_items():
t.tock()
def sample():
print(directions_to_point("nwwswee"))
seen = {Point(0, 0)}
floor = Floor()
for line in (
"sesenwnenenewseeswwswswwnenewsewsw",
"neeenesenwnwwswnenewnwwsewnenwseswesw",
"seswneswswsenwwnwse",
"nwnwneseeswswnenewneswwnewseswneseene",
"swweswneswnenwsewnwneneseenw",
"eesenwseswswnenwswnwnwsewwnwsene",
"sewnenenenesenwsewnenwwwse",
"wenwwweseeeweswwwnwwe",
"wsweesenenewnwwnwsenewsenwwsesesenwne",
"neeswseenwwswnwswswnw",
"nenwswwsewswnenenewsenwsenwnesesenew",
"enewnwewneswsewnwswenweswnenwsenwsw",
"sweneswneswneneenwnewenewwneswswnese",
"swwesenesewenwneswnwwneseswwne",
"enesenwswwswneneswsenwnewswseenwsese",
"wnwnesenesenenwwnenwsewesewsesesew",
"nenewswnwewswnenesenwnesewesw",
"eneswnwswnwsenenwnwnwwseeswneewsenese",
"neswnwewnwnwseenwseesewsenwsweewe",
"wseweeenwnesenwwwswnew",
):
p = directions_to_point(line)
print(f"Parsed point {p}")
if p in seen:
print("seen!")
seen.add(p)
floor.get_point(p, expand=True).flip()
black = count_black(floor.iter_items())
print("Day 0")
print(f"Number black is {black}")
for day in range(100):
floor.expand_all(1)
floor.true_up()
floor.tick()
floor.tock()
black = count_black(floor.iter_items())
total = sum(map(lambda x: 1, floor.iter_items()))
print(f"Day {day+1}: {black} / {total}")
def part1():
floor = Floor()
with open("input.txt") as f:
for line in f:
line = line.strip()
p = directions_to_point(line)
floor.get_point(p, expand=True).flip()
black = count_black(floor.iter_items())
print(f"Number black is {black}")
def part2():
floor = Floor()
with open("input.txt") as f:
for line in f:
line = line.strip()
p = directions_to_point(line)
floor.get_point(p, expand=True).flip()
black = count_black(floor.iter_items())
print("Day 0")
print(f"Number black is {black}")
for day in range(1, 11):
floor.tick()
floor.tock()
black = count_black(floor.iter_items())
print(f"Day {day}: {black}")
if __name__ == "__main__":
sample()
# part1()
# part2()

136
d24/main2.py Executable file
View File

@ -0,0 +1,136 @@
#! /usr/bin/env python3
from typing import Iterable
# from typing import Tuple
from typing import Set
from typing import Dict
# from typing import Optional
import itertools
from collections import Counter
from collections import namedtuple
Point = namedtuple("Point", "x y")
D2P = {
"se": Point(1, -1),
"sw": Point(-1, -1),
"ne": Point(1, 1),
"nw": Point(-1, 1),
"w": Point(-2, 0),
"e": Point(2, 0),
}
def directions_to_point(s: str) -> Point:
point = Point(0, 0)
direction = ""
for c in s:
direction += c
if direction in D2P:
point = add_points(point, D2P[direction])
direction = ""
if direction != "":
raise ValueError("Something left over unexpectedly")
return point
def add_points(p1, p2) -> Point:
return Point(
p1.x + p2.x,
p1.y + p2.y,
)
def neighbors(point: Point) -> Iterable[Point]:
for diff in D2P.values():
yield add_points(point, diff)
def neighbor_counts(points: Set[Point]) -> Dict[Point, int]:
# return {
# p: sum(map(lambda x: 1 if x in points else 0, neighbors(p)))
# for p in points
# }
return Counter(itertools.chain.from_iterable(map(neighbors, points)))
def next_generation(points: Set[Point]):
counts = neighbor_counts(points)
return (
{p for p in points if counts[p] in (1, 2)} |
{p for p in counts if p not in points and counts[p] == 2}
)
def point_deltas() -> Iterable[Point]:
return D2P.values()
def life(points: Set[Point], n: int) -> Set[Point]:
for r in range(n):
points = next_generation(points)
return points
def sample():
black: Set[Point] = set()
for line in (
"sesenwnenenewseeswwswswwnenewsewsw",
"neeenesenwnwwswnenewnwwsewnenwseswesw",
"seswneswswsenwwnwse",
"nwnwneseeswswnenewneswwnewseswneseene",
"swweswneswnenwsewnwneneseenw",
"eesenwseswswnenwswnwnwsewwnwsene",
"sewnenenenesenwsewnenwwwse",
"wenwwweseeeweswwwnwwe",
"wsweesenenewnwwnwsenewsenwwsesesenwne",
"neeswseenwwswnwswswnw",
"nenwswwsewswnenenewsenwsenwnesesenew",
"enewnwewneswsewnwswenweswnenwsenwsw",
"sweneswneswneneenwnewenewwneswswnese",
"swwesenesewenwneswnwwneseswwne",
"enesenwswwswneneswsenwnewswseenwsese",
"wnwnesenesenenwwnenwsewesewsesesew",
"nenewswnwewswnenesenwnesewesw",
"eneswnwswnwsenenwnwnwwseeswneewsenese",
"neswnwewnwnwseenwseesewsenwsweewe",
"wseweeenwnesenwwwswnew",
):
p = directions_to_point(line)
if p in black:
black.remove(p)
else:
black.add(p)
print(f"Num black is {len(black)}")
rounds = 100
black = life(black, rounds)
print(f"Num black after {rounds} is {len(black)}")
def part2():
black: Set[Point] = set()
with open("input.txt") as f:
for line in f:
line = line.strip()
p = directions_to_point(line)
if p in black:
black.remove(p)
else:
black.add(p)
print(f"Num black is {len(black)}")
rounds = 100
black = life(black, rounds)
print(f"Num black after {rounds} is {len(black)}")
if __name__ == "__main__":
# sample()
part2()

14
main.go Normal file
View File

@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
wm := NewLinkedGrid(5, 5)
wm.Print()
a := []int{1, 2, 3, 4}
_ = MapInt(a, func(v int) (int, error) { return v * 2, nil })
fmt.Println(a)
r, _ := ReduceInt(a, 0, func(t, v int) (int, error) { return t + v, nil })
fmt.Println(r)
}

300
util.go Normal file
View File

@ -0,0 +1,300 @@
package main
import (
"bufio"
"errors"
"fmt"
"math"
"os"
)
var (
errItemAlreadySet = errors.New("cannot set item in direction as one is already set")
)
// ProcessLines maps a function on lines parsed from a file.
func ProcessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
// ProcessGroups maps a function on groups of lines parsed from a file separated by some string.
func ProcessGroups(path, separator string, f func([]string) (stop bool, err error)) error {
group := []string{}
if err := ProcessLines(path, func(line string) (stop bool, err error) {
if line == separator {
stop, err = f(group)
if stop || err != nil {
return
}
group = []string{}
} else {
group = append(group, line)
}
return
}); err != nil {
return err
}
_, err := f(group)
return err
}
// StringSet is a set of strings..
type StringSet map[string]bool
// Add an item to a StringSet.
func (s *StringSet) Add(v string) {
(*s)[v] = true
}
// AddAll adds all items in a list to the set.
func (s *StringSet) AddAll(l []string) {
for _, v := range l {
s.Add(v)
}
}
// Items returns all values in the set as a list.
func (s StringSet) Items() []string {
values := []string{}
for k := range s {
values = append(values, k)
}
return values
}
// NewStringSet creates an empty string set.
func NewStringSet(values []string) StringSet {
v := StringSet{}
v.AddAll(values)
return v
}
// Union returns the union of two SringSets.
func Union(s1, s2 StringSet) StringSet {
union := NewStringSet(s1.Items())
union.AddAll(s2.Items())
return union
}
// Intersection returns the union of two SringSets.
func Intersection(s1, s2 StringSet) StringSet {
intersect := StringSet{}
for v := range s1 {
if _, ok := s2[v]; ok {
intersect.Add(v)
}
}
return intersect
}
// Difference returns the value of s1 with values of s2 removed.
func Difference(s1, s2 StringSet) StringSet {
difference := StringSet{}
for v := range s1 {
if _, ok := s2[v]; !ok {
difference.Add(v)
}
}
return difference
}
// Point represents a point on a coordinate system.
type Point struct {
x, y int
}
// AddPoints adds two points together.
func AddPoints(p1, p2 Point) Point {
return Point{
p1.x + p2.x,
p1.y + p2.y,
}
}
// PowInt is equivalent to math.Pow but for integers.
func PowInt(x, y int) int {
return int(math.Pow(float64(x), float64(y)))
}
// LinkedGridItem is a single item in a linked grid.
type LinkedGridItem struct {
location Point
left, right, up, down *LinkedGridItem
grid *LinkedGrid
}
func (item LinkedGridItem) String() string {
return fmt.Sprintf("%v", item.location)
}
// Location of the item.
func (item LinkedGridItem) Location() Point {
return item.location
}
// Left gives a pointer to the item on the left.
func (item LinkedGridItem) Left() *LinkedGridItem {
return item.left
}
// Up gives a pointer to the item above.
func (item LinkedGridItem) Up() *LinkedGridItem {
return item.up
}
// Right gives a pointer to the item on the right.
func (item LinkedGridItem) Right() *LinkedGridItem {
return item.right
}
// Down gives a pointer to the item below.
func (item LinkedGridItem) Down() *LinkedGridItem {
return item.down
}
// SetLeft gives a pointer to the item on the left.
func (item *LinkedGridItem) SetLeft(other *LinkedGridItem) error {
if item.left != nil || other.right != nil {
return errItemAlreadySet
}
item.left = other
other.right = item
return nil
}
// SetUp gives a pointer to the item on the up.
func (item *LinkedGridItem) SetUp(other *LinkedGridItem) error {
if item.up != nil || other.down != nil {
return errItemAlreadySet
}
item.up = other
other.down = item
return nil
}
// SetRight gives a pointer to the item on the right.
func (item *LinkedGridItem) SetRight(other *LinkedGridItem) error {
if item.right != nil || other.left != nil {
return errItemAlreadySet
}
item.right = other
other.left = item
return nil
}
// SetDown gives a pointer to the item on the down.
func (item *LinkedGridItem) SetDown(other *LinkedGridItem) error {
if item.down != nil || other.up != nil {
return errItemAlreadySet
}
item.down = other
other.up = item
return nil
}
// LinkedGrid is a 2d array of grid square.
type LinkedGrid [][]*LinkedGridItem
// Print a linked grid.
func (grid LinkedGrid) Print() {
for _, row := range grid {
for _, item := range row {
fmt.Print(item.String())
}
fmt.Print("\n")
}
}
// NewLinkedGrid initializes a new linked grid of a given size.
func NewLinkedGrid(width, height int) *LinkedGrid {
var w = make(LinkedGrid, height)
for y := 0; y < height; y++ {
w[y] = make([]*LinkedGridItem, width)
for x := 0; x < height; x++ {
item := LinkedGridItem{location: Point{x, y}}
if x != 0 {
_ = item.SetLeft(w[y][x-1])
}
if y != 0 {
_ = item.SetUp(w[y-1][x])
}
w[y][x] = &item
}
}
return &w
}
// MapInt maps a function onto a list of ints.
func MapInt(a []int, f func(int) (int, error)) error {
var err error
for i, v := range a {
a[i], err = f(v)
if err != nil {
return err
}
}
return nil
}
// ReduceInt maps a function onto a list of ints.
func ReduceInt(a []int, start int, f func(int, int) (int, error)) (int, error) {
var err error
result := start
for _, v := range a {
result, err = f(result, v)
if err != nil {
return 0, err
}
}
return result, nil
}