├── 2019 ├── 1 │ ├── Makefile │ ├── aoc1.go │ ├── day.mk │ └── sample.txt ├── 2 │ ├── Makefile │ ├── aoc2.go │ ├── day.mk │ └── sample.txt ├── 5 │ ├── Makefile │ ├── aoc5.go │ ├── day.mk │ └── sample.txt ├── 7 │ ├── Makefile │ ├── aoc7.go │ └── day.mk ├── 9 │ ├── Makefile │ ├── aoc9.go │ ├── day.mk │ └── sample.txt ├── 11 │ ├── Makefile │ ├── aoc11.go │ ├── day.mk │ └── sample.txt ├── 13 │ ├── Makefile │ ├── aoc13.go │ ├── day.mk │ └── sample.txt ├── 15 │ ├── Makefile │ ├── aoc15.go │ ├── day.mk │ └── sample.txt ├── 17 │ ├── Makefile │ ├── aoc17.go │ ├── day.mk │ └── sample.txt ├── 19 │ ├── Makefile │ ├── aoc19.go │ └── day.mk ├── 21 │ ├── Makefile │ ├── aoc21.go │ └── day.mk ├── 23 │ ├── Makefile │ ├── aoc23.go │ └── day.mk ├── 25 │ ├── Makefile │ ├── aoc25.go │ ├── day.mk │ └── intcode.go ├── Makefile ├── README.md ├── bench.sh ├── day.mk ├── download │ ├── go.mod │ └── main.go ├── header │ └── main.go ├── runtime.sh └── runtime │ ├── go.mod │ └── main.go ├── 2021 ├── 1 │ ├── Makefile │ └── aoc1.go ├── 2 │ ├── Makefile │ └── aoc2.go ├── 3 │ ├── Makefile │ ├── aoc3.go │ └── sample.txt ├── 4 │ ├── Makefile │ ├── aoc4.go │ └── sample.txt ├── 5 │ ├── Makefile │ ├── aoc5.go │ └── sample.txt ├── 6 │ ├── Makefile │ ├── aoc6.go │ ├── aoc6.py │ └── sample.txt ├── 7 │ ├── Makefile │ ├── aoc7.go │ ├── aoc7.py │ └── sample.txt ├── 8 │ ├── Makefile │ ├── aoc8.go │ └── sample.txt ├── 9 │ ├── Makefile │ ├── aoc9.2.py │ ├── aoc9.go │ └── sample.txt ├── 10 │ ├── Makefile │ ├── aoc10.go │ └── sample.txt ├── 11 │ ├── Makefile │ ├── aoc11.go │ └── sample.txt ├── 12 │ ├── Makefile │ ├── aoc12.go │ ├── sample1.txt │ ├── sample2.txt │ └── sample3.txt ├── 13 │ ├── Makefile │ ├── aoc13.go │ └── sample.txt ├── 14 │ ├── Makefile │ ├── aoc14.go │ └── sample.txt ├── 15 │ ├── Makefile │ ├── aoc15.go │ └── sample.txt ├── 16 │ ├── Makefile │ ├── aoc16.go │ ├── go.mod │ ├── go.sum │ ├── sample1.txt │ ├── sample2.txt │ ├── sample3.txt │ └── sample4.txt ├── 17 │ ├── Makefile │ └── aoc17.go ├── 18 │ ├── Makefile │ ├── aoc18.go │ └── sample.txt ├── 19 │ ├── Makefile │ ├── aoc19.go │ └── sample.txt ├── 20 │ ├── Makefile │ ├── aoc20.go │ └── sample.txt ├── 21 │ ├── Makefile │ ├── aoc21.go │ └── sample.txt ├── 22 │ ├── Makefile │ ├── aoc22.go │ ├── rsc │ │ ├── rsc22.go │ │ └── time.md.sav │ └── sample.txt ├── 23 │ ├── Makefile │ ├── aoc23.go │ ├── aoc23_test.go │ ├── go.mod │ ├── pprof001.jpg │ └── pprof001.svg ├── 24 │ ├── 0trace.txt │ ├── 1flow.txt │ ├── 2crack.txt │ ├── Makefile │ ├── aoc24.go │ ├── aoc24.py │ └── rsc │ │ └── aoc24.go ├── 25 │ ├── Makefile │ ├── aoc25.go │ └── sample.txt ├── FR_README.md ├── Makefile ├── README.md ├── bench.sh ├── day.mk ├── download │ ├── go.mod │ └── main.go ├── header │ └── main.go ├── runtime.sh └── runtime │ ├── go.mod │ └── main.go ├── 2022 ├── 1 │ ├── Makefile │ └── aoc1.go ├── 2 │ ├── Makefile │ ├── aoc2.go │ └── sample.txt ├── 3 │ ├── Makefile │ ├── aoc3.go │ └── sample.txt ├── 4 │ ├── Makefile │ ├── aoc4.go │ └── sample.txt ├── 5 │ ├── Makefile │ └── aoc5.go ├── 6 │ ├── Makefile │ ├── aoc6.go │ └── sample.txt ├── 7 │ ├── Makefile │ ├── aoc7.go │ └── sample.txt ├── 8 │ ├── Makefile │ ├── aoc8.go │ └── sample.txt ├── 9 │ ├── Makefile │ ├── aoc9.go │ └── sample.txt ├── 10 │ ├── Makefile │ ├── aoc10.go │ └── sample.txt ├── 11 │ ├── Makefile │ ├── aoc11.go │ └── sample.txt ├── 12 │ ├── Makefile │ ├── aoc12.go │ └── sample.txt ├── 13 │ ├── Makefile │ ├── aoc13.go │ └── sample.txt ├── 14 │ ├── Makefile │ ├── aoc14.go │ └── sample.txt ├── 15 │ ├── Makefile │ ├── aoc15.go │ └── sample.txt ├── 16 │ ├── Makefile │ ├── aoc16.go │ └── sample.txt ├── 17 │ ├── Makefile │ ├── aoc17.go │ └── sample.txt ├── 18 │ ├── Makefile │ ├── aoc18.go │ └── sample.txt ├── 19 │ ├── Makefile │ ├── aoc19.go │ └── sample.txt ├── 20 │ ├── Makefile │ ├── aoc20.go │ └── sample.txt ├── 21 │ ├── Makefile │ ├── aoc21.go │ └── sample.txt ├── 22 │ ├── Makefile │ ├── aoc22.go │ └── sample.txt ├── 23 │ ├── Makefile │ ├── aoc23.go │ └── sample.txt ├── 24 │ ├── Makefile │ ├── aoc24.go │ └── sample.txt ├── 25 │ ├── Makefile │ ├── aoc25.go │ └── sample.txt ├── Makefile ├── README.md ├── bench.sh ├── day.mk ├── download │ ├── go.mod │ └── main.go ├── header │ └── main.go ├── runtime.sh └── runtime │ ├── go.mod │ └── main.go ├── 2023 ├── 1 │ ├── Makefile │ ├── aoc1.go │ └── sample.txt ├── 2 │ ├── Makefile │ ├── aoc2.go │ └── sample.txt ├── 3 │ ├── Makefile │ ├── aoc3.go │ └── sample.txt ├── 4 │ ├── Makefile │ ├── aoc4.go │ └── sample.txt ├── 5 │ ├── Makefile │ ├── aoc5.go │ └── sample.txt ├── 6 │ ├── Makefile │ ├── aoc6.go │ └── sample.txt ├── 7 │ ├── Makefile │ ├── aoc7.go │ └── sample.txt ├── 8 │ ├── Makefile │ └── aoc8.go ├── 9 │ ├── Makefile │ ├── aoc9.go │ └── sample.txt ├── 10 │ ├── Makefile │ ├── aoc10.go │ └── sample.txt ├── 11 │ ├── Makefile │ ├── aoc11.go │ └── sample.txt ├── 12 │ ├── Makefile │ ├── aoc12.go │ └── sample.txt ├── 13 │ ├── Makefile │ ├── aoc13.go │ ├── fastpal.py │ ├── sample.txt │ ├── sample1.txt │ ├── sample2.txt │ ├── sample4.txt │ ├── sample5.txt │ └── sample6.txt ├── 14 │ ├── Makefile │ ├── aoc14.go │ └── sample.txt ├── 15 │ ├── Makefile │ ├── aoc15.go │ └── sample.txt ├── 16 │ ├── Makefile │ ├── aoc16.go │ └── sample.txt ├── 17 │ ├── Makefile │ ├── aoc17.go │ ├── sample.txt │ └── sample1.txt ├── 18 │ ├── Makefile │ ├── aoc18.go │ └── sample.txt ├── 19 │ ├── Makefile │ ├── aoc19.go │ └── sample.txt ├── 20 │ ├── Makefile │ ├── aoc20.go │ └── sample.txt ├── 21 │ ├── Makefile │ ├── aoc21.go │ └── sample.txt ├── 22 │ ├── Makefile │ ├── aoc22.go │ └── sample.txt ├── 23 │ ├── Makefile │ ├── aoc23.go │ └── sample.txt ├── 24 │ ├── Makefile │ └── aoc24.go ├── 25 │ ├── Makefile │ └── aoc25.go ├── Makefile ├── README.md ├── bench.sh ├── day.mk ├── download │ ├── go.mod │ └── main.go ├── header │ └── main.go ├── runtime.sh └── runtime │ ├── go.mod │ └── main.go ├── 2024 ├── 1 │ ├── Makefile │ ├── aoc1.go │ ├── day.mk │ ├── sample.txt │ └── stats.sh ├── 2 │ ├── Makefile │ ├── aoc2.go │ ├── day.mk │ └── sample.txt ├── 3 │ ├── Makefile │ ├── aoc3.go │ ├── day.mk │ └── sample.txt ├── 4 │ ├── Makefile │ ├── aoc4.go │ ├── day.mk │ └── sample.txt ├── 5 │ ├── Makefile │ ├── aoc5.go │ ├── day.mk │ └── sample.txt ├── 6 │ ├── Makefile │ ├── aoc6.go │ ├── day.mk │ └── sample.txt ├── 7 │ ├── Makefile │ ├── aoc7.go │ ├── day.mk │ └── sample.txt ├── 8 │ ├── Makefile │ ├── aoc8.go │ ├── day.mk │ └── sample.txt ├── 9 │ ├── Makefile │ ├── aoc9.go │ ├── day.mk │ └── sample.txt ├── 10 │ ├── Makefile │ ├── aoc10.go │ ├── day.mk │ └── sample.txt ├── 11 │ ├── Makefile │ ├── aoc11.go │ ├── day.mk │ └── sample.txt ├── 12 │ ├── Makefile │ ├── aoc12.go │ ├── day.mk │ └── sample.txt ├── 13 │ ├── Makefile │ ├── aoc13.go │ ├── day.mk │ └── sample.txt ├── 14 │ ├── Makefile │ ├── aoc14.go │ ├── day.mk │ └── sample.txt ├── 15 │ ├── Makefile │ ├── aoc15.go │ ├── day.mk │ ├── sample.txt │ ├── sample1.txt │ ├── sample2.txt │ └── sample3.txt ├── 16 │ ├── Makefile │ ├── aoc16.go │ ├── day.mk │ └── sample.txt ├── 17 │ ├── Makefile │ ├── aoc17.go │ ├── day.mk │ └── sample.txt ├── 18 │ ├── Makefile │ ├── aoc18.go │ ├── day.mk │ └── sample.txt ├── 19 │ ├── Makefile │ ├── aoc19.go │ ├── day.mk │ └── sample.txt ├── 20 │ ├── Makefile │ ├── aoc20.go │ ├── day.mk │ └── sample.txt ├── 21 │ ├── Makefile │ ├── aoc21.go │ ├── day.mk │ └── sample.txt ├── 22 │ ├── Makefile │ ├── aoc22.go │ ├── day.mk │ ├── sample.txt │ └── stats │ │ └── stats.go ├── 23 │ ├── Makefile │ ├── aoc23.go │ ├── day.mk │ └── sample.txt ├── 24 │ ├── Makefile │ ├── aoc24.go │ ├── day.mk │ └── sample.txt ├── 25 │ ├── Makefile │ ├── aoc25.go │ ├── day.mk │ └── sample.txt ├── Makefile ├── README.md ├── bench.sh ├── day.mk ├── download │ ├── go.mod │ └── main.go ├── header │ └── main.go ├── images │ ├── aoc14-6516.png │ ├── aoc18.png │ ├── aoc19.svg │ ├── aoc19a.svg │ ├── aoc2024.png │ ├── aoc22.jpg │ ├── aoc23a.png │ ├── aoc23b.png │ └── aocjack.jpg ├── runtime.sh └── runtime │ ├── go.mod │ └── main.go ├── .gitignore ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | # AoC asks to not publish inputs 18 | input*.txt 19 | output.txt 20 | time.md 21 | runtime.md 22 | -------------------------------------------------------------------------------- /2019/1/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/1/aoc1.go: -------------------------------------------------------------------------------- 1 | // aoc1.go -- 2 | // advent of code 2019 day 1 3 | // 4 | // https://adventofcode.com/2019/day/1 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-1: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | func main() { 20 | Σ1, Σ2 := 0, 0 21 | 22 | f := func(x int) int { return x/3 - 2 } 23 | 24 | // fofo...f(x) reapeatedly apply f to x while x > 0 25 | fofo := func(x int) (Σ int) { 26 | for x > 0 { 27 | Σ, x = Σ+x, f(x) 28 | } 29 | return 30 | } 31 | 32 | input := bufio.NewScanner(os.Stdin) 33 | for input.Scan() { 34 | x := atoi(input.Text()) 35 | Σ1 += f(x) 36 | Σ2 += fofo(f(x)) 37 | } 38 | fmt.Println(Σ1, Σ2) // part 1 & 2 39 | } 40 | 41 | // strconv.Atoi simplified core loop 42 | // s is ^\d+$ 43 | func atoi(s string) (n int) { 44 | for i := range s { 45 | n = 10*n + int(s[i]-'0') 46 | } 47 | return 48 | } 49 | -------------------------------------------------------------------------------- /2019/1/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/1/sample.txt: -------------------------------------------------------------------------------- 1 | 12 2 | 14 3 | 1969 4 | 100756 -------------------------------------------------------------------------------- /2019/11/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/11/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/11/sample.txt: -------------------------------------------------------------------------------- 1 | 104,1125899906842624,99 -------------------------------------------------------------------------------- /2019/13/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/13/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/13/sample.txt: -------------------------------------------------------------------------------- 1 | 104,1125899906842624,99 -------------------------------------------------------------------------------- /2019/15/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/15/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/15/sample.txt: -------------------------------------------------------------------------------- 1 | 104,1125899906842624,99 -------------------------------------------------------------------------------- /2019/17/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/17/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/17/sample.txt: -------------------------------------------------------------------------------- 1 | 104,1125899906842624,99 -------------------------------------------------------------------------------- /2019/19/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/19/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/2/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/2/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/2/sample.txt: -------------------------------------------------------------------------------- 1 | 1,9,10,3,2,3,11,0,99,30,40,50 2 | 1,0,0,0,99 3 | 2,3,0,3,99 4 | 2,4,4,5,99,0 5 | 1,1,1,4,99,5,6,0,99 -------------------------------------------------------------------------------- /2019/21/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/21/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/23/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/23/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/25/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/25/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/5/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/5/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/5/sample.txt: -------------------------------------------------------------------------------- 1 | 3,7,1,7,6,1,99,0 -------------------------------------------------------------------------------- /2019/7/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/7/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/9/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2019/9/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/9/sample.txt: -------------------------------------------------------------------------------- 1 | 104,1125899906842624,99 -------------------------------------------------------------------------------- /2019/Makefile: -------------------------------------------------------------------------------- 1 | GO = go build 2 | 3 | TARGETS := bench binrun build check clean header run 4 | 5 | SUBDIRS := $(wildcard */.) 6 | SUBDIRS := $(filter-out download/. header/. runtime/., images/., $(SUBDIRS)) 7 | 8 | $(TARGETS): $(SUBDIRS) 9 | $(SUBDIRS): 10 | @$(MAKE) -C $@ $(MAKECMDGOALS) 11 | 12 | cyclo: 13 | @gocyclo -ignore "download|images|header|runtime" -top 10 -avg . 14 | 15 | lines: 16 | @find . -name '*go' \( -not -iname "main.go" \) | grep -v 'v1' | xargs wc -l | sort 17 | 18 | runtime: 19 | @./runtime.sh | sort -n -k 4 > runtime.md 20 | 21 | .PHONY: $(TARGETS) $(SUBDIRS) cyclo lines runtime 22 | -------------------------------------------------------------------------------- /2019/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | hyperfine --warmup 100 "cat input.txt > /dev/null" "./${1} < input.txt" --export-markdown time.md 4 | -------------------------------------------------------------------------------- /2019/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2019/download/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/download 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2019/download/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "os" 11 | "path" 12 | "strconv" 13 | ) 14 | 15 | const ( 16 | OUT = "input.txt" 17 | URL = "https://adventofcode.com/%d/day/%d/input" 18 | ) 19 | 20 | var client http.Client 21 | 22 | func main() { 23 | if _, err := os.Stat(OUT); !errors.Is(err, os.ErrNotExist) { 24 | log.Printf("input file %s already exists", OUT) 25 | os.Exit(0) 26 | } 27 | 28 | session := os.Getenv("SESSION") 29 | if len(session) == 0 { 30 | log.Println("$SESSION not set") 31 | os.Exit(0) 32 | } 33 | 34 | pwd, err := os.Getwd() 35 | if err != nil { 36 | log.Fatalf("error finding out pwd: %s", err.Error()) 37 | } 38 | pwd = path.Clean(pwd) 39 | 40 | day, err := strconv.ParseInt(path.Base(pwd), 10, 0) 41 | if err != nil { 42 | log.Fatalf("error computing day from pwd: %s", err.Error()) 43 | } 44 | 45 | year, err := strconv.ParseInt(path.Base(path.Dir(pwd)), 10, 0) 46 | if err != nil { 47 | log.Fatalf("error computing year from pwd: %s", err.Error()) 48 | } 49 | 50 | url := fmt.Sprintf(URL, year, day) 51 | log.Printf("downloading from %s in session %s...", url, session[:6]) 52 | 53 | jar, err := cookiejar.New(nil) 54 | if err != nil { 55 | log.Fatalf("error creating cookie jar: %s\n", err.Error()) 56 | } 57 | client = http.Client{ 58 | Jar: jar, 59 | } 60 | 61 | if err := downloadInputFile(OUT, url, session); err != nil { 62 | log.Fatalf("error downloading input file: %s", err.Error()) 63 | } 64 | } 65 | 66 | func downloadInputFile(filepath string, url string, session string) error { 67 | cookie := &http.Cookie{ 68 | Name: "session", 69 | Value: session, 70 | MaxAge: 300, 71 | } 72 | 73 | req, err := http.NewRequest("GET", url, nil) 74 | if err != nil { 75 | return fmt.Errorf("error building GET request: %w", err) 76 | } 77 | 78 | req.AddCookie(cookie) 79 | resp, err := client.Do(req) 80 | if err != nil { 81 | return fmt.Errorf("error making request: %w", err) 82 | } 83 | defer resp.Body.Close() 84 | 85 | out, err := os.Create(filepath) 86 | if err != nil { 87 | return fmt.Errorf("error creating file: %w", err) 88 | } 89 | defer out.Close() 90 | 91 | _, err = io.Copy(out, resp.Body) 92 | if err != nil { 93 | return fmt.Errorf("error while copying data: %w", err) 94 | } 95 | 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /2019/runtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #shellcheck disable=SC2046 # cmdline must split 4 | go run ./runtime/main.go $(find . -name time.md) 5 | -------------------------------------------------------------------------------- /2019/runtime/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/runtime 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2019/runtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | var runtime float64 14 | fmt.Println("| day | time |") 15 | fmt.Println("|-----|-----:|") 16 | for _, f := range os.Args[1:] { 17 | fd, err := os.Open(f) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | input := bufio.NewScanner(fd) 23 | times := make([]float64, 0, 2) 24 | for input.Scan() { 25 | line := input.Text() 26 | line = strings.Replace(line, "\\|", "", 1) 27 | if strings.Contains(line, "input.txt") { 28 | args := strings.Fields(strings.Split(line, "|")[3]) 29 | f, _ := strconv.ParseFloat(args[0], 64) 30 | times = append(times, f) 31 | } 32 | } 33 | fd.Close() 34 | labels := strings.Split(f, "/") 35 | label := labels[len(labels)-2] 36 | 37 | time := times[1] - times[0] 38 | if time < 0 { 39 | time = 0 40 | } 41 | fmt.Printf("| %s | %.1f |\n", label, time) 42 | runtime += time 43 | } 44 | fmt.Printf("| total | %.1f |\n", runtime) 45 | } 46 | -------------------------------------------------------------------------------- /2021/1/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/1/aoc1.go: -------------------------------------------------------------------------------- 1 | // aoc1.go -- 2 | // advent of code 2021 day 1 3 | // 4 | // https://adventofcode.com/2021/day/1 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-1: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strconv" 18 | ) 19 | 20 | // MaxInt is defined in the idiomatic way 21 | const MaxInt = int(^uint(0) >> 1) 22 | 23 | func main() { 24 | old1, old2, old3 := MaxInt, MaxInt, MaxInt // 3 last depths window 25 | 26 | n1, n2 := 0, 0 27 | input := bufio.NewScanner(os.Stdin) 28 | for input.Scan() { 29 | cur, _ := strconv.Atoi(input.Text()) 30 | if old1 < cur { // increase! 31 | n1++ 32 | } 33 | if old3 < cur { // increase! 34 | n2++ 35 | } 36 | old1, old2, old3 = cur, old1, old2 // shift/update window 37 | } 38 | fmt.Println(n1) // part1 39 | fmt.Println(n2) // part2 40 | } 41 | 42 | func atoi(s string) (n int) { 43 | n, _ = strconv.Atoi(s) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /2021/10/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/10/aoc10.go: -------------------------------------------------------------------------------- 1 | // aoc10.go -- 2 | // advent of code 2021 day 10 3 | // 4 | // https://adventofcode.com/2021/day/10 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-10: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "sort" 18 | ) 19 | 20 | func main() { 21 | stack := make([]byte, 0, 128) 22 | 23 | empty := func() bool { 24 | return len(stack) == 0 25 | } 26 | 27 | push := func(b byte) { 28 | stack = append(stack, b) 29 | } 30 | 31 | pop := func() byte { 32 | if i := len(stack) - 1; i >= 0 { 33 | pop := stack[i] 34 | stack, stack[i] = stack[:i], 0 35 | return pop 36 | } 37 | return 0 38 | } 39 | 40 | closing := [128]byte{ 41 | '(': ')', '[': ']', '{': '}', '<': '>', 42 | } 43 | scales := [...][128]int64{ 44 | 1: {')': 3, ']': 57, '}': 1197, '>': 25137}, // for part1 45 | 2: {')': 1, ']': 2, '}': 3, '>': 4}, // for part2 46 | } 47 | 48 | scores := make([]int64, 0, 128) 49 | sum, input := int64(0), bufio.NewScanner(os.Stdin) 50 | SCAN: 51 | for input.Scan() { 52 | stack = stack[:0] // reset 53 | for _, b := range input.Bytes() { 54 | if v := closing[b]; v > 0 { 55 | push(v) 56 | } else if a := pop(); a != b { // discard corrupted 57 | sum += scales[1][b] 58 | continue SCAN 59 | } 60 | } 61 | 62 | var n int64 63 | for !empty() { 64 | n = 5*n + scales[2][pop()] 65 | } 66 | if n > 0 { 67 | scores = append(scores, n) 68 | } 69 | } 70 | 71 | fmt.Println(sum) // part1 72 | 73 | sort.Slice(scores, func(i, j int) bool { return scores[i] < scores[j] }) 74 | fmt.Println(scores[len(scores)/2]) // median, part2 75 | } 76 | -------------------------------------------------------------------------------- /2021/10/sample.txt: -------------------------------------------------------------------------------- 1 | [({(<(())[]>[[{[]{<()<>> 2 | [(()[<>])]({[<{<<[]>>( 3 | {([(<{}[<>[]}>{[]{[(<()> 4 | (((({<>}<{<{<>}{[]{[]{} 5 | [[<[([]))<([[{}[[()]]] 6 | [{[{({}]{}}([{[{{{}}([] 7 | {<[[]]>}<{[{[{[]{()[[[] 8 | [<(<(<(<{}))><([]([]() 9 | <{([([[(<>()){}]>(<<{{ 10 | <{([{{}}[<[[[<>{}]]]>[]] 11 | -------------------------------------------------------------------------------- /2021/11/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/11/sample.txt: -------------------------------------------------------------------------------- 1 | 5483143223 2 | 2745854711 3 | 5264556173 4 | 6141336146 5 | 6357385478 6 | 4167524645 7 | 2176841721 8 | 6882881134 9 | 4846848554 10 | 5283751526 11 | -------------------------------------------------------------------------------- /2021/12/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/12/sample1.txt: -------------------------------------------------------------------------------- 1 | start-A 2 | start-b 3 | A-c 4 | A-b 5 | b-d 6 | A-end 7 | b-end 8 | -------------------------------------------------------------------------------- /2021/12/sample2.txt: -------------------------------------------------------------------------------- 1 | dc-end 2 | HN-start 3 | start-kj 4 | dc-start 5 | dc-HN 6 | LN-dc 7 | HN-end 8 | kj-sa 9 | kj-HN 10 | kj-dc 11 | -------------------------------------------------------------------------------- /2021/12/sample3.txt: -------------------------------------------------------------------------------- 1 | fs-end 2 | he-DX 3 | fs-he 4 | start-DX 5 | pj-DX 6 | end-zg 7 | zg-sl 8 | zg-pj 9 | pj-he 10 | RW-he 11 | fs-DX 12 | pj-RW 13 | zg-RW 14 | start-pj 15 | he-WI 16 | zg-he 17 | pj-fs 18 | start-RW 19 | -------------------------------------------------------------------------------- /2021/13/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/13/sample.txt: -------------------------------------------------------------------------------- 1 | 6,10 2 | 0,14 3 | 9,10 4 | 0,3 5 | 10,4 6 | 4,11 7 | 6,0 8 | 6,12 9 | 4,1 10 | 0,13 11 | 10,12 12 | 3,4 13 | 3,0 14 | 8,4 15 | 1,10 16 | 2,14 17 | 8,10 18 | 9,0 19 | 20 | fold along y=7 21 | fold along x=5 22 | -------------------------------------------------------------------------------- /2021/14/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/14/aoc14.go: -------------------------------------------------------------------------------- 1 | // aoc14.go -- 2 | // advent of code 2021 day 14 3 | // 4 | // https://adventofcode.com/2021/day/14 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-14: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | type histo map[byte]int64 21 | 22 | var ( 23 | rules map[string]byte 24 | cache map[string][]histo 25 | ) 26 | 27 | func init() { 28 | rules = make(map[string]byte) 29 | cache = make(map[string][]histo) 30 | } 31 | 32 | func merge(a, b histo) histo { 33 | for k, v := range b { 34 | a[k] += v 35 | } 36 | return a 37 | } 38 | 39 | func popcnt(rule string, depth int) histo { 40 | if len(cache[rule][depth]) > 0 { 41 | return cache[rule][depth] 42 | } 43 | 44 | cache[rule][depth] = histo{rules[rule]: 1} // cache current rule byte product 45 | 46 | if depth > 1 { // subsequent rules 47 | l := string([]byte{rule[0], rules[rule]}) // left 48 | r := string([]byte{rules[rule], rule[1]}) // right 49 | cache[rule][depth] = merge(cache[rule][depth], popcnt(l, depth-1)) 50 | cache[rule][depth] = merge(cache[rule][depth], popcnt(r, depth-1)) 51 | } 52 | 53 | return cache[rule][depth] 54 | } 55 | 56 | func main() { 57 | var seed []byte 58 | 59 | const ( 60 | depth1 = 10 61 | depth2 = 40 62 | ) 63 | 64 | input := bufio.NewScanner(os.Stdin) 65 | for input.Scan() { 66 | line := input.Text() 67 | if args := strings.Split(line, " -> "); len(args) == 2 { 68 | rules[args[0]] = args[1][0] 69 | cache[args[0]] = make([]histo, depth2+1) // allocate cache space to accommodate for new rule 70 | } else if line != "" { 71 | seed = []byte(line) 72 | } 73 | } 74 | 75 | extent := func(depth int) int64 { 76 | popcnts := make(histo) 77 | for _, b := range seed { 78 | popcnts[b]++ 79 | } 80 | for i := range seed[:len(seed)-1] { // extract and count pairs from seed 81 | popcnts = merge(popcnts, popcnt(string(seed[i:i+2]), depth)) 82 | } 83 | 84 | min, max := extrema(popcnts) 85 | return max - min 86 | } 87 | 88 | fmt.Println(extent(depth1)) // part1 89 | fmt.Println(extent(depth2)) // part2 90 | } 91 | 92 | func extrema(m histo) (int64, int64) { 93 | const ( 94 | MaxInt64 = int64(^uint64(0) >> 1) 95 | MinInt64 = -MaxInt64 - 1 96 | ) 97 | 98 | min, max := MaxInt64, MinInt64 99 | for _, v := range m { 100 | if v < min { 101 | min = v 102 | } 103 | if v > max { 104 | max = v 105 | } 106 | } 107 | return min, max 108 | } 109 | -------------------------------------------------------------------------------- /2021/14/sample.txt: -------------------------------------------------------------------------------- 1 | NNCB 2 | 3 | CH -> B 4 | HH -> N 5 | CB -> H 6 | NH -> C 7 | HB -> C 8 | HC -> B 9 | HN -> C 10 | NN -> C 11 | BH -> H 12 | NC -> B 13 | NB -> B 14 | BN -> B 15 | BB -> N 16 | BC -> B 17 | CC -> N 18 | CN -> C 19 | -------------------------------------------------------------------------------- /2021/15/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/15/sample.txt: -------------------------------------------------------------------------------- 1 | 1163751742 2 | 1381373672 3 | 2136511328 4 | 3694931569 5 | 7463417111 6 | 1319128137 7 | 1359912421 8 | 3125421639 9 | 1293138521 10 | 2311944581 11 | -------------------------------------------------------------------------------- /2021/16/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/16/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2021/16 2 | 3 | go 1.21.1 4 | 5 | require github.com/bearmini/bitstream-go v0.0.0-20190121230027-bec1c9ea0d3c 6 | 7 | require github.com/pkg/errors v0.8.0 // indirect 8 | -------------------------------------------------------------------------------- /2021/16/go.sum: -------------------------------------------------------------------------------- 1 | github.com/bearmini/bitstream-go v0.0.0-20190121230027-bec1c9ea0d3c h1:4RL7ENhXVDHqTk7vSgM7zUNHdYW7LfWUIBH2WZ/FZLc= 2 | github.com/bearmini/bitstream-go v0.0.0-20190121230027-bec1c9ea0d3c/go.mod h1:keOh1QpnRe0nCHGjev5R37jMl0zlLP+3ktETWfa4eik= 3 | github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= 4 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 5 | -------------------------------------------------------------------------------- /2021/16/sample1.txt: -------------------------------------------------------------------------------- 1 | 8A004A801A8002F478 2 | -------------------------------------------------------------------------------- /2021/16/sample2.txt: -------------------------------------------------------------------------------- 1 | 620080001611562C8802118E34 2 | -------------------------------------------------------------------------------- /2021/16/sample3.txt: -------------------------------------------------------------------------------- 1 | EE00D40C823060 2 | -------------------------------------------------------------------------------- /2021/16/sample4.txt: -------------------------------------------------------------------------------- 1 | D2FE28 2 | -------------------------------------------------------------------------------- /2021/17/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/17/aoc17.go: -------------------------------------------------------------------------------- 1 | // aoc17.go -- 2 | // advent of code 2021 day 17 3 | // 4 | // https://adventofcode.com/2021/day/17 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-17: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "fmt" 15 | "math" 16 | ) 17 | 18 | // Axis 19 | const ( 20 | X = iota 21 | Y 22 | ) 23 | 24 | type ( 25 | point [2]int 26 | speed [2]int 27 | ) 28 | 29 | // target area: x=150..193, y=-136..-86 30 | var ( 31 | min = point{150, -136} 32 | max = point{193, -86} 33 | ) 34 | 35 | func hit(v speed) bool { 36 | var p point 37 | for { // shoot 38 | p[X] += v[X] 39 | p[Y] += v[Y] 40 | 41 | if v[X] != 0 { 42 | v[X]-- 43 | } 44 | v[Y]-- 45 | 46 | if p[X] > max[X] || p[Y] < min[Y] { // over/under shoot 47 | return false 48 | } 49 | 50 | λ := func(a int) bool { 51 | return min[a] <= p[a] && p[a] <= max[a] 52 | } 53 | 54 | if λ(X) && λ(Y) { 55 | return true 56 | } 57 | } 58 | } 59 | 60 | func main() { 61 | vmin := speed{ 62 | int(math.Sqrt(float64(2 * min[X]))), // FPU rules! 63 | min[Y], 64 | } 65 | 66 | vmax := speed{ 67 | max[X], 68 | int(math.Abs(float64(min[Y] + 1))), // since we use math... 69 | } 70 | 71 | fmt.Println((vmax[Y] + 1) * vmax[Y] / 2) // part1 72 | 73 | n := 0 74 | for vx := vmin[X]; vx <= vmax[X]; vx++ { 75 | for vy := vmin[Y]; vy <= vmax[Y]; vy++ { 76 | if hit(speed{vx, vy}) { 77 | n++ 78 | } 79 | } 80 | } 81 | fmt.Println(n) // part2 82 | } 83 | -------------------------------------------------------------------------------- /2021/18/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/18/sample.txt: -------------------------------------------------------------------------------- 1 | [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] 2 | [[[5,[2,8]],4],[5,[[9,9],0]]] 3 | [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] 4 | [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] 5 | [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] 6 | [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] 7 | [[[[5,4],[7,7]],8],[[8,3],8]] 8 | [[9,3],[[9,9],[6,[4,9]]]] 9 | [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] 10 | [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]] 11 | -------------------------------------------------------------------------------- /2021/19/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/19/sample.txt: -------------------------------------------------------------------------------- 1 | --- scanner 0 --- 2 | 404,-588,-901 3 | 528,-643,409 4 | -838,591,734 5 | 390,-675,-793 6 | -537,-823,-458 7 | -485,-357,347 8 | -345,-311,381 9 | -661,-816,-575 10 | -876,649,763 11 | -618,-824,-621 12 | 553,345,-567 13 | 474,580,667 14 | -447,-329,318 15 | -584,868,-557 16 | 544,-627,-890 17 | 564,392,-477 18 | 455,729,728 19 | -892,524,684 20 | -689,845,-530 21 | 423,-701,434 22 | 7,-33,-71 23 | 630,319,-379 24 | 443,580,662 25 | -789,900,-551 26 | 459,-707,401 27 | 28 | --- scanner 1 --- 29 | 686,422,578 30 | 605,423,415 31 | 515,917,-361 32 | -336,658,858 33 | 95,138,22 34 | -476,619,847 35 | -340,-569,-846 36 | 567,-361,727 37 | -460,603,-452 38 | 669,-402,600 39 | 729,430,532 40 | -500,-761,534 41 | -322,571,750 42 | -466,-666,-811 43 | -429,-592,574 44 | -355,545,-477 45 | 703,-491,-529 46 | -328,-685,520 47 | 413,935,-424 48 | -391,539,-444 49 | 586,-435,557 50 | -364,-763,-893 51 | 807,-499,-711 52 | 755,-354,-619 53 | 553,889,-390 54 | 55 | --- scanner 2 --- 56 | 649,640,665 57 | 682,-795,504 58 | -784,533,-524 59 | -644,584,-595 60 | -588,-843,648 61 | -30,6,44 62 | -674,560,763 63 | 500,723,-460 64 | 609,671,-379 65 | -555,-800,653 66 | -675,-892,-343 67 | 697,-426,-610 68 | 578,704,681 69 | 493,664,-388 70 | -671,-858,530 71 | -667,343,800 72 | 571,-461,-707 73 | -138,-166,112 74 | -889,563,-600 75 | 646,-828,498 76 | 640,759,510 77 | -630,509,768 78 | -681,-892,-333 79 | 673,-379,-804 80 | -742,-814,-386 81 | 577,-820,562 82 | 83 | --- scanner 3 --- 84 | -589,542,597 85 | 605,-692,669 86 | -500,565,-823 87 | -660,373,557 88 | -458,-679,-417 89 | -488,449,543 90 | -626,468,-788 91 | 338,-750,-386 92 | 528,-832,-391 93 | 562,-778,733 94 | -938,-730,414 95 | 543,643,-506 96 | -524,371,-870 97 | 407,773,750 98 | -104,29,83 99 | 378,-903,-323 100 | -778,-728,485 101 | 426,699,580 102 | -438,-605,-362 103 | -469,-447,-387 104 | 509,732,623 105 | 647,635,-688 106 | -868,-804,481 107 | 614,-800,639 108 | 595,780,-596 109 | 110 | --- scanner 4 --- 111 | 727,592,562 112 | -293,-554,779 113 | 441,611,-461 114 | -714,465,-776 115 | -743,427,-804 116 | -660,-479,-426 117 | 832,-632,460 118 | 927,-485,-438 119 | 408,393,-506 120 | 466,436,-512 121 | 110,16,151 122 | -258,-428,682 123 | -393,719,612 124 | -211,-452,876 125 | 808,-476,-593 126 | -575,615,604 127 | -485,667,467 128 | -680,325,-822 129 | -627,-443,-432 130 | 872,-547,-609 131 | 833,512,582 132 | 807,604,487 133 | 839,-516,451 134 | 891,-625,532 135 | -652,-548,-490 136 | 30,-46,-14 137 | -------------------------------------------------------------------------------- /2021/2/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/2/aoc2.go: -------------------------------------------------------------------------------- 1 | // aoc2.go -- 2 | // advent of code 2021 day 2 3 | // 4 | // https://adventofcode.com/2021/day/2 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-2: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strconv" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | x, y, aim := 0, 0, 0 23 | 24 | input := bufio.NewScanner(os.Stdin) 25 | for input.Scan() { 26 | line := input.Text() 27 | arg := atoi(strings.Fields(line)[1]) 28 | switch line[0] { 29 | case 'f': // forward 30 | x += arg 31 | y += aim * arg 32 | case 'u': // up 33 | aim -= arg 34 | case 'd': // down 35 | aim += arg 36 | } 37 | } 38 | fmt.Println(x * aim) // part1 39 | fmt.Println(x * y) // part2 40 | } 41 | 42 | func atoi(s string) (n int) { 43 | n, _ = strconv.Atoi(s) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /2021/20/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/20/sample.txt: -------------------------------------------------------------------------------- 1 | ..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..# 2 | 3 | #..#. 4 | #.... 5 | ##..# 6 | ..#.. 7 | ..### 8 | -------------------------------------------------------------------------------- /2021/21/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/21/sample.txt: -------------------------------------------------------------------------------- 1 | Player 1 starting position: 4 2 | Player 2 starting position: 8 3 | -------------------------------------------------------------------------------- /2021/22/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/22/rsc/rsc22.go: -------------------------------------------------------------------------------- 1 | // https://www.youtube.com/watch?v=JyrNC74r2SI&list=PLrwpzH1_9ufMLOB6BAdzO08Qx-9jHGfGg&index=25 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | func main() { 12 | data, _ := os.ReadFile("input.txt") 13 | text := strings.Fields(r.Replace(string(data))) 14 | 15 | type dim struct { 16 | min, max int 17 | } 18 | 19 | type flip struct { 20 | on int 21 | p [3]dim 22 | } 23 | 24 | var prog []*flip 25 | 26 | const Off = 100_000 27 | for ; len(text) > 0; text = text[7:] { 28 | var f flip 29 | f.on, 30 | f.p[0].min, f.p[0].max, 31 | f.p[1].min, f.p[1].max, 32 | f.p[2].min, f.p[2].max = 33 | atoi(text[0]), 34 | atoi(text[1])+Off, 35 | atoi(text[2])+Off+1, 36 | atoi(text[3])+Off, 37 | atoi(text[4])+Off+1, 38 | atoi(text[5])+Off, 39 | atoi(text[6])+Off+1 40 | prog = append(prog, &f) 41 | } 42 | 43 | const N = 850 44 | 45 | remap := new([3][2 * Off]int) 46 | width := new([3][N]int) 47 | for _, f := range prog { 48 | for i, d := range f.p { 49 | remap[i][d.min] = 1 50 | remap[i][d.max] = 1 51 | } 52 | } 53 | 54 | for i := range remap { 55 | t := 0 56 | for j, v := range &remap[i] { 57 | t += v 58 | remap[i][j] = t 59 | width[i][t]++ 60 | } 61 | } 62 | for _, f := range prog { 63 | for i, d := range f.p { 64 | f.p[i] = dim{remap[i][d.min], remap[i][d.max]} 65 | } 66 | } 67 | 68 | sw := new([N][N][N]byte) 69 | for _, f := range prog { 70 | for x := f.p[0].min; x < f.p[0].max; x++ { 71 | for y := f.p[1].min; y < f.p[1].max; y++ { 72 | for z := f.p[2].min; z < f.p[2].max; z++ { 73 | sw[x][y][z] = byte(f.on) 74 | } 75 | } 76 | } 77 | } 78 | total := 0 79 | for x := range sw { 80 | for y := range sw { 81 | for z := range sw { 82 | total += width[0][x] * width[1][y] * width[2][z] * int(sw[x][y][z]) 83 | } 84 | } 85 | } 86 | fmt.Println(total) 87 | } 88 | 89 | func atoi(s string) int { 90 | n, _ := strconv.Atoi(s) 91 | return n 92 | } 93 | 94 | var r = strings.NewReplacer( 95 | "x=", "", 96 | "y=", "", 97 | "z=", "", 98 | "on", "1", 99 | "off", "0", 100 | ",", " ", 101 | "..", " ", 102 | ) 103 | -------------------------------------------------------------------------------- /2021/22/rsc/time.md.sav: -------------------------------------------------------------------------------- 1 | | Command | Mean [ms] | Min [ms] | Max [ms] | Relative | 2 | |:---|---:|---:|---:|---:| 3 | | `cat input.txt` | 0.4 ± 0.2 | 0.1 | 1.0 | 1.00 | 4 | | `./rsc22` | 922.6 ± 9.8 | 907.0 | 1046.2 | 2137.73 ± 800.96 | 5 | -------------------------------------------------------------------------------- /2021/22/sample.txt: -------------------------------------------------------------------------------- 1 | on x=-20..26,y=-36..17,z=-47..7 2 | on x=-20..33,y=-21..23,z=-26..28 3 | on x=-22..28,y=-29..23,z=-38..16 4 | on x=-46..7,y=-6..46,z=-50..-1 5 | on x=-49..1,y=-3..46,z=-24..28 6 | on x=2..47,y=-22..22,z=-23..27 7 | on x=-27..23,y=-28..26,z=-21..29 8 | on x=-39..5,y=-6..47,z=-3..44 9 | on x=-30..21,y=-8..43,z=-13..34 10 | on x=-22..26,y=-27..20,z=-29..19 11 | off x=-48..-32,y=26..41,z=-47..-37 12 | on x=-12..35,y=6..50,z=-50..-2 13 | off x=-48..-32,y=-32..-16,z=-15..-5 14 | on x=-18..26,y=-33..15,z=-7..46 15 | off x=-40..-22,y=-38..-28,z=23..41 16 | on x=-16..35,y=-41..10,z=-47..6 17 | off x=-32..-23,y=11..30,z=-14..3 18 | on x=-49..-5,y=-3..45,z=-29..18 19 | off x=18..30,y=-20..-8,z=-3..13 20 | on x=-41..9,y=-7..43,z=-33..15 21 | on x=-54112..-39298,y=-85059..-49293,z=-27449..7877 22 | on x=967..23432,y=45373..81175,z=27513..53682 23 | -------------------------------------------------------------------------------- /2021/23/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk 2 | -------------------------------------------------------------------------------- /2021/23/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2021/23 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2021/23/pprof001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2021/23/pprof001.jpg -------------------------------------------------------------------------------- /2021/24/1flow.txt: -------------------------------------------------------------------------------- 1 | x, y, z = 0, 0, 0 2 | w = A 3 | x = (z % 26) + 12 4 | y = 1 + 25 * (x != A) 5 | z = z * y 6 | y = (A + 6) * (x != A) 7 | z = z + y 8 | 9 | w = B 10 | x = (z % 26) + 10 11 | y = 1 + 25 * (x != B) 12 | z = z * y 13 | y = (B + 2) * (x != B) 14 | z = z + y 15 | 16 | w = C 17 | x = (z % 26) + 10 18 | y = 1 + 25 * (x != C) 19 | z = z * y 20 | y = (C + 13) * (x != C) 21 | z = z + y 22 | 23 | w = D 24 | z = z / 26 25 | x = (z % 26) - 6 26 | y = 1 + 25 * (x != D) 27 | z = z * y 28 | y = (D + 8) * (x != D) 29 | z = z + y 30 | 31 | w = E 32 | x = (z % 26) + 11 33 | y = 1 + 25 * (x != E) 34 | z = z * y 35 | y = (E + 13) * (x != E) 36 | z = z + y 37 | 38 | w = F 39 | z = z / 26 40 | x = (z % 26) - 12 41 | y = 1 + 25 * (x != F) 42 | z = z * y 43 | y = (F + 8) * (x != F) 44 | z = z + y 45 | 46 | w = G 47 | x = (z % 26) + 11 48 | y = 1 + 25 * (x != G) 49 | z = z * y 50 | y = (G + 3) * (x != G) 51 | z = z + y 52 | 53 | w = H 54 | x = (z % 26) + 12 55 | y = 1 + 25 * (x != H) 56 | z = z * y 57 | y = (H + 11) * (x != H) 58 | z = z + y 59 | 60 | w = I 61 | x = (z % 26) + 12 62 | y = 1 + 25 * (x != I) 63 | z = z * y 64 | y = (I + 10) * (x != I) 65 | z = z + y 66 | 67 | w = J 68 | z = z / 26 69 | x = (z % 26) - 2 70 | y = 1 + 25 * (x != J) 71 | z = z * y 72 | y = (J + 8) * (x != J) 73 | z = z + y 74 | 75 | w = K 76 | z = z / 26 77 | x = (z % 26) - 5 78 | y = 1 + 25 * (x != K) 79 | z = z * y 80 | y = (K + 14) * (x != K) 81 | z = z + y 82 | 83 | w = L 84 | z = z / 26 85 | x = (z % 26) - 4 86 | y = 1 + 25 * (x != L) 87 | z = z * y 88 | y = (L + 6) * (x != L) 89 | z = z + y 90 | 91 | w = M 92 | z = z / 26 93 | x = (z % 26) - 4 94 | y = 1 + 25 * (x != M) 95 | z = z * y 96 | y = (M + 8) * (x != M) 97 | z = z + y 98 | 99 | w = N 100 | z = z / 26 101 | x = (z % 26) - 12 102 | y = 1 + 25 * (x != N) 103 | z = z * y 104 | y = (N + 2) * (x != N) 105 | z = z + y 106 | -------------------------------------------------------------------------------- /2021/24/2crack.txt: -------------------------------------------------------------------------------- 1 | A + 6 2 | 26*(A+6) + (B+2) 3 | 26^2*(A+6) + 26*(B+2) + (C+13) 4 | (D == C+7) 26*(A+6) + (B+2) 5 | 26^2*(A+ 6) + 26*(B+2) + (E+13) 6 | (F == E+1) 26*(A+6) + (B+2) 7 | 26^2*(A+6) + 26*(B+2) + (G+3) 8 | 26^3*(A+6) + 26^2*(B+2) + 26*(G+3) + (H+11) 9 | 26^4*(A+6) + 26^3*(B+2) + 26^2*(G+3) + 26*(H+11) + (I+10) 10 | (J == I+8) 26^3*(A+6) + 26^2*(B+2) + 26*(G+3) + (H+11) 11 | (K == H+6) 26^2*(A+6) + 26^1*(B+2) + (G+3) 12 | (L == G-1) 26*(A+6) + (B+2) 13 | (M == B-2) 26*(A+6) 14 | (N == A-6) 0 15 | 16 | A 7..9 17 | B 3..9 18 | C 1..2 19 | C+7 20 | E 1..8 21 | E+1 22 | G 2..9 23 | H 1..3 24 | I 1 25 | I+8 9 26 | H+6 27 | G-1 28 | B-2 29 | A-6 30 | 31 | A B C D E F G H I J K L M N 32 | 9 9 2 9 8 9 9 3 1 9 9 8 7 3 33 | 7 3 1 8 1 2 2 1 1 9 7 1 1 1 -------------------------------------------------------------------------------- /2021/24/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/24/aoc24.go: -------------------------------------------------------------------------------- 1 | // aoc24.go -- 2 | // advent of code 2021 day 24 3 | // 4 | // https://adventofcode.com/2021/day/24 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-24: initial commit 10 | 11 | // 12 | package main 13 | 14 | import ( 15 | "bufio" 16 | "fmt" 17 | "os" 18 | "strconv" 19 | "strings" 20 | ) 21 | 22 | func main() { 23 | code := make([]string, 0, 256) 24 | 25 | input := bufio.NewScanner(os.Stdin) 26 | for input.Scan() { 27 | line := input.Text() 28 | code = append(code, line) 29 | } 30 | 31 | type item struct { 32 | j, b int 33 | } 34 | stack := make([]item, 0, 8) 35 | 36 | push := func(j, b int) { 37 | stack = append(stack, item{j, b}) 38 | } 39 | 40 | pop := func() (int, int) { 41 | i := len(stack) - 1 42 | pop := stack[i] 43 | stack, stack[i] = stack[:i], item{} 44 | return pop.j, pop.b 45 | } 46 | 47 | p := 99999999999999 48 | q := 11111111111111 49 | 50 | for i := 0; i < 14; i++ { 51 | arg := strings.Fields(code[18*i+5]) 52 | a, _ := strconv.Atoi(arg[len(arg)-1]) 53 | 54 | arg = strings.Fields(code[18*i+15]) 55 | b, _ := strconv.Atoi(arg[len(arg)-1]) 56 | 57 | if a > 0 { 58 | push(i, b) 59 | } else { 60 | j, b := pop() 61 | 62 | xp, xq := 13-i, 13-i // exponents 63 | switch { 64 | case a > -b: 65 | xp += i - j 66 | case a < -b: 67 | xq += i - j 68 | } 69 | 70 | p -= abs(a+b) * pow(10, xp) 71 | q += abs(a+b) * pow(10, xq) 72 | } 73 | } 74 | fmt.Println(p) // part1 75 | fmt.Println(q) // part2 76 | } 77 | 78 | func abs(a int) int { 79 | if a < 0 { 80 | return -a 81 | } 82 | return a 83 | } 84 | 85 | func pow(a, n int) int { 86 | if n == 0 { 87 | return 1 88 | } 89 | 90 | b := 1 91 | for n > 1 { 92 | if (n & 1) == 1 { 93 | b = a * b 94 | a = a * a 95 | n = (n - 1) / 2 96 | } else { 97 | a = a * a 98 | n /= 2 99 | } 100 | } 101 | return a * b 102 | } 103 | -------------------------------------------------------------------------------- /2021/24/aoc24.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # https://www.reddit.com/r/adventofcode/comments/rnejv5/2021_day_24_solutions/hqstr1a/?utm_source=reddit&utm_medium=web2x&context=3 3 | 4 | instr, stack = [*open(0)], [] 5 | 6 | p, q = 99999999999999, 11111111111111 7 | 8 | for i in range(14): 9 | a = int(instr[18*i+5].split()[-1]) 10 | b = int(instr[18*i+15].split()[-1]) 11 | 12 | if a > 0: stack +=[(i, b)]; continue 13 | 14 | j, b = stack.pop() 15 | p -= abs((a+b)*10**(13-[i,j][a>-b])) 16 | q += abs((a+b)*10**(13-[i,j][a<-b])) 17 | 18 | print(p, q) 19 | -------------------------------------------------------------------------------- /2021/25/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/25/aoc25.go: -------------------------------------------------------------------------------- 1 | // aoc25.go -- 2 | // advent of code 2021 day 25 3 | // 4 | // https://adventofcode.com/2021/day/25 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-25: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | const ( 21 | w = 139 22 | h = 137 23 | ) 24 | 25 | type board [w * h]byte 26 | 27 | func main() { 28 | var nxt board 29 | 30 | input := bufio.NewScanner(os.Stdin) 31 | for j := 0; input.Scan(); j++ { 32 | low, max := slice(j) 33 | copy(nxt[low:max:max], input.Bytes()) 34 | } 35 | 36 | s, n := 0, 1 // step, change count 37 | for n > 0 { 38 | s, n = s+1, 0 // advance step, reset change count 39 | 40 | cur := nxt 41 | // east scan 42 | for j := 0; j < h; j++ { 43 | crow := cur.row(j) 44 | nrow := nxt.row(j) 45 | for i := 0; i < w; i++ { 46 | ii := (i + 1) % w 47 | if crow[i] == '>' && crow[ii] == '.' { 48 | nrow[i], nrow[ii] = nrow[ii], nrow[i] // swap! 49 | n++ 50 | } 51 | } 52 | } 53 | 54 | cur = nxt 55 | // south scan 56 | for j := 0; j < h; j++ { 57 | jj := (j + 1) % h 58 | chead, ctail := cur.row(j), cur.row(jj) 59 | nhead, ntail := nxt.row(j), nxt.row(jj) 60 | for i := 0; i < w; i++ { 61 | if chead[i] == 'v' && ctail[i] == '.' { 62 | nhead[i], ntail[i] = ntail[i], nhead[i] // swap! 63 | n++ 64 | } 65 | } 66 | } 67 | } 68 | fmt.Println(s) 69 | } 70 | 71 | func at(j, i int) int { 72 | return j*w + i 73 | } 74 | 75 | func slice(j int) (low, max int) { 76 | low = j * w 77 | max = low + w 78 | return 79 | } 80 | 81 | func (b *board) row(j int) []byte { 82 | low, max := slice(j) 83 | return b[low:max:max] 84 | } 85 | 86 | func (b *board) String() string { 87 | var sb strings.Builder 88 | for j := 0; j < h; j++ { 89 | low, max := slice(j) 90 | sb.Write(b[low:max:max]) 91 | sb.WriteByte('\n') 92 | } 93 | 94 | return sb.String() 95 | } 96 | -------------------------------------------------------------------------------- /2021/25/sample.txt: -------------------------------------------------------------------------------- 1 | v...>>.vv> 2 | .vv>>.vv.. 3 | >>.>v>...v 4 | >>v>>.>.v. 5 | v>v.vv.v.. 6 | >.>>..v... 7 | .vv..>.>v. 8 | v.v..>>v.v 9 | ....v..v.> 10 | -------------------------------------------------------------------------------- /2021/3/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/3/aoc3.go: -------------------------------------------------------------------------------- 1 | // aoc3.go -- 2 | // advent of code 2021 day 3 3 | // 4 | // https://adventofcode.com/2021/day/3 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-3: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strconv" 18 | ) 19 | 20 | const ( 21 | width = 12 // bits 22 | bitmask = (1 << width) - 1 23 | ) 24 | 25 | func popcounts(nums []string) []int { 26 | popcnts := make([]int, width) 27 | for _, n := range nums { 28 | for i, c := range n { 29 | if c == '1' { 30 | popcnts[i]++ 31 | } 32 | } 33 | } 34 | return popcnts 35 | } 36 | 37 | type gas int 38 | 39 | const ( 40 | o2 gas = iota 41 | co2 42 | ) 43 | 44 | func rate(nums []string, g gas) (int64, error) { 45 | bs := append(nums[:0:0], nums...) // clone binary strings 46 | 47 | bits := [...]string{o2: "01", co2: "10"}[g] // most popular bit filters by gas 48 | 49 | for i := 0; i < width && len(bs) > 1; i++ { 50 | popcnts := popcounts(bs) 51 | 52 | j := 0 53 | for _, s := range bs { 54 | switch { 55 | case s[i] == bits[0] && len(bs) > 2*popcnts[i]: 56 | bs[j], j = s, j+1 57 | case s[i] == bits[1] && len(bs) <= 2*popcnts[i]: 58 | bs[j], j = s, j+1 59 | } 60 | } 61 | bs = bs[:j] 62 | } 63 | return strconv.ParseInt(bs[0], 2, 32) 64 | } 65 | 66 | func main() { 67 | nums := make([]string, 0, 1024) 68 | 69 | input := bufio.NewScanner(os.Stdin) 70 | for input.Scan() { 71 | line := input.Text() 72 | nums = append(nums, line) 73 | } 74 | 75 | rates := make(chan int64) 76 | defer close(rates) 77 | 78 | go func() { 79 | n, _ := rate(nums, o2) 80 | rates <- n 81 | }() 82 | 83 | go func() { 84 | n, _ := rate(nums, co2) 85 | rates <- n 86 | }() 87 | 88 | var ε int 89 | for _, popcnt := range popcounts(nums) { 90 | ε <<= 1 91 | if 2*popcnt <= len(nums) { 92 | ε |= 1 93 | } 94 | } 95 | γ := ^ε & bitmask 96 | fmt.Println(ε * γ) // part1 97 | 98 | n := int64(1) 99 | for i := 0; i < 2; i++ { 100 | n *= <-rates 101 | } 102 | fmt.Println(n) // part2 103 | } 104 | -------------------------------------------------------------------------------- /2021/3/sample.txt: -------------------------------------------------------------------------------- 1 | 00100 2 | 11110 3 | 10110 4 | 10111 5 | 10101 6 | 01111 7 | 00111 8 | 11100 9 | 10000 10 | 11001 11 | 00010 12 | 01010 13 | -------------------------------------------------------------------------------- /2021/4/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/4/sample.txt: -------------------------------------------------------------------------------- 1 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 2 | 3 | 22 13 17 11 0 4 | 8 2 23 4 24 5 | 21 9 14 16 7 6 | 6 10 3 18 5 7 | 1 12 20 15 19 8 | 9 | 3 15 0 2 22 10 | 9 18 13 17 5 11 | 19 8 7 25 23 12 | 20 11 10 24 4 13 | 14 21 16 12 6 14 | 15 | 14 21 17 24 4 16 | 10 16 15 9 19 17 | 18 8 23 26 20 18 | 22 11 13 6 5 19 | 2 0 12 3 7 20 | -------------------------------------------------------------------------------- /2021/5/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/5/aoc5.go: -------------------------------------------------------------------------------- 1 | // aoc5.go -- 2 | // advent of code 2021 day 5 3 | // 4 | // https://adventofcode.com/2021/day/5 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-5: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strconv" 18 | "strings" 19 | ) 20 | 21 | type point struct { 22 | x, y int 23 | } 24 | 25 | // Point constructs a point object 26 | func Point(a, b string) point { 27 | x, _ := strconv.Atoi(strings.TrimSpace(a)) 28 | y, _ := strconv.Atoi(strings.TrimSpace(b)) 29 | 30 | return point{x, y} 31 | } 32 | 33 | const ( 34 | w = 1000 35 | h = 1000 36 | ) 37 | 38 | type canvas [w * h]int 39 | 40 | var can1, can2 canvas 41 | 42 | // plot draws a line on the canvas according to part 1&2 constraints 43 | func plot(a, b point) { 44 | Δx, Δy := b.x-a.x, b.y-a.y 45 | 46 | switch { 47 | case Δx == 0: 48 | x := a.x 49 | ymin, ymax := sort(a.y, b.y) 50 | for y := ymin; y <= ymax; y++ { 51 | can1[x*w+y]++ 52 | can2[x*w+y]++ 53 | } 54 | case Δy == 0: 55 | y := a.y 56 | xmin, xmax := sort(a.x, b.x) 57 | for x := xmin; x <= xmax; x++ { 58 | can1[x*w+y]++ 59 | can2[x*w+y]++ 60 | } 61 | default: 62 | m := Δy / Δx 63 | c := a.y - a.x*m 64 | xmin, xmax := sort(a.x, b.x) 65 | for x := xmin; x <= xmax; x++ { 66 | y := m*x + c 67 | can2[x*w+y]++ 68 | } 69 | } 70 | } 71 | 72 | func popcounts() (int, int) { 73 | popcnt1, popcnt2 := 0, 0 74 | for i := range can1 { 75 | if can1[i] > 1 { 76 | popcnt1++ 77 | } 78 | if can2[i] > 1 { 79 | popcnt2++ 80 | } 81 | } 82 | return popcnt1, popcnt2 83 | } 84 | 85 | func main() { 86 | input := bufio.NewScanner(os.Stdin) 87 | for input.Scan() { 88 | line := strings.Replace(input.Text(), "->", ",", 1) 89 | args := strings.Split(line, ",") 90 | 91 | a, b := Point(args[0], args[1]), Point(args[2], args[3]) 92 | plot(a, b) 93 | } 94 | 95 | fmt.Println(popcounts()) // part1 & part2 96 | } 97 | 98 | func sort(a, b int) (int, int) { 99 | if a < b { 100 | return a, b 101 | } 102 | return b, a 103 | } 104 | -------------------------------------------------------------------------------- /2021/5/sample.txt: -------------------------------------------------------------------------------- 1 | 0,9 -> 5,9 2 | 8,0 -> 0,8 3 | 9,4 -> 3,4 4 | 2,2 -> 2,1 5 | 7,0 -> 7,4 6 | 6,4 -> 2,0 7 | 0,9 -> 2,9 8 | 3,4 -> 1,4 9 | 0,0 -> 8,8 10 | 5,5 -> 8,2 11 | -------------------------------------------------------------------------------- /2021/6/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/6/aoc6.go: -------------------------------------------------------------------------------- 1 | // aoc6.go -- 2 | // advent of code 2021 day 6 3 | // 4 | // https://adventofcode.com/2021/day/6 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-6: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strconv" 18 | "strings" 19 | ) 20 | 21 | type popcnts [9]uint64 22 | 23 | // incube computes fishes population. 24 | func incube(a []uint64) { 25 | i, n := len(a)-1, a[0] 26 | copy(a, a[1:]) 27 | a[6], a[i] = a[6]+n, n 28 | } 29 | 30 | func popcnt(p popcnts) uint64 { 31 | var popcnt uint64 32 | for _, n := range p { 33 | popcnt += n 34 | } 35 | return popcnt 36 | } 37 | 38 | func main() { 39 | var fishes popcnts 40 | 41 | input := bufio.NewScanner(os.Stdin) 42 | for input.Scan() { 43 | args := strings.Split(input.Text(), ",") 44 | for _, arg := range args { 45 | i, _ := strconv.Atoi(arg) 46 | fishes[i]++ 47 | } 48 | } 49 | 50 | for i := 0; i < 256; i++ { 51 | if i == 80 { 52 | fmt.Println(popcnt(fishes)) // part1 53 | } 54 | incube(fishes[:]) // pass slice 55 | } 56 | fmt.Println(popcnt(fishes)) // part2 57 | } 58 | -------------------------------------------------------------------------------- /2021/6/aoc6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | from io import StringIO 5 | from collections import Counter, deque 6 | 7 | def incube(fishes, days): 8 | popcnt = deque([fishes[i] for i in range(9)]) 9 | for _ in range(days): 10 | popcnt.rotate(-1) 11 | popcnt[6] += popcnt[-1] 12 | return popcnt 13 | 14 | 15 | def load(fd): 16 | lines = fd.readline() 17 | return Counter(int(x) for x in lines.strip().split(",")) 18 | 19 | 20 | def main(): 21 | fishes = load(sys.stdin) 22 | days = int(sys.argv[1]) 23 | print(sum(incube(fishes, days))) 24 | 25 | if __name__ == "__main__": 26 | main() -------------------------------------------------------------------------------- /2021/6/sample.txt: -------------------------------------------------------------------------------- 1 | 3,4,3,1,2 2 | -------------------------------------------------------------------------------- /2021/7/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/7/aoc7.go: -------------------------------------------------------------------------------- 1 | // aoc7.go -- 2 | // advent of code 2021 day 7 3 | // 4 | // https://adventofcode.com/2021/day/7 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2021-12-7: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "math" 17 | "os" 18 | "sort" 19 | "strconv" 20 | "strings" 21 | ) 22 | 23 | type pos []int 24 | 25 | func (p pos) mean() int { 26 | sum := 0 27 | for _, x := range p { 28 | sum += x 29 | } 30 | return int(math.Floor(float64(sum) / float64(len(p)))) // Round doesn't work on my input 31 | } 32 | 33 | func (p pos) median() int { 34 | sort.Ints(p) 35 | return p[len(p)/2] 36 | } 37 | 38 | // sumdist does parallel summation of distances for part1 & part2. 39 | func (p pos) sumdist() (int, int) { 40 | m1, m2 := p.median(), p.mean() 41 | g := func(x int) int { return (x * (x + 1)) / 2 } // gauss sum 42 | 43 | sum1, sum2 := 0, 0 44 | for _, x := range p { 45 | sum1 += abs(x - m1) // dist1 46 | sum2 += g(abs(x - m2)) // dist2 47 | } 48 | return sum1, sum2 49 | } 50 | 51 | func main() { 52 | crabs := make(pos, 0, 1000) 53 | 54 | input := bufio.NewScanner(os.Stdin) 55 | for input.Scan() { 56 | for _, arg := range strings.Split(input.Text(), ",") { 57 | x, _ := strconv.Atoi(arg) 58 | crabs = append(crabs, x) 59 | } 60 | } 61 | fmt.Println(crabs.sumdist()) // part1 & part2 62 | } 63 | 64 | func abs(n int) int { 65 | if n < 0 { 66 | return -n 67 | } 68 | return n 69 | } 70 | -------------------------------------------------------------------------------- /2021/7/aoc7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | from statistics import mean, median 5 | 6 | def load(fd): 7 | line = fd.readline() 8 | return [int(x) for x in line.strip().split(",")] 9 | 10 | def part1(data) : 11 | m = median(sorted(data)) 12 | return [abs(x - m) for x in data] 13 | 14 | def part2(data): 15 | def g(x): 16 | return (x * (x+1))/2 17 | 18 | m = int(mean(data)) # round doesn't work on my input 19 | return [g(abs(x - m)) for x in data] 20 | 21 | def main(): 22 | data = load(sys.stdin) 23 | for fun in [part1, part2]: 24 | print(int(sum(fun(data)))) 25 | 26 | if __name__ == "__main__": 27 | main() -------------------------------------------------------------------------------- /2021/7/sample.txt: -------------------------------------------------------------------------------- 1 | 16,1,2,0,4,2,7,1,2,14 2 | -------------------------------------------------------------------------------- /2021/8/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/8/sample.txt: -------------------------------------------------------------------------------- 1 | be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe 2 | edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc 3 | fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg 4 | fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb 5 | aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea 6 | fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb 7 | dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe 8 | bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef 9 | egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb 10 | gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce -------------------------------------------------------------------------------- /2021/9/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2021/9/aoc9.2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy import ndimage 3 | 4 | grid = [] 5 | with open("input.txt") as f: 6 | for args in f: 7 | args = list(args.split()[0]) 8 | grid.append([int(arg) for arg in args]) 9 | 10 | basins, n = ndimage.label((np.array(grid) < 9).astype(int)) 11 | counts = [(basins == x).sum() for x in range(1, n+1)] 12 | print(np.sort(counts)[-3:].prod()) -------------------------------------------------------------------------------- /2021/9/sample.txt: -------------------------------------------------------------------------------- 1 | 2199943210 2 | 3987894921 3 | 9856789892 4 | 8767896789 5 | 9899965678 6 | -------------------------------------------------------------------------------- /2021/Makefile: -------------------------------------------------------------------------------- 1 | GO = go build 2 | 3 | TARGETS := bench build check clean header run 4 | 5 | SUBDIRS := $(wildcard */.) 6 | SUBDIRS := $(filter-out download/. header/. runtime/., $(SUBDIRS)) 7 | 8 | $(TARGETS): $(SUBDIRS) 9 | $(SUBDIRS): 10 | @$(MAKE) -C $@ $(MAKECMDGOALS) 11 | 12 | cyclo: 13 | @gocyclo -top 10 -avg . 14 | 15 | lines: 16 | @find . -name '*go' \( -not -iname "main.go" \) | grep -v 'v1' | xargs wc -l | sort 17 | 18 | runtime: 19 | @./runtime.sh | sort -n -k 4 > runtime.md 20 | 21 | .PHONY: $(TARGETS) $(SUBDIRS) cyclo lines runtime 22 | -------------------------------------------------------------------------------- /2021/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | hyperfine --warmup 100 "cat input.txt > /dev/null" "./${1} < input.txt" --export-markdown time.md 4 | -------------------------------------------------------------------------------- /2021/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | build: input.txt 20 | $(GOC) $(SRC) 21 | 22 | check: 23 | $(GOV) $(SRC) 24 | 25 | clean: 26 | go clean 27 | rm -f $(BIN) 28 | 29 | header: 30 | @go run $(HEADER) 31 | 32 | input.txt: 33 | @go run $(DOWNLOAD) 34 | 35 | go.mod: 36 | @go mod init 2>/dev/null 37 | 38 | gobench: go.mod input.txt 39 | go test -bench=. -benchmem 40 | 41 | cpuprof: build 42 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 43 | 44 | memprof: build 45 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 46 | 47 | run: input.txt 48 | go run ./$(SRC) < $(IN) 49 | 50 | sample: 51 | go run ./$(SRC) < $(EX) 52 | 53 | 54 | .PHONY: bench build check clean cpuprof exemple gobench header memprof run sample 55 | -------------------------------------------------------------------------------- /2021/download/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/download 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2021/download/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "os" 11 | "path" 12 | "strconv" 13 | ) 14 | 15 | const ( 16 | OUT = "input.txt" 17 | URL = "https://adventofcode.com/%d/day/%d/input" 18 | ) 19 | 20 | var client http.Client 21 | 22 | func main() { 23 | if _, err := os.Stat(OUT); !errors.Is(err, os.ErrNotExist) { 24 | log.Printf("input file %s already exists", OUT) 25 | os.Exit(0) 26 | } 27 | 28 | session := os.Getenv("SESSION") 29 | if len(session) == 0 { 30 | log.Println("$SESSION not set") 31 | os.Exit(0) 32 | } 33 | 34 | pwd, err := os.Getwd() 35 | if err != nil { 36 | log.Fatalf("error finding out pwd: %s", err.Error()) 37 | } 38 | pwd = path.Clean(pwd) 39 | 40 | day, err := strconv.ParseInt(path.Base(pwd), 10, 0) 41 | if err != nil { 42 | log.Fatalf("error computing day from pwd: %s", err.Error()) 43 | } 44 | 45 | year, err := strconv.ParseInt(path.Base(path.Dir(pwd)), 10, 0) 46 | if err != nil { 47 | log.Fatalf("error computing year from pwd: %s", err.Error()) 48 | } 49 | 50 | url := fmt.Sprintf(URL, year, day) 51 | log.Printf("downloading from %s in session %s...", url, session[:6]) 52 | 53 | jar, err := cookiejar.New(nil) 54 | if err != nil { 55 | log.Fatalf("error creating cookie jar: %s\n", err.Error()) 56 | } 57 | client = http.Client{ 58 | Jar: jar, 59 | } 60 | 61 | if err := downloadInputFile(OUT, url, session); err != nil { 62 | log.Fatalf("error downloading input file: %s", err.Error()) 63 | } 64 | } 65 | 66 | func downloadInputFile(filepath string, url string, session string) error { 67 | cookie := &http.Cookie{ 68 | Name: "session", 69 | Value: session, 70 | MaxAge: 300, 71 | } 72 | 73 | req, err := http.NewRequest("GET", url, nil) 74 | if err != nil { 75 | return fmt.Errorf("error building GET request: %w", err) 76 | } 77 | 78 | req.AddCookie(cookie) 79 | resp, err := client.Do(req) 80 | if err != nil { 81 | return fmt.Errorf("error making request: %w", err) 82 | } 83 | defer resp.Body.Close() 84 | 85 | out, err := os.Create(filepath) 86 | if err != nil { 87 | return fmt.Errorf("error creating file: %w", err) 88 | } 89 | defer out.Close() 90 | 91 | _, err = io.Copy(out, resp.Body) 92 | if err != nil { 93 | return fmt.Errorf("error while copying data: %w", err) 94 | } 95 | 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /2021/runtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #shellcheck disable=SC2046 # cmdline must split 4 | go run ./runtime/main.go $(find . -name time.md) 5 | -------------------------------------------------------------------------------- /2021/runtime/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/runtime 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2021/runtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | var runtime float64 14 | fmt.Println("| day | time |") 15 | fmt.Println("|-----|-----:|") 16 | for _, f := range os.Args[1:] { 17 | fd, err := os.Open(f) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | input := bufio.NewScanner(fd) 23 | times := make([]float64, 0, 2) 24 | for input.Scan() { 25 | line := input.Text() 26 | line = strings.Replace(line, "\\|", "", 1) 27 | if strings.Contains(line, "input.txt") { 28 | args := strings.Fields(strings.Split(line, "|")[2]) 29 | f, _ := strconv.ParseFloat(args[0], 64) 30 | times = append(times, f) 31 | } 32 | } 33 | fd.Close() 34 | labels := strings.Split(f, "/") 35 | label := labels[len(labels)-2] 36 | 37 | time := times[1] - times[0] 38 | if time < 0 { 39 | time = 0 40 | } 41 | fmt.Printf("| %s | %.1f |\n", label, time) 42 | runtime += time 43 | } 44 | fmt.Printf("| total | %.1f |\n", runtime) 45 | } 46 | -------------------------------------------------------------------------------- /2022/1/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/1/aoc1.go: -------------------------------------------------------------------------------- 1 | // aoc1.go -- 2 | // advent of code 2022 day 1 3 | // 4 | // https://adventofcode.com/2022/day/1 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-1: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | func main() { 20 | var m1, m2, m3, sum int 21 | 22 | max3 := func() { 23 | switch { 24 | case sum > m1: 25 | m1, m2, m3 = sum, m1, m2 26 | case sum > m2: 27 | m2, m3 = sum, m2 28 | case sum > m3: 29 | m3 = sum 30 | } 31 | } 32 | 33 | input := bufio.NewScanner(os.Stdin) 34 | for input.Scan() { 35 | if line := input.Text(); len(line) > 0 { 36 | sum += atoi(line) 37 | continue 38 | } 39 | 40 | max3() 41 | sum = 0 42 | } 43 | max3() 44 | 45 | fmt.Println(m1, m1+m2+m3) // part 1 & 2 46 | } 47 | 48 | // strconv.Atoi simplified core loop 49 | // s is ^\d+$ 50 | func atoi(s string) (n int) { 51 | for i := range s { 52 | n = 10*n + int(s[i]-'0') 53 | } 54 | return 55 | } 56 | -------------------------------------------------------------------------------- /2022/10/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/10/aoc10.go: -------------------------------------------------------------------------------- 1 | // aoc10.go -- 2 | // advent of code 2022 day 10 3 | // 4 | // https://adventofcode.com/2022/day/10 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-10: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "bytes" 16 | "fmt" 17 | "os" 18 | ) 19 | 20 | func main() { 21 | // machine initial state 22 | // register X, clock and signal strength 23 | X := 1 24 | clk, sig := 0, 0 25 | 26 | // part2 27 | const ( 28 | Black = ' ' 29 | // undefined is very bright 30 | White = '\uFFFD' 31 | ) 32 | 33 | // part2 decode/display message 34 | // synchronous scan display to fb 35 | var fb bytes.Buffer 36 | crt := func() { 37 | // sync beamer xpos 38 | bmx := clk%40 - 1 39 | if bmx < 0 { 40 | bmx += 40 41 | } 42 | 43 | // CR/LF beamer, slightly incorrect but ok 44 | if bmx == 0 { 45 | fb.WriteByte('\n') 46 | } 47 | 48 | // beam 49 | pix := Black 50 | if abs(X-bmx) <= 1 { 51 | // in range, light on! 52 | pix = White 53 | } 54 | fb.WriteByte(byte(pix)) 55 | } 56 | 57 | input := bufio.NewScanner(os.Stdin) 58 | for input.Scan() { 59 | // fetch instruction 60 | ins := input.Text() 61 | 62 | clk++ // tick 63 | crt() // beam CRT 64 | 65 | // decode, monitor power, beam CRT, execute 66 | switch ins[0] { 67 | case 'a': 68 | // part1 sync signal monitoring 69 | switch clk % 40 { 70 | default: 71 | clk++ 72 | case 19: 73 | clk++ 74 | sig += clk * X 75 | case 20: 76 | sig += clk * X 77 | clk++ 78 | } 79 | 80 | crt() // beam CRT 81 | 82 | // addx 83 | X += atoi(ins[5:]) 84 | case 'n': 85 | // part1 sync signal monitoring 86 | if clk%40 == 20 { 87 | sig += clk * X 88 | } 89 | // noop 90 | } 91 | 92 | } 93 | 94 | fmt.Print(sig) // part1 95 | fmt.Println(fb.String()) // part2 96 | } 97 | 98 | func abs(n int) int { 99 | if n < 0 { 100 | return -n 101 | } 102 | return n 103 | } 104 | 105 | // strconv.Atoi simplified core loop 106 | // s is ^-?\d+$ 107 | func atoi(s string) (n int) { 108 | neg := 1 109 | if s[0] == '-' { 110 | neg, s = -1, s[1:] 111 | } 112 | 113 | for i := range s { 114 | n = 10*n + int(s[i]-'0') 115 | } 116 | return neg * n 117 | } 118 | -------------------------------------------------------------------------------- /2022/10/sample.txt: -------------------------------------------------------------------------------- 1 | addx 15 2 | addx -11 3 | addx 6 4 | addx -3 5 | addx 5 6 | addx -1 7 | addx -8 8 | addx 13 9 | addx 4 10 | noop 11 | addx -1 12 | addx 5 13 | addx -1 14 | addx 5 15 | addx -1 16 | addx 5 17 | addx -1 18 | addx 5 19 | addx -1 20 | addx -35 21 | addx 1 22 | addx 24 23 | addx -19 24 | addx 1 25 | addx 16 26 | addx -11 27 | noop 28 | noop 29 | addx 21 30 | addx -15 31 | noop 32 | noop 33 | addx -3 34 | addx 9 35 | addx 1 36 | addx -3 37 | addx 8 38 | addx 1 39 | addx 5 40 | noop 41 | noop 42 | noop 43 | noop 44 | noop 45 | addx -36 46 | noop 47 | addx 1 48 | addx 7 49 | noop 50 | noop 51 | noop 52 | addx 2 53 | addx 6 54 | noop 55 | noop 56 | noop 57 | noop 58 | noop 59 | addx 1 60 | noop 61 | noop 62 | addx 7 63 | addx 1 64 | noop 65 | addx -13 66 | addx 13 67 | addx 7 68 | noop 69 | addx 1 70 | addx -33 71 | noop 72 | noop 73 | noop 74 | addx 2 75 | noop 76 | noop 77 | noop 78 | addx 8 79 | noop 80 | addx -1 81 | addx 2 82 | addx 1 83 | noop 84 | addx 17 85 | addx -9 86 | addx 1 87 | addx 1 88 | addx -3 89 | addx 11 90 | noop 91 | noop 92 | addx 1 93 | noop 94 | addx 1 95 | noop 96 | noop 97 | addx -13 98 | addx -19 99 | addx 1 100 | addx 3 101 | addx 26 102 | addx -30 103 | addx 12 104 | addx -1 105 | addx 3 106 | addx 1 107 | noop 108 | noop 109 | noop 110 | addx -9 111 | addx 18 112 | addx 1 113 | addx 2 114 | noop 115 | noop 116 | addx 9 117 | noop 118 | noop 119 | noop 120 | addx -1 121 | addx 2 122 | addx -37 123 | addx 1 124 | addx 3 125 | noop 126 | addx 15 127 | addx -21 128 | addx 22 129 | addx -6 130 | addx 1 131 | noop 132 | addx 2 133 | addx 1 134 | noop 135 | addx -10 136 | noop 137 | noop 138 | addx 20 139 | addx 1 140 | addx 2 141 | addx 2 142 | addx -6 143 | addx -11 144 | noop 145 | noop 146 | noop 147 | -------------------------------------------------------------------------------- /2022/11/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/11/sample.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 79, 98 3 | Operation: new = old * 19 4 | Test: divisible by 23 5 | If true: throw to monkey 2 6 | If false: throw to monkey 3 7 | 8 | Monkey 1: 9 | Starting items: 54, 65, 75, 74 10 | Operation: new = old + 6 11 | Test: divisible by 19 12 | If true: throw to monkey 2 13 | If false: throw to monkey 0 14 | 15 | Monkey 2: 16 | Starting items: 79, 60, 97 17 | Operation: new = old * old 18 | Test: divisible by 13 19 | If true: throw to monkey 1 20 | If false: throw to monkey 3 21 | 22 | Monkey 3: 23 | Starting items: 74 24 | Operation: new = old + 3 25 | Test: divisible by 17 26 | If true: throw to monkey 0 27 | If false: throw to monkey 1 28 | -------------------------------------------------------------------------------- /2022/12/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/12/sample.txt: -------------------------------------------------------------------------------- 1 | Sabqponm 2 | abcryxxl 3 | accszExk 4 | acctuvwj 5 | abdefghi 6 | -------------------------------------------------------------------------------- /2022/13/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/13/sample.txt: -------------------------------------------------------------------------------- 1 | [1,1,3,1,1] 2 | [1,1,5,1,1] 3 | 4 | [[1],[2,3,4]] 5 | [[1],4] 6 | 7 | [9] 8 | [[8,7,6]] 9 | 10 | [[4,4],4,4] 11 | [[4,4],4,4,4] 12 | 13 | [7,7,7,7] 14 | [7,7,7] 15 | 16 | [] 17 | [3] 18 | 19 | [[[]]] 20 | [[]] 21 | 22 | [1,[2,[3,[4,[5,6,7]]]],8,9] 23 | [1,[2,[3,[4,[5,6,0]]]],8,9] 24 | -------------------------------------------------------------------------------- /2022/14/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/14/sample.txt: -------------------------------------------------------------------------------- 1 | 498,4 -> 498,6 -> 496,6 2 | 503,4 -> 502,4 -> 502,9 -> 494,9 3 | -------------------------------------------------------------------------------- /2022/15/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/15/sample.txt: -------------------------------------------------------------------------------- 1 | Sensor at x=2, y=18: closest beacon is at x=-2, y=15 2 | Sensor at x=9, y=16: closest beacon is at x=10, y=16 3 | Sensor at x=13, y=2: closest beacon is at x=15, y=3 4 | Sensor at x=12, y=14: closest beacon is at x=10, y=16 5 | Sensor at x=10, y=20: closest beacon is at x=10, y=16 6 | Sensor at x=14, y=17: closest beacon is at x=10, y=16 7 | Sensor at x=8, y=7: closest beacon is at x=2, y=10 8 | Sensor at x=2, y=0: closest beacon is at x=2, y=10 9 | Sensor at x=0, y=11: closest beacon is at x=2, y=10 10 | Sensor at x=20, y=14: closest beacon is at x=25, y=17 11 | Sensor at x=17, y=20: closest beacon is at x=21, y=22 12 | Sensor at x=16, y=7: closest beacon is at x=15, y=3 13 | Sensor at x=14, y=3: closest beacon is at x=15, y=3 14 | Sensor at x=20, y=1: closest beacon is at x=15, y=3 15 | -------------------------------------------------------------------------------- /2022/16/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/16/sample.txt: -------------------------------------------------------------------------------- 1 | Valve AA has flow rate=0; tunnels lead to valves DD, II, BB 2 | Valve BB has flow rate=13; tunnels lead to valves CC, AA 3 | Valve CC has flow rate=2; tunnels lead to valves DD, BB 4 | Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE 5 | Valve EE has flow rate=3; tunnels lead to valves FF, DD 6 | Valve FF has flow rate=0; tunnels lead to valves EE, GG 7 | Valve GG has flow rate=0; tunnels lead to valves FF, HH 8 | Valve HH has flow rate=22; tunnel leads to valve GG 9 | Valve II has flow rate=0; tunnels lead to valves AA, JJ 10 | Valve JJ has flow rate=21; tunnel leads to valve II 11 | -------------------------------------------------------------------------------- /2022/17/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/17/sample.txt: -------------------------------------------------------------------------------- 1 | >>><<><>><<<>><>>><<<>>><<<><<<>><>><<>> -------------------------------------------------------------------------------- /2022/18/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/18/sample.txt: -------------------------------------------------------------------------------- 1 | 2,2,2 2 | 1,2,2 3 | 3,2,2 4 | 2,1,2 5 | 2,3,2 6 | 2,2,1 7 | 2,2,3 8 | 2,2,4 9 | 2,2,6 10 | 1,2,5 11 | 3,2,5 12 | 2,1,5 13 | 2,3,5 14 | -------------------------------------------------------------------------------- /2022/19/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/19/sample.txt: -------------------------------------------------------------------------------- 1 | Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. 2 | Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian. 3 | -------------------------------------------------------------------------------- /2022/2/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/2/aoc2.go: -------------------------------------------------------------------------------- 1 | // aoc2.go -- 2 | // advent of code 2022 day 2 3 | // 4 | // https://adventofcode.com/2022/day/2 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-2: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | // see day2 notes 20 | func main() { 21 | scale := []int{ 22 | 1, 2, 0, 23 | 0, 1, 2, 24 | 2, 0, 1, 25 | } 26 | 27 | scores := 0 28 | 29 | input := bufio.NewScanner(os.Stdin) 30 | for input.Scan() { 31 | line := input.Text() 32 | 33 | r := int(line[0] - 'A') // opponent move 34 | c := int(line[2] - 'X') // our move or goal 35 | 36 | // pack parts 1&2 scores 37 | scores += pack(1+c+3*scale[3*r+c], 1+scale[3*(2-c)+r]+3*c) // apply symmetry 38 | } 39 | 40 | fmt.Println(unpack(scores)) 41 | 42 | } 43 | 44 | const WIDTH = 16 45 | 46 | func pack(a, b int) int { 47 | return a<> WIDTH, n & ((1 << WIDTH) - 1) 52 | } 53 | -------------------------------------------------------------------------------- /2022/2/sample.txt: -------------------------------------------------------------------------------- 1 | A Y 2 | B X 3 | C Z 4 | -------------------------------------------------------------------------------- /2022/20/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/20/sample.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | -3 4 | 3 5 | -2 6 | 0 7 | 4 8 | -------------------------------------------------------------------------------- /2022/21/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/21/sample.txt: -------------------------------------------------------------------------------- 1 | root: pppw + sjmn 2 | dbpl: 5 3 | cczh: sllz + lgvd 4 | zczc: 2 5 | ptdq: humn - dvpt 6 | dvpt: 3 7 | lfqf: 4 8 | humn: 5 9 | ljgn: 2 10 | sjmn: drzm * dbpl 11 | sllz: 4 12 | pppw: cczh / lfqf 13 | lgvd: ljgn * ptdq 14 | drzm: hmdt - zczc 15 | hmdt: 32 16 | -------------------------------------------------------------------------------- /2022/22/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/22/sample.txt: -------------------------------------------------------------------------------- 1 | ...# 2 | .#.. 3 | #... 4 | .... 5 | ...#.......# 6 | ........#... 7 | ..#....#.... 8 | ..........#. 9 | ...#.... 10 | .....#.. 11 | .#...... 12 | ......#. 13 | 14 | 10R5L5R10L4R5L5 15 | -------------------------------------------------------------------------------- /2022/23/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/23/sample.txt: -------------------------------------------------------------------------------- 1 | .............. 2 | .............. 3 | .......#...... 4 | .....###.#.... 5 | ...#...#.#.... 6 | ....#...##.... 7 | ...#.###...... 8 | ...##.#.##.... 9 | ....#..#...... 10 | .............. 11 | .............. 12 | .............. 13 | -------------------------------------------------------------------------------- /2022/24/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/24/sample.txt: -------------------------------------------------------------------------------- 1 | #.###### 2 | #>>.<^<# 3 | #.<..<<# 4 | #>v.><># 5 | #<^v^^># 6 | ######.# 7 | -------------------------------------------------------------------------------- /2022/25/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/25/sample.txt: -------------------------------------------------------------------------------- 1 | 1=-0-2 2 | 12111 3 | 2=0= 4 | 21 5 | 2=01 6 | 111 7 | 20012 8 | 112 9 | 1=-1= 10 | 1-12 11 | 12 12 | 1= 13 | 122 14 | -------------------------------------------------------------------------------- /2022/3/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/3/aoc3.go: -------------------------------------------------------------------------------- 1 | // aoc3.go -- 2 | // advent of code 2022 day 3 3 | // 4 | // https://adventofcode.com/2022/day/3 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-3: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | // part indices 20 | const ( 21 | Part1 = iota 22 | Part2 23 | ) 24 | 25 | func main() { 26 | // stricly positive integers are required 27 | // see day3 notes 28 | const ( 29 | Head = 1 30 | Tail = 2 31 | ) 32 | 33 | prios := [2]int{} 34 | 35 | count := func(p int, c rune) { 36 | prios[p] += int(c - 'a' + 1) 37 | if c < 'a' { 38 | prios[p] += 'a' - 'A' + 26 39 | } 40 | } 41 | 42 | nline := 0 43 | chunk := [2][]int{} 44 | input := bufio.NewScanner(os.Stdin) 45 | for input.Scan() { 46 | seen := make([]int, 128) 47 | 48 | line := input.Text() 49 | 50 | // part1 scan 51 | head, tail := line[:len(line)/2], line[len(line)/2:] 52 | 53 | // turn head into a set 54 | for _, c := range head { 55 | seen[c] = Head 56 | } 57 | 58 | // intersect while adding tail to the set 59 | for _, c := range tail { 60 | if seen[c] == Head { 61 | // head and tail common item 62 | count(Part1, c) 63 | } 64 | seen[c] = Tail 65 | } 66 | 67 | // part2 68 | if nline%3 == 2 { 69 | // chunk scan every 3 input lines 70 | for _, c := range line { 71 | if chunk[0][c]*chunk[1][c] > 0 { 72 | // chunk common badge 73 | count(Part2, c) 74 | break // done scanning! 75 | } 76 | } 77 | } 78 | 79 | // store set according to line parity 80 | chunk[nline&1] = seen 81 | nline++ // input is 300 lines 82 | } 83 | 84 | fmt.Println(prios[Part1], prios[Part2]) 85 | } 86 | -------------------------------------------------------------------------------- /2022/3/sample.txt: -------------------------------------------------------------------------------- 1 | vJrwpWtwJgWrhcsFMMfFFhFp 2 | jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL 3 | PmmdzqPrVvPwwTWBwg 4 | wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn 5 | ttgJtRGJQctTZtZT 6 | CrZsJsPPZsGzwwsLwLmpwMDw -------------------------------------------------------------------------------- /2022/4/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/4/aoc4.go: -------------------------------------------------------------------------------- 1 | // aoc4.go -- 2 | // advent of code 2022 day 4 3 | // 4 | // https://adventofcode.com/2022/day/4 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-4: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | // part indices 21 | const ( 22 | Part1 = iota 23 | Part2 24 | ) 25 | 26 | func main() { 27 | counts := [2]int{} 28 | 29 | input := bufio.NewScanner(os.Stdin) 30 | for input.Scan() { 31 | // input text: ^(\d+)-(\d+),(\d+)-(\d+)$ 32 | // fields: 0 1 2 3 33 | // varname: l1 r1 l2 r2 34 | fields := strings.FieldsFunc( 35 | input.Text(), 36 | func(r rune) bool { 37 | return r == '-' || r == ',' 38 | }, 39 | ) 40 | 41 | l1 := atoi(fields[0]) 42 | r1 := atoi(fields[1]) 43 | l2 := atoi(fields[2]) 44 | r2 := atoi(fields[3]) 45 | 46 | // closed segments layout ex. 47 | // l1 r1 48 | // |----------| 49 | // |-------| 50 | // l2 r2 51 | switch { 52 | case (l1-l2)*(r1-r2) <= 0: // 1D contains 53 | counts[Part1]++ 54 | case (l1-r2)*(r1-l2) <= 0: // 1D intersect 55 | counts[Part2]++ 56 | } 57 | } 58 | 59 | // every contained segment is intersecting as well 60 | fmt.Println(counts[Part1], counts[Part1]+counts[Part2]) 61 | } 62 | 63 | // strconv.Atoi simplified core loop 64 | // s is ^\d+$ 65 | func atoi(s string) (n int) { 66 | for i := range s { 67 | n = 10*n + int(s[i]-'0') 68 | } 69 | return 70 | } 71 | -------------------------------------------------------------------------------- /2022/4/sample.txt: -------------------------------------------------------------------------------- 1 | 2-4,6-8 2 | 2-3,4-5 3 | 5-7,7-9 4 | 2-8,3-7 5 | 6-6,4-6 6 | 2-6,4-8 -------------------------------------------------------------------------------- /2022/5/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/6/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/6/aoc6.go: -------------------------------------------------------------------------------- 1 | // aoc6.go -- 2 | // advent of code 2022 day 6 3 | // 4 | // https://adventofcode.com/2022/day/6 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-6: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | func main() { 20 | // state handlers for parts 1&2 21 | // https://go.dev/talks/2011/lex.slide 22 | type state func(int) (next state, match bool) 23 | 24 | var ( 25 | wlen int 26 | seen [128]int 27 | part1, part2 state 28 | ) 29 | 30 | // https://go.dev/talks/2011/lex.slide#19 31 | part1 = func(wlen int) (next state, match bool) { 32 | if wlen == 4 { 33 | return part2, true // part1 done, transition to part2 34 | } 35 | return part1, false // part1 not done, no match 36 | } 37 | 38 | part2 = func(wlen int) (next state, match bool) { 39 | if wlen == 14 { 40 | return nil, true // part2 done, transition to end 41 | } 42 | return part2, false // part2 not done, no match 43 | } 44 | 45 | // initial state is solving for part1 46 | check := part1 47 | 48 | // slide over single line input 49 | input := bufio.NewScanner(os.Stdin) 50 | input.Scan() 51 | for i, c := range input.Bytes() { 52 | // outside current window? 53 | // extend window! 54 | // or 55 | // repeating inside? 56 | // shrink window! 57 | switch { 58 | case i-seen[c] > wlen: 59 | wlen++ // extend right 60 | case i-seen[c] < wlen: 61 | wlen = i - seen[c] // shrink left 62 | } 63 | seen[c] = i 64 | 65 | // dynamic state machine 66 | // states are self transitioning check functions 67 | var match bool 68 | if check, match = check(wlen); match { 69 | fmt.Println(i + 1) 70 | if check == nil { // terminal state 71 | return 72 | } 73 | } 74 | 75 | // terminal state check could be here (canonical) but 76 | // in this case it would only be an extraneous test as 77 | // we already know that transitions occurs on matches 78 | // see https://go.dev/talks/2011/lex.slide#20 79 | // 80 | // if check == nil { // terminal state 81 | // return 82 | // } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /2022/6/sample.txt: -------------------------------------------------------------------------------- 1 | mjqjpqmgbljsphdztnvjfqwrcgsmlb 2 | bvwbjplbgvbhsrlpgdmjqwftvncz 3 | nppdvjthqldpwncqszvftbrmjlhg 4 | nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg 5 | zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw -------------------------------------------------------------------------------- /2022/7/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/7/aoc7.go: -------------------------------------------------------------------------------- 1 | // aoc7.go -- 2 | // advent of code 2022 day 7 3 | // 4 | // https://adventofcode.com/2022/day/7 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-7: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "slices" 18 | "sort" 19 | "strings" 20 | ) 21 | 22 | var subdirs []int // subdir sizes 23 | 24 | func main() { 25 | var root int // root size 26 | input := bufio.NewScanner(os.Stdin) 27 | input.Scan() 28 | _ = input.Text() // discard initial cd / 29 | root = tree(input) 30 | 31 | // part1 sum 32 | smalls := 0 33 | for i := 0; subdirs[i] <= 100_000; i++ { 34 | smalls += subdirs[i] 35 | } 36 | 37 | // part2 binsearch 38 | i := sort.SearchInts(subdirs, root-40_000_000) 39 | 40 | fmt.Println(smalls, subdirs[i]) 41 | } 42 | 43 | func tree(input *bufio.Scanner) int { 44 | root := 0 45 | for input.Scan() { 46 | line := input.Text() 47 | 48 | switch line[0] { 49 | case 'd': 50 | // discard dir 51 | case '$': 52 | fields := strings.Fields(line[2:]) 53 | if fields[0] == "cd" { 54 | switch fields[1] { 55 | case "..": 56 | return root 57 | default: 58 | subdir := tree(input) 59 | root += subdir 60 | subdirs = append(subdirs, subdir) 61 | } 62 | } 63 | // discard ls 64 | default: 65 | root += file(line) 66 | } 67 | } 68 | slices.Sort(subdirs) 69 | return root 70 | } 71 | 72 | func file(line string) int { 73 | fields := strings.Fields(line) 74 | return atoi(fields[0]) 75 | } 76 | 77 | // strconv.Atoi simplified core loop 78 | // s is ^\d+$ 79 | func atoi(s string) (n int) { 80 | for i := range s { 81 | n = 10*n + int(s[i]-'0') 82 | } 83 | return 84 | } 85 | -------------------------------------------------------------------------------- /2022/7/sample.txt: -------------------------------------------------------------------------------- 1 | $ cd / 2 | $ ls 3 | dir a 4 | 14848514 b.txt 5 | 8504156 c.dat 6 | dir d 7 | $ cd a 8 | $ ls 9 | dir e 10 | 29116 f 11 | 2557 g 12 | 62596 h.lst 13 | $ cd e 14 | $ ls 15 | 584 i 16 | $ cd .. 17 | $ cd .. 18 | $ cd d 19 | $ ls 20 | 4060174 j 21 | 8033020 d.log 22 | 5626152 d.ext 23 | 7214296 k 24 | -------------------------------------------------------------------------------- /2022/8/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/8/aoc8.go: -------------------------------------------------------------------------------- 1 | // aoc8.go -- 2 | // advent of code 2022 day 8 3 | // 4 | // https://adventofcode.com/2022/day/8 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2022-12-8: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | // part indices 20 | const ( 21 | Part1 = iota 22 | Part2 23 | ) 24 | 25 | func main() { 26 | counts := [2]int{0, 0} 27 | 28 | // store all axis 29 | M := make([][]byte, 0, 128) 30 | input := bufio.NewScanner(os.Stdin) 31 | for input.Scan() { 32 | M = append(M, []byte(input.Text())) 33 | } 34 | 35 | W, Σ := mirror(M), transpose(M) 36 | Ͻ := mirror(Σ) // Ͻ reads reverse (lunate) Σ 37 | 38 | views := func(x, y int) [4][]byte { 39 | U := Ͻ[x][len(Ͻ[0])-y:] // up 40 | L := W[y][len(W[0])-x:] // left 41 | R := M[y][x+1:] // right 42 | D := Σ[x][y+1:] // down 43 | 44 | return [4][]byte{U, L, R, D} 45 | } 46 | 47 | // part2 48 | dist := func(o byte, axis []byte) (int, byte) { 49 | var ( 50 | acc int 51 | x byte 52 | ) 53 | for _, x = range axis { 54 | acc++ 55 | if x >= o { 56 | break 57 | } 58 | } 59 | return acc, x 60 | } 61 | 62 | for y, r := range M { 63 | for x, o := range r { 64 | seen := false // part1 65 | count := 1 // part2 66 | 67 | for _, v := range views(x, y) { 68 | d, h := dist(o, v) 69 | 70 | // part1 71 | if !seen && o > h { 72 | counts[Part1]++ 73 | seen = true 74 | } 75 | 76 | // part2 77 | count *= d 78 | } 79 | 80 | // part2 81 | counts[Part2] = max(counts[Part2], count) 82 | } 83 | } 84 | 85 | fmt.Println(counts[Part1], counts[Part2]) 86 | } 87 | 88 | func transpose(m [][]byte) [][]byte { 89 | t := mkmat(len(m[0]), len(m)) 90 | for i := 0; i < len(t); i++ { 91 | r := t[i] 92 | for j := 0; j < len(r); j++ { 93 | r[j] = m[j][i] 94 | } 95 | } 96 | return t 97 | } 98 | 99 | func mirror(m [][]byte) [][]byte { 100 | t := mkmat(len(m[0]), len(m)) 101 | for i := 0; i < len(t); i++ { 102 | r := t[i] 103 | for j := 0; j < len(r); j++ { 104 | r[j] = m[i][len(r)-(j+1)] 105 | } 106 | } 107 | return t 108 | } 109 | 110 | func mkmat(h, w int) [][]byte { 111 | r := make([]byte, h*w) 112 | m := make([][]byte, h) 113 | lo, hi := 0, w 114 | for i := range m { 115 | m[i] = r[lo:hi:hi] 116 | lo, hi = hi, hi+w 117 | } 118 | return m 119 | } 120 | -------------------------------------------------------------------------------- /2022/8/sample.txt: -------------------------------------------------------------------------------- 1 | 30373 2 | 25512 3 | 65332 4 | 33549 5 | 35390 -------------------------------------------------------------------------------- /2022/9/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2022/9/sample.txt: -------------------------------------------------------------------------------- 1 | R 4 2 | U 4 3 | L 3 4 | D 1 5 | R 4 6 | D 1 7 | L 5 8 | R 2 9 | -------------------------------------------------------------------------------- /2022/Makefile: -------------------------------------------------------------------------------- 1 | GO = go build 2 | 3 | TARGETS := bench binrun build check clean header run 4 | 5 | SUBDIRS := $(wildcard */.) 6 | SUBDIRS := $(filter-out download/. header/. runtime/., $(SUBDIRS)) 7 | 8 | $(TARGETS): $(SUBDIRS) 9 | $(SUBDIRS): 10 | @$(MAKE) -C $@ $(MAKECMDGOALS) 11 | 12 | cyclo: 13 | @gocyclo -top 10 -avg . 14 | 15 | lines: 16 | @find . -name '*go' \( -not -iname "main.go" \) | grep -v 'v1' | xargs wc -l | sort 17 | 18 | runtime: 19 | @./runtime.sh | sort -n -k 4 > runtime.md 20 | 21 | .PHONY: $(TARGETS) $(SUBDIRS) cyclo lines runtime 22 | -------------------------------------------------------------------------------- /2022/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | hyperfine --warmup 100 "cat input.txt > /dev/null" "./${1} < input.txt" --export-markdown time.md 4 | -------------------------------------------------------------------------------- /2022/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2022/download/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/download 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2022/download/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "os" 11 | "path" 12 | "strconv" 13 | ) 14 | 15 | const ( 16 | OUT = "input.txt" 17 | URL = "https://adventofcode.com/%d/day/%d/input" 18 | ) 19 | 20 | var client http.Client 21 | 22 | func main() { 23 | if _, err := os.Stat(OUT); !errors.Is(err, os.ErrNotExist) { 24 | log.Printf("input file %s already exists", OUT) 25 | os.Exit(0) 26 | } 27 | 28 | session := os.Getenv("SESSION") 29 | if len(session) == 0 { 30 | log.Println("$SESSION not set") 31 | os.Exit(0) 32 | } 33 | 34 | pwd, err := os.Getwd() 35 | if err != nil { 36 | log.Fatalf("error finding out pwd: %s", err.Error()) 37 | } 38 | pwd = path.Clean(pwd) 39 | 40 | day, err := strconv.ParseInt(path.Base(pwd), 10, 0) 41 | if err != nil { 42 | log.Fatalf("error computing day from pwd: %s", err.Error()) 43 | } 44 | 45 | year, err := strconv.ParseInt(path.Base(path.Dir(pwd)), 10, 0) 46 | if err != nil { 47 | log.Fatalf("error computing year from pwd: %s", err.Error()) 48 | } 49 | 50 | url := fmt.Sprintf(URL, year, day) 51 | log.Printf("downloading from %s in session %s...", url, session[:6]) 52 | 53 | jar, err := cookiejar.New(nil) 54 | if err != nil { 55 | log.Fatalf("error creating cookie jar: %s\n", err.Error()) 56 | } 57 | client = http.Client{ 58 | Jar: jar, 59 | } 60 | 61 | if err := downloadInputFile(OUT, url, session); err != nil { 62 | log.Fatalf("error downloading input file: %s", err.Error()) 63 | } 64 | } 65 | 66 | func downloadInputFile(filepath string, url string, session string) error { 67 | cookie := &http.Cookie{ 68 | Name: "session", 69 | Value: session, 70 | MaxAge: 300, 71 | } 72 | 73 | req, err := http.NewRequest("GET", url, nil) 74 | if err != nil { 75 | return fmt.Errorf("error building GET request: %w", err) 76 | } 77 | 78 | req.AddCookie(cookie) 79 | resp, err := client.Do(req) 80 | if err != nil { 81 | return fmt.Errorf("error making request: %w", err) 82 | } 83 | defer resp.Body.Close() 84 | 85 | out, err := os.Create(filepath) 86 | if err != nil { 87 | return fmt.Errorf("error creating file: %w", err) 88 | } 89 | defer out.Close() 90 | 91 | _, err = io.Copy(out, resp.Body) 92 | if err != nil { 93 | return fmt.Errorf("error while copying data: %w", err) 94 | } 95 | 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /2022/runtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #shellcheck disable=SC2046 # cmdline must split 4 | go run ./runtime/main.go $(find . -name time.md) 5 | -------------------------------------------------------------------------------- /2022/runtime/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/runtime 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2022/runtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | var runtime float64 14 | fmt.Println("| day | time |") 15 | fmt.Println("|-----|-----:|") 16 | for _, f := range os.Args[1:] { 17 | fd, err := os.Open(f) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | input := bufio.NewScanner(fd) 23 | times := make([]float64, 0, 2) 24 | for input.Scan() { 25 | line := input.Text() 26 | line = strings.Replace(line, "\\|", "", 1) 27 | if strings.Contains(line, "input.txt") { 28 | args := strings.Fields(strings.Split(line, "|")[3]) 29 | f, _ := strconv.ParseFloat(args[0], 64) 30 | times = append(times, f) 31 | } 32 | } 33 | fd.Close() 34 | labels := strings.Split(f, "/") 35 | label := labels[len(labels)-2] 36 | 37 | time := times[1] - times[0] 38 | if time < 0 { 39 | time = 0 40 | } 41 | fmt.Printf("| %s | %.1f |\n", label, time) 42 | runtime += time 43 | } 44 | fmt.Printf("| total | %.1f |\n", runtime) 45 | } 46 | -------------------------------------------------------------------------------- /2023/1/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/1/sample.txt: -------------------------------------------------------------------------------- 1 | two1nine 2 | eightwothree 3 | abcone2threexyz 4 | xtwone3four 5 | 4nineeightseven2 6 | zoneight234 7 | 7pqrstsixteen 8 | -------------------------------------------------------------------------------- /2023/10/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/10/sample.txt: -------------------------------------------------------------------------------- 1 | .F----7F7F7F7F-7.... 2 | .|F--7||||||||FJ.... 3 | .||.FJ||||||||L7.... 4 | FJL7L7LJLJ||LJ.L-7.. 5 | L--J.L7...LJS7F-7L7. 6 | ....F-J..F7FJ|L7L7L7 7 | ....L7.F7||L7|.L7L7| 8 | .....|FJLJ|FJ|F7|.LJ 9 | ....FJL-7.||.||||... 10 | ....L---J.LJ.LJLJ... 11 | -------------------------------------------------------------------------------- /2023/11/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/11/aoc11.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "slices" 8 | ) 9 | 10 | func main() { 11 | u := make(universe, 0, 128) 12 | 13 | input := bufio.NewScanner(os.Stdin) 14 | for j := 0; input.Scan(); j++ { 15 | u = u.readline(j, input.Text()) 16 | } 17 | 18 | fmt.Println(u.pairdist(2), u.pairdist(1_000_000)) 19 | } 20 | 21 | type galaxy struct { 22 | y, x int 23 | } 24 | 25 | func cmp(a, b galaxy) int { 26 | if a.x == b.x { 27 | return a.y - b.y 28 | } 29 | return a.x - b.x 30 | } 31 | 32 | type universe []galaxy 33 | 34 | func (u universe) readline(j int, line string) universe { 35 | for i := range line { 36 | if line[i] == '#' { 37 | u = append(u, galaxy{j, i}) 38 | } 39 | } 40 | return u 41 | } 42 | 43 | func (u universe) split2D() [2][]int { 44 | X, Y := make([]int, len(u)), make([]int, len(u)) 45 | for i := range u { 46 | Y[i], X[i] = u[i].y, u[i].x 47 | } 48 | return [2][]int{Y, X} 49 | } 50 | 51 | func expand(C counter, k int) (CC counter) { 52 | type sd struct { 53 | src, dst int 54 | } 55 | 56 | remap := func(L []int) (T []sd) { 57 | T = make([]sd, 0, len(L)) 58 | CC = make(counter, len(L)) 59 | 60 | old := sd{-1, -1} 61 | for _, x := range L { 62 | n := old.dst + k*(x-old.src-1) + 1 63 | T = append(T, sd{x, n}) 64 | old = sd{x, n} 65 | } 66 | return 67 | } 68 | 69 | for _, x := range remap(C.list()) { 70 | CC[x.dst] = C[x.src] 71 | } 72 | 73 | return CC 74 | } 75 | 76 | // k factor, d pairwise distance sum 77 | func (u universe) pairdist(k int) (d int) { 78 | d = 0 79 | for _, dim := range u.split2D() { 80 | n := pairdist1D(expand(count(dim), k)) 81 | d += n 82 | } 83 | return 84 | } 85 | 86 | func pairdist1D(C counter) int { 87 | off, K, X := C.sum(), 0, 0 88 | for k, v := range C { 89 | K += k * v 90 | } 91 | 92 | acc := 0 93 | for _, x := range C.list() { 94 | k := K - off*(x-X) 95 | acc += k * C[x] 96 | off -= C[x] 97 | K, X = k, x 98 | } 99 | 100 | return acc 101 | } 102 | 103 | type counter map[int]int 104 | 105 | func count(L []int) (C counter) { 106 | C = make(counter, len(L)) 107 | for i := range L { 108 | C[L[i]]++ 109 | } 110 | return 111 | } 112 | 113 | func (C counter) list() (L []int) { 114 | L = make([]int, 0, len(C)) 115 | for i := range C { 116 | L = append(L, i) 117 | } 118 | slices.Sort(L) 119 | 120 | return 121 | } 122 | 123 | func (C counter) sum() (S int) { 124 | S = 0 125 | for _, x := range C { 126 | S += x 127 | } 128 | return 129 | } 130 | -------------------------------------------------------------------------------- /2023/11/sample.txt: -------------------------------------------------------------------------------- 1 | ...#...... 2 | .......#.. 3 | #......... 4 | .......... 5 | ......#... 6 | .#........ 7 | .........# 8 | .......... 9 | .......#.. 10 | #...#..... 11 | -------------------------------------------------------------------------------- /2023/12/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/12/aoc12.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | sum1, sum2 := 0, 0 12 | 13 | input := bufio.NewScanner(os.Stdin) 14 | for input.Scan() { 15 | input := fields(input.Text()) 16 | 17 | blocks := split(input[1], ",") 18 | 19 | springs1 := input[0] 20 | blocks1 := make([]int, len(blocks)) 21 | for i := range blocks { 22 | blocks1[i] = atoi(blocks[i]) 23 | } 24 | 25 | springs2 := join([]string{ 26 | springs1, springs1, springs1, springs1, springs1, 27 | }, "?") 28 | blocks2 := make([]int, 5*len(blocks1)) 29 | for i := 0; i < len(blocks2); i += len(blocks1) { 30 | copy(blocks2[i:], blocks1) 31 | } 32 | 33 | sum1 += solve(springs1, blocks1) 34 | sum2 += solve(springs2, blocks2) 35 | 36 | } 37 | fmt.Println(sum1, sum2) 38 | } 39 | 40 | func solve(springs string, blocks []int) int { 41 | springs = "." + strings.TrimRight(springs, ".") 42 | 43 | // rolling block arrangement counts 44 | // ie. dp table last 2 rows 45 | cur := make([]int, len(springs)+1) 46 | nxt := make([]int, len(springs)+1) 47 | 48 | cur[0] = 1 // match at start 49 | for i, c := range springs { 50 | if c == '#' { 51 | break 52 | } 53 | cur[i+1] = 1 54 | } 55 | 56 | for _, block := range blocks { 57 | build := 0 58 | // build current block in all possible locations 59 | for i, c := range springs { 60 | build++ 61 | if c == '.' { 62 | build = 0 // restart 63 | } 64 | 65 | // propagate current arrangement count 66 | if c != '#' { 67 | nxt[i+1] = nxt[i] 68 | } 69 | 70 | if build >= block && springs[i-block] != '#' { 71 | // current block is buildable in nxt[i+1] ways 72 | // accumulate arrangements of i springs into all blocks up to current 73 | nxt[i+1] += cur[i-block] 74 | } 75 | } 76 | 77 | // current is base counts for next block 78 | cur, nxt = nxt, cur 79 | clear(nxt) 80 | } 81 | 82 | // arrangements of all springs into all blocks 83 | return cur[len(cur)-1] 84 | } 85 | 86 | var ( 87 | fields = strings.Fields 88 | join = strings.Join 89 | split = strings.Split 90 | trimRight = strings.TrimRight 91 | ) 92 | 93 | // strconv.Atoi simplified core loop 94 | // s is ^\d+$ 95 | func atoi(s string) (n int) { 96 | for i := range s { 97 | n = 10*n + int(s[i]-'0') 98 | } 99 | return 100 | } 101 | -------------------------------------------------------------------------------- /2023/12/sample.txt: -------------------------------------------------------------------------------- 1 | ???.### 1,1,3 2 | .??..??...?##. 1,1,3 3 | ?#?#?#?#?#?#?#? 1,3,1,6 4 | ????.#...#... 4,1,1 5 | ????.######..#####. 1,6,5 6 | ?###???????? 3,2,1 7 | -------------------------------------------------------------------------------- /2023/13/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/13/sample.txt: -------------------------------------------------------------------------------- 1 | #.##..##. 2 | ..#.##.#. 3 | ##......# 4 | ##......# 5 | ..#.##.#. 6 | ..##..##. 7 | #.#.##.#. 8 | 9 | #...##..# 10 | #....#..# 11 | ..##..### 12 | #####.##. 13 | #####.##. 14 | ..##..### 15 | #....#..# 16 | -------------------------------------------------------------------------------- /2023/13/sample1.txt: -------------------------------------------------------------------------------- 1 | ..##. 2 | ##..# 3 | #...# 4 | ..##. 5 | ..##. 6 | -------------------------------------------------------------------------------- /2023/13/sample2.txt: -------------------------------------------------------------------------------- 1 | #.##..##. 2 | ..#.##.#. 3 | ##......# 4 | ##......# 5 | ..#.##.#. 6 | ..##..##. 7 | #.#.##.#. 8 | 9 | #...##..# 10 | #....#..# 11 | ..##..### 12 | #####.##. 13 | #####.##. 14 | ..##..### 15 | #....#..# 16 | 17 | .#.##.#.# 18 | .##..##.. 19 | .#.##.#.. 20 | #......## 21 | #......## 22 | .#.##.#.. 23 | .##..##.# 24 | 25 | #..#....# 26 | ###..##.. 27 | .##.##### 28 | .##.##### 29 | ###..##.. 30 | #..#....# 31 | #..##...# 32 | -------------------------------------------------------------------------------- /2023/13/sample4.txt: -------------------------------------------------------------------------------- 1 | ###....### 2 | ..#.###... 3 | #.#....### 4 | ..#.#..... 5 | #..#...##. 6 | -------------------------------------------------------------------------------- /2023/13/sample5.txt: -------------------------------------------------------------------------------- 1 | #.###.##..#.... 2 | .#.###.....#### 3 | ...##...###.##. 4 | ...######..#..# 5 | ##.#..#.##..##. 6 | .#.##..#....##. 7 | ##..##.#...#### 8 | .####..##.##### 9 | #.####.#....##. 10 | ..#.###.#..#..# 11 | ##...####...##. 12 | ##...####...##. 13 | ..#.###.#..#..# 14 | #.###..#....##. 15 | .####..##.##### 16 | -------------------------------------------------------------------------------- /2023/13/sample6.txt: -------------------------------------------------------------------------------- 1 | .##.######### 2 | #.####......# 3 | ####.#.####.# 4 | ....#.######. 5 | .##..##.##.## 6 | ....###....## 7 | ######......# 8 | ####.###..### 9 | #..#.#.#..#.# 10 | -------------------------------------------------------------------------------- /2023/14/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/14/sample.txt: -------------------------------------------------------------------------------- 1 | O....#.... 2 | O.OO#....# 3 | .....##... 4 | OO.#O....O 5 | .O.....O#. 6 | O.#..O.#.# 7 | ..O..#O..O 8 | .......O.. 9 | #....###.. 10 | #OO..#.... 11 | -------------------------------------------------------------------------------- /2023/15/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/15/sample.txt: -------------------------------------------------------------------------------- 1 | rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 2 | -------------------------------------------------------------------------------- /2023/16/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/16/sample.txt: -------------------------------------------------------------------------------- 1 | .|...\.... 2 | |.-.\..... 3 | .....|-... 4 | ........|. 5 | .......... 6 | .........\ 7 | ..../.\\.. 8 | .-.-/..|.. 9 | .|....-|.\ 10 | ..//.|.... 11 | -------------------------------------------------------------------------------- /2023/17/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/17/sample.txt: -------------------------------------------------------------------------------- 1 | 2413432311323 2 | 3215453535623 3 | 3255245654254 4 | 3446585845452 5 | 4546657867536 6 | 1438598798454 7 | 4457876987766 8 | 3637877979653 9 | 4654967986887 10 | 4564679986453 11 | 1224686865563 12 | 2546548887735 13 | 4322674655533 14 | -------------------------------------------------------------------------------- /2023/17/sample1.txt: -------------------------------------------------------------------------------- 1 | 111111111111 2 | 999999999991 3 | 999999999991 4 | 999999999991 5 | 999999999991 6 | -------------------------------------------------------------------------------- /2023/18/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/18/aoc18.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | 12 | var p1, p2 lagoon 13 | 14 | decode := func(s string) (byte, int) { 15 | θ := "RDLU"[s[len(s)-1]-'0'] // last char encodes R, D, L or U 16 | k := htoi(s[:len(s)-1]) // first chars encodes an hex number 17 | return θ, k 18 | } 19 | 20 | input := bufio.NewScanner(os.Stdin) 21 | for j := 0; input.Scan(); j++ { 22 | args := fields(input.Text()) 23 | 24 | θ, k := args[0][0], atoi(args[1]) 25 | p1 = p1.append(θ, k) 26 | 27 | x := args[2][2 : len(args[2])-1] // slice the hex part out of args[2] "^(#\h+)$" with \h hex digit 28 | p2 = p2.append(decode(x)) 29 | } 30 | 31 | fmt.Println(p1.area(), p2.area()) 32 | } 33 | 34 | type vec struct { 35 | y, x int 36 | } 37 | 38 | func (p vec) add(u vec) vec { 39 | return vec{p.y + u.y, p.x + u.x} 40 | } 41 | 42 | func (p vec) scale(k int) vec { 43 | return vec{k * p.y, k * p.x} 44 | } 45 | 46 | type lagoon struct { 47 | cur vec 48 | peri, lace int 49 | } 50 | 51 | func (p lagoon) append(θ byte, k int) lagoon { 52 | δ := []vec{ 53 | 'R': {0, -1}, 'D': {-1, 0}, 'L': {0, 1}, 'U': {1, 0}, 54 | } 55 | 56 | cur := p.cur 57 | new := cur.add(δ[θ].scale(k)) 58 | 59 | p.peri += k 60 | p.lace += cur.x*new.y - new.x*cur.y // shoelace formula 61 | 62 | p.cur = new 63 | return p 64 | } 65 | 66 | func (p lagoon) area() int { 67 | return (p.peri+p.lace)/2 + 1 68 | } 69 | 70 | var fields, index = strings.Fields, strings.Index 71 | 72 | // strconv.Atoi simplified core loop 73 | // s is ^\d+$ 74 | func atoi(s string) (n int) { 75 | for i := range s { 76 | n = 10*n + int(s[i]-'0') 77 | } 78 | return 79 | } 80 | 81 | func htoi(s string) (n int) { 82 | ctoi := func(c byte) int { 83 | return index("0123456789abcdef", string(c)) 84 | } 85 | 86 | for i := range s { 87 | n = 16*n + ctoi(s[i]) 88 | } 89 | return 90 | } 91 | -------------------------------------------------------------------------------- /2023/18/sample.txt: -------------------------------------------------------------------------------- 1 | R 6 (#70c710) 2 | D 5 (#0dc571) 3 | L 2 (#5713f0) 4 | D 2 (#d2c081) 5 | R 2 (#59c680) 6 | D 2 (#411b91) 7 | L 5 (#8ceee2) 8 | U 2 (#caa173) 9 | L 1 (#1b58a2) 10 | U 2 (#caa171) 11 | R 2 (#7807d2) 12 | U 3 (#a77fa3) 13 | L 2 (#015232) 14 | U 2 (#7a21e3) -------------------------------------------------------------------------------- /2023/19/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/19/sample.txt: -------------------------------------------------------------------------------- 1 | px{a<2006:qkq,m>2090:A,rfg} 2 | pv{a>1716:R,A} 3 | lnx{m>1548:A,A} 4 | rfg{s<537:gd,x>2440:R,A} 5 | qs{s>3448:A,lnx} 6 | qkq{x<1416:A,crn} 7 | crn{x>2662:A,R} 8 | in{s<1351:px,qqz} 9 | qqz{s>2770:qs,m<1801:hdj,R} 10 | gd{a>3333:R,R} 11 | hdj{m>838:A,pv} 12 | 13 | {x=787,m=2655,a=1222,s=2876} 14 | {x=1679,m=44,a=2067,s=496} 15 | {x=2036,m=264,a=79,s=2244} 16 | {x=2461,m=1339,a=466,s=291} 17 | {x=2127,m=1623,a=2188,s=1013} 18 | -------------------------------------------------------------------------------- /2023/2/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/2/aoc2.go: -------------------------------------------------------------------------------- 1 | // aoc2.go -- 2 | // advent of code 2023 day 2 3 | // 4 | // https://adventofcode.com/2023/day/2 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2023-12-2: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | func main() { 21 | idsum, pwsum := 0, 0 22 | 23 | input := bufio.NewScanner(os.Stdin) 24 | for i := 1; input.Scan(); i++ { 25 | valid, power := true, [3]int{} 26 | 27 | // input is ^Game \d+:\s(.*;\s)+(.*)$ 28 | input := input.Text() 29 | 30 | draws := split(input[index(input, ": ")+2:], "; ") // ditch "^Game X: " prefix, split tail 31 | for j := range draws { 32 | 33 | rgb := split(draws[j], ", ") // split game drawings 34 | for i := range rgb { 35 | fields := fields(rgb[i]) // split RGB component and count 36 | color := index("bgr", fields[1][:1]) // single char 'r', 'g' or 'b' -> R, G, B 37 | count := atoi(fields[0]) 38 | 39 | // check validity, part1 40 | valid = valid && count <= 14-color 41 | 42 | // record max RGB power, part2 43 | power[color] = max(power[color], count) 44 | } 45 | } 46 | if valid { 47 | idsum += i // part1 48 | } 49 | pwsum += power[B] * power[G] * power[R] // part2 50 | } 51 | fmt.Println(idsum, pwsum) 52 | } 53 | 54 | // package strings wrappers/sugars 55 | var index, fields, split = strings.Index, strings.Fields, strings.Split 56 | 57 | const ( 58 | B = iota 59 | G 60 | R 61 | ) 62 | 63 | // strconv.Atoi simplified core loop 64 | // s is ^\d+$ 65 | func atoi(s string) (n int) { 66 | for i := range s { 67 | n = 10*n + int(s[i]-'0') 68 | } 69 | return 70 | } 71 | 72 | var DEBUG = true 73 | 74 | func debug(a ...any) (int, error) { 75 | if DEBUG { 76 | return fmt.Println(a...) 77 | } 78 | return 0, nil 79 | } 80 | -------------------------------------------------------------------------------- /2023/2/sample.txt: -------------------------------------------------------------------------------- 1 | Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green 2 | Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue 3 | Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red 4 | Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red 5 | Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green 6 | -------------------------------------------------------------------------------- /2023/20/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/20/sample.txt: -------------------------------------------------------------------------------- 1 | broadcaster -> a 2 | %a -> inv, con 3 | &inv -> b 4 | %b -> con 5 | &con -> output 6 | -------------------------------------------------------------------------------- /2023/21/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/21/sample.txt: -------------------------------------------------------------------------------- 1 | ........... 2 | .....###.#. 3 | .###.##..#. 4 | ..#.#...#.. 5 | ....#.#.... 6 | .##..S####. 7 | .##..#...#. 8 | .......##.. 9 | .##.#.####. 10 | .##..##.##. 11 | ........... 12 | -------------------------------------------------------------------------------- /2023/22/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/22/sample.txt: -------------------------------------------------------------------------------- 1 | 1,0,1~1,2,1 2 | 0,0,2~2,0,2 3 | 0,2,3~2,2,3 4 | 0,0,4~0,2,4 5 | 2,0,5~2,2,5 6 | 0,1,6~2,1,6 7 | 1,1,8~1,1,9 -------------------------------------------------------------------------------- /2023/23/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/23/sample.txt: -------------------------------------------------------------------------------- 1 | #.##################### 2 | #.......#########...### 3 | #######.#########.#.### 4 | ###.....#.>.>.###.#.### 5 | ###v#####.#v#.###.#.### 6 | ###.>...#.#.#.....#...# 7 | ###v###.#.#.#########.# 8 | ###...#.#.#.......#...# 9 | #####.#.#.#######.#.### 10 | #.....#.#.#.......#...# 11 | #.#####.#.#.#########v# 12 | #.#...#...#...###...>.# 13 | #.#.#v#######v###.###v# 14 | #...#.>.#...>.>.#.###.# 15 | #####v#.#.###v#.#.###.# 16 | #.....#...#...#.#.#...# 17 | #.#########.###.#.#.### 18 | #...###...#...#...#.### 19 | ###.###.#.###v#####v### 20 | #...#...#.#.>.>.#.>.### 21 | #.###.###.#.###.#.#v### 22 | #.....###...###...#...# 23 | #####################.# 24 | -------------------------------------------------------------------------------- /2023/24/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/25/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/3/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/3/sample.txt: -------------------------------------------------------------------------------- 1 | 467..114.. 2 | ...*...... 3 | ..35..633. 4 | ......#... 5 | 617*...... 6 | .....+.58. 7 | ..592..... 8 | ......755. 9 | ...$.*.... 10 | .664.598.. -------------------------------------------------------------------------------- /2023/4/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/4/sample.txt: -------------------------------------------------------------------------------- 1 | Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 2 | Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 3 | Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 4 | Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 5 | Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 6 | Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 7 | -------------------------------------------------------------------------------- /2023/5/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/5/sample.txt: -------------------------------------------------------------------------------- 1 | seeds: 79 14 55 13 2 | 3 | seed-to-soil map: 4 | 50 98 2 5 | 52 50 48 6 | 7 | soil-to-fertilizer map: 8 | 0 15 37 9 | 37 52 2 10 | 39 0 15 11 | 12 | fertilizer-to-water map: 13 | 49 53 8 14 | 0 11 42 15 | 42 0 7 16 | 57 7 4 17 | 18 | water-to-light map: 19 | 88 18 7 20 | 18 25 70 21 | 22 | light-to-temperature map: 23 | 45 77 23 24 | 81 45 19 25 | 68 64 13 26 | 27 | temperature-to-humidity map: 28 | 0 69 1 29 | 1 0 69 30 | 31 | humidity-to-location map: 32 | 60 56 37 33 | 56 93 4 -------------------------------------------------------------------------------- /2023/6/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/6/sample.txt: -------------------------------------------------------------------------------- 1 | Time: 7 15 30 2 | Distance: 9 40 200 3 | -------------------------------------------------------------------------------- /2023/7/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/7/sample.txt: -------------------------------------------------------------------------------- 1 | 32T3K 765 2 | T55J5 684 3 | KK677 28 4 | KTJJT 220 5 | QQQJA 483 6 | -------------------------------------------------------------------------------- /2023/8/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/9/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2023/9/aoc9.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | const NELEM = 21 11 | 12 | func main() { 13 | sumL, sumR := 0, 0 14 | history := make([]int, NELEM) 15 | 16 | input := bufio.NewScanner(os.Stdin) 17 | for input.Scan() { 18 | fields := fields(input.Text()) 19 | for i := range fields { 20 | history[i] = atoi(fields[i]) 21 | } 22 | history = history[:len(fields)] 23 | L, R := next(history) 24 | 25 | sumL += L // part2 26 | sumR += R // part1 27 | } 28 | 29 | fmt.Println(sumR, sumL) 30 | } 31 | 32 | func isZero(a []int) bool { 33 | sum := 0 34 | for i := range a { 35 | sum |= a[i] 36 | } 37 | return sum == 0 38 | } 39 | 40 | func next(a []int) (int, int) { 41 | difs := make([]int, len(a)-1) 42 | 43 | for i := range a[:len(difs)] { 44 | difs[i] = a[i+1] - a[i] 45 | } 46 | 47 | if isZero(difs) { 48 | return a[0], a[0] 49 | } 50 | 51 | L, R := next(difs) 52 | return a[0] - L, a[len(a)-1] + R 53 | } 54 | 55 | var fields = strings.Fields 56 | 57 | // strconv.Atoi simplified core loop 58 | // s is ^-?\d+$ 59 | func atoi(s string) (n int) { 60 | neg := 1 61 | if s[0] == '-' { 62 | neg, s = -1, s[1:] 63 | } 64 | 65 | for i := range s { 66 | n = 10*n + int(s[i]-'0') 67 | } 68 | return neg * n 69 | } 70 | -------------------------------------------------------------------------------- /2023/9/sample.txt: -------------------------------------------------------------------------------- 1 | 0 3 6 9 12 15 2 | 1 3 6 10 15 21 3 | 10 13 16 21 30 45 4 | -------------------------------------------------------------------------------- /2023/Makefile: -------------------------------------------------------------------------------- 1 | GO = go build 2 | 3 | TARGETS := bench binrun build check clean header run 4 | 5 | SUBDIRS := $(wildcard */.) 6 | SUBDIRS := $(filter-out download/. header/. runtime/., $(SUBDIRS)) 7 | 8 | $(TARGETS): $(SUBDIRS) 9 | $(SUBDIRS): 10 | @$(MAKE) -C $@ $(MAKECMDGOALS) 11 | 12 | cyclo: 13 | @gocyclo -top 10 -avg . 14 | 15 | lines: 16 | @find . -name '*go' \( -not -iname "main.go" \) | grep -v 'v1' | xargs wc -l | sort 17 | 18 | runtime: 19 | @./runtime.sh | sort -n -k 4 > runtime.md 20 | 21 | .PHONY: $(TARGETS) $(SUBDIRS) cyclo lines runtime 22 | -------------------------------------------------------------------------------- /2023/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | hyperfine --warmup 100 "cat input.txt > /dev/null" "./${1} < input.txt" --export-markdown time.md 4 | -------------------------------------------------------------------------------- /2023/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2023/download/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/download 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2023/download/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "os" 11 | "path" 12 | "strconv" 13 | ) 14 | 15 | const ( 16 | OUT = "input.txt" 17 | URL = "https://adventofcode.com/%d/day/%d/input" 18 | ) 19 | 20 | var client http.Client 21 | 22 | func main() { 23 | if _, err := os.Stat(OUT); !errors.Is(err, os.ErrNotExist) { 24 | log.Printf("input file %s already exists", OUT) 25 | os.Exit(0) 26 | } 27 | 28 | session := os.Getenv("SESSION") 29 | if len(session) == 0 { 30 | log.Println("$SESSION not set") 31 | os.Exit(0) 32 | } 33 | 34 | pwd, err := os.Getwd() 35 | if err != nil { 36 | log.Fatalf("error finding out pwd: %s", err.Error()) 37 | } 38 | pwd = path.Clean(pwd) 39 | 40 | day, err := strconv.ParseInt(path.Base(pwd), 10, 0) 41 | if err != nil { 42 | log.Fatalf("error computing day from pwd: %s", err.Error()) 43 | } 44 | 45 | year, err := strconv.ParseInt(path.Base(path.Dir(pwd)), 10, 0) 46 | if err != nil { 47 | log.Fatalf("error computing year from pwd: %s", err.Error()) 48 | } 49 | 50 | url := fmt.Sprintf(URL, year, day) 51 | log.Printf("downloading from %s in session %s...", url, session[:6]) 52 | 53 | jar, err := cookiejar.New(nil) 54 | if err != nil { 55 | log.Fatalf("error creating cookie jar: %s\n", err.Error()) 56 | } 57 | client = http.Client{ 58 | Jar: jar, 59 | } 60 | 61 | if err := downloadInputFile(OUT, url, session); err != nil { 62 | log.Fatalf("error downloading input file: %s", err.Error()) 63 | } 64 | } 65 | 66 | func downloadInputFile(filepath string, url string, session string) error { 67 | cookie := &http.Cookie{ 68 | Name: "session", 69 | Value: session, 70 | MaxAge: 300, 71 | } 72 | 73 | req, err := http.NewRequest("GET", url, nil) 74 | if err != nil { 75 | return fmt.Errorf("error building GET request: %w", err) 76 | } 77 | 78 | req.AddCookie(cookie) 79 | resp, err := client.Do(req) 80 | if err != nil { 81 | return fmt.Errorf("error making request: %w", err) 82 | } 83 | defer resp.Body.Close() 84 | 85 | out, err := os.Create(filepath) 86 | if err != nil { 87 | return fmt.Errorf("error creating file: %w", err) 88 | } 89 | defer out.Close() 90 | 91 | _, err = io.Copy(out, resp.Body) 92 | if err != nil { 93 | return fmt.Errorf("error while copying data: %w", err) 94 | } 95 | 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /2023/runtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #shellcheck disable=SC2046 # cmdline must split 4 | go run ./runtime/main.go $(find . -name time.md) 5 | -------------------------------------------------------------------------------- /2023/runtime/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/runtime 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2023/runtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | var runtime float64 14 | fmt.Println("| day | time |") 15 | fmt.Println("|-----|-----:|") 16 | for _, f := range os.Args[1:] { 17 | fd, err := os.Open(f) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | input := bufio.NewScanner(fd) 23 | times := make([]float64, 0, 2) 24 | for input.Scan() { 25 | line := input.Text() 26 | line = strings.Replace(line, "\\|", "", 1) 27 | if strings.Contains(line, "input.txt") { 28 | args := strings.Fields(strings.Split(line, "|")[3]) 29 | f, _ := strconv.ParseFloat(args[0], 64) 30 | times = append(times, f) 31 | } 32 | } 33 | fd.Close() 34 | labels := strings.Split(f, "/") 35 | label := labels[len(labels)-2] 36 | 37 | time := times[1] - times[0] 38 | if time < 0 { 39 | time = 0 40 | } 41 | fmt.Printf("| %s | %.1f |\n", label, time) 42 | runtime += time 43 | } 44 | fmt.Printf("| total | %.1f |\n", runtime) 45 | } 46 | -------------------------------------------------------------------------------- /2024/1/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/1/aoc1.go: -------------------------------------------------------------------------------- 1 | // aoc1.go -- 2 | // advent of code 2024 day 1 3 | // 4 | // https://adventofcode.com/2024/day/1 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-1: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "slices" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | input := bufio.NewScanner(os.Stdin) 23 | 24 | var left, right []int 25 | for input.Scan() { 26 | words := strings.Fields(input.Text()) 27 | left = append(left, atoi(words[0])) 28 | right = append(right, atoi(words[1])) 29 | } 30 | 31 | // presort 32 | slices.Sort(left) 33 | slices.Sort(right) 34 | 35 | sum, sim := 0, 0 36 | for i := range left { 37 | sum += abs(left[i] - right[i]) // part 1 38 | sim += left[i] * popcnt(right, left[i]) // part 2 39 | } 40 | fmt.Println(sum, sim) // part 1 & 2 41 | } 42 | 43 | func popcnt(slice []int, n int) (count int) { 44 | // find the first occurrence of n using binary search 45 | start, _ := slices.BinarySearch(slice, n) 46 | 47 | // count the number of occurrences of n 48 | for _, x := range slice[start:] { 49 | if x != n { 50 | return 51 | } 52 | count++ 53 | } 54 | 55 | return 56 | } 57 | 58 | // strconv.Atoi simplified core loop 59 | // s is ^\d+$ 60 | func atoi(s string) (n int) { 61 | for i := range s { 62 | n = 10*n + int(s[i]-'0') 63 | } 64 | return 65 | } 66 | 67 | func abs(n int) int { 68 | if n < 0 { 69 | return -n 70 | } 71 | return n 72 | } 73 | -------------------------------------------------------------------------------- /2024/1/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/1/sample.txt: -------------------------------------------------------------------------------- 1 | 3 4 2 | 4 3 3 | 2 5 4 | 1 3 5 | 3 9 6 | 3 3 -------------------------------------------------------------------------------- /2024/1/stats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # Input file 4 | file="input.txt" 5 | 6 | # Extract the first and second columns into separate arrays 7 | col1=($(awk '{print $1}' $file)) 8 | col2=($(awk '{print $2}' $file)) 9 | 10 | # Function to count duplicates in an array 11 | count_duplicates() { 12 | local arr=("$@") 13 | local counts=() 14 | 15 | # Count occurrences using associative array 16 | for val in $arr; do 17 | ((counts[$val]++)) 18 | done 19 | 20 | # Count and print the number of duplicates 21 | local duplicate_count=0 22 | for val count in ${(kv)counts}; do 23 | if (( count > 1 )); then 24 | ((duplicate_count++)) 25 | fi 26 | done 27 | 28 | echo $duplicate_count 29 | } 30 | 31 | # Count duplicates for each column 32 | echo "Duplicates in column 1: $(count_duplicates $col1)" 33 | echo "Duplicates in column 2: $(count_duplicates $col2)" 34 | 35 | -------------------------------------------------------------------------------- /2024/10/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/10/aoc10.go: -------------------------------------------------------------------------------- 1 | // aoc10.go -- 2 | // advent of code 2024 day 10 3 | // 4 | // https://adventofcode.com/2024/day/10 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-10: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | const MAXDIM = 60 20 | 21 | type Cell struct { 22 | r, c int 23 | } 24 | 25 | func main() { 26 | grid := make([][]int, 0, MAXDIM) 27 | 28 | input := bufio.NewScanner(os.Stdin) 29 | for input.Scan() { 30 | line := input.Bytes() 31 | row := make([]int, 0, len(line)) 32 | for _, c := range line { 33 | row = append(row, btoi(c)) 34 | } 35 | grid = append(grid, row) 36 | } 37 | 38 | fmt.Println(solve(grid)) // part 1 & 2 39 | } 40 | 41 | var neighbors = []Cell{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} 42 | 43 | func solve(grid [][]int) (int, int) { 44 | H, W := len(grid), len(grid[0]) 45 | 46 | seen := make([][]bool, H) 47 | for i := range seen { 48 | seen[i] = make([]bool, W) 49 | } 50 | 51 | // recursive dfs search for paths 52 | var research func(p Cell, target int, goals map[Cell]bool) int 53 | research = func(p Cell, target int, goals map[Cell]bool) int { 54 | if p.r < 0 || p.r >= H || p.c < 0 || p.c >= W || seen[p.r][p.c] || grid[p.r][p.c] != target { 55 | return 0 56 | } 57 | 58 | // if we reach 9, we found a valid path 59 | if target == 9 { 60 | goals[p] = true // remember the goal 61 | return 1 // count the path 62 | } 63 | 64 | // mark the cell 65 | seen[p.r][p.c] = true 66 | 67 | // count the paths from the neighbors 68 | count := 0 69 | for _, x := range neighbors { 70 | count += research(add(p, x), target+1, goals) 71 | } 72 | 73 | // unmark the cell 74 | seen[p.r][p.c] = false 75 | return count 76 | } 77 | 78 | // path score 79 | scores := make(map[Cell]int, 318) // arbitrary but educated guess 80 | 81 | // find all starting points 82 | count2 := 0 83 | for r := 0; r < H; r++ { 84 | for c := 0; c < W; c++ { 85 | if grid[r][c] == 0 { 86 | goals := make(map[Cell]bool, 8) 87 | count2 += research(Cell{r, c}, 0, goals) 88 | scores[Cell{r, c}] = len(goals) 89 | } 90 | } 91 | } 92 | 93 | count1 := 0 94 | for _, v := range scores { 95 | count1 += v 96 | } 97 | 98 | return count1, count2 99 | } 100 | 101 | func add(a, b Cell) Cell { 102 | return Cell{a.r + b.r, a.c + b.c} 103 | } 104 | 105 | func btoi(b byte) int { 106 | return int(b - '0') 107 | } 108 | -------------------------------------------------------------------------------- /2024/10/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/10/sample.txt: -------------------------------------------------------------------------------- 1 | 89010123 2 | 78121874 3 | 87430965 4 | 96549874 5 | 45678903 6 | 32019012 7 | 01329801 8 | 10456732 -------------------------------------------------------------------------------- /2024/11/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/11/aoc11.go: -------------------------------------------------------------------------------- 1 | // aoc11.go -- 2 | // advent of code 2024 day 11 3 | // 4 | // https://adventofcode.com/2024/day/11 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-11: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | const MAXN = 3799 // arbitrary but educated guess 21 | 22 | func main() { 23 | stones := NewCounter(0) 24 | 25 | input := bufio.NewScanner(os.Stdin) 26 | for input.Scan() { 27 | for _, n := range strings.Fields(input.Text()) { 28 | stones[atoi(n)] = 1 29 | } 30 | } 31 | 32 | blink := func(n int) { 33 | for i := 0; i < n; i++ { 34 | stones = stones.Blink() 35 | } 36 | } 37 | 38 | blink(25) 39 | count1 := stones.Popcnt() 40 | 41 | blink(50) 42 | count2 := stones.Popcnt() 43 | 44 | fmt.Println(count1, count2) 45 | } 46 | 47 | type Counter map[int]int 48 | 49 | func NewCounter(size int) Counter { 50 | if size == 0 || size > MAXN { 51 | size = MAXN 52 | } 53 | return make(map[int]int, size) 54 | } 55 | 56 | func (c Counter) Popcnt() (pop int) { 57 | for _, n := range c { 58 | pop += n 59 | } 60 | return 61 | } 62 | 63 | func (c Counter) Blink() Counter { 64 | next := NewCounter(3 * len(c) / 2) 65 | for n, count := range c { 66 | for _, m := range blink(n) { 67 | next[m] += count 68 | } 69 | } 70 | return next 71 | } 72 | 73 | func blink(n int) []int { 74 | ndigit := log10(n) 75 | 76 | switch { 77 | case n == 0: 78 | return []int{1} 79 | case ndigit%2 == 0: 80 | // split stone in half 81 | d := pow10(ndigit / 2) 82 | return []int{n / d, n % d} 83 | default: 84 | return []int{2024 * n} 85 | } 86 | } 87 | 88 | func log10(n int) (i int) { 89 | for i = 0; n > 0; i++ { 90 | n /= 10 91 | } 92 | return 93 | } 94 | 95 | // pow10 returns 10^n for n in [0,6] in O(1) 96 | func pow10(n int) int { 97 | return []int{ 98 | 1, 10, 100, 1000, 10000, 100000, 1000000, 99 | }[n] 100 | } 101 | 102 | // strconv.Atoi simplified core loop 103 | // s is ^\d+$ 104 | func atoi(s string) (n int) { 105 | for i := range s { 106 | n = 10*n + int(s[i]-'0') 107 | } 108 | return 109 | } 110 | -------------------------------------------------------------------------------- /2024/11/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/11/sample.txt: -------------------------------------------------------------------------------- 1 | 125 17 -------------------------------------------------------------------------------- /2024/12/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/12/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/12/sample.txt: -------------------------------------------------------------------------------- 1 | RRRRIICCFF 2 | RRRRIICCCF 3 | VVRRRRCFFF 4 | VVRRRCJFFF 5 | VVVVCJJCFE 6 | VVIVCCJJEE 7 | VVIIICJJEE 8 | MIIIIIJJEE 9 | MIIISIJEEE 10 | MMMISSJEEE 11 | -------------------------------------------------------------------------------- /2024/13/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/13/aoc13.go: -------------------------------------------------------------------------------- 1 | // aoc13.go -- 2 | // advent of code 2024 day 13 3 | // 4 | // https://adventofcode.com/2024/day/13 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-13: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | func main() { 21 | var sum1, sum2 int 22 | 23 | system := make([]int, 0, 4) 24 | 25 | input := bufio.NewScanner(os.Stdin) 26 | for input.Scan() { 27 | line := input.Text() 28 | switch { 29 | case line == "": 30 | // reset system on new line 31 | system = system[:0] 32 | 33 | case line[0] == 'B': 34 | // read any button 35 | args := strings.Split(line[10:], ", ") 36 | system = append(system, atoi(args[0][2:]), atoi(args[1][2:])) 37 | 38 | case line[0] == 'P': 39 | // read target X, Y 40 | args := strings.Split(line[7:], ", ") 41 | system = append(system, atoi(args[0][2:]), atoi(args[1][2:])) 42 | 43 | // solve for A, B 44 | A, B := solve(system, 0) 45 | sum1 += A*3 + B // part 1 46 | 47 | A, B = solve(system, 10_000_000_000_000) 48 | sum2 += A*3 + B // part 2 49 | } 50 | } 51 | 52 | fmt.Println(sum1, sum2) // part 1 & 2 53 | } 54 | 55 | // solve for A, B 56 | func solve(sys []int, off int) (A, B int) { 57 | var Δ int 58 | 59 | // unpack system 60 | ax, ay, bx, by, X, Y := sys[0], sys[1], sys[2], sys[3], sys[4], sys[5] 61 | 62 | X += off 63 | Y += off 64 | 65 | // compute determinant 66 | Δ = ax*by - ay*bx 67 | 68 | if Δ == 0 { 69 | // no solution 70 | return 71 | } 72 | 73 | A = (X*by - Y*bx) / Δ 74 | B = (ax*Y - X*ay) / Δ 75 | 76 | // check solution 77 | if A < 0 || B < 0 || A*ax != X-B*bx || A*ay != Y-B*by { 78 | return 0, 0 // invalid! 79 | } 80 | 81 | // all done 82 | return 83 | } 84 | 85 | // strconv.Atoi simplified core loop 86 | // s is ^\d+$ 87 | func atoi(s string) (n int) { 88 | for i := range s { 89 | n = 10*n + int(s[i]-'0') 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /2024/13/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/13/sample.txt: -------------------------------------------------------------------------------- 1 | Button A: X+94, Y+34 2 | Button B: X+22, Y+67 3 | Prize: X=8400, Y=5400 4 | 5 | Button A: X+26, Y+66 6 | Button B: X+67, Y+21 7 | Prize: X=12748, Y=12176 8 | 9 | Button A: X+17, Y+86 10 | Button B: X+84, Y+37 11 | Prize: X=7870, Y=6450 12 | 13 | Button A: X+69, Y+23 14 | Button B: X+27, Y+71 15 | Prize: X=18641, Y=10279 16 | -------------------------------------------------------------------------------- /2024/14/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/14/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/14/sample.txt: -------------------------------------------------------------------------------- 1 | p=0,4 v=3,-3 2 | p=6,3 v=-1,-3 3 | p=10,3 v=-1,2 4 | p=2,0 v=2,-1 5 | p=0,0 v=1,3 6 | p=3,0 v=-2,-2 7 | p=7,6 v=-1,-3 8 | p=3,0 v=-1,-2 9 | p=9,3 v=2,3 10 | p=7,3 v=-1,2 11 | p=2,4 v=2,-3 12 | p=9,5 v=-3,-3 -------------------------------------------------------------------------------- /2024/15/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/15/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/15/sample.txt: -------------------------------------------------------------------------------- 1 | sample2.txt -------------------------------------------------------------------------------- /2024/15/sample1.txt: -------------------------------------------------------------------------------- 1 | ########## 2 | #..O..O.O# 3 | #...O..O.# 4 | #...O.O.O# 5 | #.OO@..O.# 6 | #O#.OOO..# 7 | #O..O..O.# 8 | #.OO.O.OO# 9 | #....O...# 10 | ########## 11 | 12 | ^vv>>^<<<^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ 13 | vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< 15 | <>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ 16 | ^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< 17 | ^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ 19 | <><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> 20 | ^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< 21 | v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ -------------------------------------------------------------------------------- /2024/15/sample3.txt: -------------------------------------------------------------------------------- 1 | ####### 2 | #...#.# 3 | #.....# 4 | #..OO@# 5 | #..O..# 6 | #.....# 7 | ####### 8 | 9 | /dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/16/sample.txt: -------------------------------------------------------------------------------- 1 | ############### 2 | #.......#....E# 3 | #.#.###.#.###.# 4 | #.....#.#...#.# 5 | #.###.#####.#.# 6 | #.#.#.......#.# 7 | #.#.#####.###.# 8 | #...........#.# 9 | ###.#.#####.#.# 10 | #...#.....#.#.# 11 | #.#.#.###.#.#.# 12 | #.....#...#.#.# 13 | #.###.#.#.#.#.# 14 | #S..#.....#...# 15 | ############### -------------------------------------------------------------------------------- /2024/17/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/17/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/17/sample.txt: -------------------------------------------------------------------------------- 1 | Register A: 729 2 | Register B: 0 3 | Register C: 0 4 | 5 | Program: 0,1,5,4,3,0 -------------------------------------------------------------------------------- /2024/18/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/18/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/18/sample.txt: -------------------------------------------------------------------------------- 1 | 5,4 2 | 4,2 3 | 4,5 4 | 3,0 5 | 2,1 6 | 6,3 7 | 2,4 8 | 1,5 9 | 0,6 10 | 3,3 11 | 2,6 12 | 5,1 13 | 1,2 14 | 5,5 15 | 2,5 16 | 6,5 17 | 1,4 18 | 0,4 19 | 6,4 20 | 1,1 21 | 6,1 22 | 1,0 23 | 0,5 24 | 1,6 25 | 2,0 -------------------------------------------------------------------------------- /2024/19/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/19/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/19/sample.txt: -------------------------------------------------------------------------------- 1 | r, wr, b, g, bwu, rb, gb, br 2 | 3 | brwrr 4 | bggr 5 | gbbr 6 | rrbgbr 7 | ubwu 8 | bwurrg 9 | brgr 10 | bbrgwb -------------------------------------------------------------------------------- /2024/2/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/2/aoc2.go: -------------------------------------------------------------------------------- 1 | // aoc2.go -- 2 | // advent of code 2024 day 2 3 | // 4 | // https://adventofcode.com/2024/day/2 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-2: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "strings" 18 | ) 19 | 20 | func main() { 21 | 22 | reports := make([][]int, 0, 1000) 23 | 24 | input := bufio.NewScanner(os.Stdin) 25 | for input.Scan() { 26 | words := strings.Fields(input.Text()) 27 | report := make([]int, len(words)) 28 | for i, word := range words { 29 | report[i] = atoi(word) 30 | } 31 | reports = append(reports, report) 32 | } 33 | 34 | var count1, count2 int // safe reports with no or a single error 35 | for _, r := range reports { 36 | switch { 37 | case safe(r, 0): 38 | // safe without any error 39 | count1++ 40 | case safe(r, 1): 41 | // safe by removing a single misplaced element 42 | count2++ 43 | } 44 | } 45 | 46 | fmt.Println(count1, count1+count2) // part 1 & 2 47 | } 48 | 49 | func safe(report []int, maxerr int) bool { 50 | // determine the trend from the first two elements 51 | trends := []bool{report[1] > report[0], report[2] > report[1]} 52 | increasing := trends[0] 53 | 54 | // catch a misplaced first element 55 | if maxerr > 0 && trends[0] != trends[1] && safe(report[1:], maxerr-1) { 56 | return true 57 | } 58 | 59 | // find the first misplaced element if any 60 | for i := 1; i < len(report); i++ { 61 | diff := report[i] - report[i-1] 62 | 63 | unsafe := abs(diff) < 1 || abs(diff) > 3 || (increasing && diff <= 0) || (!increasing && diff >= 0) 64 | if unsafe { 65 | if maxerr == 0 { 66 | return false 67 | } 68 | 69 | // attempt to remove either the previous or the current element in turn and check 70 | // if the resulting report is safe 71 | left, right := remove(clone(report), i-1), remove(report, i) 72 | return safe(left, maxerr-1) || safe(right, maxerr-1) 73 | } 74 | } 75 | 76 | return true 77 | } 78 | 79 | func clone(slice []int) []int { 80 | return append([]int(nil), slice...) 81 | } 82 | 83 | func remove(slice []int, i int) []int { 84 | return append(slice[:i], slice[i+1:]...) 85 | } 86 | 87 | // strconv.Atoi simplified core loop 88 | // s is ^\d+$ 89 | func atoi(s string) (n int) { 90 | for i := range s { 91 | n = 10*n + int(s[i]-'0') 92 | } 93 | return 94 | } 95 | 96 | func abs(n int) int { 97 | if n < 0 { 98 | return -n 99 | } 100 | return n 101 | } 102 | -------------------------------------------------------------------------------- /2024/2/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/2/sample.txt: -------------------------------------------------------------------------------- 1 | 7 6 4 2 1 2 | 1 2 7 8 9 3 | 9 7 6 2 1 4 | 1 3 2 4 5 5 | 8 6 4 4 1 6 | 1 3 6 7 9 7 | 34 33 34 35 38 41 42 45 -------------------------------------------------------------------------------- /2024/20/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/20/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/20/sample.txt: -------------------------------------------------------------------------------- 1 | ############### 2 | #...#...#.....# 3 | #.#.#.#.#.###.# 4 | #S#...#.#.#...# 5 | #######.#.#.### 6 | #######.#.#...# 7 | #######.#.###.# 8 | ###..E#...#...# 9 | ###.#######.### 10 | #...###...#...# 11 | #.#####.#.###.# 12 | #.#...#.#.#...# 13 | #.#.#.#.#.#.### 14 | #...#...#...### 15 | ############### -------------------------------------------------------------------------------- /2024/21/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/21/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/21/sample.txt: -------------------------------------------------------------------------------- 1 | 029A 2 | 980A 3 | 179A 4 | 456A 5 | 379A -------------------------------------------------------------------------------- /2024/22/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/22/aoc22.go: -------------------------------------------------------------------------------- 1 | // aoc22.go -- 2 | // advent of code 2024 day 22 3 | // 4 | // https://adventofcode.com/2024/day/22 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-22: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "slices" 18 | ) 19 | 20 | const ( 21 | VOFF = 9 22 | NLOOP = 2000 23 | MAXDIM = 0xFFFFF 24 | ) 25 | 26 | func main() { 27 | seqs := make([]int, MAXDIM) 28 | 29 | sum1 := 0 30 | input := bufio.NewScanner(os.Stdin) 31 | for input.Scan() { 32 | n := atoi(input.Text()) 33 | sum1 += rehash(n, NLOOP, seqs) 34 | } 35 | 36 | count2 := slices.Max(seqs) 37 | 38 | fmt.Println(sum1, count2) // part 1 & 2 39 | } 40 | 41 | const MinInt = -1 << 31 42 | 43 | var SEEN = make([]int, MAXDIM) 44 | 45 | func rehash(a, n int, seqs []int) int { 46 | color := a 47 | 48 | // loop on digits 49 | key, cur := 0, a%10 50 | for i := 0; i < n; i++ { 51 | a = hash(a) // rehash 52 | nxt := a % 10 // next digit 53 | 54 | δ := nxt - cur + VOFF // vertical offset to avoid negative keys 55 | key = ((key << 5) & MAXDIM) + δ // running key 56 | 57 | if i > 3 && SEEN[key] != color { // color as seen 58 | SEEN[key] = color 59 | seqs[key] += nxt 60 | } 61 | 62 | cur = nxt 63 | } 64 | 65 | return a 66 | } 67 | 68 | func hash(a int) int { 69 | a ^= (a << 6) & 0xFFFFFF 70 | a ^= (a >> 5) & 0xFFFFFF 71 | a ^= (a << 11) & 0xFFFFFF 72 | return a 73 | } 74 | 75 | // strconv.Atoi simplified core loop 76 | // s is ^\d+$ 77 | func atoi(s string) (n int) { 78 | for i := range s { 79 | n = 10*n + int(s[i]-'0') 80 | } 81 | return 82 | } 83 | -------------------------------------------------------------------------------- /2024/22/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/22/sample.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 2024 5 | -------------------------------------------------------------------------------- /2024/23/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/23/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/23/sample.txt: -------------------------------------------------------------------------------- 1 | kh-tc 2 | qp-kh 3 | de-cg 4 | ka-co 5 | yn-aq 6 | qp-ub 7 | cg-tb 8 | vc-aq 9 | tb-ka 10 | wh-tc 11 | yn-cg 12 | kh-ub 13 | ta-co 14 | de-co 15 | tc-td 16 | tb-wq 17 | wh-td 18 | ta-ka 19 | td-qp 20 | aq-cg 21 | wq-ub 22 | ub-vc 23 | de-ta 24 | wq-aq 25 | wq-vc 26 | wh-yn 27 | ka-de 28 | kh-ta 29 | co-tc 30 | wh-qp 31 | tb-vc 32 | td-yn -------------------------------------------------------------------------------- /2024/24/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/24/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/24/sample.txt: -------------------------------------------------------------------------------- 1 | x00: 1 2 | x01: 0 3 | x02: 1 4 | x03: 1 5 | x04: 0 6 | y00: 1 7 | y01: 1 8 | y02: 1 9 | y03: 1 10 | y04: 1 11 | 12 | ntg XOR fgs -> mjb 13 | y02 OR x01 -> tnw 14 | kwq OR kpj -> z05 15 | x00 OR x03 -> fst 16 | tgd XOR rvg -> z01 17 | vdt OR tnw -> bfw 18 | bfw AND frj -> z10 19 | ffh OR nrd -> bqk 20 | y00 AND y03 -> djm 21 | y03 OR y00 -> psh 22 | bqk OR frj -> z08 23 | tnw OR fst -> frj 24 | gnj AND tgd -> z11 25 | bfw XOR mjb -> z00 26 | x03 OR x00 -> vdt 27 | gnj AND wpb -> z02 28 | x04 AND y00 -> kjc 29 | djm OR pbm -> qhw 30 | nrd AND vdt -> hwm 31 | kjc AND fst -> rvg 32 | y04 OR y02 -> fgs 33 | y01 AND x02 -> pbm 34 | ntg OR kjc -> kwq 35 | psh XOR fgs -> tgd 36 | qhw XOR tgd -> z09 37 | pbm OR djm -> kpj 38 | x03 XOR y03 -> ffh 39 | x00 XOR y04 -> ntg 40 | bfw OR bqk -> z06 41 | nrd XOR fgs -> wpb 42 | frj XOR qhw -> z04 43 | bqk OR frj -> z07 44 | y03 OR x01 -> nrd 45 | hwm AND bqk -> z03 46 | tgd XOR rvg -> z12 47 | tnw OR pbm -> gnj -------------------------------------------------------------------------------- /2024/25/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/25/aoc25.go: -------------------------------------------------------------------------------- 1 | // aoc25.go -- 2 | // advent of code 2024 day 25 3 | // 4 | // https://adventofcode.com/2024/day/25 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-25: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | func main() { 20 | schems := make([]int, 0, 500) 21 | 22 | input := bufio.NewScanner(os.Stdin) 23 | var hash int 24 | for input.Scan() { 25 | row := input.Bytes() 26 | switch { 27 | case len(row) == 0: 28 | schems, hash = append(schems, hash), 0 29 | default: 30 | for _, c := range row { 31 | hash <<= 1 32 | if c == '#' { 33 | hash |= 1 34 | } 35 | } 36 | } 37 | } 38 | schems = append(schems, hash) 39 | 40 | count1 := 0 41 | for i, a := range schems[:len(schems)-1] { 42 | for _, b := range schems[i+1:] { 43 | if a^b == a+b { 44 | count1++ 45 | } 46 | } 47 | } 48 | 49 | fmt.Println(count1) // part 1 50 | } 51 | 52 | // ____ ___ _____ _____ _________ _______________ ________ _____ 53 | // \ \/ / / \ / _ \ / _____/ \_____ \ _ \ \_____ \ / | | 54 | // \ / ______ / \ / \ / /_\ \ \_____ \ / ____/ /_\ \ / ____/ / | |_ 55 | // / \ /_____/ / Y \/ | \/ \ / \ \_/ \/ \/ ^ / 56 | // /___/\ \ \____|__ /\____|__ /_______ / \_______ \_____ /\_______ \____ | 57 | // \_/ \/ \/ \/ \/ \/ \/ |__| 58 | // ___________ __ .__ _____ _________ 59 | // /_ \ _ \_/ |_| |__ / _ \ ____ \_ ___ \ 60 | // | / /_\ \ __\ | \ / /_\ \ / _ \/ \ \/ 61 | // | \ \_/ \ | | Y \ / | ( <_> ) \____ 62 | // |___|\_____ /__| |___| / \____|__ /\____/ \______ / 63 | // \/ \/ \/ \/ 64 | -------------------------------------------------------------------------------- /2024/25/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/25/sample.txt: -------------------------------------------------------------------------------- 1 | ##### 2 | .#### 3 | .#### 4 | .#### 5 | .#.#. 6 | .#... 7 | ..... 8 | 9 | ##### 10 | ##.## 11 | .#.## 12 | ...## 13 | ...#. 14 | ...#. 15 | ..... 16 | 17 | ..... 18 | #.... 19 | #.... 20 | #...# 21 | #.#.# 22 | #.### 23 | ##### 24 | 25 | ..... 26 | ..... 27 | #.#.. 28 | ###.. 29 | ###.# 30 | ###.# 31 | ##### 32 | 33 | ..... 34 | ..... 35 | ..... 36 | #.... 37 | #.#.. 38 | #.#.# 39 | ##### -------------------------------------------------------------------------------- /2024/3/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/3/aoc3.go: -------------------------------------------------------------------------------- 1 | // aoc3.go -- 2 | // advent of code 2024 day 3 3 | // 4 | // https://adventofcode.com/2024/day/3 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-3: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "fmt" 15 | "os" 16 | "regexp" 17 | ) 18 | 19 | const ( 20 | IN = iota 21 | OUT 22 | ) 23 | 24 | func main() { 25 | data, err := os.ReadFile("input.txt") 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | re := regexp.MustCompile(`mul\((\d+),(\d+)\)|do\(\)|don\'t\(\)`) 31 | matches := re.FindAllStringSubmatch(string(data), -1) 32 | 33 | sum1, sum2 := 0, 0 34 | state := IN 35 | for _, match := range matches { 36 | switch match[0] { 37 | case "do()": 38 | state = IN 39 | case "don't()": 40 | state = OUT 41 | default: 42 | n := atoi(match[1]) * atoi(match[2]) 43 | sum1 += n 44 | if state == IN { 45 | sum2 += n 46 | } 47 | } 48 | } 49 | fmt.Println(sum1, sum2) 50 | } 51 | 52 | func atoi(s string) (n int) { 53 | for i := range s { 54 | n = 10*n + int(s[i]-'0') 55 | } 56 | return 57 | } 58 | -------------------------------------------------------------------------------- /2024/3/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/3/sample.txt: -------------------------------------------------------------------------------- 1 | xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5)) -------------------------------------------------------------------------------- /2024/4/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/4/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/4/sample.txt: -------------------------------------------------------------------------------- 1 | MMMSXXMASM 2 | MSAMXMSMSA 3 | AMXSXMAAMM 4 | MSAMASMSMX 5 | XMASAMXAMM 6 | XXAMMXXAMA 7 | SMSMSASXSS 8 | SAXAMASAAA 9 | MAMMMXMMMM 10 | MXMXAXMASX -------------------------------------------------------------------------------- /2024/5/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/5/aoc5.go: -------------------------------------------------------------------------------- 1 | // aoc5.go -- 2 | // advent of code 2024 day 5 3 | // 4 | // https://adventofcode.com/2024/day/5 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-5: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "slices" 18 | "strings" 19 | ) 20 | 21 | const ( 22 | RULE = iota 23 | UPDATE 24 | ) 25 | 26 | func main() { 27 | sum1, sum2 := 0, 0 28 | rules := [100][]int{} 29 | for i := range rules { 30 | // preallocate 24 rules per index 31 | rules[i] = make([]int, 0, 24) 32 | } 33 | 34 | state := RULE 35 | input := bufio.NewScanner(os.Stdin) 36 | for input.Scan() { 37 | line := input.Text() 38 | if line == "" { 39 | state = UPDATE 40 | continue 41 | } 42 | 43 | switch state { 44 | case RULE: 45 | words := strings.Split(line, "|") 46 | cur, nxt := atoi(words[0]), atoi(words[1]) 47 | rules[cur] = append(rules[cur], nxt) 48 | case UPDATE: 49 | words := strings.Split(line, ",") 50 | indices := make([]int, len(words)) 51 | for i, w := range words { 52 | indices[i] = atoi(w) 53 | } 54 | 55 | sum1 += median(indices) 56 | if !safe(indices, rules) { 57 | sum1 -= median(indices) 58 | sum2 += median(sort(indices, rules)) 59 | } 60 | } 61 | } 62 | fmt.Println(sum1, sum2) // part 1 & 2 63 | } 64 | 65 | func safe(indices []int, rules [100][]int) bool { 66 | pre := indices[0] 67 | for _, cur := range indices[1:] { 68 | if !slices.Contains(rules[pre], cur) { 69 | return false 70 | } 71 | pre = cur 72 | } 73 | 74 | return true 75 | } 76 | 77 | func sort(indices []int, rules [100][]int) []int { 78 | slices.SortFunc(indices, func(a, b int) int { 79 | if slices.Contains(rules[b], a) { 80 | return -1 81 | } 82 | return 0 83 | }) 84 | return indices 85 | } 86 | 87 | func median(indices []int) int { 88 | return indices[len(indices)/2] 89 | } 90 | 91 | // strconv.Atoi simplified core loop 92 | // s is ^\d+$ 93 | func atoi(s string) (n int) { 94 | for i := range s { 95 | n = 10*n + int(s[i]-'0') 96 | } 97 | return 98 | } 99 | -------------------------------------------------------------------------------- /2024/5/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/5/sample.txt: -------------------------------------------------------------------------------- 1 | 47|53 2 | 97|13 3 | 97|61 4 | 97|47 5 | 75|29 6 | 61|13 7 | 75|53 8 | 29|13 9 | 97|29 10 | 53|29 11 | 61|53 12 | 97|53 13 | 61|29 14 | 47|13 15 | 75|47 16 | 97|75 17 | 47|61 18 | 75|61 19 | 47|29 20 | 75|13 21 | 53|13 22 | 23 | 75,47,61,53,29 24 | 97,61,53,29,13 25 | 75,29,13 26 | 75,97,47,61,53 27 | 61,13,29 28 | 97,13,75,29,47 -------------------------------------------------------------------------------- /2024/6/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/6/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/6/sample.txt: -------------------------------------------------------------------------------- 1 | ....#..... 2 | .........# 3 | .......... 4 | ..#....... 5 | .......#.. 6 | .......... 7 | .#..^..... 8 | ........#. 9 | #......... 10 | ......#... -------------------------------------------------------------------------------- /2024/7/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/7/aoc7.go: -------------------------------------------------------------------------------- 1 | // aoc7.go -- 2 | // advent of code 2024 day 7 3 | // 4 | // https://adventofcode.com/2024/day/7 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-7: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | "slices" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | sum1, sum2 := 0, 0 23 | 24 | input := bufio.NewScanner(os.Stdin) 25 | for input.Scan() { 26 | line := input.Text() 27 | words := strings.Fields(strings.Replace(line, ":", " ", 1)) 28 | nums := make([]int, len(words)) 29 | for i, word := range words { 30 | nums[i] = atoi(word) 31 | } 32 | 33 | switch { 34 | case check(nums, false): 35 | sum1 += nums[0] 36 | case check(nums, true): 37 | sum2 += nums[0] 38 | } 39 | } 40 | fmt.Println(sum1, sum1+sum2) // part 1 & 2 41 | } 42 | 43 | func check(nums []int, hascons bool) bool { 44 | acc, nums := nums[0], nums[1:] 45 | 46 | if !hascons { // incorrect but ok because of main calling order 47 | slices.Reverse(nums) 48 | } 49 | 50 | var recheck func(int, []int) bool 51 | 52 | recheck = func(acc int, nums []int) bool { 53 | switch { 54 | case acc < 0: 55 | return false 56 | case len(nums) == 1: 57 | return acc == nums[0] 58 | case hascons && acc%mask(nums[0]) == nums[0] && recheck(acc/mask(nums[0]), nums[1:]): 59 | return true 60 | case acc%nums[0] == 0 && recheck(acc/nums[0], nums[1:]): 61 | return true 62 | case recheck(acc-nums[0], nums[1:]): 63 | return true 64 | } 65 | return false 66 | } 67 | 68 | return recheck(acc, nums) 69 | } 70 | 71 | func mask(n int) int { 72 | return pow10(log10(n)) 73 | } 74 | 75 | func log10(n int) int { 76 | i := 0 77 | for n > 0 { 78 | n /= 10 79 | i++ 80 | } 81 | return i 82 | } 83 | 84 | // pow10 returns 10^n for n in [0,3] in O(1) 85 | func pow10(n int) int { 86 | return []int{ 87 | 1, 10, 100, 1000, 88 | }[n] 89 | } 90 | 91 | // strconv.Atoi simplified core loop 92 | // s is ^\d+$ 93 | func atoi(s string) (n int) { 94 | for i := range s { 95 | n = 10*n + int(s[i]-'0') 96 | } 97 | return 98 | } 99 | -------------------------------------------------------------------------------- /2024/7/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/7/sample.txt: -------------------------------------------------------------------------------- 1 | 190: 10 19 2 | 3267: 81 40 27 3 | 83: 17 5 4 | 156: 15 6 5 | 7290: 6 8 6 15 6 | 161011: 16 10 13 7 | 192: 17 8 14 8 | 21037: 9 7 18 13 9 | 292: 11 6 16 20 -------------------------------------------------------------------------------- /2024/8/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/8/aoc8.go: -------------------------------------------------------------------------------- 1 | // aoc8.go -- 2 | // advent of code 2024 day 8 3 | // 4 | // https://adventofcode.com/2024/day/8 5 | // https://github.com/erik-adelbert/aoc 6 | // 7 | // (ɔ) Erik Adelbert - erik_AT_adelbert_DOT_fr 8 | // ------------------------------------------- 9 | // 2024-12-8: initial commit 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | const ( 20 | ASCIIMAX = 123 // [0-9A-Za-z] -> 48-122 21 | MAXDIM = 50 22 | ) 23 | 24 | type Point struct { 25 | y, x int 26 | } 27 | 28 | type City struct { 29 | H, W int 30 | antennas [][]Point // antennas map 31 | } 32 | 33 | func (c City) inbounds(p Point) bool { 34 | return p.y >= 0 && p.x >= 0 && p.y < c.H && p.x < c.W 35 | } 36 | 37 | func main() { 38 | antennas := make([][]Point, ASCIIMAX) 39 | 40 | input := bufio.NewScanner(os.Stdin) 41 | h, w := 0, 0 42 | for input.Scan() { 43 | line := input.Text() 44 | for i, c := range line { 45 | if c != '.' { 46 | antennas[c] = append(antennas[c], Point{h, i}) 47 | } 48 | } 49 | w = len(line) 50 | h++ 51 | } 52 | 53 | city := City{h, w, antennas} 54 | count1 := antinodes(city, 1, 2) 55 | count2 := antinodes(city, 0, max(city.H, city.W)) 56 | fmt.Println(count1, count2) // part 1 & 2 57 | } 58 | 59 | func antinodes(city City, dmin, dmax int) int { // min distance, max distance 60 | H, W := city.H, city.W 61 | 62 | antinodes := make([]int, H*W) 63 | for _, set := range city.antennas['0':ASCIIMAX] { 64 | for i, a := range set { 65 | for _, b := range set[i+1:] { 66 | for d := dmin; d < dmax; d++ { // distance factor 67 | δy, δx := b.y-a.y, b.x-a.x 68 | p1 := Point{a.y - δy*d, a.x - δx*d} 69 | p2 := Point{b.y + δy*d, b.x + δx*d} 70 | 71 | if city.inbounds(p1) { 72 | antinodes[p1.y*W+p1.x] = 1 73 | } 74 | 75 | if city.inbounds(p2) { 76 | antinodes[p2.y*W+p2.x] = 1 77 | } 78 | 79 | if !city.inbounds(p1) && !city.inbounds(p2) { 80 | break 81 | } 82 | } 83 | } 84 | } 85 | } 86 | count := 0 87 | for _, n := range antinodes { 88 | count += n 89 | } 90 | return count 91 | } 92 | -------------------------------------------------------------------------------- /2024/8/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/8/sample.txt: -------------------------------------------------------------------------------- 1 | ............ 2 | ........0... 3 | .....0...... 4 | .......0.... 5 | ....0....... 6 | ......A..... 7 | ............ 8 | ............ 9 | ........A... 10 | .........A.. 11 | ............ 12 | ............ -------------------------------------------------------------------------------- /2024/9/Makefile: -------------------------------------------------------------------------------- 1 | include ../day.mk -------------------------------------------------------------------------------- /2024/9/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/9/sample.txt: -------------------------------------------------------------------------------- 1 | 2333133121414131402 2 | 3 | -------------------------------------------------------------------------------- /2024/Makefile: -------------------------------------------------------------------------------- 1 | GO = go build 2 | 3 | TARGETS := bench binrun build check clean header run 4 | 5 | SUBDIRS := $(wildcard */.) 6 | SUBDIRS := $(filter-out download/. header/. runtime/., images/., $(SUBDIRS)) 7 | 8 | $(TARGETS): $(SUBDIRS) 9 | $(SUBDIRS): 10 | @$(MAKE) -C $@ $(MAKECMDGOALS) 11 | 12 | cyclo: 13 | @gocyclo -ignore "download|images|header|runtime" -top 10 -avg . 14 | 15 | lines: 16 | @find . -name '*go' \( -not -iname "main.go" \) | grep -v 'v1' | xargs wc -l | sort 17 | 18 | runtime: 19 | @./runtime.sh | sort -n -k 4 > runtime.md 20 | 21 | .PHONY: $(TARGETS) $(SUBDIRS) cyclo lines runtime 22 | -------------------------------------------------------------------------------- /2024/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | hyperfine --warmup 100 "cat input.txt > /dev/null" "./${1} < input.txt" --export-markdown time.md 4 | -------------------------------------------------------------------------------- /2024/day.mk: -------------------------------------------------------------------------------- 1 | GOC = go build 2 | GOV = go vet 3 | 4 | BENCH = ../bench.sh 5 | 6 | DOWNLOAD = ../download/main.go 7 | HEADER = ../header/main.go 8 | 9 | EX = sample.txt 10 | IN = input.txt 11 | 12 | BIN = $(addprefix aoc,$(shell basename $(CURDIR))) 13 | SRC = $(BIN).go 14 | 15 | bench: build 16 | $(BENCH) $(BIN) 17 | @$(MAKE) clean 18 | 19 | binrun: input.txt 20 | ./$(BIN) < $(IN) 21 | 22 | build: input.txt 23 | $(GOC) $(SRC) 24 | 25 | check: 26 | $(GOV) $(SRC) 27 | 28 | clean: 29 | go clean 30 | rm -f $(BIN) 31 | 32 | header: 33 | @go run $(HEADER) 34 | 35 | input.txt: 36 | @go run $(DOWNLOAD) 37 | 38 | go.mod: 39 | @go mod init 2>/dev/null 40 | 41 | gobench: go.mod input.txt 42 | go test -bench=. -benchmem 43 | 44 | cpuprof: build 45 | ./$(BIN) -cpuprofile=$(BIN).cpu.prof < $(IN) 46 | 47 | memprof: build 48 | ./$(BIN) -memprofile=$(BIN).mem.prof < $(IN) 49 | 50 | run: input.txt 51 | go run ./$(SRC) < $(IN) 52 | 53 | sample: 54 | go run ./$(SRC) < $(EX) 55 | 56 | 57 | .PHONY: bench binrun build check clean cpuprof exemple gobench header memprof run sample 58 | -------------------------------------------------------------------------------- /2024/download/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/download 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2024/download/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "os" 11 | "path" 12 | "strconv" 13 | ) 14 | 15 | const ( 16 | OUT = "input.txt" 17 | URL = "https://adventofcode.com/%d/day/%d/input" 18 | ) 19 | 20 | var client http.Client 21 | 22 | func main() { 23 | if _, err := os.Stat(OUT); !errors.Is(err, os.ErrNotExist) { 24 | log.Printf("input file %s already exists", OUT) 25 | os.Exit(0) 26 | } 27 | 28 | session := os.Getenv("SESSION") 29 | if len(session) == 0 { 30 | log.Println("$SESSION not set") 31 | os.Exit(0) 32 | } 33 | 34 | pwd, err := os.Getwd() 35 | if err != nil { 36 | log.Fatalf("error finding out pwd: %s", err.Error()) 37 | } 38 | pwd = path.Clean(pwd) 39 | 40 | day, err := strconv.ParseInt(path.Base(pwd), 10, 0) 41 | if err != nil { 42 | log.Fatalf("error computing day from pwd: %s", err.Error()) 43 | } 44 | 45 | year, err := strconv.ParseInt(path.Base(path.Dir(pwd)), 10, 0) 46 | if err != nil { 47 | log.Fatalf("error computing year from pwd: %s", err.Error()) 48 | } 49 | 50 | url := fmt.Sprintf(URL, year, day) 51 | log.Printf("downloading from %s in session %s...", url, session[:6]) 52 | 53 | jar, err := cookiejar.New(nil) 54 | if err != nil { 55 | log.Fatalf("error creating cookie jar: %s\n", err.Error()) 56 | } 57 | client = http.Client{ 58 | Jar: jar, 59 | } 60 | 61 | if err := downloadInputFile(OUT, url, session); err != nil { 62 | log.Fatalf("error downloading input file: %s", err.Error()) 63 | } 64 | } 65 | 66 | func downloadInputFile(filepath string, url string, session string) error { 67 | cookie := &http.Cookie{ 68 | Name: "session", 69 | Value: session, 70 | MaxAge: 300, 71 | } 72 | 73 | req, err := http.NewRequest("GET", url, nil) 74 | if err != nil { 75 | return fmt.Errorf("error building GET request: %w", err) 76 | } 77 | 78 | req.AddCookie(cookie) 79 | resp, err := client.Do(req) 80 | if err != nil { 81 | return fmt.Errorf("error making request: %w", err) 82 | } 83 | defer resp.Body.Close() 84 | 85 | out, err := os.Create(filepath) 86 | if err != nil { 87 | return fmt.Errorf("error creating file: %w", err) 88 | } 89 | defer out.Close() 90 | 91 | _, err = io.Copy(out, resp.Body) 92 | if err != nil { 93 | return fmt.Errorf("error while copying data: %w", err) 94 | } 95 | 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /2024/images/aoc14-6516.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aoc14-6516.png -------------------------------------------------------------------------------- /2024/images/aoc18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aoc18.png -------------------------------------------------------------------------------- /2024/images/aoc2024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aoc2024.png -------------------------------------------------------------------------------- /2024/images/aoc22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aoc22.jpg -------------------------------------------------------------------------------- /2024/images/aoc23a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aoc23a.png -------------------------------------------------------------------------------- /2024/images/aoc23b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aoc23b.png -------------------------------------------------------------------------------- /2024/images/aocjack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erik-adelbert/aoc/68b0d88b2d3b67ef30278023b26e9aab805e61e9/2024/images/aocjack.jpg -------------------------------------------------------------------------------- /2024/runtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #shellcheck disable=SC2046 # cmdline must split 4 | go run ./runtime/main.go $(find . -name time.md) 5 | -------------------------------------------------------------------------------- /2024/runtime/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/erik-adelbert/aoc/2022/runtime 2 | 3 | go 1.21.1 4 | -------------------------------------------------------------------------------- /2024/runtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | var runtime float64 14 | fmt.Println("| day | time |") 15 | fmt.Println("|-----|-----:|") 16 | for _, f := range os.Args[1:] { 17 | fd, err := os.Open(f) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | input := bufio.NewScanner(fd) 23 | times := make([]float64, 0, 2) 24 | for input.Scan() { 25 | line := input.Text() 26 | line = strings.Replace(line, "\\|", "", 1) 27 | if strings.Contains(line, "input.txt") { 28 | args := strings.Fields(strings.Split(line, "|")[3]) 29 | f, _ := strconv.ParseFloat(args[0], 64) 30 | times = append(times, f) 31 | } 32 | } 33 | fd.Close() 34 | labels := strings.Split(f, "/") 35 | label := labels[len(labels)-2] 36 | 37 | time := times[1] - times[0] 38 | if time < 0 { 39 | time = 0 40 | } 41 | fmt.Printf("| %s | %.1f |\n", label, time) 42 | runtime += time 43 | } 44 | fmt.Printf("| total | %.1f |\n", runtime) 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # aoc 3 | 4 | My advent of code solutions 5 | 6 | All programs have been carefully composed and run collectively in around 62ms(2023), 49ms(2022) and 249ms(2021). 7 | Coding notes have proven useful for others on reddit. 8 | 9 | Happy coding! 10 | 11 | ## Installation and benchmark 12 | 13 | 0. optionnally install [gocyclo](https://github.com/fzipp/gocyclo) 14 | 1. install [hyperfine](https://github.com/sharkdp/hyperfine) 15 | 2. `git clone` this repository somewhere in your `$GOPATH` 16 | 3. `export` envar `$SESSION` with your AoC `session` value (get it from the cookie stored in your browser) 17 | 4. `$ cd 2023` 18 | 5. `$ make` 19 | 6. `$ make runtime && cat runtime.md` 20 | 7. explore the other `Makefile` goals 21 | --------------------------------------------------------------------------------