├── resources ├── 2015 │ ├── advent_tree.png │ ├── prob15test │ ├── prob15 │ ├── prob19.mol │ ├── prob23 │ ├── prob14 │ ├── prob19.rules │ ├── prob9 │ └── prob13 ├── 2016 │ ├── day12 │ ├── day23 │ ├── day25 │ ├── day1 │ ├── day2 │ └── day21 ├── 2017 │ ├── day06 │ ├── day23 │ ├── day13 │ ├── day18 │ ├── day24 │ ├── day22 │ ├── day02 │ ├── day25 │ ├── day01 │ └── day21 └── 2018 │ └── day06 ├── doc └── 2015 │ ├── intro.md │ ├── 04.md │ ├── 17.md │ ├── 10.md │ ├── 12.md │ ├── 09.md │ ├── 03.md │ ├── 01.md │ ├── 20.md │ ├── 02.md │ ├── 11.md │ ├── 23.md │ ├── 07.md │ ├── 06.md │ ├── 05.md │ ├── 16.md │ ├── 14.md │ ├── 15.md │ ├── 08.md │ ├── 13.md │ ├── 19.md │ ├── 21.md │ ├── 18.md │ └── 25.md ├── .gitignore ├── src ├── advent-2016 │ ├── core.clj │ ├── day6.clj │ ├── day3.clj │ ├── day18.clj │ ├── day16.clj │ ├── utils.clj │ ├── day20.clj │ ├── day1.clj │ ├── day15.clj │ ├── day5.clj │ ├── day17.clj │ ├── day14.clj │ ├── day2.clj │ ├── day8.clj │ ├── day12.clj │ ├── day7.clj │ ├── day4.clj │ ├── day9.clj │ ├── day13.clj │ ├── day19.clj │ ├── day25.clj │ ├── day10.clj │ ├── day22.clj │ ├── day21.clj │ ├── day23.clj │ └── day24.clj ├── advent-2015 │ ├── day10.clj │ ├── day01.clj │ ├── day04.clj │ ├── core.clj │ ├── day25.clj │ ├── day03.clj │ ├── day12.clj │ ├── day09.clj │ ├── day08.clj │ ├── day17.clj │ ├── day05.clj │ ├── day02.clj │ ├── day14.clj │ ├── day15.clj │ ├── day13.clj │ ├── day23.clj │ ├── day20.clj │ ├── day11.clj │ ├── day24.clj │ ├── day16.clj │ ├── day06.clj │ ├── day19.clj │ ├── day18.clj │ ├── day21.clj │ └── day07.clj ├── advent-2018 │ ├── day01.clj │ ├── day05.clj │ ├── day03.clj │ ├── day02.clj │ ├── day04.clj │ ├── day07.clj │ └── day06.clj └── advent-2017 │ ├── day04.clj │ ├── day09.clj │ ├── day02.clj │ ├── day01.clj │ ├── day12.clj │ ├── day06.clj │ ├── day15.clj │ ├── day08.clj │ ├── day25.clj │ ├── day13.clj │ ├── day10.clj │ ├── day20.clj │ ├── day19.clj │ ├── day11.clj │ ├── day05.clj │ ├── day16.clj │ ├── day14.clj │ ├── day03.clj │ ├── day17.clj │ ├── day21.clj │ ├── day07.clj │ ├── day24.clj │ ├── day22.clj │ └── day23.clj ├── project.clj └── README.md /resources/2017/day06: -------------------------------------------------------------------------------- 1 | 0 5 10 0 11 14 13 4 11 8 8 7 1 4 12 11 -------------------------------------------------------------------------------- /resources/2015/advent_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhauman/advent-of-clojure/HEAD/resources/2015/advent_tree.png -------------------------------------------------------------------------------- /doc/2015/intro.md: -------------------------------------------------------------------------------- 1 | # Introduction to advent 2 | 3 | TODO: write [great documentation](http://jacobian.org/writing/what-to-write/) 4 | -------------------------------------------------------------------------------- /resources/2015/prob15test: -------------------------------------------------------------------------------- 1 | Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8 2 | Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | .hgignore 11 | .hg/ 12 | .\#* 13 | \#* 14 | dd3.clj -------------------------------------------------------------------------------- /src/advent-2016/core.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.core 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def lines (line-seq (io/reader (io/resource "2016/day4")))) 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/2016/day12: -------------------------------------------------------------------------------- 1 | cpy 1 a 2 | cpy 1 b 3 | cpy 26 d 4 | jnz c 2 5 | jnz 1 5 6 | cpy 7 c 7 | inc d 8 | dec c 9 | jnz c -2 10 | cpy a c 11 | inc a 12 | dec b 13 | jnz b -2 14 | cpy c b 15 | dec d 16 | jnz d -6 17 | cpy 13 c 18 | cpy 14 d 19 | inc a 20 | dec d 21 | jnz d -2 22 | dec c 23 | jnz c -5 -------------------------------------------------------------------------------- /src/advent-2015/day10.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day10) 2 | 3 | (defn count-encode [x] 4 | (apply str 5 | (mapcat 6 | (juxt count first) 7 | (partition-by identity x)))) 8 | 9 | ;; part 1 and part 2 10 | #_(count (nth (iterate count-encode "1321131112") 40 #_50)) 11 | -------------------------------------------------------------------------------- /resources/2015/prob15: -------------------------------------------------------------------------------- 1 | Sprinkles: capacity 2, durability 0, flavor -2, texture 0, calories 3 2 | Butterscotch: capacity 0, durability 5, flavor -3, texture 0, calories 3 3 | Chocolate: capacity 0, durability 0, flavor 5, texture -1, calories 8 4 | Candy: capacity 0, durability -1, flavor 0, texture 5, calories 8 -------------------------------------------------------------------------------- /resources/2016/day23: -------------------------------------------------------------------------------- 1 | cpy a b 2 | dec b 3 | cpy a d 4 | cpy 0 a 5 | cpy b c 6 | inc a 7 | dec c 8 | jnz c -2 9 | dec d 10 | jnz d -5 11 | dec b 12 | cpy b c 13 | cpy c d 14 | dec d 15 | inc c 16 | jnz d -2 17 | tgl c 18 | cpy -16 c 19 | jnz 1 c 20 | cpy 81 c 21 | jnz 94 d 22 | inc a 23 | inc d 24 | jnz d -2 25 | inc c 26 | jnz c -5 -------------------------------------------------------------------------------- /src/advent-2015/day01.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day01 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def prob1 (slurp (io/resource "2015/prob1"))) 6 | 7 | ;; part 1 8 | #_(reduce + (map {\( 1 \) -1} prob1)) 9 | 10 | ;; part 2 11 | #_(count 12 | (take-while #(not= % -1) 13 | (reductions + 0 (map {\( 1 \) -1} prob1)))) 14 | -------------------------------------------------------------------------------- /resources/2016/day25: -------------------------------------------------------------------------------- 1 | cpy a d 2 | cpy 4 c 3 | cpy 633 b 4 | inc d 5 | dec b 6 | jnz b -2 7 | dec c 8 | jnz c -5 9 | cpy d a 10 | jnz 0 0 11 | cpy a b 12 | cpy 0 a 13 | cpy 2 c 14 | jnz b 2 15 | jnz 1 6 16 | dec b 17 | dec c 18 | jnz c -4 19 | inc a 20 | jnz 1 -7 21 | cpy 2 b 22 | jnz c 2 23 | jnz 1 4 24 | dec b 25 | dec c 26 | jnz 1 -4 27 | jnz 0 0 28 | out b 29 | jnz a -19 30 | jnz 1 -21 -------------------------------------------------------------------------------- /src/advent-2015/day04.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day04 2 | (:require 3 | [clojure.java.io :as io] 4 | [digest :refer [md5]])) 5 | 6 | ;; day 4 7 | 8 | ;; part 1 9 | #_(first 10 | (filter 11 | #(= "00000" #_ "000000" (subs (second %) 0 5 #_6)) 12 | (map 13 | (juxt identity md5) 14 | (map-indexed #(str %2 %1) (repeat "yzbqklnj"))))) 15 | 16 | ;; part 2 change the parameters above 17 | -------------------------------------------------------------------------------- /resources/2017/day23: -------------------------------------------------------------------------------- 1 | set b 67 2 | set c b 3 | jnz a 2 4 | jnz 1 5 5 | mul b 100 6 | sub b -100000 7 | set c b 8 | sub c -17000 9 | set f 1 10 | set d 2 11 | set e 2 12 | set g d 13 | mul g e 14 | sub g b 15 | jnz g 2 16 | set f 0 17 | sub e -1 18 | set g e 19 | sub g b 20 | jnz g -8 21 | sub d -1 22 | set g d 23 | sub g b 24 | jnz g -13 25 | jnz f 2 26 | sub h -1 27 | set g b 28 | sub g c 29 | jnz g 2 30 | jnz 1 3 31 | sub b -17 32 | jnz 1 -23 -------------------------------------------------------------------------------- /src/advent-2015/core.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.core 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [clojure.core.match :refer [match]] 6 | [clojure.pprint :as p] 7 | [clojure.set :refer [union intersection difference]] 8 | [clojure.math.combinatorics :as combo] 9 | [clojure.walk :refer [prewalk postwalk]] 10 | [digest :refer [md5]])) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/advent-2015/day25.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day25) 2 | 3 | ; Enter the code at row 2947, column 3029. 4 | 5 | (defn pos-from-row-col [r c] 6 | (+ (nth 7 | (reductions + (range)) 8 | (dec (+ c (dec r)))) 9 | c)) 10 | 11 | (defn at-pos [pos] 12 | (loop [x 20151125 13 | c (dec pos)] 14 | (if (zero? c) 15 | x 16 | (recur (rem (* x 252533) 33554393) 17 | (dec c))))) 18 | 19 | #_(at-pos (pos-from-row-col 2947 3029)) 20 | -------------------------------------------------------------------------------- /resources/2017/day13: -------------------------------------------------------------------------------- 1 | 0: 3 2 | 1: 2 3 | 2: 4 4 | 4: 6 5 | 6: 5 6 | 8: 6 7 | 10: 6 8 | 12: 4 9 | 14: 8 10 | 16: 8 11 | 18: 9 12 | 20: 8 13 | 22: 6 14 | 24: 14 15 | 26: 12 16 | 28: 10 17 | 30: 12 18 | 32: 8 19 | 34: 10 20 | 36: 8 21 | 38: 8 22 | 40: 12 23 | 42: 12 24 | 44: 12 25 | 46: 12 26 | 48: 14 27 | 52: 14 28 | 54: 12 29 | 56: 12 30 | 58: 12 31 | 60: 12 32 | 62: 14 33 | 64: 14 34 | 66: 14 35 | 68: 14 36 | 70: 14 37 | 72: 14 38 | 80: 18 39 | 82: 14 40 | 84: 20 41 | 86: 14 42 | 90: 17 43 | 96: 20 44 | 98: 24 -------------------------------------------------------------------------------- /resources/2015/prob19.mol: -------------------------------------------------------------------------------- 1 | CRnCaCaCaSiRnBPTiMgArSiRnSiRnMgArSiRnCaFArTiTiBSiThFYCaFArCaCaSiThCaPBSiThSiThCaCaPTiRnPBSiThRnFArArCaCaSiThCaSiThSiRnMgArCaPTiBPRnFArSiThCaSiRnFArBCaSiRnCaPRnFArPMgYCaFArCaPTiTiTiBPBSiThCaPTiBPBSiRnFArBPBSiRnCaFArBPRnSiRnFArRnSiRnBFArCaFArCaCaCaSiThSiThCaCaPBPTiTiRnFArCaPTiBSiAlArPBCaCaCaCaCaSiRnMgArCaSiThFArThCaSiThCaSiRnCaFYCaSiRnFYFArFArCaSiRnFYFArCaSiRnBPMgArSiThPRnFArCaSiRnFArTiRnSiRnFYFArCaSiRnBFArCaSiRnTiMgArSiThCaSiThCaFArPRnFArSiRnFArTiTiTiTiBCaCaSiRnCaCaFYFArSiThCaPTiBPTiBCaSiThSiRnMgArCaF -------------------------------------------------------------------------------- /src/advent-2018/day01.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day01 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data 7 | (->> (io/resource "2018/day01") 8 | slurp 9 | (format "(%s)") 10 | read-string)) 11 | 12 | ;; part 1 13 | (def part1 (partial reduce +)) 14 | 15 | #_ (= (part1 data) 510) 16 | 17 | ;; part 2 18 | (defn part2 [d] 19 | (reduce 20 | #(if (%1 %2) (reduced %2) (conj %1 %2)) 21 | #{0} 22 | (reductions + (cycle d)))) 23 | 24 | #_(part2 data) 25 | -------------------------------------------------------------------------------- /resources/2015/prob23: -------------------------------------------------------------------------------- 1 | jio a, +22 2 | inc a 3 | tpl a 4 | tpl a 5 | tpl a 6 | inc a 7 | tpl a 8 | inc a 9 | tpl a 10 | inc a 11 | inc a 12 | tpl a 13 | inc a 14 | inc a 15 | tpl a 16 | inc a 17 | inc a 18 | tpl a 19 | inc a 20 | inc a 21 | tpl a 22 | jmp +19 23 | tpl a 24 | tpl a 25 | tpl a 26 | tpl a 27 | inc a 28 | inc a 29 | tpl a 30 | inc a 31 | tpl a 32 | inc a 33 | inc a 34 | tpl a 35 | inc a 36 | inc a 37 | tpl a 38 | inc a 39 | tpl a 40 | tpl a 41 | jio a, +8 42 | inc b 43 | jie a, +4 44 | tpl a 45 | inc a 46 | jmp +2 47 | hlf a 48 | jmp -7 -------------------------------------------------------------------------------- /src/advent-2017/day04.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day04 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [medley.core :as m])) 6 | 7 | (def data 8 | (->> (io/resource "2017/day04") 9 | io/reader 10 | line-seq 11 | (mapv #(string/split % #"\s")))) 12 | 13 | ;; part 1 14 | #_(count (filter #(= (count (distinct %)) (count %)) 15 | data)) 16 | 17 | ;; part 2 18 | #_(count (filter #(= (count (m/distinct-by frequencies %)) (count %)) 19 | data)) 20 | 21 | 22 | -------------------------------------------------------------------------------- /resources/2017/day18: -------------------------------------------------------------------------------- 1 | set i 31 2 | set a 1 3 | mul p 17 4 | jgz p p 5 | mul a 2 6 | add i -1 7 | jgz i -2 8 | add a -1 9 | set i 127 10 | set p 735 11 | mul p 8505 12 | mod p a 13 | mul p 129749 14 | add p 12345 15 | mod p a 16 | set b p 17 | mod b 10000 18 | snd b 19 | add i -1 20 | jgz i -9 21 | jgz a 3 22 | rcv b 23 | jgz b -1 24 | set f 0 25 | set i 126 26 | rcv a 27 | rcv b 28 | set p a 29 | mul p -1 30 | add p b 31 | jgz p 4 32 | snd a 33 | set a b 34 | jgz 1 3 35 | snd b 36 | set f 1 37 | add i -1 38 | jgz i -11 39 | snd a 40 | jgz f -16 41 | jgz a -19 -------------------------------------------------------------------------------- /resources/2017/day24: -------------------------------------------------------------------------------- 1 | 31/13 2 | 34/4 3 | 49/49 4 | 23/37 5 | 47/45 6 | 32/4 7 | 12/35 8 | 37/30 9 | 41/48 10 | 0/47 11 | 32/30 12 | 12/5 13 | 37/31 14 | 7/41 15 | 10/28 16 | 35/4 17 | 28/35 18 | 20/29 19 | 32/20 20 | 31/43 21 | 48/14 22 | 10/11 23 | 27/6 24 | 9/24 25 | 8/28 26 | 45/48 27 | 8/1 28 | 16/19 29 | 45/45 30 | 0/4 31 | 29/33 32 | 2/5 33 | 33/9 34 | 11/7 35 | 32/10 36 | 44/1 37 | 40/32 38 | 2/45 39 | 16/16 40 | 1/18 41 | 38/36 42 | 34/24 43 | 39/44 44 | 32/37 45 | 26/46 46 | 25/33 47 | 9/10 48 | 0/29 49 | 38/8 50 | 33/33 51 | 49/19 52 | 18/20 53 | 49/39 54 | 18/39 55 | 26/13 56 | 19/32 -------------------------------------------------------------------------------- /src/advent-2015/day03.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day03 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def prob3 (slurp (io/resource "2015/prob3"))) 6 | 7 | (defn positions-visited [data] 8 | (set 9 | (reductions 10 | #(map + %1 %2) 11 | [0 0] 12 | (map {\^ [0 1] 13 | \v [0 -1] 14 | \> [1 0] 15 | \< [-1 0]} data)))) 16 | 17 | ;; part 1 18 | #_(count 19 | (positions-visited prob3)) 20 | 21 | ;; part 2 22 | 23 | #_(count 24 | (set 25 | (mapcat positions-visited 26 | (let [p (partition 2 prob3)] 27 | [(map first p) (map second p)])))) 28 | -------------------------------------------------------------------------------- /src/advent-2016/day6.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day6 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def data (line-seq (io/reader (io/resource "2016/day6")))) 6 | 7 | (def transpose (partial apply mapv vector)) 8 | 9 | (defn pull-by [sort-fn d] 10 | (->> d 11 | frequencies 12 | (sort-by sort-fn) 13 | ffirst)) 14 | 15 | ;; part 1 16 | #_(->> data 17 | transpose 18 | (map (partial pull-by (comp - second)))) 19 | ;; => (\x \h \n \q \p \q \q \l) 20 | 21 | ;; part 2 22 | #_(->> data 23 | transpose 24 | (map (partial pull-by second))) 25 | ;; => (\b \r \h \a \i \l \r \o) 26 | -------------------------------------------------------------------------------- /resources/2016/day1: -------------------------------------------------------------------------------- 1 | R3, L5, R2, L2, R1, L3, R1, R3, L4, R3, L1, L1, R1, L3, R2, L3, L2, R1, R1, L1, R4, L1, L4, R3, L2, L2, R1, L1, R5, R4, R2, L5, L2, R5, R5, L2, R3, R1, R1, L3, R1, L4, L4, L190, L5, L2, R4, L5, R4, R5, L4, R1, R2, L5, R50, L2, R1, R73, R1, L2, R191, R2, L4, R1, L5, L5, R5, L3, L5, L4, R4, R5, L4, R4, R4, R5, L2, L5, R3, L4, L4, L5, R2, R2, R2, R4, L3, R4, R5, L3, R5, L2, R3, L1, R2, R2, L3, L1, R5, L3, L5, R2, R4, R1, L1, L5, R3, R2, L3, L4, L5, L1, R3, L5, L2, R2, L3, L4, L1, R1, R4, R2, R2, R4, R2, R2, L3, L3, L4, R4, L4, L4, R1, L4, L4, R1, L2, R5, R2, R3, R3, L2, L5, R3, L3, R5, L2, R3, R2, L4, L3, L1, R2, L2, L3, L5, R3, L1, L3, L4, L3 -------------------------------------------------------------------------------- /resources/2018/day06: -------------------------------------------------------------------------------- 1 | 268, 273 2 | 211, 325 3 | 320, 225 4 | 320, 207 5 | 109, 222 6 | 267, 283 7 | 119, 70 8 | 138, 277 9 | 202, 177 10 | 251, 233 11 | 305, 107 12 | 230, 279 13 | 243, 137 14 | 74, 109 15 | 56, 106 16 | 258, 97 17 | 248, 346 18 | 71, 199 19 | 332, 215 20 | 208, 292 21 | 154, 80 22 | 74, 256 23 | 325, 305 24 | 174, 133 25 | 148, 51 26 | 112, 71 27 | 243, 202 28 | 136, 237 29 | 227, 90 30 | 191, 145 31 | 345, 133 32 | 340, 299 33 | 322, 256 34 | 86, 323 35 | 341, 310 36 | 342, 221 37 | 50, 172 38 | 284, 160 39 | 267, 142 40 | 244, 153 41 | 131, 147 42 | 245, 323 43 | 42, 241 44 | 90, 207 45 | 245, 167 46 | 335, 106 47 | 299, 158 48 | 181, 186 49 | 349, 286 50 | 327, 108 -------------------------------------------------------------------------------- /resources/2015/prob14: -------------------------------------------------------------------------------- 1 | Vixen can fly 19 km/s for 7 seconds, but then must rest for 124 seconds. 2 | Rudolph can fly 3 km/s for 15 seconds, but then must rest for 28 seconds. 3 | Donner can fly 19 km/s for 9 seconds, but then must rest for 164 seconds. 4 | Blitzen can fly 19 km/s for 9 seconds, but then must rest for 158 seconds. 5 | Comet can fly 13 km/s for 7 seconds, but then must rest for 82 seconds. 6 | Cupid can fly 25 km/s for 6 seconds, but then must rest for 145 seconds. 7 | Dasher can fly 14 km/s for 3 seconds, but then must rest for 38 seconds. 8 | Dancer can fly 3 km/s for 16 seconds, but then must rest for 37 seconds. 9 | Prancer can fly 25 km/s for 6 seconds, but then must rest for 143 seconds. -------------------------------------------------------------------------------- /resources/2015/prob19.rules: -------------------------------------------------------------------------------- 1 | Al => ThF 2 | Al => ThRnFAr 3 | B => BCa 4 | B => TiB 5 | B => TiRnFAr 6 | Ca => CaCa 7 | Ca => PB 8 | Ca => PRnFAr 9 | Ca => SiRnFYFAr 10 | Ca => SiRnMgAr 11 | Ca => SiTh 12 | F => CaF 13 | F => PMg 14 | F => SiAl 15 | H => CRnAlAr 16 | H => CRnFYFYFAr 17 | H => CRnFYMgAr 18 | H => CRnMgYFAr 19 | H => HCa 20 | H => NRnFYFAr 21 | H => NRnMgAr 22 | H => NTh 23 | H => OB 24 | H => ORnFAr 25 | Mg => BF 26 | Mg => TiMg 27 | N => CRnFAr 28 | N => HSi 29 | O => CRnFYFAr 30 | O => CRnMgAr 31 | O => HP 32 | O => NRnFAr 33 | O => OTi 34 | P => CaP 35 | P => PTi 36 | P => SiRnFAr 37 | Si => CaSi 38 | Th => ThCa 39 | Ti => BP 40 | Ti => TiTi 41 | e => HF 42 | e => NAl 43 | e => OMg -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject advent "0.1.0-SNAPSHOT" 2 | :description "FIXME: write description" 3 | :url "http://example.com/FIXME" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [[org.clojure/clojure "1.9.0"] 7 | [digest "1.4.4"] 8 | [medley "0.8.4"] 9 | [criterium "0.4.4"] 10 | [clj-time "0.15.1"] 11 | [net.mikera/core.matrix "0.57.0"] 12 | [org.clojure/math.combinatorics "0.1.1"] 13 | [org.clojure/core.match "0.2.2"]] 14 | 15 | :profiles { :repl { :repl-options {:init (set! *print-length* 500)}} }) 16 | -------------------------------------------------------------------------------- /src/advent-2015/day12.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day12 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [clojure.walk :refer [prewalk]])) 6 | 7 | (def prob12 (slurp (io/resource "2015/prob12"))) 8 | 9 | ;; part 1 10 | #_(reduce + (map read-string (re-seq #"[-]{0,1}\d+" prob12))) 11 | 12 | ;; part 2 13 | 14 | (defn has-red? [m] 15 | (some (fn [me] ((set me) "red")) m)) 16 | 17 | #_(as-> prob12 a 18 | (string/replace a ":" " ") 19 | (read-string a) 20 | (prewalk #(cond 21 | (and (map? %) (has-red? %)) nil 22 | (map? %) (seq %) 23 | :else %) a) 24 | (flatten a) 25 | (filter integer? a) 26 | (reduce + a)) 27 | -------------------------------------------------------------------------------- /src/advent-2016/day3.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day3 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def lines (line-seq (io/reader (io/resource "2016/day3")))) 6 | 7 | (defn parse-triangle [line] 8 | (read-string (str "[" line "]"))) 9 | 10 | (defn valid? [[a b c]] 11 | (and (> (+ a b) c) 12 | (> (+ b c) a) 13 | (> (+ c a) b))) 14 | 15 | ;; part 1 16 | #_(->> lines 17 | (map parse-triangle) 18 | (filter valid?) 19 | count) 20 | ;; => 862 21 | 22 | (def transpose (partial apply mapv vector)) 23 | 24 | ;; part 2 25 | #_(->> lines 26 | (map parse-triangle) 27 | (partition 3) 28 | (mapcat transpose) 29 | (filter valid?) 30 | count) 31 | ;; => 1577 32 | -------------------------------------------------------------------------------- /src/advent-2015/day09.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day09 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.set :refer [union]] 5 | [clojure.math.combinatorics :as combo])) 6 | 7 | (def prob9 8 | (line-seq (io/reader (io/resource "2015/prob9")))) 9 | 10 | (defn tokens [x] (read-string (str "(" x ")") )) 11 | 12 | (def dist-map 13 | (into {} (map (comp (fn [[a _ b _ c]] [#{a b} c]) 14 | tokens) 15 | prob9))) 16 | 17 | (def towns (reduce union (keys dist-map))) 18 | 19 | ;; part 1 20 | #_(reduce min #_max ; part 2 21 | (map 22 | #(reduce + (map (comp dist-map set) 23 | (partition 2 1 %))) 24 | (combo/permutations towns))) 25 | -------------------------------------------------------------------------------- /src/advent-2016/day18.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day18) 2 | 3 | (def input 4 | (str "...^^^^^..^...^...^^^^^^...^.^^^.^.^.^^.^^^" 5 | ".....^.^^^...^^^^^^.....^.^^...^^^^^...^.^^^.^^......^^^^")) 6 | 7 | (def t? #{"^^." ".^^" "^.." "..^"}) 8 | 9 | (defn next-trap? [x] 10 | (if (t? (apply str x)) \^ \.)) 11 | 12 | (defn next-row [r] 13 | (->> (cons \. (conj r \.)) 14 | (partition 3 1) 15 | (mapv next-trap?))) 16 | 17 | (defn find-answer [rows r] 18 | (->> (iterate next-row (vec r)) 19 | (pmap #(count (filter #{\.} %))) 20 | (take rows) 21 | (reduce +))) 22 | 23 | ;; part 1 24 | #_(find-answer 40 input) 25 | ;; => 1982 26 | 27 | ;; part 2 28 | #_ (time (find-answer 400000 input)) 29 | ;; => 20005203 30 | -------------------------------------------------------------------------------- /resources/2017/day22: -------------------------------------------------------------------------------- 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 | #.....##..####.##.###..#. -------------------------------------------------------------------------------- /resources/2015/prob9: -------------------------------------------------------------------------------- 1 | Tristram to AlphaCentauri = 34 2 | Tristram to Snowdin = 100 3 | Tristram to Tambi = 63 4 | Tristram to Faerun = 108 5 | Tristram to Norrath = 111 6 | Tristram to Straylight = 89 7 | Tristram to Arbre = 132 8 | AlphaCentauri to Snowdin = 4 9 | AlphaCentauri to Tambi = 79 10 | AlphaCentauri to Faerun = 44 11 | AlphaCentauri to Norrath = 147 12 | AlphaCentauri to Straylight = 133 13 | AlphaCentauri to Arbre = 74 14 | Snowdin to Tambi = 105 15 | Snowdin to Faerun = 95 16 | Snowdin to Norrath = 48 17 | Snowdin to Straylight = 88 18 | Snowdin to Arbre = 7 19 | Tambi to Faerun = 68 20 | Tambi to Norrath = 134 21 | Tambi to Straylight = 107 22 | Tambi to Arbre = 40 23 | Faerun to Norrath = 11 24 | Faerun to Straylight = 66 25 | Faerun to Arbre = 144 26 | Norrath to Straylight = 115 27 | Norrath to Arbre = 135 28 | Straylight to Arbre = 127 -------------------------------------------------------------------------------- /src/advent-2015/day08.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day08 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def prob8 6 | (line-seq (io/reader (io/resource "2015/prob8")))) 7 | 8 | (defn unescape-trunc [input] 9 | (drop (condp = (take 2 input) 10 | [\\ \"] 2 11 | [\\ \\] 2 12 | [\\ \x] 4 13 | 1) 14 | input)) 15 | 16 | (defn unescape-len [x] 17 | (+ -2 18 | (count (take-while not-empty 19 | (iterate unescape-trunc x))))) 20 | 21 | ;; part 1 22 | #_(reduce + 0 (map #(- (count %) (unescape-len %)) prob8)) 23 | 24 | (defn expand-len [w] 25 | (reduce + 2 26 | (map #(condp = % 27 | \" 2 28 | \\ 2 29 | 1) 30 | w))) 31 | 32 | ;; part 2 33 | #_(reduce + 0 (map #(- (expand-len %) (count %)) prob8)) 34 | -------------------------------------------------------------------------------- /src/advent-2015/day17.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day17) 2 | 3 | (def prob17 [43 3 4 10 21 44 4 6 47 41 34 17 17 44 36 31 46 9 27 38]) 4 | 5 | (def p [20, 15, 10, 5, 5]) 6 | 7 | (def find-combos 8 | (memoize 9 | (fn [target items] 10 | (if (zero? 0) 11 | [[]] 12 | (mapcat 13 | (fn [[x & xs]] 14 | (map #(cons x %) 15 | (find-combos (- target x) xs))) 16 | (take-while not-empty 17 | (iterate rest (filter #(<= % target) items)))))))) 18 | 19 | #_(time 20 | (count (find-combos 150 (reverse (sort prob17))))) 21 | 22 | ;part 2 23 | 24 | ;; find the minimum number of containers 25 | #_(reduce min (map count (find-combos 150 (reverse (sort prob17))))) 26 | 27 | ;; find the number of ways that the can be used 28 | #_(count (filter #(= (count %) 4) (find-combos 150 (reverse (sort prob17))))) 29 | -------------------------------------------------------------------------------- /src/advent-2015/day05.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day05 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def prob5 6 | (line-seq (io/reader (io/resource "2015/prob5")))) 7 | 8 | (defn test-word [line] 9 | (and 10 | (not (re-matches #".*(ab|cd|pq|xy).*" line)) 11 | (<= 3 (count (filter #(re-matches #".*(a|e|i|o|u).*" (str %)) line))) 12 | (some 13 | #(apply = %) 14 | (partition 2 1 line)))) 15 | 16 | ; part 1 17 | #_(count (filter test-word prob5)) 18 | 19 | (defn non-consecutive-pairs [word] 20 | (some 21 | (fn [[x & xs]] (some #(> (- % x) 1) xs)) 22 | (vals 23 | (apply merge-with concat 24 | (map-indexed (fn [a b] {b [a]}) (partition 2 1 word)))))) 25 | 26 | (defn test-word2 [word] 27 | (and 28 | (non-consecutive-pairs word) 29 | (some (fn [[a _ b]] (= a b)) (partition 3 1 word)))) 30 | 31 | ; part 2 32 | #_(count (filter test-word2 prob5)) 33 | -------------------------------------------------------------------------------- /src/advent-2016/day16.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day16) 2 | 3 | (def input "11110010111001001") 4 | 5 | (defn expand [a] 6 | (concat a (cons \0 (map {\1 \0 \0 \1} (reverse a))))) 7 | 8 | (defn expand-until [size initial] 9 | (first (filter #(>= (count %) size) (iterate expand initial)))) 10 | 11 | (defn check-sum* [s] 12 | (map (fn [[a b]] (if (= a b) \1 \0)) (partition 2 s))) 13 | 14 | (defn check-sum [s] 15 | (first (filter (comp odd? count) (iterate check-sum* s)))) 16 | 17 | (defn find-answer [size s] 18 | (->> (expand-until size s) 19 | (take size) 20 | check-sum 21 | (apply str))) 22 | 23 | #_(find-answer 272 input) 24 | ;; => 01110011101111011 25 | 26 | ;; not performant (222 seconds) but 35Megs isn't impossible 27 | ;; structural sharing and seqs perform their magic here 28 | #_ (def res (time (find-answer 35651584 input))) 29 | ;; => 11001111011000111 30 | 31 | -------------------------------------------------------------------------------- /src/advent-2015/day02.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day02 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def prob2 7 | (line-seq (io/reader (io/resource "2015/prob2")))) 8 | 9 | (defn parse-dims [line] 10 | (map read-string (string/split line #"x"))) 11 | 12 | (def dimensions (map parse-dims prob2)) 13 | 14 | (defn side-dims [dims] 15 | (partition 2 1 (conj (vec dims) (first dims)))) 16 | 17 | (defn calc-area-of-present [dims] 18 | (as-> dims x 19 | (side-dims x) 20 | (map #(apply * %) x) 21 | (reduce + (reduce min x) 22 | (map #(* 2 %) x)))) 23 | 24 | ;; part 1 25 | #_(reduce + (map calc-area-of-present dimensions)) 26 | 27 | (defn calc-shortest-perimiter [dims] 28 | (as-> dims x 29 | (side-dims x) 30 | (first (sort-by #(apply * %) x)) 31 | (+ (apply * dims) 32 | (* 2 (apply + x))))) 33 | 34 | ;; part 2 35 | #_(reduce + (map calc-shortest-perimiter dimensions)) 36 | -------------------------------------------------------------------------------- /src/advent-2018/day05.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day05 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [medley.core :as med] 6 | [clj-time.core :as t])) 7 | 8 | (def data (string/trim (slurp (io/resource "2018/day05")))) 9 | 10 | (defn eliminate [accum [x y & xs]] 11 | (cond 12 | (nil? x) accum 13 | (nil? y) (cons x accum) 14 | (= (Math/abs (- (int x) (int y))) 32) 15 | (recur (rest accum) (cond-> xs 16 | (not-empty accum) 17 | (conj (first accum)))) 18 | :else (recur (cons x accum) (cons y xs)))) 19 | 20 | ;; part 1 21 | #_ (count (eliminate '() data)) 22 | 23 | (defn part2 [d] 24 | (->> (distinct (string/lower-case d)) 25 | (map #(do #{% (char (- (int %) 32))})) 26 | (map #(filter (complement %) d)) 27 | (map #(count (eliminate '() %))) 28 | (reduce min))) 29 | 30 | #_(part2 data) 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/advent-2017/day09.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day09 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data (slurp (io/resource "2017/day09"))) 7 | 8 | (defn parse-structure [data] 9 | (-> data 10 | ;; eliminate escapes 11 | (string/replace #"(!+)(.)" #(if (odd? (count (second %))) "" (last %))) 12 | ;; replace garbage with garbage count 13 | (string/replace #"<[^>]*>" (comp str dec dec count)) 14 | (string/replace "{" "(") 15 | (string/replace "}" ")") 16 | ;; parse as clojure data!! 17 | read-string)) 18 | 19 | (defn score 20 | ([data] (score data 1)) 21 | ([data depth] 22 | (cond 23 | (number? data) 0 24 | (empty? data) depth 25 | :else (+ depth (apply + (map #(score % (inc depth)) data)))))) 26 | 27 | ;; part 1 28 | #_ (score (parse-structure data)) 29 | ;;=> 13154 30 | 31 | ;; part 2 32 | #_ (apply + (flatten (parse-structure data))) 33 | ;;=> 6369 34 | -------------------------------------------------------------------------------- /src/advent-2016/utils.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.utils) 2 | 3 | (defn log [x] (println "log: " (pr-str x)) x) 4 | 5 | (def transpose (partial apply mapv vector)) 6 | 7 | (defn rotate-left [v i] 8 | (let [c (count v)] 9 | (into [] (comp (drop (mod i c)) (take c)) (cycle v)))) 10 | 11 | (defn rotate-right [v i] 12 | (rotate-left v (- i))) 13 | 14 | (defn insert-at [x n i] 15 | (let [[a b] (split-at n x)] 16 | (into (conj (vec a) i) b))) 17 | 18 | (defn delete-at [x n] 19 | (let [[a b] (split-at n x)] 20 | (into (vec a) (rest b)))) 21 | 22 | (defn pluck [pred list] 23 | [(filter pred list) (remove pred list)]) 24 | 25 | (def to-int #(Integer/parseInt %)) 26 | (def to-ints (partial map to-int)) 27 | 28 | (defn apply-times [n f init] 29 | (loop [c 0 h init] (if (= c n) h (recur (inc c) (f h))))) 30 | 31 | (defn indexes-by [f coll] 32 | (sequence 33 | (comp 34 | (map-indexed vector) 35 | (filter (comp f second)) 36 | (map first)) 37 | coll)) 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advent of Clojure 2 | 3 | My [Advent of Code](http://adventofcode.com/) Solutions in Clojure. 4 | 5 | ## Code layout 6 | 7 | **The solutions** are in the `src/advent-[year]` directories. 8 | 9 | **The problem inputs** are in the `resources/[year]` directories. 10 | 11 | ## Solutions 12 | 13 | When you are finished working on the problem, there are solutions 14 | available for you to get another point of view on the problem. 15 | 16 | * [2015](https://github.com/bhauman/advent-of-clojure/tree/master/src/advent-2015) 17 | * [2016](https://github.com/bhauman/advent-of-clojure/tree/master/src/advent-2016) 18 | * [2017](https://github.com/bhauman/advent-of-clojure/tree/master/src/advent-2017) 19 | * [2018](https://github.com/bhauman/advent-of-clojure/tree/master/src/advent-2018) 20 | 21 | ![advent tree](https://raw.githubusercontent.com/bhauman/advent-of-clojure/master/resources/2015/advent_tree.png) 22 | 23 | For more coding problems see [4Clojure](https://www.4clojure.com/) 24 | -------------------------------------------------------------------------------- /src/advent-2017/day02.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day02 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data (->> 7 | (io/resource "2017/day02") 8 | io/reader 9 | line-seq 10 | (mapv (comp (partial mapv read-string) 11 | #(string/split % #"\s+"))))) 12 | 13 | (defn checksum-1 [row] 14 | (- (apply max row) (apply min row))) 15 | 16 | (and 17 | (= 8 (checksum-1 [5 1 9 5])) 18 | (= 4 (checksum-1 [7 5 3])) 19 | (= 6 (checksum-1 [2 4 6 8]))) 20 | 21 | ;; part 1 22 | #_(apply + (map checksum-1 data)) 23 | 24 | (defn checksum-2 [row] 25 | (first (for [a row 26 | b row 27 | :when (and (not= a b) 28 | (= 0 (rem a b)))] 29 | (/ a b)))) 30 | 31 | (and 32 | (= (checksum-2 [5 9 2 8]) 4) 33 | (= (checksum-2 [9 4 7 3]) 3) 34 | (= (checksum-2 [3 8 6 5]) 2)) 35 | 36 | ;; part 2 37 | #_(apply + (map checksum-2 data)) 38 | 39 | -------------------------------------------------------------------------------- /src/advent-2017/day01.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day01 2 | (:require [clojure.java.io :as io])) 3 | 4 | (def data (mapv 5 | (comp read-string str) 6 | (slurp (io/resource "2017/day01")))) 7 | 8 | (defn count-em [d] 9 | (->> (partition 2 1 (conj (vec d) (first d))) 10 | (filter (partial apply =)) 11 | (map first) 12 | (apply +))) 13 | 14 | (comment 15 | (count-em [1 1 2 2]) 16 | (count-em [1 1 1 1]) 17 | (count-em [1 2 3 4]) 18 | (count-em [9 1 2 1 2 1 2 9])) 19 | 20 | ;; part 1 21 | #_(count-em data) 22 | 23 | (defn count-em2 [d] 24 | (->> (map 25 | vector 26 | d 27 | (drop (/ (clojure.core/count d) 2) (cycle d))) 28 | (filter (partial apply =)) 29 | (map first) 30 | (apply +))) 31 | 32 | (comment 33 | (count-em2 [1 2 1 2]) 34 | (count-em2 [1 2 2 1]) 35 | (count-em2 [1 2 3 4 2 5]) 36 | (count-em2 [1 2 3 1 2 3]) 37 | (count-em2 [1 2 1 3 1 4 1 5])) 38 | 39 | ;; part 2 40 | #_(count-em2 data) 41 | 42 | -------------------------------------------------------------------------------- /src/advent-2016/day20.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day20 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data 7 | (->> (slurp (io/resource "2016/day20")) 8 | string/split-lines 9 | (map #(string/split % #"-")) 10 | (map #(mapv read-string %)) 11 | (mapv #(do (assert (apply < %)) %)) 12 | sort)) 13 | 14 | (defn overlap? [[l h] [l2 h2]] (>= (inc h) l2)) 15 | 16 | (defn merge-em [[l h] [l2 h2]] [(min l l2) (max h h2)]) 17 | 18 | (defn merge-all [ips] 19 | (reduce (fn [[accum & xs :as st] nxt] 20 | (if (overlap? accum nxt) 21 | (cons (merge-em accum nxt) xs) 22 | (cons nxt st))) 23 | [[0 0]] 24 | ips)) 25 | 26 | ;; part 1 27 | #_(-> (merge-all data) last last inc) 28 | ;; => 4793564 29 | 30 | (defn size [[l h]] (inc (- h l))) 31 | 32 | ;; part 2 33 | #_(->> (merge-all data) 34 | (map size) 35 | (reduce +) 36 | (- (size [0 4294967295]))) 37 | ;; => 146 38 | -------------------------------------------------------------------------------- /src/advent-2016/day1.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day1 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def data (read-string (str "[" (slurp (io/resource "2016/day1")) "]"))) 6 | 7 | (defn parse-data [d] 8 | (->> d 9 | (map name) 10 | (map (juxt first 11 | #(Integer/parseInt (apply str (rest %))))))) 12 | 13 | (defn positions [d] 14 | (->> (map first d) 15 | (reductions #(({\L dec \R inc} %2) %1) 0) 16 | rest 17 | (map #(mod % 4)) 18 | (map [[0 1] [1 0] [0 -1] [-1 0]]) 19 | (mapcat repeat (map second d)) 20 | (reductions (partial map +) (list 0 0)))) 21 | 22 | (defn point-to-dist [p] 23 | (->> p 24 | (map #(Math/abs %)) 25 | (reduce +))) 26 | 27 | ;; part 1 28 | #_(->> data 29 | parse-data 30 | positions 31 | last 32 | point-to-dist) 33 | ;; => 291 34 | 35 | ;; part 2 36 | #_(->> data 37 | parse-data 38 | positions 39 | (reductions conj (list)) 40 | (filter (fn [[x & xs]] ((set xs) x))) 41 | ffirst 42 | point-to-dist) 43 | ;; => 159 44 | -------------------------------------------------------------------------------- /src/advent-2018/day03.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day03 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data 7 | (->> (line-seq (io/reader (io/resource "2018/day03"))) 8 | (map #(->> % 9 | (re-seq #"\d+") 10 | (map read-string))))) 11 | 12 | (defn square [m [id x y w h]] 13 | (reduce 14 | #(update %1 %2 (fn [p] (if p 'X id))) 15 | m 16 | (for [x' (range x (+ x w)) 17 | y' (range y (+ y h))] 18 | [x' y']))) 19 | 20 | (def fabric 21 | (memoize 22 | (fn [data] 23 | (reduce square {} data)))) 24 | 25 | (defn part1 [d] 26 | (count (filter #(= 'X %) (vals (fabric d))))) 27 | 28 | #_ (time (part1 data)) 29 | 30 | (defn part2 [d cloth] 31 | (let [actual-area-map (frequencies (vals cloth)) 32 | ideal-area-map 33 | (into {} (map (fn [[id _ _ w h]] [id (* w h)])) d)] 34 | (->> (keys actual-area-map) 35 | (filter #(= (get actual-area-map %) 36 | (get ideal-area-map %))) 37 | first))) 38 | 39 | #_ (time (part2 data (fabric data))) 40 | -------------------------------------------------------------------------------- /src/advent-2016/day15.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day15) 2 | 3 | (def start-state [[5 17] 4 | [8 19] 5 | [1 7] 6 | [7 13] 7 | [1 5] 8 | [0 3]]) 9 | 10 | (defn disc-at-t [[pos disc-size] t] 11 | [(mod (+ t pos) disc-size) disc-size]) 12 | 13 | (defn state-of-discs-at-t [s t] 14 | (map-indexed (fn [i disc] (disc-at-t disc (+ 1 t i))) s)) 15 | 16 | (def completed #(every? zero? (map first %))) 17 | 18 | (defn times-with-aligned-discs [s start step] 19 | (->> (range start Integer/MAX_VALUE step) 20 | (filter #(completed (state-of-discs-at-t s %))))) 21 | 22 | (defn next-step [{:keys [pos step]} state] 23 | (let [[next-pos after-pos] 24 | (take 2 (times-with-aligned-discs state pos step))] 25 | {:pos next-pos :step (- after-pos next-pos)})) 26 | 27 | (defn find-answer [state] 28 | (reduce next-step {:pos 0 :step 1} (rest (reductions conj [] state)))) 29 | 30 | ;; part 1 31 | #_(find-answer start-state) 32 | ;; => 16824 33 | 34 | #_(find-answer (conj start-state [0 11])) 35 | ;; => 3543984 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/advent-2015/day14.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day14 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def prob14 (line-seq (io/reader (io/resource "2015/prob14")))) 7 | 8 | (defn line-to-data [line] 9 | (map read-string (re-seq #"\d+" line))) 10 | 11 | (def reindeer (map line-to-data prob14)) 12 | 13 | (defn traveled [[speed travel restt] seconds] 14 | (let [period (+ travel restt)] 15 | (+ (* travel speed (int (/ seconds period))) 16 | (let [finalp (rem seconds period)] 17 | (if (> travel finalp) 18 | (* speed finalp) 19 | (* speed travel)))))) 20 | 21 | ; part 1 22 | #_(reduce max (map #(traveled % 2503) reindeer)) 23 | 24 | (defn winners [reindeer seconds] 25 | (let [res (apply merge-with concat 26 | (map 27 | #(hash-map (traveled % seconds) [%]) 28 | reindeer))] 29 | (get res (apply max (keys res))))) 30 | 31 | ; part 2 32 | #_(reduce max 33 | (vals 34 | (frequencies 35 | (mapcat (partial winners reindeer) 36 | (range 1 (inc 2503)))))) 37 | -------------------------------------------------------------------------------- /src/advent-2016/day5.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day5 2 | (:require 3 | [clojure.java.io :as io] 4 | [digest :refer [md5]] 5 | [medley.core :refer [distinct-by]])) 6 | 7 | (def input "ffykfhsq") 8 | 9 | (defn find-password [code] 10 | (transduce 11 | (comp 12 | (map #(md5 (str code %))) 13 | (filter #(= "00000" (subs % 0 5))) 14 | (map #(nth % 5)) 15 | (take 8)) 16 | conj 17 | [] 18 | (range))) 19 | 20 | #_ (def res (time (find-password input))) 21 | ;; => [\c \6 \6 \9 \7 \b \5 \5] 22 | ;; 23.4 seconds baby! 23 | 24 | (defn find-codes-2 [code] 25 | (transduce 26 | (comp 27 | (map #(md5 (str code %))) 28 | (filter #(and (= "00000" (subs % 0 5)) 29 | (> 8 (Integer/parseInt (subs % 5 6) 16)))) 30 | (map (juxt #(Integer/parseInt (str (nth % 5))) 31 | #(nth % 6))) 32 | (distinct-by first) 33 | (take 8)) 34 | conj 35 | [] 36 | (range))) 37 | 38 | (defn result-password [codes] 39 | (reduce #(assoc %1 (first %2) (second %2)) (vec (replicate 8 '_)) codes)) 40 | 41 | #_ (def res2 (time (result-password (find-codes-2 input)))) 42 | ;; => [\8 \c \3 \5 \d \1 \a \b] 43 | ;; 110 seconds 44 | -------------------------------------------------------------------------------- /src/advent-2017/day12.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day12 2 | (:require 3 | [clojure.java.io :as io] 4 | 5 | [clojure.set :as st])) 6 | 7 | (def data (->> (io/resource "2017/day12") 8 | io/reader 9 | line-seq 10 | (map #(format "[%s]" %)) 11 | (map read-string))) 12 | 13 | (defn index [data'] 14 | (reduce (fn [accum [node _ & direct-connect]] 15 | (as-> (set direct-connect) x 16 | (disj x node) 17 | (assoc accum node x))) 18 | {} 19 | data')) 20 | 21 | ;; find group without cycles 22 | 23 | (defn group [idx root] 24 | (into #{} 25 | (tree-seq (let [seen (atom #{})] 26 | (fn [x] (when-not (@seen x) 27 | (swap! seen conj x)))) 28 | idx 29 | root))) 30 | 31 | ;; part 1 32 | #_(let [idx (index data)] 33 | (time (count (group idx 0)))) 34 | ;; => 113 35 | 36 | ;; part 2 37 | ;; not worth optimizing for problem space 38 | #_(let [idx (index data)] 39 | (->> (map #(group idx %) (keys idx)) 40 | (into #{}) 41 | count)) 42 | ;; => 202 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /resources/2017/day02: -------------------------------------------------------------------------------- 1 | 626 2424 2593 139 2136 163 1689 367 2235 125 2365 924 135 2583 1425 2502 2 | 183 149 3794 5221 5520 162 5430 4395 2466 1888 3999 3595 195 181 6188 4863 3 | 163 195 512 309 102 175 343 134 401 372 368 321 350 354 183 490 4 | 2441 228 250 2710 200 1166 231 2772 1473 2898 2528 2719 1736 249 1796 903 5 | 3999 820 3277 3322 2997 1219 1014 170 179 2413 183 3759 3585 2136 3700 188 6 | 132 108 262 203 228 104 205 126 69 208 235 311 313 258 110 117 7 | 963 1112 1106 50 186 45 154 60 1288 1150 986 232 872 433 48 319 8 | 111 1459 98 1624 2234 2528 93 1182 97 583 2813 3139 1792 1512 1326 3227 9 | 371 374 459 83 407 460 59 40 42 90 74 163 494 250 488 444 10 | 1405 2497 2079 2350 747 1792 2412 2615 89 2332 1363 102 81 2346 122 1356 11 | 1496 2782 2257 2258 961 214 219 2998 400 230 2676 3003 2955 254 2250 2707 12 | 694 669 951 455 2752 216 1576 3336 251 236 222 2967 3131 3456 1586 1509 13 | 170 2453 1707 2017 2230 157 2798 225 1891 945 943 2746 186 206 2678 2156 14 | 3632 3786 125 2650 1765 1129 3675 3445 1812 3206 99 105 1922 112 1136 3242 15 | 6070 6670 1885 1994 178 230 5857 241 253 5972 7219 252 806 6116 4425 3944 16 | 2257 155 734 228 204 2180 175 2277 180 2275 2239 2331 2278 1763 112 2054 -------------------------------------------------------------------------------- /src/advent-2016/day17.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day17 2 | (:require 3 | [digest :refer [md5]])) 4 | 5 | (def input "mmsxrhfx") 6 | 7 | (def dir-map 8 | {[0 -1] \U [0 1] \D [-1 0] \L [1 0] \R }) 9 | 10 | (defn directions [code [path pos]] 11 | (->> (md5 (apply str code path)) 12 | (take 4) 13 | (keep-indexed (fn [i v] (when (#{\b \c \d \e \f} v) i))) 14 | (map [[0 -1] [0 1] [-1 0] [1 0]]) 15 | (map #(vector (conj path (dir-map %)) (map + pos %))) 16 | (filter #(let [[_ [a b]] %] 17 | (and (<= 0 a 3) (<= 0 b 3)))))) 18 | 19 | (def finished? #(= [3 3] (second %))) 20 | 21 | (defn breadth-first-level [input positions] 22 | (->> positions 23 | (filter (comp not finished?)) 24 | (mapcat (partial directions input)) 25 | (sort-by #(if (finished? %) 0 1)))) 26 | 27 | (defn find-answer [s] 28 | (->> (iterate (partial breadth-first-level s) [[[] [0 0]]]) 29 | (take-while not-empty) 30 | (filter (comp finished? first)) 31 | (map #(apply str (ffirst %))))) 32 | 33 | ;; part1 34 | #_(first (find-answer input)) 35 | ;; => RLDUDRDDRR 36 | 37 | ;; part 2 38 | #_(count (last (find-answer input))) 39 | ;; => 590 40 | -------------------------------------------------------------------------------- /doc/2015/04.md: -------------------------------------------------------------------------------- 1 | # Day 4: The Ideal Stocking Stuffer 2 | 3 | Santa needs help mining some AdventCoins (very similar to bitcoins) to 4 | use as gifts for all the economically forward-thinking little girls 5 | and boys. 6 | 7 | To do this, he needs to find MD5 hashes which, in hexadecimal, start 8 | with at least five zeroes. The input to the MD5 hash is some secret 9 | key (your puzzle input, given below) followed by a number in decimal. 10 | To mine AdventCoins, you must find Santa the lowest positive number 11 | (no leading zeroes: 1, 2, 3, ...) that produces such a hash. 12 | 13 | For example: 14 | 15 | If your secret key is abcdef, the answer is `609043`, because the MD5 16 | hash of `abcdef609043` starts with five zeroes `(000001dbbfa...)`, and 17 | it is the lowest such number to do so. 18 | 19 | If your secret key is `pqrstuv`, the lowest number it combines with to 20 | make an MD5 hash starting with five zeroes is `1048970`; that is, the 21 | MD5 hash of `pqrstuv1048970` looks like `000006136ef...`. 22 | 23 | Your secrect key: `yzbqklnj` 24 | 25 | Your puzzle answer was **`282749`**. 26 | 27 | ## Part Two 28 | 29 | Now find one that starts with six zeroes. 30 | 31 | Your puzzle answer was **`9962624`**. 32 | -------------------------------------------------------------------------------- /src/advent-2015/day15.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day15 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [clojure.math.combinatorics :refer [selections combinations]])) 6 | 7 | (def prob15 8 | (line-seq (io/reader (io/resource "2015/prob15")))) 9 | 10 | (defn read-ingredient [line] 11 | (as-> line x 12 | (string/replace x ":" "") 13 | (read-string (str "(" x ")")) 14 | (filter integer? x))) 15 | 16 | (def ingredients (map read-ingredient prob15)) 17 | 18 | (defn ingredient-value [ingred tsp] 19 | (map #(* tsp %) (butlast ingred))) 20 | 21 | (defn recipe-value [parts] 22 | (->> parts 23 | (map ingredient-value ingredients) 24 | (reduce #(map + %1 %2)) 25 | (map #(max 0 %)) 26 | (reduce *))) 27 | 28 | (defn partitions [i] 29 | (for [x (range (inc i)) 30 | y (range (inc (- i x))) 31 | z (range (inc (- i x y)))] 32 | [x y z (- i x y z)])) 33 | 34 | #_(def res (mapv (juxt identity recipe-value) (partitions 100))) 35 | 36 | ;; part 1 37 | #_(apply max (map second res)) 38 | 39 | ;; part 2 40 | (defn calorie-value [parts] 41 | (reduce + (map * parts (map last ingredients)))) 42 | 43 | #_(reduce max (map second (filter #(= 500 (calorie-value (first %))) res))) 44 | -------------------------------------------------------------------------------- /src/advent-2016/day14.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day14 2 | (:require 3 | [advent-2016.utils :refer [apply-times]] 4 | [digest :refer [md5]] 5 | [medley.core :refer [assoc-some]])) 6 | 7 | (def next-hash (comp md5 str)) 8 | 9 | (def stretched-hash (comp (partial apply-times 2016 md5) next-hash)) 10 | 11 | (defn triple-and-fives [h] 12 | (-> {} 13 | (assoc-some :triple (second (re-find #"(.)\1\1" h))) 14 | (assoc-some :fives (not-empty (set (map second (re-seq #"(.)\1\1\1\1" h))))) 15 | not-empty)) 16 | 17 | (defn code-key? [salted-hasher i] 18 | (when-let [{:keys [triple]} (salted-hasher i)] 19 | (->> (range (inc i) (+ 1000 i)) 20 | (keep (comp :fives salted-hasher)) 21 | (some #(contains? % triple))))) 22 | 23 | (defn find-answer [index-has-key?] 24 | (time (->> (filter index-has-key? (range)) 25 | (take 64) 26 | (map #(do (prn %) %)) 27 | last))) 28 | 29 | (defn make-index-pred [salted-hasher] 30 | (partial code-key? (memoize (comp triple-and-fives salted-hasher)))) 31 | 32 | ;; part 1 33 | #_(find-answer (make-index-pred (partial next-hash "ahsbgdzn"))) 34 | ;; => 23890 35 | 36 | ;; part 2 37 | #_(find-answer (make-index-pred (partial stretched-hash "ahsbgdzn"))) 38 | ;; => 22696 39 | -------------------------------------------------------------------------------- /src/advent-2015/day13.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day13 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [clojure.set :refer [union]] 6 | [clojure.math.combinatorics :refer [permutations]])) 7 | 8 | (def prob13 9 | (line-seq (io/reader (io/resource "2015/prob13")))) 10 | 11 | (defn line-to-data [line] 12 | (as-> line x 13 | (string/replace x "." "") 14 | (read-string (str "(" x ")")) 15 | ((juxt (comp set (juxt first last)) 16 | #((if (= (nth % 2) 'lose) - +) (nth % 3))) x) 17 | (apply hash-map x))) 18 | 19 | (def seating-pair-values (apply merge-with + (map line-to-data prob13))) 20 | 21 | (def guest-names (reduce union (keys seating-pair-values))) 22 | 23 | (defn arrangement-value [pair-values order] 24 | (reduce + 25 | (map (comp pair-values set) 26 | (partition 2 1 (cons (last order) order))))) 27 | 28 | ;; part 1 29 | #_(reduce max (map (partial arrangement-value seating-pair-values) 30 | (permutations guest-names))) 31 | 32 | ;; part 2 33 | #_(let [pair-values (into seating-pair-values 34 | (map #(vector #{'me %} 0) guest-names))] 35 | (reduce max (map (partial arrangement-value pair-values) 36 | (permutations (cons 'me guest-names))))) 37 | -------------------------------------------------------------------------------- /src/advent-2017/day06.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day06 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def test-data [0 2 7 0]) 6 | 7 | (def data (read-string 8 | (str "[" (slurp (io/resource "2017/day06")) "]"))) 9 | 10 | (defn redistribute [block] 11 | (let [max-val (apply max block) 12 | position (.indexOf block max-val)] 13 | (reduce #(update-in %1 [(mod %2 (count %1))] inc) 14 | (assoc block position 0) 15 | (range (inc position) 16 | (+ (inc position) max-val))))) 17 | 18 | ; part 1 19 | (defn part1 [first-block] 20 | (count (reduce 21 | (fn [history-set next-block] 22 | (if (history-set next-block) 23 | (reduced history-set) 24 | (conj history-set next-block))) 25 | #{} 26 | (iterate redistribute first-block)))) 27 | 28 | #_(part1 data) 29 | ;;=> 7864 30 | 31 | ;; part 2 32 | (defn part2 [first-block] 33 | (reduce 34 | (fn [history-map next-block] 35 | (if-let [result (history-map next-block)] 36 | (reduced (- (count history-map) result)) 37 | (assoc history-map next-block (count history-map)))) 38 | {} 39 | (iterate redistribute first-block))) 40 | 41 | #_(part2 data) 42 | ;;=> 1695 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/advent-2017/day15.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day15) 2 | 3 | (defn transition [f v] 4 | (rem (* ^long f ^long v) 2147483647)) 5 | 6 | (def a-transition (partial transition 16807)) 7 | (def b-transition (partial transition 48271)) 8 | 9 | (defn generate [a-start b-start] 10 | (rest 11 | (map = 12 | (map #(bit-and 2r1111111111111111 ^long %) 13 | (iterate a-transition a-start)) 14 | (map #(bit-and 2r1111111111111111 ^long %) 15 | (iterate b-transition b-start))))) 16 | 17 | ;; part 1 18 | #_(time 19 | (count (filter identity 20 | (take 40000000 (generate 783 325))))) 21 | ;; Elapsed time: 34519.967381 msecs 22 | ;; => 650 23 | 24 | (defn generate-2 [a-start b-start] 25 | (rest 26 | (map = 27 | (map #(bit-and 2r1111111111111111 ^long %) 28 | (filter #(zero? ^long (mod ^long % 4)) 29 | (iterate a-transition a-start))) 30 | (map #(bit-and 2r1111111111111111 ^long %) 31 | (filter #(zero? ^long (mod ^long % 8)) 32 | (iterate b-transition b-start)))))) 33 | 34 | #_(set! *unchecked-math* :warn-on-boxed) 35 | 36 | ;; part 2 37 | #_(time 38 | (count (filter identity 39 | (take 5000000 (generate-2 783 325))))) 40 | ;; => 336 41 | ;; Elapsed time: 17035.632906 msecs 42 | -------------------------------------------------------------------------------- /doc/2015/17.md: -------------------------------------------------------------------------------- 1 | # Day 17: No Such Thing as Too Much 2 | 3 | The elves bought too much eggnog again - `150` liters this time. To fit 4 | it all into your refrigerator, you'll need to move it into smaller 5 | containers. You take an inventory of the capacities of the available 6 | containers. 7 | 8 | For example, suppose you have containers of size `20`, `15`, `10`, `5`, and `5` 9 | liters. If you need to store 25 liters, there are four ways to do it: 10 | 11 | ``` 12 | 15 and 10 13 | 20 and 5 (the first 5) 14 | 20 and 5 (the second 5) 15 | 15, 5, and 5 16 | ``` 17 | 18 | Filling all containers entirely, how many different combinations of 19 | containers can exactly fit all `150` liters of eggnog? 20 | 21 | Your puzzle answer was **`1638`**. 22 | 23 | ## Part Two 24 | 25 | While playing with all the containers in the kitchen, another load of 26 | eggnog arrives! The shipping and receiving department is requesting as 27 | many containers as you can spare. 28 | 29 | Find the minimum number of containers that can exactly fit all `150` 30 | liters of eggnog. How many different ways can you fill that number of 31 | containers and still hold exactly 150 litres? 32 | 33 | In the example above, the minimum number of containers was two. There 34 | were three ways to use that many containers, and so the answer there 35 | would be `3`. 36 | 37 | Your puzzle answer was `17`. -------------------------------------------------------------------------------- /src/advent-2015/day23.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.core 2 | (:require [clojure.java.io :as io])) 3 | 4 | (def prog 5 | (map #(read-string (str "(" % ")")) 6 | (line-seq (io/reader (io/resource "2015/prob23"))))) 7 | 8 | (defn run [prog start-state] 9 | (loop [{:keys [pos] :as st} start-state] 10 | (if (not (< pos (count prog))) 11 | st 12 | (recur 13 | (let [[cmd sec :as inst] (nth prog pos) 14 | reg-key (when (symbol? sec) sec)] 15 | (condp = cmd 16 | 'jio (if (= (st reg-key) 1) 17 | (update-in st [:pos] + (last inst)) 18 | (update-in st [:pos] inc)) 19 | 'jie (if (even? (st reg-key)) 20 | (update-in st [:pos] + (last inst)) 21 | (update-in st [:pos] inc)) 22 | 'jmp (-> st 23 | (update-in [:pos] + (last inst))) 24 | 'inc (-> st 25 | (update-in [reg-key] inc) 26 | (update-in [:pos] inc)) 27 | 'tpl (-> st 28 | (update-in [reg-key] * 3) 29 | (update-in [:pos] inc)) 30 | 'hlf (-> st 31 | (update-in [reg-key] #(int (/ % 2))) 32 | (update-in [:pos] inc)))))))) 33 | 34 | #_(run prog {'a 0 'b 0 :pos 0}) 35 | 36 | #_(run prog {'a 1 'b 0 :pos 0}) 37 | -------------------------------------------------------------------------------- /src/advent-2017/day08.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day08 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (defn parse-data [lines] 7 | (->> lines 8 | (map #(str "[" % "]")) 9 | (map read-string))) 10 | 11 | (def data (->> (io/resource "2017/day08") 12 | io/reader 13 | line-seq 14 | parse-data)) 15 | 16 | (def fn-map 17 | (->> (map (juxt identity eval)'(> < >= <= ==)) 18 | (into {'inc (fnil + 0) 19 | 'dec (fnil - 0) 20 | '!= not=}))) 21 | 22 | (defn eval-exp [accum [reg inc-dec value _ cond-reg pred pred-val]] 23 | (if ((fn-map pred) (get accum cond-reg 0) pred-val) 24 | (update accum reg (fn-map inc-dec) value) 25 | accum)) 26 | 27 | (defn part1 [instructions] 28 | (->> (reduce eval-exp {} instructions) 29 | vals 30 | (apply max))) 31 | 32 | ;; part 1 33 | #_(part1 data) 34 | ;; => 5075 35 | 36 | (defn part2 [instructions] 37 | (->> (reductions eval-exp {} instructions) 38 | (keep vals) 39 | (map (partial apply max)) 40 | (apply max))) 41 | 42 | ;; part 2 43 | #_(part2 data) 44 | ;; => 7310 45 | 46 | 47 | (comment 48 | (def test-data 49 | (-> "b inc 5 if a > 1 50 | a inc 1 if b < 5 51 | c dec -10 if a >= 1 52 | c inc -20 if c == 10" 53 | string/split-lines 54 | parse-data)) 55 | ) 56 | -------------------------------------------------------------------------------- /src/advent-2015/day20.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day20) 2 | 3 | ;; happy to say that I did this without looking at the forums 4 | ;; spent a decent amount of time understanding this page: 5 | ;; http://mathschallenge.net/library/number/sum_of_divisors 6 | 7 | (defn value* [p n] 8 | (/ (dec (java.lang.Math/pow p (inc n))) 9 | (dec p))) 10 | 11 | (defn sum-of-divisors [prime-factors] 12 | (apply * (map #(apply value* %) (frequencies prime-factors)))) 13 | 14 | ;; I searched prime combinations by hand maximizing the (/ sum-of-divisors house-number) 15 | ;; and getting a feel for the search space 16 | (let [d [2 2 2 2 3 3 3 5 5 7 11] 17 | house-number (apply * d) 18 | sum-of-presents (sum-of-divisors d)] 19 | [house-number 20 | sum-of-presents 21 | (/ sum-of-presents house-number) 22 | (java.lang.Math/abs (- sum-of-presents 3600000)) 23 | (< house-number 900900)]) ;; 900900 is the last minimum I found 24 | 25 | ;; part 2 26 | 27 | ;; brute force: I know the bounds now and understand the 28 | ;; character of the space a bit better 29 | 30 | (defn divisors [n] 31 | (cons n (filter #(and 32 | (>= (* 50 %) n) 33 | (zero? (rem n %))) 34 | (range 16632 (inc (/ n 2)))))) 35 | 36 | #_(first (filter #(>= (* 11 (apply + (divisors %))) 37 | 36000000) 38 | (range 831600 900900 5))) 39 | -------------------------------------------------------------------------------- /doc/2015/10.md: -------------------------------------------------------------------------------- 1 | # Day 10: Elves Look, Elves Say 2 | 3 | Today, the Elves are playing a game called look-and-say. They take 4 | turns making sequences by reading aloud the previous sequence and 5 | using that reading as the next sequence. For example, `211` is read as 6 | "one two, two ones", which becomes `1221` (`1` `2`, `2` `1`s). 7 | 8 | Look-and-say sequences are generated iteratively, using the previous 9 | value as input for the next step. For each step, take the previous 10 | value, and replace each run of digits (like `111`) with the number of 11 | digits (`3`) followed by the digit itself (`1`). 12 | 13 | For example: 14 | 15 | `1` becomes `11` (`1` copy of digit `1`). 16 | 17 | `11` becomes `21` (`2` copies of digit `1`). 18 | 19 | `21` becomes `1211` (one `2` followed by one `1`). 20 | 21 | `1211` becomes `111221` (one `1`, one `2`, and two `1`s). 22 | 23 | `111221` becomes `312211` (three `1`s, two `2`s, and one `1`). 24 | 25 | Starting with the digits in your puzzle input, apply this process `40` 26 | times. What is the length of the result? 27 | 28 | Your puzzle answer was **`492982`**. 29 | 30 | ## Part Two 31 | 32 | Neat, right? You might also enjoy hearing John Conway talking about 33 | this sequence (that's Conway of Conway's Game of Life fame). 34 | 35 | Now, starting again with the digits in your puzzle input, apply this 36 | process `50` times. What is the length of the new result? 37 | 38 | Your puzzle answer was **`6989950`**. -------------------------------------------------------------------------------- /src/advent-2017/day25.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day25 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (defn parse-state-program [state-program] 7 | (mapv (comp 8 | read-string 9 | #(subs % 0 (dec (count %))) 10 | last 11 | #(string/split % #"\s")) 12 | state-program)) 13 | 14 | (def tape-program 15 | (->> (io/resource "2017/day25") 16 | io/reader 17 | line-seq 18 | (drop 2) 19 | (partition 10) 20 | (map rest) 21 | (map parse-state-program))) 22 | 23 | (defn options->machine [machine [state current write direction next-state]] 24 | (assoc-in machine [state current] [write direction next-state])) 25 | 26 | (defn program->state-machine [machine [state & args]] 27 | (reduce options->machine machine (map #(cons state %) (partition 4 args)))) 28 | 29 | (def state-machine (reduce program->state-machine {} tape-program)) 30 | 31 | (defn transition [state-machine [state ^long position tape]] 32 | (let [[write direction next-state] (get-in state-machine [state (get tape position 0)])] 33 | [next-state 34 | ((if (= 'right direction) inc dec) position) 35 | (assoc tape position write)])) 36 | 37 | #_(->> (nth (iterate (partial transition state-machine) ['A 0 {}]) 38 | 12368930) 39 | last 40 | vals 41 | (reduce +) 42 | time) 43 | ;; => 2725 44 | ;; Elapsed time: 14319.600632 msecs 45 | -------------------------------------------------------------------------------- /src/advent-2015/day11.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day11) 2 | 3 | (defn straight-test [x] 4 | (some (fn [r] 5 | (let [[a b c] (map byte r)] 6 | (and a b c (= (+ 2 a) (inc b) c)))) 7 | (partition 3 1 x))) 8 | 9 | (defn not-iol [x] 10 | (not (re-matches #".*(i|o|l).*" (apply str x)))) 11 | 12 | (defn has-different-pairs [x] 13 | (< 1 14 | (count (set (filter #(apply = %) (partition 2 1 x)))))) 15 | 16 | (defn valid-password? [p] 17 | (and 18 | (not-iol p) 19 | (has-different-pairs p) 20 | (straight-test p))) 21 | 22 | (defn adjust-char [x] 23 | (char 24 | (+ 25 | (if (<= (byte x) (byte \9)) 49 10) 26 | (byte x)))) 27 | 28 | (defn adjust-char-back [x] 29 | (char 30 | (- 31 | (byte x) 32 | (if (<= (byte x) (byte \j)) 49 10)))) 33 | 34 | (def base26->password #(apply str (mapv adjust-char %))) 35 | 36 | (def password->base26 #(apply str (mapv adjust-char-back %))) 37 | 38 | (defn long->password [i] 39 | (-> i 40 | (java.lang.Long/toString 26) 41 | base26->password)) 42 | 43 | (defn password->long [s] 44 | (-> s 45 | password->base26 46 | (java.lang.Long/valueOf 26))) 47 | 48 | (defn base26-passwords [start-int] 49 | (filter valid-password? 50 | (map long->password (iterate inc start-int)))) 51 | 52 | ;; part 1 53 | #_(first (base26-passwords (password->long "cqjxjnds"))) 54 | 55 | ;; part 2 56 | #_(second (base26-passwords (password->long "cqjxxyzz"))) 57 | -------------------------------------------------------------------------------- /src/advent-2016/day2.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day2 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def lines (line-seq (io/reader (io/resource "2016/day2")))) 6 | 7 | (def dir {\U [0 -1] 8 | \D [0 1] 9 | \R [1 0] 10 | \L [-1 0]}) 11 | 12 | (def pos-number #(+ 5 (* 3 (second %)) (first %))) 13 | 14 | (defn in-bounds? [[x y]] 15 | (and (<= -1 x 1) (<= -1 y 1))) 16 | 17 | (defn code-to-pos [bound-fn start code] 18 | (->> code 19 | (map dir) 20 | (reduce (fn [a v] 21 | (let [cp (map + a v)] 22 | (if (bound-fn cp) cp a))) 23 | start))) 24 | 25 | ;; part 1 26 | #_(->> lines 27 | (reductions (partial code-to-pos in-bounds?) 28 | [0 0]) 29 | rest 30 | (map pos-number)) 31 | ;; => (7 8 2 9 3) 32 | 33 | (defn in-part-2-bounds [[x y]] 34 | (and (<= -2 x 2) 35 | (let [bound (- 2 (Math/abs x))] 36 | (<= (- bound) y bound)))) 37 | 38 | (def keypad-map 39 | (into {} 40 | (map 41 | vector 42 | (->> (for [y (range -2 3) 43 | x (range -2 3)] 44 | [x y]) 45 | (filter in-part-2-bounds)) 46 | (map inc (range))))) 47 | 48 | ;; part 2 49 | #_(->> lines 50 | (reductions (partial code-to-pos in-part-2-bounds) [-2 0]) 51 | rest 52 | (map keypad-map) 53 | (map #(format "%X" %))) 54 | 55 | ; => ("A" "C" "8" "C" "8") 56 | -------------------------------------------------------------------------------- /src/advent-2017/day13.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day13 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data (->> (io/resource "2017/day13") 7 | io/reader 8 | line-seq 9 | (map #(string/replace % #":" "")) 10 | (map #(format "[%s]" %)) 11 | (map read-string) 12 | (into (sorted-map)))) 13 | 14 | (defn scanner-position [count level-size] 15 | (let [level-size (dec level-size) 16 | division (/ count level-size)] 17 | (if (even? (long division)) 18 | (rem count level-size) 19 | (- level-size (rem count level-size))))) 20 | 21 | ;; part 1 22 | #_(->> data 23 | (map (juxt #(scanner-position (key %) (val %)) identity)) 24 | (filter (comp zero? first)) 25 | (map (comp #(apply * %) second)) 26 | (apply +)) 27 | ;; => 1476 28 | 29 | (defn build-can-pass-at-time?-fn [data'] 30 | (let [data-size (apply max (keys data'))] 31 | (fn [time-offset] 32 | (some 33 | (fn [[level range']] 34 | (zero? 35 | (scanner-position (+ level time-offset) range'))) 36 | data')))) 37 | 38 | (defn how-many-pico-seconds-to-delay? [data'] 39 | (->> (map (build-can-pass-at-time?-fn data') (range)) 40 | (take-while identity) 41 | count)) 42 | 43 | ;; part 2 44 | #_ (time (how-many-pico-seconds-to-delay? data)) 45 | ;; Elapsed time: 6779.875129 msecs 46 | ;; => 3937334 47 | 48 | -------------------------------------------------------------------------------- /src/advent-2015/day24.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day24 2 | (:require 3 | [clojure.math.combinatorics :as combo])) 4 | 5 | ;; workarea 6 | (def input [1 3 5 11 13 17 19 23 29 31 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113]) 7 | 8 | (def total (apply + input)) 9 | 10 | ;; really fast way to do this 11 | (def find-sets= 12 | (memoize 13 | (fn [g n] 14 | (cond 15 | (< n 0) nil 16 | (= n 0) [[]] 17 | :else 18 | (filter 19 | not-empty 20 | (mapcat 21 | (fn [[f & r]] (map #(cons f %) (find-sets= r (- n f)))) 22 | (take-while not-empty (iterate rest g)))))))) 23 | 24 | ;; part 1 25 | #_(first 26 | (sort (map #(apply * %) 27 | (second (first (group-by count (find-sets= (reverse input) (/ total 3)))))))) 28 | 29 | ;; part 2 30 | #_(first 31 | (sort (map #(apply * %) 32 | (second (first (group-by count (find-sets= (reverse input) (/ total 4)))))))) 33 | 34 | 35 | ;; another way is to get smallest combinations 36 | 37 | ;; part 1 38 | (reduce min 39 | (map #(apply * %) 40 | ;; use a loop here instead of laziness 41 | ;; as laziness will 'look ahead' and that becomes 42 | ;; combinatorially problematic 43 | (loop [x 1] 44 | (let [combs (combo/combinations input x)] 45 | (if-let [res (not-empty (filter #(= (/ total 3) (apply + %)) combs))] 46 | res 47 | (recur (inc x))))))) 48 | -------------------------------------------------------------------------------- /src/advent-2016/day8.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day8 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data (line-seq (io/reader (io/resource "2016/day8")))) 7 | 8 | (def board (vec (repeat 6 (vec (repeat 50 '_))))) 9 | 10 | (defn rect [b w h] 11 | (->> (for [x (range w) y (range h)] [y x]) 12 | (reduce #(assoc-in %1 %2 'X) b))) 13 | 14 | (def transpose #(apply mapv vector %)) 15 | 16 | (defn rotate [v a] 17 | (let [c (count v) 18 | r (- c (mod a c))] 19 | (vec (concat (drop r v) (take r v))))) 20 | 21 | (defn rotate-row [b c a] 22 | (update-in b [c] rotate a)) 23 | 24 | (defn rotate-column [b c a] 25 | (-> b transpose (rotate-row c a) transpose)) 26 | 27 | (def to-ints (partial map #(Integer/parseInt %))) 28 | 29 | (defn parse-rect-args [x] (to-ints (string/split x #"x"))) 30 | 31 | (defn parse-rotate-args [x] (to-ints [(subs (first x) 2) (last x)])) 32 | 33 | (defn line-to-command [b line] 34 | (let [[x & xs] (string/split line #"\s")] 35 | (if (= "rect" x) 36 | (apply rect b (parse-rect-args (first xs))) 37 | (let [[x & xs] xs] 38 | (if (= "column" x) 39 | (apply rotate-column b (parse-rotate-args xs)) 40 | (apply rotate-row b (parse-rotate-args xs))))))) 41 | 42 | ;; part 1 43 | #_(->> data 44 | (reduce line-to-command board) 45 | (apply concat) 46 | (filter #{'X}) 47 | count) 48 | ;; => 121 49 | 50 | ;; part 2 51 | #_(reduce line-to-command board data) 52 | ;; => RURUCEOEIL 53 | -------------------------------------------------------------------------------- /doc/2015/12.md: -------------------------------------------------------------------------------- 1 | # Day 12: JSAbacusFramework.io 2 | 3 | Santa's Accounting-Elves need help balancing the books after a recent 4 | order. Unfortunately, their accounting software uses a peculiar 5 | storage format. That's where you come in. 6 | 7 | They have a JSON document which contains a variety of things: arrays 8 | (`[1,2,3]`), objects (`{"a":1, "b":2}`), numbers, and strings. Your first 9 | job is to simply find all of the numbers throughout the document and 10 | add them together. 11 | 12 | For example: 13 | 14 | `[1,2,3]` and `{"a":2,"b":4}` both have a sum of 6. 15 | 16 | `[[[3]]]` and `{"a":{"b":4},"c":-1}` both have a sum of 3. 17 | 18 | `{"a":[-1,1]}` and `[-1,{"a":1}]` both have a sum of 0. 19 | 20 | `[]` and `{}` both have a sum of 0. 21 | 22 | You will not encounter any strings containing numbers. 23 | 24 | What is the sum of all numbers in the document? 25 | 26 | Your puzzle answer was **`156366`**. 27 | 28 | ## Part Two 29 | 30 | Uh oh - the Accounting-Elves have realized that they double-counted 31 | everything red. 32 | 33 | Ignore any object (and all of its children) which has any property 34 | with the value `"red"`. Do this only for objects (`{...}`), not arrays 35 | (`[...]`). 36 | 37 | `[1,2,3]` still has a sum of 6. 38 | 39 | `[1,{"c":"red","b":2},3]` now has a sum of 4, because the middle object is ignored. 40 | 41 | `{"d":"red","e":[1,2,3,4],"f":5}` now has a sum of 0, because the entire structure is ignored. 42 | 43 | `[1,"red",5]` has a sum of 6, because "red" in an array has no effect. 44 | 45 | Your puzzle answer was **`96852`**. -------------------------------------------------------------------------------- /src/advent-2017/day10.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day10 2 | (:require 3 | [clojure.string :as string] 4 | [clojure.core.reducers :as r])) 5 | 6 | (def data [102,255,99,252,200,24,219,57,103,2,226,254,1,0,69,216]) 7 | 8 | ;; optimized for speed 9 | (defn inplace-reverse [x pos length] 10 | (let [idx (mapv #(mod % (count x)) 11 | (range pos (+ pos length))) 12 | vs (r/reduce #(cons (get x %2) %1) '() idx)] 13 | (persistent! 14 | (loop [[id & idx'] idx 15 | [v & vs'] vs 16 | x (transient x)] 17 | (if id 18 | (recur idx' vs' (assoc! x id v)) 19 | x))))) 20 | 21 | (defn transition [[x pos skip] length] 22 | [(inplace-reverse x pos length) 23 | (+ pos length skip) 24 | (inc skip)]) 25 | 26 | (def hash-round #(r/reduce transition %2 %1)) 27 | 28 | ;; part 1 29 | #_ (->> (hash-round data [(vec (range 256)) 0 0]) 30 | first 31 | (take 2) 32 | (apply *)) 33 | ;; => 5577 34 | 35 | (defn sparse-hash [data] 36 | (first 37 | (nth (iterate (partial hash-round (concat data [17, 31, 73, 47, 23])) 38 | [(vec (range 256)) 0 0]) 39 | 64))) 40 | 41 | (defn dense-hash [sparseh] 42 | (->> sparseh 43 | (partition 16) 44 | (map #(reduce bit-xor %)) 45 | (map #(format "%02x" %)) 46 | (apply str))) 47 | 48 | (def part-2 (comp dense-hash sparse-hash)) 49 | 50 | ;; part 2 51 | #_ (time (part-2 (map int (string/join "," data)))) 52 | ;; Elapsed time: 55.868713 msecs 53 | ;; => 44f4befb0f303c0bafd085f97741d51d 54 | 55 | -------------------------------------------------------------------------------- /src/advent-2017/day20.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day20 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def data 6 | (->> (io/resource "2017/day20") 7 | io/reader 8 | line-seq 9 | (map #(re-seq #"[-]*\d+" %)) 10 | (map #(map read-string %)) 11 | (map (comp vec (partial partition 3))))) 12 | 13 | (defn val-vec [n] 14 | (if (number? n) [n n n] n)) 15 | 16 | (def vec* (partial mapv *)) 17 | (def vec+ (partial mapv +)) 18 | 19 | (defn position-at-time [[start-position start-velocity acceleration] t] 20 | ;; 1/2 a t^2 + v t + c 21 | (vec+ (vec* 22 | acceleration 23 | (val-vec (* 0.5 t t))) 24 | (vec* start-velocity (val-vec t)) 25 | start-position)) 26 | 27 | (defn distance-at-time [t particle] 28 | (apply + (map #(Math/abs %) (position-at-time particle t)))) 29 | 30 | ;; part 1 31 | #_ (->> data 32 | (map (juxt identity (partial distance-at-time 1000))) 33 | (sort-by second) 34 | ffirst 35 | (.indexOf data) 36 | time) 37 | ;; => 150 38 | ;; Elapsed time: 32.838903 msecs 39 | 40 | (defn particle-step [[position velocity acceleration :as particle]] 41 | (let [v (vec+ velocity acceleration)] 42 | [(vec+ position v) v acceleration])) 43 | 44 | (defn step [state] 45 | (->> state 46 | (mapv particle-step) 47 | (group-by first) 48 | (filter #(= 1 (count (second %)))) 49 | (mapv (comp first second)))) 50 | 51 | ;; part 2 52 | (->> data 53 | (iterate step) 54 | (drop 100) 55 | first 56 | count 57 | time) 58 | ;; => 657 59 | -------------------------------------------------------------------------------- /src/advent-2016/day12.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day12 2 | (:require 3 | [advent-2016.utils :as u] 4 | [clojure.java.io :as io] 5 | [clojure.string :as string])) 6 | 7 | #_(remove-ns 'advent-2016.day12) 8 | 9 | (defn parse-instructions [s] 10 | (->> s 11 | (string/split-lines) 12 | (map #(str "[" % "]")) 13 | (map read-string) 14 | vec)) 15 | 16 | (def input (parse-instructions (slurp (io/resource "2016/day12")))) 17 | 18 | (defn reg-or-val [s reg-val] (if (symbol? reg-val) (get s reg-val) reg-val)) 19 | 20 | (defn update-reg [s reg f] 21 | (-> s (update reg f) (update :pos inc))) 22 | 23 | (defmulti trans (fn [_ b] (first b))) 24 | (defmethod trans 'inc [s [_ reg]] (update-reg s reg inc)) 25 | (defmethod trans 'dec [s [_ reg]] (update-reg s reg dec)) 26 | 27 | (defmethod trans 'cpy [s [_ reg-val reg]] 28 | (-> s (assoc reg (reg-or-val s reg-val)) (update :pos inc))) 29 | 30 | (defmethod trans 'jnz [s [_ reg-val steps]] 31 | (update s :pos + 32 | (if-not (zero? (reg-or-val s reg-val)) steps 1))) 33 | 34 | (def start-state '{a 0 b 0 c 0 d 0 :pos 0}) 35 | 36 | (defn run-prog [start-state input] 37 | (let [input (vec input)] 38 | (take-while (comp not nil?) 39 | (iterate (fn [{:keys [pos] :as s}] 40 | (when-let [inst (get input pos nil)] 41 | (trans s inst))) 42 | start-state)))) 43 | 44 | ;; part 1 45 | #_ (time (last (run-prog start-state input))) 46 | ;; => 317993 47 | 48 | ;; part 2 49 | #_ (time (last (run-prog (assoc start-state 'c 1) input))) 50 | ;; => 9227647 51 | -------------------------------------------------------------------------------- /src/advent-2017/day19.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day19 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def data 6 | (->> (io/resource "2017/day19") 7 | io/reader 8 | line-seq 9 | (mapv vec))) 10 | 11 | (def directions [[1 0] [-1 0] [0 1] [0 -1]]) 12 | 13 | (defn letter? [char'] 14 | (<= (int \A) (int char') (int \Z))) 15 | 16 | (defn starting-x [char-map] 17 | (.indexOf (first char-map) \|)) 18 | 19 | (defn next-directions [char-map [pos prev-pos]] 20 | (if (not= \+ (get-in char-map pos)) 21 | [(mapv - pos prev-pos)] 22 | directions)) 23 | 24 | (defn next-position [char-map [pos prev-pos :as state]] 25 | (->> (next-directions char-map state) 26 | (mapv (partial mapv + pos)) 27 | (filter #(not= prev-pos %)) 28 | (filter #(not= \space (get-in char-map %))) 29 | first)) 30 | 31 | (defn move [char-map [pos :as state]] 32 | [(next-position char-map state) pos]) 33 | 34 | #_(->> (iterate (partial move data) 35 | (let [start-x (starting-x data)] 36 | [[0 start-x] [-1 start-x]])) 37 | (map first) 38 | (take-while identity) 39 | (map (partial get-in data)) 40 | (filter letter?) 41 | (apply str) 42 | time) 43 | ;; part 1 44 | ;; => EOCZQMURF 45 | ;; Elapsed time: 80.573515 msecs 46 | 47 | ;; part 2 48 | #_(->> (iterate (partial move data) 49 | (let [start-x (starting-x data)] 50 | [[0 start-x] [-1 start-x]])) 51 | (map first) 52 | (take-while identity) 53 | count 54 | time) 55 | ;; => 16312 56 | ;; Elapsed time: 72.912626 msecs 57 | -------------------------------------------------------------------------------- /src/advent-2016/day7.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day7 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def data (line-seq (io/reader (io/resource "2016/day7")))) 6 | 7 | (defn abba? [[a b c d :as x]] 8 | {:pre [(= 4 (count x))]} 9 | (and (not= a b) (= a d) (= b c))) 10 | 11 | (defn separate-parts [s] 12 | (->> s 13 | (partition-by #{\[ \]}) 14 | (reduce (fn [{:keys [k] :as st} v] 15 | (condp = v 16 | [\[] (assoc st :k :neg) 17 | [\]] (assoc st :k :pos) 18 | (update-in st [k] conj v))) 19 | {:k :pos}))) 20 | 21 | (defn contains-abba? [s] 22 | (some abba? (partition 4 1 s))) 23 | 24 | (defn supports-tls? [s] 25 | (let [{:keys [pos neg]} (separate-parts s)] 26 | (and (some contains-abba? pos) 27 | (every? (complement contains-abba?) neg)))) 28 | 29 | ;; part 1 30 | #_(count (filter identity (map supports-tls? data))) 31 | ;; => 115 32 | 33 | (defn ssl? [[a b c :as x]] 34 | {:pre [(= 3 (count x))]} 35 | (and (not= a b) (= a c))) 36 | 37 | (defn ssl-inv? [[a b c :as x] [a1 b1 c1 :as y]] 38 | {:pre [(= 3 (count x)) (= 3 (count y)) (ssl? x)]} 39 | (and (= a b1) (= b a1 c1))) 40 | 41 | (defn contains-pred? [f s] 42 | (first (filter f (partition 3 1 s)))) 43 | 44 | (defn supports-ssl? [s] 45 | (let [{:keys [pos neg]} (separate-parts s)] 46 | (some identity 47 | (for [ssl-x (mapcat #(filter ssl? (partition 3 1 %)) pos)] 48 | (some #(contains-pred? (partial ssl-inv? ssl-x) %) neg))))) 49 | 50 | ;; part 2 51 | #_(count (filter identity (map supports-ssl? data))) 52 | ;; => 231 53 | 54 | -------------------------------------------------------------------------------- /doc/2015/09.md: -------------------------------------------------------------------------------- 1 | # Day 9: All in a Single Night 2 | 3 | Every year, Santa manages to deliver all of his presents in a single 4 | night. 5 | 6 | This year, however, he has some new locations to visit; his elves have 7 | provided him the distances between every pair of locations. He can 8 | start and end at any two (different) locations he wants, but he must 9 | visit each location exactly once. What is the shortest distance he can 10 | travel to achieve this? 11 | 12 | For example, given the following distances: 13 | 14 | ``` 15 | London to Dublin = 464 16 | London to Belfast = 518 17 | Dublin to Belfast = 141 18 | ``` 19 | 20 | The possible routes are therefore: 21 | 22 | ``` 23 | Dublin -> London -> Belfast = 982 24 | London -> Dublin -> Belfast = 605 25 | London -> Belfast -> Dublin = 659 26 | Dublin -> Belfast -> London = 659 27 | Belfast -> Dublin -> London = 605 28 | Belfast -> London -> Dublin = 982 29 | ``` 30 | 31 | The shortest of these is `London -> Dublin -> Belfast = 605`, and so the answer is `605` in this example. 32 | 33 | What is the distance of the shortest route? 34 | 35 | Your puzzle answer was **`251`**. 36 | 37 | --- Part Two --- 38 | 39 | The next year, just to show off, Santa decides to take the route with 40 | the longest distance instead. 41 | 42 | He can still start and end at any two (different) locations he wants, 43 | and he still must visit each location exactly once. 44 | 45 | For example, given the distances above, the longest route would be `982` 46 | via (for example) `Dublin -> London -> Belfast`. 47 | 48 | What is the distance of the longest route? 49 | 50 | Your puzzle answer was **`898`**. 51 | 52 | -------------------------------------------------------------------------------- /src/advent-2015/day16.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day16 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def prob16 7 | (line-seq (io/reader (io/resource "2015/prob16")))) 8 | 9 | (defn read-grandma [line] 10 | (as-> line x 11 | (string/replace x ":" "") 12 | (read-string (str "(" x ")")) 13 | (map #(if (symbol? %) (keyword %) %) x) 14 | (apply hash-map x))) 15 | 16 | (def grandmas (map read-grandma prob16)) 17 | 18 | (defn dist* [a b] (java.lang.Math/abs (- a b))) 19 | 20 | (def clues 21 | {:children 3 22 | :cats 7 23 | :samoyeds 2 24 | :pomeranians 3 25 | :akitas 0 26 | :vizslas 0 27 | :goldfish 5 28 | :trees 3 29 | :cars 2 30 | :perfumes 1}) 31 | 32 | (def clues-dist-map 33 | (zipmap (keys clues) 34 | (map #(partial dist* %) (vals clues)))) 35 | 36 | (defn distance [clues-dist-map grandma] 37 | (->> grandma 38 | (filter #(not= :Sue (first %)) ) 39 | (map (fn [[k v]] ((clues-dist-map k) v)) ) 40 | (apply +))) 41 | 42 | ;; part 1 43 | #_(first (sort-by second (map (juxt :Sue (partial distance clues-dist-map)) grandmas))) 44 | 45 | (defn lt-dist [a b] 46 | (if (< a b) 47 | 0 48 | (dist* (inc a) b))) 49 | 50 | (defn gt-dist [a b] 51 | (if (> a b) 52 | 0 53 | (dist* a (inc b)))) 54 | 55 | (def new-dist-map 56 | (assoc clues-dist-map 57 | :cats #(gt-dist % 7) 58 | :trees #(gt-dist % 3) 59 | :pomeranians #(lt-dist % 3) 60 | :goldfish #(lt-dist % 5))) 61 | 62 | ; part 2 63 | #_(first (sort-by second (map (juxt :Sue (partial distance new-dist-map)) grandmas))) 64 | -------------------------------------------------------------------------------- /src/advent-2015/day06.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day06 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | ;; day 6 6 | 7 | (def prob6 8 | (line-seq (io/reader (io/resource "2015/prob6")))) 9 | 10 | (defn parse-command [line] 11 | (let [x (->> (str "[" line "]") 12 | read-string 13 | (group-by integer?))] 14 | [(x false) (x true)])) 15 | 16 | ;; expand in to instructions for each position 17 | (defn to-bytecode [[command [x1 y1 x2 y2]]] 18 | (map 19 | #(vector command %) 20 | (for [x (range x1 (inc x2)) 21 | y (range y1 (inc y2))] 22 | [x y]))) 23 | 24 | (defn action [board [command loc]] 25 | (condp = command 26 | '(turn on through) (assoc! board loc true) 27 | '(turn off through) (assoc! board loc false) 28 | '(toggle through) (assoc! board loc (not (board loc))))) 29 | 30 | #_(def part1 (persistent! 31 | (reduce action (transient {}) 32 | (mapcat (comp to-bytecode parse-command) 33 | prob6)))) 34 | 35 | ;; part 1 36 | #_(count (filter identity (vals part1))) 37 | 38 | (defn action2 [board [command loc]] 39 | (assoc! board loc 40 | ((condp = command 41 | '(turn on through) inc 42 | '(turn off through) #(max (dec %) 0) 43 | '(toggle through) (partial + 2)) 44 | (or (get board loc) 0)))) 45 | 46 | #_(def part2 (persistent! 47 | (reduce action2 (transient {}) 48 | (mapcat (comp to-bytecode parse-command) 49 | prob6)))) 50 | ;; part 2 51 | #_(reduce + 0 (filter identity (vals part2))) 52 | -------------------------------------------------------------------------------- /src/advent-2015/day19.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day19 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | ;; workarea 6 | (def rule-lines 7 | (line-seq (io/reader (io/resource "2015/prob19.rules")))) 8 | 9 | (defn parse-rule [x] 10 | (map (comp seq name) 11 | ((juxt first last) 12 | (read-string (str "(" x ")")) ))) 13 | 14 | (def rules (map parse-rule rule-lines)) 15 | 16 | (def molecule (slurp (io/resource "2015/prob19.mol"))) 17 | 18 | (defn rule-replacements [[match replace :as rule] s] 19 | (if (empty? s) [] 20 | (let [replacements (map #(cons (first s) %) 21 | (rule-replacements rule (rest s)))] 22 | (if (= match (take (count match) s)) 23 | (cons (concat replace (drop (count match) s)) replacements) 24 | replacements)))) 25 | ; part 1 26 | #_(count (set (mapcat #(rule-replacements % molecule) 27 | rules))) 28 | 29 | (def reversed-rules 30 | (map #(map reverse %) rules)) 31 | 32 | (defn apply-rule [[match replace] s] 33 | (let [n (count replace)] 34 | (when (= replace (take n s)) 35 | (concat match (drop n s))))) 36 | 37 | (defn first-rule-reduce [rules s] 38 | (if (empty? s) nil 39 | (if-let [result (first (keep #(apply-rule % s) rules))] 40 | result 41 | (when-let [res (first-rule-reduce rules (rest s))] 42 | (cons (first s) res))))) 43 | 44 | ; part 2 45 | ; this is set up to be solved in reverse easily 46 | ; discovered this by reading the adventofcode reddit forum 47 | 48 | (count (take-while #(not= % [\e]) 49 | (iterate (partial first-rule-reduce reversed-rules) 50 | (reverse molecule)))) 51 | -------------------------------------------------------------------------------- /src/advent-2016/day4.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day4 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def lines (line-seq (io/reader (io/resource "2016/day4")))) 7 | 8 | (defn parse-room [s] 9 | (let [parts (string/split s #"-") 10 | [id chk] (string/split (last parts) #"\[")] 11 | {:word (apply concat (butlast parts)) 12 | :chksum (butlast chk) 13 | :id (Integer/parseInt id)})) 14 | 15 | (defn checksum [word] 16 | (->> word 17 | frequencies 18 | (sort-by (fn [[a b]] [(- b) (int a)])) 19 | (map first) 20 | (take 5))) 21 | 22 | (defn real-room? [{:keys [word chksum] :as room}] 23 | (= (checksum word) chksum)) 24 | 25 | (comment 26 | (real-room? (parse-room "aaaaa-bbb-z-y-x-123[abxyz]")) 27 | (real-room? (parse-room "a-b-c-d-e-f-g-h-987[abcde]")) 28 | (real-room? (parse-room "not-a-real-room-404[oarel]")) 29 | (real-room? (parse-room "totally-real-room-200[decoy]")) 30 | ) 31 | 32 | ;; part 1 33 | #_(->> lines 34 | (map parse-room) 35 | (filter real-room?) 36 | (map :id) 37 | (reduce +)) 38 | ;;=> 278221 39 | 40 | (defn shift-letter [n letter] 41 | (-> letter 42 | int 43 | (- 97) 44 | (+ n) 45 | (mod 26) 46 | (+ 97) 47 | char)) 48 | 49 | (defn decrypt [{:keys [word id] :as room}] 50 | (assoc room :decrypted 51 | (apply str (map (partial shift-letter id) word)))) 52 | 53 | #_(decrypt (parse-room "qzmt-zixmtkozy-ivhz-343")) 54 | 55 | ;; part 2 56 | #_(->> lines 57 | (map parse-room) 58 | (filter real-room?) 59 | (map decrypt) 60 | (filter #(re-matches #".*north.*" (:decrypted %))) 61 | first 62 | :id) 63 | ;; => 267 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/advent-2015/day18.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day18 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.set :refer [intersection union]])) 5 | 6 | (def prob18 7 | (line-seq (io/reader (io/resource "2015/prob18")))) 8 | 9 | (defn create-board [lines] 10 | (into #{} 11 | (mapcat 12 | (fn [y line] 13 | (keep-indexed #(when (= \# %2) [%1 y]) line)) 14 | (range 100) 15 | lines))) 16 | 17 | (def offsets [[0 1] [0 -1] [1 0] [-1 0] [1 1] [1 -1] [-1 1] [-1 -1]]) 18 | 19 | (def get-neighbors 20 | (memoize 21 | (fn [location] 22 | (into #{} (filter #(every? (fn [x] (<= 0 x 99)) %) 23 | (map #(map + % location) offsets)))))) 24 | 25 | (defn count-neighbors [board location] 26 | (count (intersection board (get-neighbors location)))) 27 | 28 | (defn cell-value [board location] 29 | (let [on? (board location) 30 | neighbors-on (count-neighbors board location)] 31 | (cond 32 | (and on? (<= 2 neighbors-on 3)) location 33 | (and (not on?) (= neighbors-on 3)) location 34 | :else nil))) 35 | 36 | (defn next-board [cell-value-fn board] 37 | (into #{} (keep (partial cell-value-fn board) 38 | (for [x (range 100) y (range 100)] [x y])))) 39 | 40 | #_(count (nth (iterate (partial next-board cell-value) 41 | (create-board prob18)) 42 | 100)) 43 | 44 | (def always-on #{[0 0] [0 99] [99 0] [99 99]}) 45 | 46 | (defn part-2-cell-value [board location] 47 | (if (always-on location) 48 | location 49 | (cell-value board location))) 50 | 51 | #_(count (nth (iterate (partial next-board part-2-cell-value) 52 | (union (create-board prob18) always-on) ) 53 | 100)) 54 | -------------------------------------------------------------------------------- /src/advent-2016/day9.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day9 2 | (:require 3 | [advent-2016.utils :as u] 4 | [clojure.java.io :as io] 5 | [clojure.string :as string])) 6 | 7 | (def data (string/trim (slurp (io/resource "2016/day9")))) 8 | 9 | (def directive-regex #"(\((\d+)x(\d+)\)).*") 10 | 11 | (defn parse-dir [s] 12 | (when-let [[_ directive & args] (re-matches directive-regex (apply str s))] 13 | [(u/to-ints args) (drop (count directive) s)])) 14 | 15 | (defn parse-directive [s] 16 | (when-let [[[cnt rpt] s] (parse-dir s)] 17 | [(take (* cnt rpt) (cycle (take cnt s))) (drop cnt s)])) 18 | 19 | (defn starts-with-directive? [d] 20 | (re-matches directive-regex (apply str (take 20 d)))) 21 | 22 | (defn has-directive? [d] 23 | (re-find directive-regex (apply str d))) 24 | 25 | (defn part1 [d] 26 | (loop [accum [] data d] 27 | (cond 28 | (empty? data) (apply str accum) 29 | (starts-with-directive? data) 30 | (let [[ac s] (parse-directive data)] 31 | (recur (concat accum ac) s)) 32 | :else (recur (conj (vec accum) (first data)) (rest data))))) 33 | 34 | ;; part 1 35 | #_(count (part1 data)) 36 | ;; => 112830 37 | 38 | (defn part2 [d] 39 | (loop [accum 0 data d] 40 | (cond 41 | (empty? data) accum 42 | (starts-with-directive? data) 43 | (when-let [[[cnt rpt] s] (parse-dir data)] 44 | (let [[part s] (split-at cnt s)] 45 | (recur (+ accum 46 | (* rpt (if (has-directive? part) (part2 part) (count part)))) 47 | s))) 48 | :else (recur (inc accum) (rest data))))) 49 | 50 | #_(part2 "(27x12)(20x12)(13x14)(7x10)(1x12)A") 51 | #_(part2 "(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN") 52 | 53 | #_(time (part2 data)) 54 | 55 | ;; => 10931789799 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/advent-2016/day13.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day13 2 | (:require 3 | [clojure.string :as string] 4 | [clojure.set :refer [union]])) 5 | 6 | (def ^:dynamic *input* 1352) 7 | (def ^:dynamic *bound* 41) 8 | (def ^:dynamic *target* [31 39]) 9 | (def ^:dynamic *upper-bound* 100) 10 | 11 | (defn open? [[x y]] 12 | (->> (+ *input* (* x x) (* 3 x) (* 2 x y) y (* y y)) 13 | Integer/toBinaryString 14 | (filter #(= \1 %)) 15 | count 16 | even?)) 17 | 18 | (defn view-structure [sz] 19 | (for [y (range sz)] 20 | (for [x (range sz)] 21 | (cond 22 | (= *target* [x y]) 'O 23 | (open? [x y]) '. 24 | :else '=)))) 25 | 26 | (defn next-steps [path-set coord] 27 | (sequence 28 | (comp 29 | (map (partial mapv + coord)) 30 | (filter #(every? (fn [i] (<= 0 i *bound*)) %)) 31 | (filter (complement path-set)) 32 | (filter open?)) 33 | [[1 0] [-1 0] [0 1] [0 -1]])) 34 | 35 | (defn depth-search [path-set coord] 36 | (cond 37 | (= coord *target*) (count path-set) 38 | (> (count path-set) *upper-bound*) Integer/MAX_VALUE 39 | :else 40 | (if-let [res (->> (next-steps path-set coord) 41 | (map #(depth-search (conj path-set coord) %)) 42 | not-empty)] 43 | (reduce min res) 44 | Integer/MAX_VALUE))) 45 | 46 | #_(view-structure 41) 47 | 48 | ;; sample input 49 | #_(depth-search #{} [1 1]) 50 | ;; => 90 51 | 52 | (defn collect-positions [path-set coord] 53 | (if (>= (count path-set) *upper-bound*) 54 | #{coord} 55 | (->> (next-steps path-set coord) 56 | (map #(collect-positions (conj path-set coord) %)) 57 | (apply union #{coord})))) 58 | 59 | ;; part 2 60 | #_(binding [*upper-bound* 50] 61 | (count (collect-positions #{} [1 1]))) 62 | ;; => 135 63 | -------------------------------------------------------------------------------- /resources/2017/day25: -------------------------------------------------------------------------------- 1 | Begin in state A. 2 | Perform a diagnostic checksum after 12368930 steps. 3 | 4 | In state A: 5 | If the current value is 0: 6 | - Write the value 1. 7 | - Move one slot to the right. 8 | - Continue with state B. 9 | If the current value is 1: 10 | - Write the value 0. 11 | - Move one slot to the right. 12 | - Continue with state C. 13 | 14 | In state B: 15 | If the current value is 0: 16 | - Write the value 0. 17 | - Move one slot to the left. 18 | - Continue with state A. 19 | If the current value is 1: 20 | - Write the value 0. 21 | - Move one slot to the right. 22 | - Continue with state D. 23 | 24 | In state C: 25 | If the current value is 0: 26 | - Write the value 1. 27 | - Move one slot to the right. 28 | - Continue with state D. 29 | If the current value is 1: 30 | - Write the value 1. 31 | - Move one slot to the right. 32 | - Continue with state A. 33 | 34 | In state D: 35 | If the current value is 0: 36 | - Write the value 1. 37 | - Move one slot to the left. 38 | - Continue with state E. 39 | If the current value is 1: 40 | - Write the value 0. 41 | - Move one slot to the left. 42 | - Continue with state D. 43 | 44 | In state E: 45 | If the current value is 0: 46 | - Write the value 1. 47 | - Move one slot to the right. 48 | - Continue with state F. 49 | If the current value is 1: 50 | - Write the value 1. 51 | - Move one slot to the left. 52 | - Continue with state B. 53 | 54 | In state F: 55 | If the current value is 0: 56 | - Write the value 1. 57 | - Move one slot to the right. 58 | - Continue with state A. 59 | If the current value is 1: 60 | - Write the value 1. 61 | - Move one slot to the right. 62 | - Continue with state E. -------------------------------------------------------------------------------- /src/advent-2017/day11.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day11 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def data (read-string (format "[%s]" (slurp (io/resource "2017/day11"))))) 6 | 7 | ;ne,ne,ne is 3 steps away. 8 | ;ne,ne,sw,sw is 0 steps away (back where you started). 9 | ;ne,ne,s,s is 2 steps away (se,se). 10 | ;se,sw,se,sw,sw is 3 steps away (s,s,sw). 11 | 12 | ;; this can be represented in terms of x and y coords 13 | ;; with a single diagonal path in each square 14 | ;; *-*-*-*-*-* 15 | ;; |/|/|/|/|/| 16 | ;; *-*-*-*-*-* 17 | ;; |/|/|/|/|/| 18 | ;; *-*-*-*-*-* 19 | ;; |/|/|/|/|/| 20 | ;; *-*-*-*-*-* 21 | ;; us regular x y coords and increment both when travelling 22 | ;; on the diagonal 23 | 24 | (def directions 25 | {'n [1 1] 26 | 's [-1 -1] 27 | 'nw [0 1] 28 | 'ne [1 0] 29 | 'se [0 -1] 30 | 'sw [-1 0]}) 31 | 32 | ;; the distance formula is (max x y) if the point lies in 33 | ;; the direction of the diagonals 34 | 35 | ;; the distance formula is (+ x y) if the point lies against 36 | ;; the direction of the diagonals 37 | 38 | (defn distance [coord] 39 | (if (or (every? pos? coord) (every? neg? coord)) 40 | (apply max (mapv #(Math/abs %) coord)) 41 | (apply + (mapv #(Math/abs %) coord)))) 42 | 43 | (defn path-to-coord [path] 44 | (reduce #(mapv + %1 (directions %2)) [0 0] path)) 45 | 46 | ;; tests 47 | #_(and 48 | (= 3 (distance (path-to-coord '(ne ne ne)))) 49 | (= 0 (distance (path-to-coord '(ne ne sw sw)))) 50 | (= 2 (distance (path-to-coord '(ne ne s s)))) 51 | (= 3 (distance (path-to-coord '(se,sw,se,sw,sw))))) 52 | 53 | ; part 1 54 | #_(distance (path-to-coord data)) 55 | ;; => 812 56 | 57 | (defn paths-to-coord [path] 58 | (reductions #(mapv + %1 (directions %2)) [0 0] path)) 59 | 60 | ;; part 2 61 | #_(reduce max (map distance (paths-to-coord data))) 62 | -------------------------------------------------------------------------------- /src/advent-2017/day05.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day05 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.core.reducers :as r])) 5 | 6 | (def test-data [0 3 0 1 -3]) 7 | 8 | (def data (->> (io/resource "2017/day05") 9 | io/reader 10 | line-seq 11 | (mapv read-string) 12 | (mapv int))) 13 | 14 | (defn interpret [{:keys [position instructions] :as env}] 15 | (when-let [inst (get instructions position)] 16 | (-> env 17 | (update :position + inst) 18 | (update-in [:instructions position] inc)))) 19 | 20 | ;; part 1 21 | #_(->> (iterate interpret {:position 0 :instructions data}) 22 | (take-while identity) 23 | rest 24 | count) 25 | ;;=> 358309 26 | 27 | (defn interpret-2 [[^int position instructions]] 28 | (when-let [inst ^int (get instructions position)] 29 | [(+ position inst) 30 | (assoc! instructions position (if (>= inst 3) (dec inst) (inc inst)))])) 31 | 32 | ;; part 2 33 | #_(time 34 | (reduce 35 | (fn [x _] (inc x)) 36 | -1 37 | (eduction 38 | (take-while identity) 39 | (iterate interpret-2 [0 (transient data)])))) 40 | 41 | ;; Elapsed time: 5873.206687 msecs 42 | ;; => 28178177 43 | 44 | ;; fastest with a native array and fully type hinted loop 45 | (comment 46 | (set! *warn-on-reflection* true) 47 | (set! *unchecked-math* :warn-on-boxed) 48 | ) 49 | 50 | #_(time 51 | (let [instructions ^ints (into-array Integer/TYPE data) 52 | length ^int (count instructions)] 53 | (loop [step 0 position 0] 54 | (if (< position length) 55 | (let [inst (aget instructions position)] 56 | (aset instructions position 57 | (if (>= inst 3) (dec inst) (inc inst))) 58 | (recur (inc step) (+ position inst))) 59 | step)))) 60 | ;; "Elapsed time: 198.752469 msecs" 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/advent-2017/day16.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day16 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def dance-calls 7 | (mapv 8 | (fn [[cmd & args]] 9 | (cons cmd (map read-string (string/split (apply str args) #"\/")))) 10 | (string/split 11 | (slurp (io/resource "2017/day16")) 12 | #","))) 13 | 14 | (def start-state '[a b c d e f g h i j k l m n o p]) 15 | 16 | (defmulti dance-mover (fn [_ [cmd]] cmd)) 17 | 18 | (defmethod dance-mover \s [state [_ n] ] 19 | (let [length (count state)] 20 | (vec (take length (drop (mod (- n) length) (cycle state)))))) 21 | 22 | (defmethod dance-mover \x [state [_ a b]] 23 | (assoc state 24 | a (get state b) 25 | b (get state a))) 26 | 27 | (defmethod dance-mover \p [state [_ pa pb]] 28 | (let [a (.indexOf state pa) 29 | b (.indexOf state pb)] 30 | (dance-mover state [\x a b]))) 31 | 32 | (defn whole-dance [dance-calls state] 33 | (reduce dance-mover state dance-calls)) 34 | 35 | ;; test data 36 | #_(whole-dance '[[\s 1] [\x 3 4] [\p e b]] '[a b c d e] ) 37 | 38 | ;; ANSWER part 1 39 | #_(->> (whole-dance dance-calls start-state) 40 | (string/join "")) 41 | ;; => lbdiomkhgcjanefp 42 | 43 | 44 | (def complete-dances (iterate (partial whole-dance dance-calls) start-state)) 45 | 46 | ;; strategy find a period for which the pattern repeats itself 47 | (defn find-cycle-period [whole-dance-seq] 48 | (->> (rest whole-dance-seq) 49 | (take-while #(not= (first whole-dance-seq) %)) 50 | count 51 | inc)) 52 | 53 | #_ (find-cycle-period complete-dances) 54 | ;; => 56 55 | 56 | ;; the dance will cycle every 56 57 | #_ (= (nth complete-dances 56) start-state) 58 | #_ (= (nth complete-dances 112) start-state) 59 | 60 | ;; part 2 answer 61 | #_ (->> (find-cycle-period complete-dances) 62 | (mod 1000000000) 63 | (nth complete-dances) 64 | (string/join "")) 65 | ;; => ejkflpgnamhdcboi 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /doc/2015/03.md: -------------------------------------------------------------------------------- 1 | # Day 3: Perfectly Spherical Houses in a Vacuum 2 | 3 | Santa is delivering presents to an infinite two-dimensional grid of houses. 4 | 5 | He begins by delivering a present to the house at his starting 6 | location, and then an elf at the North Pole calls him via radio and 7 | tells him where to move next. Moves are always exactly one house to 8 | the north (^), south (v), east (>), or west (<). After each move, he 9 | delivers another present to the house at his new location. 10 | 11 | However, the elf back at the north pole has had a little too much 12 | eggnog, and so his directions are a little off, and Santa ends up 13 | visiting some houses more than once. How many houses receive at least 14 | one present? 15 | 16 | For example: 17 | 18 | `>` delivers presents to 2 houses: one at the starting location, and 19 | one to the east. 20 | 21 | `^>v<` delivers presents to 4 houses in a square, including twice to the 22 | house at his starting/ending location. 23 | 24 | `^v^v^v^v^v` delivers a bunch of presents to some very lucky children at 25 | only 2 houses. 26 | 27 | Your puzzle answer was **`2081`**. 28 | 29 | ## Part Two 30 | 31 | The next year, to speed up the process, Santa creates a robot version 32 | of himself, Robo-Santa, to deliver presents with him. 33 | 34 | Santa and Robo-Santa start at the same location (delivering two 35 | presents to the same starting house), then take turns moving based on 36 | instructions from the elf, who is eggnoggedly reading from the same 37 | script as the previous year. 38 | 39 | This year, how many houses receive at least one present? 40 | 41 | For example: 42 | 43 | `^v` delivers presents to 3 houses, because Santa goes north, and then Robo-Santa goes south. 44 | 45 | `^>v<` now delivers presents to 3 houses, and Santa and Robo-Santa end up back where they started. 46 | 47 | `^v^v^v^v^v` now delivers presents to 11 houses, with Santa going one direction and Robo-Santa going the other. 48 | 49 | Your puzzle answer was **`2341`**. -------------------------------------------------------------------------------- /src/advent-2015/day21.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day21 2 | (:require 3 | [clojure.math.combinatorics :as combo])) 4 | 5 | (defn read-table [table-str] 6 | (partition 4 (read-string (str "(" table-str ")")))) 7 | 8 | (def weapons 9 | (read-table 10 | "Dagger 8 4 0 11 | Shortsword 10 5 0 12 | Warhammer 25 6 0 13 | Longsword 40 7 0 14 | Greataxe 74 8 0")) 15 | 16 | (def armor 17 | (read-table 18 | "None 0 0 0 19 | Leather 13 0 1 20 | Chainmail 31 0 2 21 | Splintmail 53 0 3 22 | Bandedmail 75 0 4 23 | Platemail 102 0 5")) 24 | 25 | (def rings 26 | (read-table 27 | "None 0 0 0 28 | Damage+1 25 1 0 29 | Damage+2 50 2 0 30 | Damage+3 100 3 0 31 | Defense+1 20 0 1 32 | Defense+2 40 0 2 33 | Defense+3 80 0 3")) 34 | 35 | (def ring-combos 36 | (cons [(first rings) (first rings)] 37 | (combo/combinations rings 2))) 38 | 39 | (defn cost [things] (reduce + (map second things))) 40 | 41 | (defn value [things] (reduce + (mapcat #(nthrest % 2) things))) 42 | 43 | (def choices 44 | (map #(concat (take 2 %) (last %)) 45 | (combo/cartesian-product weapons armor ring-combos))) 46 | 47 | (defn your-player-wins? [total] 48 | (->> (reductions #(map - %1 %2) [109 100] (cycle [[total 0] [0 10]])) 49 | (filter #(some (partial >= 0) %)) 50 | first 51 | second 52 | pos?)) 53 | 54 | ;; part 1 55 | #_(your-player-wins? 11) ;; you win if total damage armor is 11 56 | 57 | ;; find minimum cost for a total of 11 58 | #_(first (sort-by second (filter #(= 11 (first %)) (map (juxt value cost identity) choices)))) 59 | 60 | 61 | ;; part 2 62 | #_(your-player-wins? 10) ;; you lose if total damage armor is 10 63 | 64 | ;; find maximum cost for a total of 10 65 | #_(last (sort-by second (filter #(= 10 (first %)) (map (juxt value cost identity) choices)))) 66 | -------------------------------------------------------------------------------- /src/advent-2017/day14.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day14 2 | (:require 3 | [advent-2017.day10 :refer [sparse-hash dense-hash]])) 4 | 5 | (def test-input "flqrgnkx") 6 | 7 | (def puzzle-input "oundnydw") 8 | 9 | (defn binary-dense-hash [sparseh] 10 | (->> sparseh 11 | (partition 16) 12 | (map #(reduce bit-xor %)) 13 | (map #(Integer/toBinaryString %)) 14 | (map #(format "%8s" %)) 15 | (apply str))) 16 | 17 | (def knot-hash (comp binary-dense-hash sparse-hash (partial map int))) 18 | 19 | (defn disk-sector-map [input] 20 | (->> (map #(str %1 "-" %2) (repeat input) (range 128)) 21 | (mapv knot-hash))) 22 | 23 | ;; part 1 24 | #_(->> (disk-sector-map puzzle-input) 25 | (map (comp count (partial filter #{\1}))) 26 | (reduce +) 27 | time) 28 | ;; Elapsed time: 3068.830745 msec 29 | ;; => 8106 30 | 31 | (def data (disk-sector-map puzzle-input)) 32 | 33 | (def directions [[0 1] [0 -1] [1 0] [-1 0]]) 34 | 35 | (defn bit-on-at? [data [y x]] 36 | (= \1 (.charAt ^String (get data y) x))) 37 | 38 | (defn children [data pos] 39 | (->> directions 40 | (map #(mapv + pos %)) 41 | (filter (fn [[y x :as pos']] 42 | (and (< -1 y 128) 43 | (< -1 x 128) 44 | (bit-on-at? data pos')))))) 45 | 46 | (defn group [children-fn pos] 47 | (set (tree-seq 48 | (let [seen (atom #{})] 49 | (fn [pos] (when-not (@seen pos) 50 | (swap! seen conj pos) 51 | (not-empty (children-fn pos))))) 52 | children-fn 53 | pos))) 54 | 55 | (defn all-groups [data] 56 | (let [children-fn (memoize (partial children data))] 57 | (into #{} 58 | (for [x (range 128) 59 | y (range 128) 60 | :let [pos [y x]] 61 | :when (bit-on-at? data pos)] 62 | (group children-fn pos))))) 63 | 64 | ;; part 2 65 | #_(time (count (all-groups data))) 66 | ;; Elapsed time: 3772.082083 msecs 67 | ;; => 1164 68 | 69 | -------------------------------------------------------------------------------- /doc/2015/01.md: -------------------------------------------------------------------------------- 1 | # Day 1: Not Quite Lisp 2 | 3 | Santa was hoping for a white Christmas, but his weather machine's 4 | "snow" function is powered by stars, and he's fresh out! To save 5 | Christmas, he needs you to collect fifty stars by December 25th. 6 | 7 | Collect stars by helping Santa solve puzzles. Two puzzles will be made 8 | available on each day in the advent calendar; the second puzzle is 9 | unlocked when you complete the first. Each puzzle grants one star. 10 | Good luck! 11 | 12 | Here's an easy puzzle to warm you up. 13 | 14 | Santa is trying to deliver presents in a large apartment building, but 15 | he can't find the right floor - the directions he got are a little 16 | confusing. He starts on the ground floor (floor 0) and then follows 17 | the instructions one character at a time. 18 | 19 | An opening parenthesis, `(`, means he should go up one floor, and a 20 | closing parenthesis, `)`, means he should go down one floor. 21 | 22 | The apartment building is very tall, and the basement is very deep; he 23 | will never find the top or bottom floors. 24 | 25 | For example: 26 | 27 | `(())` and `()()` both result in floor 0. 28 | 29 | `(((` and `(()(()(` both result in floor 3. 30 | 31 | `))(((((` also results in floor 3. 32 | 33 | `())` and `))(` both result in floor -1 (the first basement level). 34 | 35 | `)))` and `)())())` both result in floor -3. 36 | 37 | To what floor do the instructions take Santa? 38 | 39 | Your puzzle answer was **`280`**. 40 | 41 | ## Part Two 42 | 43 | Now, given the same instructions, find the position of the first 44 | character that causes him to enter the basement (floor -1). The first 45 | character in the instructions has position 1, the second character has 46 | position 2, and so on. 47 | 48 | For example: 49 | 50 | `)` causes him to enter the basement at character position 1. 51 | 52 | `()())` causes him to enter the basement at character position 5. 53 | 54 | What is the position of the character that causes Santa to first enter the basement? 55 | 56 | Your puzzle answer was **`1797`**. -------------------------------------------------------------------------------- /resources/2017/day01: -------------------------------------------------------------------------------- 1 | 5672987533353956199629683941564528646262567117433461547747793928322958646779832484689174151918261551689221756165598898428736782194511627829355718493723961323272136452517987471351381881946883528248611611258656199812998632682668749683588515362946994415852337196718476219162124978836537348924591957188827929753417884942133844664636969742547717228255739959316351852731598292529837885992781815131876183578461135791315287135243541659853734343376618419952776165544829717676988897684141328138348382882699672957866146524759879236555935723655326743713542931693477824289283542468639522271643257212833248165391957686226311246517978319253977276663825479144321155712866946255992634876158822855382331452649953283788863248192338245943966269197421474555779135168637263279579842885347152287275679811576594376535226167894981226866222987522415785244875882556414956724976341627123557214837873872723618395529735349273241686548287549763993653379539445435319698825465289817663294436458194867278623978745981799283789237555242728291337538498616929817268211698649236646127899982839523784837752863458819965485149812959121884771849954723259365778151788719941888128618552455879369919511319735525621198185634342538848462461833332917986297445388515717463168515123732455576143447454835849565757773325367469763383757677938748319968971312267871619951657267913817242485559771582167295794259441256284168356292785568858527184122231262465193612127961685513913835274823892596923786613299747347259254823531262185328274367529265868856512185135329652635938373266759964119863494798222245536758792389789818646655287856173534479551364115976811459677123592747375296313667253413698823655218254168196162883437389718167743871216373164865426458794239496224858971694877159591215772938396827435289734165853975267521291574436567193473814247981877735223376964125359992555885137816647382139596646856417424617847981855532914872251686719394341764324395254556782277426326331441981737557262581762412544849689472281645835957667217384334435391572985228286537574388834835693416821419655967456137395465649249256572866516984318344482684936625486311718525523265165 -------------------------------------------------------------------------------- /doc/2015/20.md: -------------------------------------------------------------------------------- 1 | # Day 20: Infinite Elves and Infinite Houses 2 | 3 | To keep the Elves busy, Santa has them deliver some presents by hand, 4 | door-to-door. He sends them down a street with infinite houses 5 | numbered sequentially: `1`, `2`, `3`, `4`, `5`, and so on. 6 | 7 | Each Elf is assigned a number, too, and delivers presents to houses 8 | based on that number: 9 | 10 | The first Elf (number 1) delivers presents to every house: 11 | `1`, `2`, `3`, `4`, `5`, .... 12 | 13 | The second Elf (number 2) delivers presents to every second house: `2`, 14 | `4`, `6`, `8`, `10`, .... 15 | 16 | Elf number 3 delivers presents to every third house: `3`, `6`, `9`, `12`, `15`, 17 | .... 18 | 19 | There are infinitely many Elves, numbered starting with 1. Each Elf 20 | delivers presents equal to ten times his or her number at each house. 21 | 22 | So, the first nine houses on the street end up like this: 23 | 24 | ``` 25 | House 1 got 10 presents. 26 | House 2 got 30 presents. 27 | House 3 got 40 presents. 28 | House 4 got 70 presents. 29 | House 5 got 60 presents. 30 | House 6 got 120 presents. 31 | House 7 got 80 presents. 32 | House 8 got 150 presents. 33 | House 9 got 130 presents. 34 | ``` 35 | 36 | The first house gets `10` presents: it is visited only by Elf `1`, which 37 | delivers `1 * 10 = 10` presents. The fourth house gets 70 presents, 38 | because it is visited by Elves `1`, `2`, and `4`, for a total of `10 + 20 + 39 | 40 = 70` presents. 40 | 41 | What is the lowest house number of the house to get at least as many 42 | presents as the number in your puzzle input? 43 | 44 | Your puzzle answer was **`831600`**. 45 | 46 | ## Part Two 47 | 48 | The Elves decide they don't want to visit an infinite number of 49 | houses. Instead, each Elf will stop after delivering presents to `50` 50 | houses. To make up for it, they decide to deliver presents equal to 51 | eleven times their number at each house. 52 | 53 | With these changes, what is the new lowest house number of the house 54 | to get at least as many presents as the number in your puzzle input? 55 | 56 | Your puzzle answer was **`884520`**. -------------------------------------------------------------------------------- /src/advent-2017/day03.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day03 2 | (:require 3 | [clojure.core.reducers :as r])) 4 | 5 | (def directions [[0 -1] [1 0] [0 1] [-1 0]]) 6 | 7 | ;; a lazy list of all the directions travelled in order 8 | ;; from the start of the spiral 9 | (def spiral-direction-list 10 | (for [step (range) 11 | stage (range (* 2 step)) 12 | :let [direction-total 13 | (- (* 2 step) 14 | (if (< stage step) 1 0))]] 15 | (mod direction-total 4))) 16 | 17 | (defn next-position [pos direction] 18 | (mapv + pos (directions direction))) 19 | 20 | (def spiral-positions-list 21 | (reductions next-position [0 0] spiral-direction-list)) 22 | 23 | (defn position-at-index [index] 24 | (nth spiral-positions-list (dec index))) 25 | 26 | ;; part 1 27 | #_(->> (position-at-index 347991) 28 | (map #(Math/abs %)) 29 | (apply +)) 30 | 31 | (def all-directions 32 | (into [[-1 -1] [-1 1] [1 -1] [1 1]] 33 | directions)) 34 | 35 | (defn all-neigbor-positions [pos] 36 | (mapv #(mapv + pos %) all-directions)) 37 | 38 | (defn neigbor-values [pos positions] 39 | (keep positions (all-neigbor-positions pos))) 40 | 41 | (defn state-transition [{:keys [positions] :as state} next-pos] 42 | (let [value (apply + (neigbor-values next-pos positions))] 43 | (-> state 44 | (assoc :value value) 45 | (assoc-in [:positions next-pos] value)))) 46 | 47 | (def neighbor-value-list 48 | (map :value 49 | (reductions 50 | state-transition 51 | {:value 1 52 | :positions {[0 0] 1}} 53 | (rest spiral-positions-list)))) 54 | 55 | ;; part 2 56 | 57 | #_(->> neighbor-value-list 58 | (filter #(> % 347991)) 59 | first) 60 | 61 | 62 | ;; After looking at some others code I especially like this 63 | ;; straightforward way of generating the spiral directions list 64 | 65 | #_(take 10 (mapcat 66 | (fn [[i [dir1 dir2]]] 67 | (vec (concat (repeat i dir1) (repeat i dir2)))) 68 | (map vector (rest (range)) (partition 2 (rest (cycle directions)))))) 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/advent-2017/day17.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day17) 2 | 3 | (def input-steps 335) 4 | 5 | ;; Use a circular linked list that takes the form 6 | ;; {a -> b, b -> c, c -> a} 7 | ;; this allows a fast insertion of DD at b like so 8 | ;; {a -> b, b -> DD, DD -> c, c -> a} 9 | 10 | ;; using an Array of Long for the underlying associative structure 11 | ;; for speed 12 | (defn splice-in-fast [^long step ^longs state ^long current-number] 13 | (loop [previous-number (dec current-number) 14 | step-count (mod step current-number)] 15 | (if (zero? ^long step-count) 16 | (let [next' (aget state previous-number)] 17 | (doto state 18 | (aset previous-number current-number) 19 | (aset current-number next'))) 20 | (recur (aget state previous-number) (dec ^long step-count))))) 21 | 22 | (def start-state (comp long-array inc)) 23 | 24 | #_(set! *warn-on-reflection* true) 25 | #_(set! *unchecked-math* :warn-on-boxed) 26 | 27 | ;; part 1 28 | #_ (-> (reduce (partial splice-in-fast input-steps) (start-state 2017) 29 | (range 1 2018)) 30 | (get 2017) 31 | time) 32 | ;; Elapsed time: 6.914165 msecs 33 | ;; = 1282 34 | 35 | ;; part 2 36 | #_ (-> (reduce (partial splice-in-fast input-steps) (start-state 50000000) 37 | (range 1 50000001)) 38 | (get 0) 39 | time) 40 | ;; => 27650600 41 | ;; around 5 minutes to complete 42 | 43 | 44 | ;; idea from @val_waeselynck 45 | 46 | ;; better solution for part 2 is to just find the last change to the 1 position 47 | ;; this only works for the 1 position in the puzzle, this is a bit subtle 48 | 49 | (defn transition [^long position ^long v] 50 | (inc ^long (mod (+ position ^long input-steps) v))) 51 | 52 | (defn find-last-after-zero [cycles] 53 | (loop [n 1 54 | pos 0 55 | after-zero nil] 56 | (let [next-pos (transition pos n)] 57 | (if (= n cycles) 58 | after-zero 59 | (recur (inc n) 60 | ^long next-pos 61 | (if (= 1 ^long next-pos) n after-zero)))))) 62 | 63 | ;; better part 2 64 | #_(time (find-last-after-zero (inc 50000000))) 65 | ;; => 27650600 66 | ;; Elapsed time: 4738.406857 msecs 67 | -------------------------------------------------------------------------------- /doc/2015/02.md: -------------------------------------------------------------------------------- 1 | # Day 2: I Was Told There Would Be No Math 2 | 3 | The elves are running low on wrapping paper, and so they need to 4 | submit an order for more. They have a list of the dimensions (length 5 | l, width w, and height h) of each present, and only want to order 6 | exactly as much as they need. 7 | 8 | Fortunately, every present is a box (a perfect right rectangular 9 | prism), which makes calculating the required wrapping paper for each 10 | gift a little easier: find the surface area of the box, which is 11 | `2*l*w + 2*w*h + 2*h*l`. The elves also need a little extra paper for each 12 | present: the area of the smallest side. 13 | 14 | For example: 15 | 16 | A present with dimensions `2x3x4` requires `2*6 + 2*12 + 2*8 = 52` square 17 | feet of wrapping paper plus `6` square feet of slack, for a total of `58` 18 | square feet. 19 | 20 | A present with dimensions `1x1x10` requires `2*1 + 2*10 + 2*10 = 42` 21 | square feet of wrapping paper plus `1` square foot of slack, for a total 22 | of `43` square feet. 23 | 24 | All numbers in the elves' list are in feet. How many total square feet 25 | of wrapping paper should they order? 26 | 27 | Your puzzle answer was **`1586300`**. 28 | 29 | ## Part Two 30 | 31 | The elves are also running low on ribbon. Ribbon is all the same 32 | width, so they only have to worry about the length they need to order, 33 | which they would again like to be exact. 34 | 35 | The ribbon required to wrap a present is the shortest distance around 36 | its sides, or the smallest perimeter of any one face. Each present 37 | also requires a bow made out of ribbon as well; the feet of ribbon 38 | required for the perfect bow is equal to the cubic feet of volume of 39 | the present. Don't ask how they tie the bow, though; they'll never 40 | tell. 41 | 42 | For example: 43 | 44 | A present with dimensions `2x3x4` requires `2+2+3+3 = 10` feet of ribbon 45 | to wrap the present plus `2*3*4 = 24` feet of ribbon for the bow, for a 46 | total of `34` feet. 47 | 48 | A present with dimensions `1x1x10` requires `1+1+1+1 = 4` feet of ribbon 49 | to wrap the present plus `1*1*10 = 10` feet of ribbon for the bow, for a 50 | total of `14` feet. 51 | 52 | How many total feet of ribbon should they order? 53 | 54 | Your puzzle answer was **`3737498`**. -------------------------------------------------------------------------------- /doc/2015/11.md: -------------------------------------------------------------------------------- 1 | # Day 11: Corporate Policy 2 | 3 | Santa's previous password expired, and he needs help choosing a new one. 4 | 5 | To help him remember his new password after the old one expires, Santa 6 | has devised a method of coming up with a password based on the 7 | previous one. Corporate policy dictates that passwords must be exactly 8 | eight lowercase letters (for security reasons), so he finds his new 9 | password by incrementing his old password string repeatedly until it 10 | is valid. 11 | 12 | Incrementing is just like counting with numbers: `xx`, `xy`, `xz`, `ya`, `yb`, 13 | and so on. Increase the rightmost letter one step; if it was `z`, it 14 | wraps around to `a`, and repeat with the next letter to the left until 15 | one doesn't wrap around. 16 | 17 | Unfortunately for Santa, a new Security-Elf recently started, and he 18 | has imposed some additional password requirements: 19 | 20 | Passwords must include one increasing straight of at least three 21 | letters, like `abc`, `bcd`, `cde`, and so on, up to `xyz`. They cannot skip 22 | letters; abd doesn't count. 23 | 24 | Passwords may not contain the letters `i`, `o`, or `l`, as these letters can 25 | be mistaken for other characters and are therefore confusing. 26 | 27 | Passwords must contain at least two different, non-overlapping pairs 28 | of letters, like `aa`, `bb`, or `zz`. 29 | 30 | For example: 31 | 32 | 33 | `hijklmmn` meets the first requirement (because it contains the 34 | straight `hij`) but fails the second requirement requirement (because 35 | it contains `i` and `l`). 36 | 37 | `abbceffg` meets the third requirement (because it repeats `bb` and `ff`) 38 | but fails the first requirement. 39 | 40 | `abbcegjk` fails the third requirement, because it only has one double letter (`bb`). 41 | 42 | The next password after `abcdefgh` is `abcdffaa`. 43 | 44 | The next password after `ghijklmn` is `ghjaabcc`, because you 45 | eventually skip all the passwords that start with `ghi...`, since `i` is 46 | not allowed. 47 | 48 | Given Santa's current password (your puzzle input), what should his next password be? 49 | 50 | Your puzzle answer was **`cqjxxyzz`**. 51 | 52 | ## Part Two 53 | 54 | Santa's password expired again. What's the next one? 55 | 56 | Your puzzle answer was **`cqkaabcc`**. -------------------------------------------------------------------------------- /src/advent-2017/day21.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day21 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def transpose (partial apply map vector)) 7 | (def flip (partial map reverse)) 8 | (def rotate-right (comp flip transpose)) 9 | 10 | (defn all-rotations [rule-key] 11 | (let [rotations (take 4 (iterate rotate-right (map seq rule-key)))] 12 | (concat rotations (map flip rotations)))) 13 | 14 | (defn expand-rule [rules [rule-key rule-val]] 15 | (->> (repeat (map seq rule-val)) 16 | (map vector (all-rotations rule-key)) 17 | (into {}) 18 | (merge rules))) 19 | 20 | (defn parse-rules [lines] 21 | (->> lines 22 | (map #(string/split % #" => ")) 23 | (map (partial map #(string/split % #"/"))) 24 | (reduce expand-rule {}))) 25 | 26 | (def rules 27 | (->> (io/resource "2017/day21") 28 | io/reader 29 | line-seq 30 | parse-rules)) 31 | 32 | (def start-pixels '((\. \# \.) 33 | (\. \. \#) 34 | (\# \# \#))) 35 | 36 | (defn break-into [grid n] 37 | (map #(map transpose (partition n (transpose %))) 38 | (partition n grid))) 39 | 40 | (defn normalize [broken-out] 41 | (mapcat #(map flatten (transpose %)) broken-out)) 42 | 43 | ;; memoized recursive solution 44 | (defn count-at-depth [depth grid] 45 | (if (zero? depth) 46 | (count (filter #{\#} (flatten grid))) 47 | (condp = (count grid) 48 | 2 (count-at-depth (dec depth) (rules grid)) 49 | 3 (count-at-depth (dec depth) (rules grid)) 50 | 4 (count-at-depth (dec depth) (->> (break-into grid 2) 51 | (map (partial map rules)) 52 | normalize)) 53 | 6 (->> (break-into grid 2) 54 | (mapcat (partial map rules)) 55 | (map #(count-at-depth (dec depth) %)) 56 | (reduce +))))) 57 | 58 | ;; part 1 59 | #_(with-redefs [count-at-depth (memoize count-at-depth)] 60 | (time (count-at-depth 5 start-pixels))) 61 | ;; => 139 62 | ;; Elapsed time: 1.537593 msecs 63 | 64 | ;; part 2 65 | #_(with-redefs [count-at-depth (memoize count-at-depth)] 66 | (time (count-at-depth 18 start-pixels))) 67 | ;; => 1857134 68 | ;; Elapsed time: 15.000658 msec 69 | -------------------------------------------------------------------------------- /src/advent-2016/day19.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day19) 2 | 3 | ;; the idea here is we can represent the data structure as a range 4 | ;; with a beginning and an end and a step 5 | 6 | (defn next-level [{:keys [begin end step] :as st}] 7 | (let [nstep (* 2 step)] 8 | (if (= 1 (mod (- (inc end) begin) nstep)) 9 | (-> st 10 | (assoc :step nstep) 11 | (update-in [:begin] #(+ % nstep))) 12 | (-> st 13 | (assoc :step nstep) 14 | (update-in [:end] #(- % step)))))) 15 | 16 | ;; part 1 17 | #_(first 18 | (filter #(= (:begin %) (:end %)) 19 | (iterate next-level {:begin 1 :end 3004953 :step 1}))) 20 | ;; => 1815603 21 | 22 | ;; For part 2 23 | 24 | ;; this problem can be done in the same manner as above but it's very tricky 25 | ;; The following is a brute force approach with an optimized data structure and algorithm 26 | 27 | ;; this can be considered an alternate approach to part one as well 28 | 29 | ;; A really good challenge is to use the approach above keeping in mind 30 | ;; the fact that the second part just keeps eliminating two neighbors at a time 31 | ;; starting at the opposite index - 1 in a cycle 32 | 33 | (defn opposite-index [cnt i] 34 | (mod (+ i (int (/ cnt 2))) cnt)) 35 | 36 | (defn make-st [s i] 37 | (let [st (into (sorted-set) s) 38 | op-i (opposite-index (count st) i)] 39 | [st (drop op-i st)])) 40 | 41 | (defn handle-empty [[st prog :as x]] 42 | (if (empty? prog) [st (seq st)] x)) 43 | 44 | (defn drop-st* [[st progress :as x]] 45 | [(disj st (first progress)) (drop 1 progress)]) 46 | 47 | (defn keep-1* [[st prog]] [st (drop 1 prog)]) 48 | 49 | (defn skip-completed [f] 50 | (fn [x] (if (= 1 (count (first x))) x (f x)))) 51 | 52 | (def drop-st (skip-completed (comp drop-st* handle-empty))) 53 | 54 | (def keep-1 (comp keep-1* handle-empty)) 55 | 56 | (declare transition) 57 | 58 | (defn transition* [[st progress :as x]] 59 | (if (odd? (count st)) 60 | (transition (keep-1 (drop-st x))) 61 | (keep-1 (drop-st (drop-st x))))) 62 | 63 | (def transition (skip-completed transition*)) 64 | 65 | (defn find-answer2 [s] 66 | (->> (iterate transition (make-st s 0)) 67 | (filter #(= 1 (count (first %)))) 68 | first)) 69 | 70 | #_(time (find-answer2 (range 1 (inc 3004953)))) 71 | ;; => 1410630 72 | -------------------------------------------------------------------------------- /doc/2015/23.md: -------------------------------------------------------------------------------- 1 | # Day 23: Opening the Turing Lock 2 | 3 | Little Jane Marie just got her very first computer for Christmas from 4 | some unknown benefactor. It comes with instructions and an example 5 | program, but the computer itself seems to be malfunctioning. She's 6 | curious what the program does, and would like you to help her run it. 7 | 8 | The manual explains that the computer supports two registers and six 9 | instructions (truly, it goes on to remind the reader, a 10 | state-of-the-art technology). The registers are named a and b, can 11 | hold any non-negative integer, and begin with a value of 0. The 12 | instructions are as follows: 13 | 14 | ``` 15 | hlf r sets register r to half its current value, then continues with the next instruction. 16 | tpl r sets register r to triple its current value, then continues with the next instruction. 17 | inc r increments register r, adding 1 to it, then continues with the next instruction. 18 | jmp offset is a jump; it continues with the instruction offset away relative to itself. 19 | jie r, offset is like jmp, but only jumps if register r is even ("jump if even"). 20 | jio r, offset is like jmp, but only jumps if register r is 1 ("jump if one", not odd). 21 | ``` 22 | 23 | All three jump instructions work with an **offset** relative to that 24 | instruction. The offset is always written with a prefix `+` or `-` to 25 | indicate the direction of the jump (forward or backward, 26 | respectively). For example, jmp `+1` would simply continue with the next 27 | instruction, while jmp `+0` would continuously jump back to itself 28 | forever. 29 | 30 | The program exits when it tries to run an instruction beyond the ones 31 | defined. 32 | 33 | For example, this program sets a to `2`, because the `jio` instruction 34 | causes it to skip the `tpl` instruction: 35 | 36 | ``` 37 | inc a 38 | jio a, +2 39 | tpl a 40 | inc a 41 | ``` 42 | 43 | What is **the value in register `b`** when the program in your puzzle input 44 | is finished executing? 45 | 46 | Your puzzle answer was **`255`**. 47 | 48 | ## Part Two 49 | 50 | The unknown benefactor is **very** thankful for releasi-- er, helping 51 | little Jane Marie with her computer. Definitely not to distract you, 52 | what is the value in register b after the program is finished 53 | executing if register a starts as `1` instead? 54 | 55 | Your puzzle answer was **`334`**. -------------------------------------------------------------------------------- /src/advent-2018/day02.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day02 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [clojure.set :as set] 6 | [medley.core :as med] 7 | [clojure.math.combinatorics :as combo])) 8 | 9 | (def data 10 | (->> (io/resource "2018/day02") 11 | slurp 12 | string/split-lines)) 13 | 14 | (defn occurs [str] 15 | (set (vals (frequencies str)))) 16 | 17 | (def transpose (partial apply mapv vector)) 18 | 19 | (defn problem-1 [d] 20 | (->> (map (comp (juxt #(when (% 2) 1) #(when (% 3) 1)) occurs) d) 21 | transpose 22 | (map #(apply + (keep identity %))) 23 | (apply *))) 24 | 25 | #_ (problem-1 data) 26 | 27 | (defn comparison [x y] 28 | (filter identity (map #(when (= %1 %2) %1) x y))) 29 | 30 | (defn problem-2 [d] 31 | (let [target (dec (count (first d)))] 32 | (->> (combo/combinations d 2) 33 | (map #(apply comparison %)) 34 | (filter #(= (count %) target)) 35 | first 36 | (apply str)))) 37 | 38 | #_ (time (problem-2 data)) 39 | 40 | (def test-data-2 41 | (map name '[abcde 42 | fghij 43 | klmno 44 | pqrst 45 | fguij 46 | axcye 47 | wvxyz])) 48 | 49 | ;; more efficient tree search 50 | (defn search [words] 51 | (when (< 1 (count words)) 52 | ;; separate into groups whos first letters differ from the other groups 53 | (let [grouped (med/map-vals (partial map #(subs % 1)) 54 | (group-by first words))] 55 | ;;two cases 56 | (or 57 | ;; everything upto now is equal except for the current letters 58 | ;; check to see if any words are equal after this point 59 | (->> (combo/combinations (map set (vals grouped)) 2) 60 | (keep #(not-empty (apply set/intersection %))) 61 | ffirst) 62 | ;; the search is now divided between words that have equal beginnings 63 | (some->> grouped 64 | (med/map-vals search) 65 | (med/filter-vals some?) 66 | first 67 | (apply cons)))))) 68 | 69 | #_(= (apply str (search data)) (problem-2 data)) 70 | 71 | #_ (time (apply str (search data))) 72 | ;; 5 ms 73 | 74 | #_(time (problem-2 data)) 75 | ;; 90ms 76 | 77 | #_(search ["abc" "ddd" "zbc" "ahg" "zzz"]) 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /doc/2015/07.md: -------------------------------------------------------------------------------- 1 | # Day 7: Some Assembly Required 2 | 3 | This year, Santa brought little Bobby Tables a set of wires and 4 | bitwise logic gates! Unfortunately, little Bobby is a little under the 5 | recommended age range, and he needs help assembling the circuit. 6 | 7 | Each wire has an identifier (some lowercase letters) and can carry a 8 | 16-bit signal (a number from 0 to 65535). A signal is provided to each 9 | wire by a gate, another wire, or some specific value. Each wire can 10 | only get a signal from one source, but can provide its signal to 11 | multiple destinations. A gate provides no signal until all of its 12 | inputs have a signal. 13 | 14 | The included instructions booklet describes how to connect the parts 15 | together: `x AND y -> z` means to connect wires `x` and `y` to an AND gate, 16 | and then connect its output to wire `z`. 17 | 18 | For example: 19 | 20 | `123 -> x` means that the signal 123 is provided to wire `x`. 21 | 22 | `x AND y -> z` means that the **bitwise AND** of wire `x` and wire `y` 23 | is provided to wire `z`. 24 | 25 | `p LSHIFT 2 -> q` means that the value from wire `p` is left-shifted 26 | by `2` and then provided to wire `q`. 27 | 28 | `NOT e -> f` means that the bitwise complement of the value from wire 29 | `e` is provided to wire `f`. 30 | 31 | Other possible gates include OR (bitwise OR) and `RSHIFT` (right-shift). 32 | If, for some reason, you'd like to emulate the circuit instead, almost 33 | all programming languages (for example, C, JavaScript, or Python) 34 | provide operators for these gates. 35 | 36 | For example, here is a simple circuit: 37 | 38 | ```` 39 | 123 -> x 40 | 456 -> y 41 | x AND y -> d 42 | x OR y -> e 43 | x LSHIFT 2 -> f 44 | y RSHIFT 2 -> g 45 | NOT x -> h 46 | NOT y -> i 47 | ``` 48 | After it is run, these are the signals on the wires: 49 | 50 | ``` 51 | d: 72 52 | e: 507 53 | f: 492 54 | g: 114 55 | h: 65412 56 | i: 65079 57 | x: 123 58 | y: 456 59 | ``` 60 | 61 | In little Bobby's kit's instructions booklet (provided as your puzzle 62 | input), what signal is ultimately provided to wire `a`? 63 | 64 | Your puzzle answer was **`3176`**. 65 | 66 | ## Part Two 67 | 68 | Now, take the signal you got on wire `a`, override wire `b` to that 69 | signal, and reset the other wires (including wire `a`). What new signal 70 | is ultimately provided to wire `a`? 71 | 72 | Your puzzle answer was **`14710`**. 73 | 74 | -------------------------------------------------------------------------------- /src/advent-2016/day25.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day25 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (defn parse-instructions [s] 7 | (->> s 8 | (string/split-lines) 9 | (map #(str "[" % "]")) 10 | (map read-string) 11 | vec)) 12 | 13 | (def input (parse-instructions (slurp (io/resource "2016/day25")))) 14 | 15 | (defn reg-or-val [s reg-val] (if (symbol? reg-val) (get s reg-val) reg-val)) 16 | 17 | (defn update-reg [s reg f] 18 | (-> s (update reg f) (update :pos inc))) 19 | 20 | (defmulti trans (fn [_ b] (first b))) 21 | 22 | (defmethod trans 'inc [s [_ reg]] 23 | (update-reg s reg inc)) 24 | 25 | (defmethod trans 'dec [s [_ reg]] 26 | (update-reg s reg dec)) 27 | 28 | (defmethod trans 'out [s [_ reg-val]] 29 | (-> s 30 | (update :output conj (reg-or-val s reg-val)) 31 | (update :pos inc))) 32 | 33 | (defmethod trans 'cpy [s [_ reg-val reg]] 34 | (-> s (assoc reg (reg-or-val s reg-val)) (update :pos inc))) 35 | 36 | (defmethod trans 'jnz [s [_ reg-val steps]] 37 | (update s :pos + 38 | (if-not (zero? (reg-or-val s reg-val)) 39 | (reg-or-val s steps) 40 | 1))) 41 | 42 | (defn start-state [instructions] 43 | (assoc '{a 0 b 0 c 0 d 0 :pos 0} 44 | :instr (vec instructions) 45 | :output [])) 46 | 47 | ;; for part 2 48 | 49 | ;; not general 50 | (defn multiply-instructions? [instructions] 51 | (= '[[inc d] 52 | [dec b] 53 | [jnz b -2] 54 | [dec c] 55 | [jnz c -5]] 56 | (take 5 instructions))) 57 | 58 | (defn multiply [st] 59 | (-> st 60 | (update 'd + (* (get st 'b) (get st 'c))) 61 | (assoc 'b 0) 62 | (assoc 'c 0) 63 | (update :pos + 5))) 64 | 65 | (defn run-prog [start-state] 66 | (take-while (comp not nil?) 67 | (iterate (fn [{:keys [pos instr] :as s}] 68 | (when-let [inst (get instr pos)] 69 | (if (multiply-instructions? (drop pos instr)) 70 | (multiply s) 71 | (trans s inst)))) 72 | start-state))) 73 | 74 | (defn try-start-int [n] 75 | (:output (last (take-while #(not= (count (:output %)) 9) 76 | (run-prog (assoc (start-state input) 'a n)))))) 77 | 78 | ;; part 1 79 | #_(count 80 | (take-while #(not= [0 1 0 1 0 1 0 1] %) 81 | (map try-start-int (range 0 1000)))) 82 | ;; => 198 83 | 84 | -------------------------------------------------------------------------------- /resources/2016/day2: -------------------------------------------------------------------------------- 1 | UUURRRRULRDLRDRRDURDDDLLDLLLULDUDDLDLULUURULRLDLRRLLLRRDRRLDDLLULUDUDDLRDRDUURDLURUURLRULLDDURULRRURDUURLULUUUURDDDDUUDLULRULLLRLLRRRURDLLRLLRRRUURULRDRUUDDDDDLLLRURRURRUURDUURDDRDLULRRLLLDRRRLURRLLURLDRRDDLDLRRLLRDRLLLLDLULDLRRDRRLDDURLULLUDLUDRRDRRLRLULURDRLRLUUUDLRLDLLLURDUDULULDDRUUURLLLDLLDDUDDRURURUDDLUULRDRRRRLDRDDURLUDURDULLDLUDLULDRLRLLRLLLLRURDURLLDRRDRLRUUUUULLLRUDURUDLLLUDLLLLRDLDRDUDRURLUDDUDDURLUUUUDDLLUDLULLLLLDUDLLRLRRDDDULULRLDRLLULDLUDLLURULRDDUURULRDLDLDLRL 2 | URUUURDULUDLUUUUDDRRRDRRRLDUDLRDRRDRDDLRUULDLLDUDULLLRLDRDRRLDLDLUUDRUULDUDULDUDURURDDURULDLURULRLULDUDDUULDLLLDDURDDRDDURUULUUDRLDDULDRRRRDURRUDLLLURDDDLRULLRDDRDDDDLUUDRDUULRRRRURULDDDLDDRDRRUDRRURUDRDDLDRRRLLURURUULUUDRDULLDRLRDRRDDURDUDLDRLUDRURDURURULDUUURDUULRRRRRUDLLULDDDRLULDDULUDRRRDDRUDRRDLDLRUULLLLRRDRRLUDRUULRDUDRDRRRDDRLLRUUDRLLLUDUDLULUUDULDRRRRDDRURULDULLURDLLLDUUDLLUDRLDURRRLDDDURUDUDURRULDD 3 | LRUDDULLLULRLUDUDUDRLLUUUULLUDLUUUUDULLUURDLLRDUDLRUDRUDDURURRURUDLLLRLDLUDRRRRRRDLUURLRDDDULRRUDRULRDRDDUULRDDLDULDRRRDDLURRURLLLRURDULLRUUUDDUDUURLRLDDUURLRDRRLURLDRLLUUURDRUUDUUUDRLURUUUDLDRRLRLLRRUURULLLRLLDLLLDULDDLDULDLDDRUDURDDURDUDURDLLLRRDDLULLLUDURLUDDLDLUUDRDRUDUUDLLDDLLLLDRDULRDLDULLRUDDUULDUDLDDDRUURLDRRLURRDDRUUDRUDLLDLULLULUDUDURDDRLRDLRLDRLDDRULLLRUDULDRLRLRULLRLLRRRLLRRRDDRULRUURRLLLRULDLUDRRDDLLLUDDUDDDLURLUDRDLURUUDLLDLULURRLLDURUDDDDRLULRDDLRLDDLRLLDDRRLRDUDUUULRRLRULUDURDUDRLRLRUDUDLLRRRRLRRUDUL 4 | RULLLLUUUDLLDLLRULLRURRULDDRDLUULDRLLRUDLLRRLRDURLLDUUUUURUUURDLUURRLDDDLRRRRLRULDUDDLURDRRUUDLRRRDLDDUDUDDRUDURURLDULLDLULDLLUDLULRDRLLURRLLDURLDLRDLULUDDULDLDDDDDUURRDRURLDLDULLURDLLDDLLUDLDLDRLRLDLRDRLDLRRUUDRURLUUUDLURUULDUDRDULLDURUDLUUURRRLLDUDUDDUUULLLRUULDLURUDDRLUDRDDLDLLUDUDRRRDDUUULUULLLRLLUURDUUDRUUULULLDLDRUUDURLLUULRLDLUURLLUUDRURDDRLURULDUDUUDRRUUURDULRLDUUDDRURURDRRULDDDRLUDLLUUDURRRLDLRLRDRURLURLLLRLDDLRRLDLDDURDUUDRDRRLDRLULDRLURUUUDDRLLLDDLDURLLLLDRDLDRRUDULURRLULRDRLLUULLRLRDRLLULUURRUDRUDDDLLDURURLURRRDLLDRDLUDRULULULRLDLRRRUUDLULDURLRDRLULRUUURRDDLRUURUDRURUDURURDD 5 | DURRDLLLDDLLDLLRLULULLRDLDRRDDRDLRULURRDUUDDRLLDDLDRRLRDUDRULDLRURDUUDRDDLLDRRDRUDUDULLDDDDLDRRRLRLRDRDLURRDDLDDDUUDRDRLLLDLUDDDLUULRDRLLLRLLUULUDDDRLDUUUURULRDDURRDRLUURLUDRLRLLLDDLRDDUULRRRRURDLDDDRLDLDRRLLDRDDUDDUURDLDUUDRDLDLDDULULUDDLRDDRLRLDDLUDLLDRLUDUDDRULLRLDLLRULRUURDDRDRDRURDRRLRDLLUDDRRDRRLDDULLLDLUDRRUDLDULDRURRDURLURRLDLRDLRUDLULUDDRULRLLDUURULURULURRLURRUULRULRRRLRDLULRLRLUDURDDRUUURDRLLRRRDDLDRRRULLDLRDRULDRRLRRDLUDDRDDDUUURRLULLDRRUULULLRRRRLDDRDDLUURLLUDLLDUDLULUULUDLLUUURRRUDDDRLLLRDRUUDUUURDRULURRLRDLLUURLRDURULDRRUDURRDDLDRLDRUUDRLLUDLRRU -------------------------------------------------------------------------------- /doc/2015/06.md: -------------------------------------------------------------------------------- 1 | # Day 6: Probably a Fire Hazard 2 | 3 | Because your neighbors keep defeating you in the holiday house 4 | decorating contest year after year, you've decided to deploy one 5 | million lights in a 1000x1000 grid. 6 | 7 | Furthermore, because you've been especially nice this year, Santa has 8 | mailed you instructions on how to display the ideal lighting 9 | configuration. 10 | 11 | Lights in your grid are numbered from 0 to 999 in each direction; the 12 | lights at each corner are at `0,0`, `0,999`, `999,999`, and `999,0`. The 13 | instructions include whether to `turn on`, `turn off`, or `toggle` various 14 | inclusive ranges given as coordinate pairs. Each coordinate pair 15 | represents opposite corners of a rectangle, inclusive; a coordinate 16 | pair like `0,0 through 2,2` therefore refers to 9 lights in a 3x3 17 | square. The lights all start turned off. 18 | 19 | To defeat your neighbors this year, all you have to do is set up your 20 | lights by doing the instructions Santa sent you in order. 21 | 22 | For example: 23 | 24 | `turn on 0,0 through 999,999` would turn on (or leave on) every 25 | light. 26 | 27 | `toggle 0,0 through 999,0` would toggle the first line of `1000` lights, 28 | turning off the ones that were on, and turning on the ones that were 29 | off. 30 | 31 | `turn off 499,499 through 500,500` would turn off (or leave off) the 32 | middle four lights. 33 | 34 | After following the instructions, how many lights are lit? 35 | 36 | Your puzzle answer was **`569999`**. 37 | 38 | ## Part Two 39 | 40 | You just finish implementing your winning light pattern when you 41 | realize you mistranslated Santa's message from Ancient Nordic Elvish. 42 | 43 | The light grid you bought actually has individual brightness controls; 44 | each light can have a brightness of zero or more. The lights all start 45 | at zero. 46 | 47 | The phrase `turn on` actually means that you should increase the 48 | brightness of those lights by `1`. 49 | 50 | The phrase `turn off` actually means that you should decrease the 51 | brightness of those lights by `1`, to a minimum of zero. 52 | 53 | The phrase `toggle` actually means that you should increase the 54 | brightness of those lights by `2`. 55 | 56 | What is the total brightness of all lights combined after following 57 | Santa's instructions? 58 | 59 | For example: 60 | 61 | `turn on 0,0 through 0,0` would increase the total brightness by `1`. 62 | 63 | `toggle 0,0 through 999,999` would increase the total brightness by 2000000. 64 | 65 | Your puzzle answer was **`17836115`**. -------------------------------------------------------------------------------- /doc/2015/05.md: -------------------------------------------------------------------------------- 1 | # Day 5: Doesn't He Have Intern-Elves For This? 2 | 3 | Santa needs help figuring out which strings in his text file are 4 | naughty or nice. 5 | 6 | A nice string is one with all of the following properties: 7 | 8 | It contains at least three vowels (aeiou only), like `aei`, `xazegov`, or 9 | `aeiouaeiouaeiou`. 10 | 11 | It contains at least one letter that appears twice in a row, like `xx`, 12 | `abcdde` (`dd`), or `aabbccdd` (`aa`, `bb`, `cc`, or `dd`). 13 | 14 | It does not contain the strings `ab`, `cd`, `pq`, or `xy`, even if they are 15 | part of one of the other requirements. 16 | 17 | For example: 18 | 19 | `ugknbfddgicrmopn` is nice because it has at least three vowels 20 | (u...i...o...), a double letter (...dd...), and none of the disallowed 21 | substrings. 22 | 23 | `aaa` is nice because it has at least three vowels and a double letter, 24 | even though the letters used by different rules overlap. 25 | 26 | `jchzalrnumimnmhp` is naughty because it has no double letter. 27 | 28 | `haegwjzuvuyypxyu` is naughty because it contains the string `xy`. 29 | 30 | `dvszwmarrgswjxmb` is naughty because it contains only one vowel. 31 | 32 | How many strings are nice? 33 | 34 | Your puzzle answer was **`238`**. 35 | 36 | --- Part Two --- 37 | 38 | Realizing the error of his ways, Santa has switched to a better model 39 | of determining whether a string is naughty or nice. None of the old 40 | rules apply, as they are all clearly ridiculous. 41 | 42 | Now, a nice string is one with all of the following properties: 43 | 44 | It contains a pair of any two letters that appears at least twice in 45 | the string without overlapping, like `xyxy` (xy) or `aabcdefgaa` (aa), but 46 | not like `aaa` (aa, but it overlaps). 47 | 48 | It contains at least one letter which repeats with exactly one letter 49 | between them, like `xyx`, `abcdefeghi` (efe), or even `aaa`. 50 | 51 | For example: 52 | 53 | `qjhvhtzxzqqjkmpb` is nice because is has a pair that appears twice (qj) and a letter that repeats with exactly one letter between them (zxz). 54 | 55 | `xxyxx` is nice because it has a pair that appears twice and a letter that repeats with one between, even though the letters used by each rule overlap. 56 | 57 | `uurcxstgmygtbstg` is naughty because it has a pair (tg) but no repeat with a single letter between them. 58 | 59 | `ieodomkazucvgmuy` is naughty because it has a repeating letter with one between (odo), but no pair that appears twice. 60 | 61 | How many strings are nice under these new rules? 62 | 63 | Your puzzle answer was 69. -------------------------------------------------------------------------------- /doc/2015/16.md: -------------------------------------------------------------------------------- 1 | # Day 16: Aunt Sue 2 | 3 | Your Aunt Sue has given you a wonderful gift, and you'd like to send 4 | her a thank you card. However, there's a small problem: she signed it 5 | "From, Aunt Sue". 6 | 7 | You have 500 Aunts named "Sue". 8 | 9 | So, to avoid sending the card to the wrong person, you need to figure 10 | out which Aunt Sue (which you conveniently number 1 to 500, for 11 | sanity) gave you the gift. You open the present and, as luck would 12 | have it, good ol' Aunt Sue got you a My First Crime Scene Analysis 13 | Machine! Just what you wanted. Or needed, as the case may be. 14 | 15 | The My First Crime Scene Analysis Machine (MFCSAM for short) can 16 | detect a few specific compounds in a given sample, as well as how many 17 | distinct kinds of those compounds there are. According to the 18 | instructions, these are what the MFCSAM can detect: 19 | 20 | `children`, by human DNA age analysis. 21 | 22 | `cats`. It doesn't differentiate individual breeds. 23 | 24 | Several seemingly random breeds of dog: `samoyeds`, `pomeranians`, `akitas`, and `vizslas`. 25 | 26 | `goldfish`. No other kinds of fish. 27 | 28 | `trees`, all in one group. 29 | 30 | `cars`, presumably by exhaust or gasoline or something. 31 | 32 | `perfumes`, which is handy, since many of your Aunts Sue wear a few 33 | kinds. 34 | 35 | In fact, many of your Aunts Sue have many of these. You put the 36 | wrapping from the gift into the MFCSAM. It beeps inquisitively at you 37 | a few times and then prints out a message on ticker tape: 38 | 39 | ``` 40 | children: 3 41 | cats: 7 42 | samoyeds: 2 43 | pomeranians: 3 44 | akitas: 0 45 | vizslas: 0 46 | goldfish: 5 47 | trees: 3 48 | cars: 2 49 | perfumes: 1 50 | ``` 51 | 52 | You make a list of the things you can remember about each Aunt Sue. 53 | Things missing from your list aren't zero - you simply don't remember 54 | the value. 55 | 56 | What is the number of the Sue that got you the gift? 57 | 58 | Your puzzle answer was 103. 59 | 60 | ## Part Two 61 | 62 | As you're about to send the thank you note, something in the MFCSAM's 63 | instructions catches your eye. Apparently, it has an outdated 64 | retroencabulator, and so the output from the machine isn't exact 65 | values - some of them indicate ranges. 66 | 67 | In particular, the cats and trees readings indicates that there are 68 | greater than that many (due to the unpredictable nuclear decay of cat 69 | dander and tree pollen), while the pomeranians and goldfish readings 70 | indicate that there are **fewer than** that many (due to the modial 71 | interaction of magnetoreluctance). 72 | 73 | What is the number of the real Aunt Sue? 74 | 75 | Your puzzle answer was `405`. -------------------------------------------------------------------------------- /src/advent-2016/day10.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day10 2 | (:require 3 | [advent-2016.utils :as u] 4 | [clojure.set :refer [difference]] 5 | [clojure.java.io :as io] 6 | [clojure.string :as string])) 7 | 8 | (def data (string/split-lines (string/trim (slurp (io/resource "2016/day10"))))) 9 | 10 | (defn addr-names [l] 11 | (->> (re-seq #"(bot|output)\s(\d+)" l) 12 | (map (comp keyword #(apply str %) rest)))) 13 | 14 | (defn parse-line [l] 15 | (let [addrs (addr-names l)] 16 | (condp = (first l) 17 | \v (vector :to (first addrs) (u/to-int (first (re-seq #"\d+" l)))) 18 | \b (cons :from addrs)))) 19 | 20 | ;; all commands originate at a unique bot 21 | #_(let [froms (map second (filter #(= (first %) :from) input))] 22 | (= (count froms) (count (set froms)))) 23 | 24 | (defn give-to-addr [registers addr v] 25 | (update registers addr (fnil conj #{}) v)) 26 | 27 | (defn move-value [registers from to v] 28 | {:pre [((get registers from) v)]} ;; must have val to give 29 | (-> registers 30 | (update from disj v) 31 | (give-to-addr to v))) 32 | 33 | (defn make-init [commands] 34 | (let [{:keys [from to]} (group-by first commands)] 35 | {:commands from 36 | :registers (reduce #(apply give-to-addr %1 (rest %2)) {} to)})) 37 | 38 | (defn high-low-command [registers [_ from low-to high-to :as com]] 39 | (let [[lv hv] ((juxt first last) (sort (get registers from #{})))] 40 | (assert (and lv hv (not= lv hv))) 41 | (-> registers 42 | (move-value from low-to lv) 43 | (move-value from high-to hv)))) 44 | 45 | (defn active-registers [x] (->> x (filter #(>= (count (val %)) 2)) keys set)) 46 | 47 | (defn transition-state [{:keys [registers commands] :as state}] 48 | (let [active-regs (active-registers registers) 49 | [active-commands rest-commands] (u/pluck #(-> % second active-regs) commands)] 50 | (when-not (empty? active-commands) 51 | (-> state 52 | (update :registers #(reduce high-low-command % active-commands)) 53 | (assoc :commands rest-commands))))) 54 | 55 | ;; part 1 56 | #_(->> (iterate transition-state (make-init (map parse-line data))) 57 | (take-while #(not (nil? %))) 58 | (map :registers) 59 | (keep #(some (fn [[k v]] (when (empty? (difference #{61 17} v)) k)) %)) 60 | first) 61 | ;;=> :bot161 62 | 63 | ;; part 2 64 | #_(->> (iterate transition-state (make-init (map parse-line data))) 65 | (take-while #(not (nil? %))) 66 | last 67 | :registers 68 | (#(select-keys % [:output0 :output1 :output2])) 69 | vals 70 | (map first) 71 | (apply *)) 72 | ;; => 133163 73 | -------------------------------------------------------------------------------- /src/advent-2018/day04.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day04 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [medley.core :as med] 6 | [clj-time.core :as t])) 7 | 8 | (defn extract-log-entry [[[type] [year month day hour min gid]]] 9 | (cond-> {:date [(+ year 500) month day] 10 | :time [hour min] 11 | :type (keyword (string/lower-case type))} 12 | gid (assoc :gid gid))) 13 | 14 | (defn advance-guard-date [{:keys [date gid time] :as log-entry}] 15 | (cond-> log-entry 16 | (and gid (= 23 (first time))) 17 | (update :date 18 | #((juxt t/year t/month t/day) 19 | (t/plus (apply t/date-time %) (t/days 1)))))) 20 | 21 | (defn time-intervals [logs] 22 | (let [res (group-by :gid logs)] 23 | [(some identity (keys res)) 24 | (->> (get res nil) 25 | (map (comp second :time)) 26 | sort 27 | (partition 2))])) 28 | 29 | (def guard-sleep-intervals 30 | (->> (line-seq (io/reader (io/resource "2018/day04"))) 31 | (map (juxt 32 | (some-fn (partial re-seq #"Guard") 33 | (partial re-seq #"wakes") 34 | (partial re-seq #"falls")) 35 | #(map (fn [x] (Integer/parseInt x)) 36 | (re-seq #"\d+" %)))) 37 | (map extract-log-entry) 38 | (map advance-guard-date) 39 | (group-by :date) 40 | vals 41 | (map time-intervals))) 42 | 43 | (defn time-asleep [intervals] 44 | (->> intervals 45 | (map #(apply - (reverse %))) 46 | (apply +))) 47 | 48 | (defn slept-the-most [interval-report] 49 | (->> interval-report 50 | (map #(update-in % [1] time-asleep)) 51 | (group-by first) 52 | (med/map-vals #(apply + (map second %))) 53 | (sort-by val >) 54 | ffirst)) 55 | 56 | #_(slept-the-most guard-sleep-intervals) 57 | 58 | (defn best-minute-for-guard [gid interval-report] 59 | (->> interval-report 60 | (filter #(= gid (first %))) 61 | (mapcat second) 62 | (mapcat #(apply range %)) 63 | frequencies 64 | (sort-by second >) 65 | first)) 66 | 67 | #_(best-minute-for-guard 421 guard-sleep-intervals) 68 | 69 | ;; part 1 70 | #_ (= (let [gid (slept-the-most guard-sleep-intervals)] 71 | (* (first (best-minute-for-guard gid guard-sleep-intervals)) 72 | gid)) 73 | 11367) 74 | 75 | ;; part 2 76 | #_(let [guard-ids (distinct (map first guard-sleep-intervals))] 77 | (->> (keep #(when-let [res (best-minute-for-guard % guard-sleep-intervals)] 78 | {:guard % :minute (first res) :total-time (second res)}) 79 | guard-ids) 80 | (sort-by :total-time >) 81 | first 82 | ((juxt :guard :minute)) 83 | (apply *))) 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/advent-2015/day07.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2015.day07 2 | (:require 3 | [clojure.java.io :as io])) 4 | 5 | (def prob7 6 | (line-seq (io/reader (io/resource "2015/prob7")))) 7 | 8 | (defn dependents [op command] 9 | (filter (complement integer?) 10 | (condp = op 11 | 'NOT (rest command) 12 | 'OR ((juxt first last) command) 13 | 'AND ((juxt first last) command) 14 | 'LSHIFT (list (first command)) 15 | 'RSHIFT (list (first command)) 16 | command))) 17 | 18 | (defn parse-connection [line] 19 | (let [tokens (read-string (str "[" line "]")) 20 | output (last tokens) 21 | command (take-while #(not= '-> %) tokens) 22 | op (first (filter #(and 23 | (not (integer? %)) 24 | (re-matches #"[A-Z]+" (name %))) command))] 25 | {:orig tokens 26 | :output output 27 | :command command 28 | :deps (dependents op command) 29 | :op op})) 30 | 31 | (def source (map parse-connection prob7)) 32 | 33 | (def source-graph (into {} (map (juxt :output identity) source) )) 34 | 35 | (defn constant-assignment? [{:keys [op command]}] 36 | (and 37 | (nil? op) 38 | (= 1 (count command)) 39 | (integer? (first command)))) 40 | 41 | (defn solvable? [source-graph {:keys [deps] :as node}] 42 | (or 43 | (and 44 | (not-empty deps) 45 | (every? (comp integer? source-graph) deps)) 46 | (constant-assignment? node))) 47 | 48 | (defn value [source-graph k] 49 | (if (integer? k) k (source-graph k))) 50 | 51 | (defn solve [source-graph {:keys [op deps command] :as node}] 52 | (if-let [sol (if (constant-assignment? node) 53 | (first command) 54 | (let [bin-args (map (partial value source-graph) 55 | ((juxt first last) command))] 56 | (condp = op 57 | 'NOT (bit-not (value source-graph (last command))) 58 | 'OR (apply bit-or bin-args) 59 | 'AND (apply bit-and bin-args) 60 | 'LSHIFT (apply bit-shift-left bin-args) 61 | 'RSHIFT (apply bit-shift-right bin-args) 62 | nil (value source-graph (first command)))))] 63 | (assoc source-graph (:output node) sol) 64 | source-graph)) 65 | 66 | (defn update-step [source-graph] 67 | (->> source-graph 68 | vals 69 | (filter (partial solvable? source-graph)) 70 | (reduce solve source-graph))) 71 | 72 | ; part 1 73 | #_((->> source-graph 74 | (iterate update-step) 75 | (filter #(integer? (% 'a))) 76 | first) 77 | 'a) 78 | 79 | ;; part 2 80 | #_((->> (assoc source-graph 'b 3176) 81 | (iterate update-step) 82 | (filter #(integer? (% 'a))) 83 | first) 84 | 'a) 85 | -------------------------------------------------------------------------------- /doc/2015/14.md: -------------------------------------------------------------------------------- 1 | # Day 14: Reindeer Olympics 2 | 3 | This year is the Reindeer Olympics! Reindeer can fly at high speeds, 4 | but must rest occasionally to recover their energy. Santa would like 5 | to know which of his reindeer is fastest, and so he has them race. 6 | 7 | Reindeer can only either be flying (always at their top speed) or 8 | resting (not moving at all), and always spend whole seconds in either 9 | state. 10 | 11 | For example, suppose you have the following Reindeer: 12 | 13 | **Comet** can fly **14 km/s for 10 seconds**, but then must rest for **127 seconds**. 14 | 15 | **Dancer** can fly **16 km/s for 11 seconds**, but then must rest for **162 seconds**. 16 | 17 | After one second, Comet has gone 14 km, while Dancer has gone 16 km. 18 | After ten seconds, Comet has gone 140 km, while Dancer has gone 160 19 | km. On the eleventh second, Comet begins resting (staying at 140 km), 20 | and Dancer continues on for a total distance of 176 km. On the 12th 21 | second, both reindeer are resting. They continue to rest until the 22 | 138th second, when Comet flies for another ten seconds. On the 174th 23 | second, Dancer flies for another 11 seconds. 24 | 25 | In this example, after the 1000th second, both reindeer are resting, 26 | and Comet is in the lead at **`1120`** km (poor Dancer has only gotten `1056` 27 | km by that point). So, in this situation, Comet would win (if the race 28 | ended at 1000 seconds). 29 | 30 | Given the descriptions of each reindeer (in your puzzle input), after 31 | exactly `2503` seconds, **what distance has the winning reindeer traveled**? 32 | 33 | Your puzzle answer was **`2660`**. 34 | 35 | ## Part Two 36 | 37 | Seeing how reindeer move in bursts, Santa decides he's not pleased 38 | with the old scoring system. 39 | 40 | Instead, at the end of each second, he awards one point to the 41 | reindeer currently in the lead. (If there are multiple reindeer tied 42 | for the lead, they each get one point.) He keeps the traditional 2503 43 | second time limit, of course, as doing otherwise would be entirely 44 | ridiculous. 45 | 46 | Given the example reindeer from above, after the first second, Dancer 47 | is in the lead and gets one point. He stays in the lead until several 48 | seconds into Comet's second burst: after the 140th second, Comet pulls 49 | into the lead and gets his first point. Of course, since Dancer had 50 | been in the lead for the 139 seconds before that, he has accumulated 51 | 139 points by the 140th second. 52 | 53 | After the 1000th second, Dancer has accumulated **`689`** points, while poor 54 | Comet, our old champion, only has `312`. So, with the new scoring 55 | system, Dancer would win (if the race ended at 1000 seconds). 56 | 57 | Again given the descriptions of each reindeer (in your puzzle input), 58 | after exactly `2503` seconds, **how many points does the winning reindeer 59 | have**? 60 | 61 | Your puzzle answer was **`1256`**. 62 | 63 | -------------------------------------------------------------------------------- /src/advent-2017/day07.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day07 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (defn parse-data [lines] 7 | (->> lines 8 | (map #(str "[" % "]")) 9 | (map read-string))) 10 | 11 | (def data (->> (io/resource "2017/day07") 12 | io/reader 13 | line-seq 14 | parse-data)) 15 | 16 | (defn index-data [graph-data] 17 | (reduce 18 | (fn [accum [name [weight] _ & children]] 19 | (-> (reduce #(assoc-in %1 [:parent %2] name) accum children) 20 | (assoc-in [:weights name] weight) 21 | (assoc-in [:children name] (set children)))) 22 | {} 23 | graph-data)) 24 | 25 | (defn tree-root [parent-graph child] 26 | (last (take-while some? (iterate parent-graph child))) ) 27 | 28 | ; part 1 29 | #_(let [{:keys [parent]} (index-data data)] 30 | (tree-root parent (rand-nth (vals parent)))) 31 | 32 | ;; the computational complexity of this problem doesn't merit 33 | ;; memoization of tree traversal 34 | (defn node-total-weight [{:keys [weights children] :as index} node] 35 | (if-let [childs (not-empty (children node))] 36 | (apply + (weights node) (map (partial node-total-weight index) childs)) 37 | (weights node))) 38 | 39 | (defn different-child [children-and-weights] 40 | (let [grouped (group-by second children-and-weights)] 41 | (when (< 1 (count grouped)) 42 | (let [[[[x _]]] (filter #(= 1 (count %)) (vals grouped))] 43 | x)))) 44 | 45 | (defn child-node-and-weight-totals [{:keys [children] :as index} node] 46 | (->> (children node) 47 | (map (juxt identity (partial node-total-weight index))) 48 | (into {}))) 49 | 50 | (defn find-deepest-unequal-child [{:keys [parent children] :as index}] 51 | (->> (tree-root parent (first (vals parent))) 52 | (iterate #(different-child (child-node-and-weight-totals index %))) 53 | (take-while some?) 54 | last)) 55 | 56 | (defn part-2 [data] 57 | (let [{:keys [parent children] :as index} (index-data data) 58 | child-node-weights (partial child-node-and-weight-totals index) 59 | deepest-unequal-node (find-deepest-unequal-child index) 60 | children-total-weight (apply + (vals (child-node-weights deepest-unequal-node))) 61 | target-weight (-> (child-node-weights (parent deepest-unequal-node)) ;; siblings 62 | (dissoc deepest-unequal-node) 63 | vals 64 | first)] 65 | (- target-weight children-total-weight))) 66 | 67 | #_ (time (part-2 data)) 68 | ;;=> 1864 69 | 70 | 71 | (comment 72 | (def test-data 73 | (-> "pbga (66) 74 | xhth (57) 75 | ebii (61) 76 | havc (66) 77 | ktlj (57) 78 | fwft (72) -> ktlj, cntj, xhth 79 | qoyq (66) 80 | padx (45) -> pbga, havc, qoyq 81 | tknk (41) -> ugml, padx, fwft 82 | jptl (61) 83 | ugml (68) -> gyxo, ebii, jptl 84 | gyxo (61) 85 | cntj (57)" 86 | string/split-lines 87 | parse-data)) 88 | ) 89 | -------------------------------------------------------------------------------- /src/advent-2016/day22.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day22 2 | (:require 3 | [advent-2016.utils :as u] 4 | [clojure.java.io :as io] 5 | [clojure.string :as string] 6 | [medley.core :refer [distinct-by]])) 7 | 8 | (defn parse-input [s] 9 | (into (sorted-map) 10 | (comp 11 | (drop 2) 12 | (map #(re-seq #"\d+" %)) 13 | (map u/to-ints) 14 | (map #(take 4 %)) 15 | (map #(partition 2 %)) 16 | (map #(mapv vec %))) 17 | (string/split-lines s))) 18 | 19 | (def data (parse-input (slurp (io/resource "2016/day22")))) 20 | 21 | (def available (partial apply -)) 22 | (def size first) 23 | (def used second) 24 | (def empty-node (comp zero? used)) 25 | 26 | (defn viable-pair? [a b] 27 | (and a b 28 | (not (empty-node a)) 29 | (>= (available b) (used a)))) 30 | 31 | ;; part 1 32 | #_(count 33 | (for [[pos1 data1] data 34 | [pos2 data2] data 35 | :when (not= pos1 pos2) 36 | :when (viable-pair? data1 data2)] 37 | [pos1 pos2])) 38 | ;; => 1045 39 | 40 | (defn view-grid [{:keys [data]}] 41 | (apply map vector (partition 30 (map used (vals data))))) 42 | 43 | (defn pp [d] 44 | (binding [clojure.pprint/*print-right-margin* 200] 45 | (clojure.pprint/pprint d))) 46 | 47 | (defn make-initial [data] 48 | {:data data 49 | :g [(->> data keys (map first) (reduce max)) 0] 50 | :last-move [(ffirst (filter (comp empty-node second) data))]}) 51 | 52 | ;; this is subtle: a preference for up and to the left is helpful 53 | ;; as it provides the very last disambiguation between = score moves 54 | (defn connections [a] 55 | (map #(mapv + a %) [[-1 0] [0 -1] [0 1] [1 0]])) 56 | 57 | (defn possible-moves [{:keys [last-move data]}] 58 | (let [to-pos (first last-move) 59 | to-data (get data to-pos)] 60 | (for [from-pos (connections to-pos) 61 | :let [from-data (get data from-pos)] 62 | :when (viable-pair? from-data to-data)] 63 | [from-pos to-pos]))) 64 | 65 | (defn make-move [{:keys [data g] :as st} [from to]] 66 | (let [from-data (get data from)] 67 | (-> st 68 | (update-in [:data to 1] + (used from-data)) 69 | (assoc-in [:data from 1] 0) 70 | (assoc :g (if (= g from) to g) 71 | :last-move [from to])))) 72 | 73 | (defn next-states [{:keys [last-move] :as st}] 74 | (->> (possible-moves st) 75 | (filter #(not= last-move (reverse %))) 76 | (map (partial make-move st)))) 77 | 78 | (defn distance [from to] 79 | (if (and from to) 80 | (apply + (map #(Math/abs %) (map - from to))) 81 | Integer/MAX_VALUE)) 82 | 83 | (defn score [{:keys [g last-move]}] 84 | [(apply + g) 85 | (distance g (first last-move))]) 86 | 87 | (defn next-level [state] 88 | (first (sort-by score (next-states state)))) 89 | 90 | (defn find-answer2 [limit data] 91 | (->> (iterate next-level (make-initial data)) 92 | (take-while #(not= (:g %) [0 0])) 93 | (take limit) 94 | count)) 95 | 96 | #_(time (find-answer2 500 data)) 97 | ;; => 265 98 | -------------------------------------------------------------------------------- /doc/2015/15.md: -------------------------------------------------------------------------------- 1 | # Day 15: Science for Hungry People 2 | 3 | Today, you set out on the task of perfecting your milk-dunking cookie 4 | recipe. All you have to do is find the right balance of ingredients. 5 | 6 | Your recipe leaves room for exactly 100 teaspoons of ingredients. You 7 | make a list of the **remaining ingredients you could use to finish the 8 | recipe** (your puzzle input) and their **properties per teaspoon**: 9 | 10 | `capacity` (how well it helps the cookie absorb milk) 11 | 12 | `durability` (how well it keeps the cookie intact when full of milk) 13 | 14 | `flavor` (how tasty it makes the cookie) 15 | 16 | `texture` (how it improves the feel of the cookie) 17 | 18 | `calories` (how many calories it adds to the cookie) 19 | 20 | You can only measure ingredients in whole-teaspoon amounts accurately, 21 | and you have to be accurate so you can reproduce your results in the 22 | future. The **total score** of a cookie can be found by adding up each of 23 | the properties (negative totals become `0`) and then multiplying 24 | together everything except calories. 25 | 26 | For instance, suppose you have these two ingredients: 27 | 28 | ``` 29 | Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8 30 | Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3 31 | ``` 32 | 33 | Then, choosing to use `44` teaspoons of butterscotch and `56` teaspoons of 34 | cinnamon (because the amounts of each ingredient must add up to `100`) 35 | would result in a cookie with the following properties: 36 | 37 | ``` 38 | A capacity of 44*-1 + 56*2 = 68 39 | A durability of 44*-2 + 56*3 = 80 40 | A flavor of 44*6 + 56*-2 = 152 41 | A texture of 44*3 + 56*-1 = 76 42 | ``` 43 | 44 | Multiplying these together (`68 * 80 * 152 * 76`, ignoring `calories` for 45 | now) results in a total score of `62842880`, which happens to be the 46 | best score possible given these ingredients. If any properties had 47 | produced a negative total, it would have instead become zero, causing 48 | the whole score to multiply to zero. 49 | 50 | Given the ingredients in your kitchen and their properties, what is 51 | the total score of the highest-scoring cookie you can make? 52 | 53 | Your puzzle answer was **`21367368`**. 54 | 55 | ## Part Two 56 | 57 | Your cookie recipe becomes wildly popular! Someone asks if you can 58 | make another recipe that has exactly 500 calories per cookie (so they 59 | can use it as a meal replacement). Keep the rest of your award-winning 60 | process the same (100 teaspoons, same ingredients, same scoring 61 | system). 62 | 63 | For example, given the ingredients above, if you had instead selected 64 | 40 teaspoons of butterscotch and 60 teaspoons of cinnamon (which still 65 | adds to 100), the total calorie count would be `40*8 + 60*3 = 500`. The 66 | total score would go down, though: only `57600000`, the best you can do 67 | in such trying circumstances. 68 | 69 | Given the ingredients in your kitchen and their properties, what is 70 | the total score of the highest-scoring cookie you can make with a 71 | calorie total of `500`? 72 | 73 | Your puzzle answer was **`1766400`**. -------------------------------------------------------------------------------- /doc/2015/08.md: -------------------------------------------------------------------------------- 1 | # Day 8: Matchsticks 2 | 3 | Space on the sleigh is limited this year, and so Santa will be 4 | bringing his list as a digital copy. He needs to know how much space 5 | it will take up when stored. 6 | 7 | It is common in many programming languages to provide a way to escape 8 | special characters in strings. For example, C, JavaScript, Perl, 9 | Python, and even PHP handle special characters in very similar ways. 10 | 11 | However, it is important to realize the difference between the number 12 | of characters in the code representation of the string literal and the 13 | number of characters in the in-memory string itself. 14 | 15 | For example: 16 | 17 | `""` is 2 characters of code (the two double quotes), but the string 18 | contains zero characters. 19 | 20 | `"abc"` is 5 characters of code, but 3 characters in the string data. 21 | 22 | `"aaa\"aaa"` is 10 characters of code, but the string itself contains 23 | six "a" characters and a single, escaped quote character, for a total 24 | of 7 characters in the string data. 25 | 26 | `"\x27"` is 6 characters of code, but the string itself contains just 27 | one - an apostrophe ('), escaped using hexadecimal notation. 28 | 29 | Santa's list is a file that contains many double-quoted string 30 | literals, one on each line. The only escape sequences used are `\\` 31 | (which represents a single backslash), `\"` (which represents a lone 32 | double-quote character), and `\x` plus two hexadecimal characters (which 33 | represents a single character with that ASCII code). 34 | 35 | Disregarding the whitespace in the file, what is the **number of 36 | characters of code for string literals** minus **the number of characters 37 | in memory for the values of the strings** in total for the entire file? 38 | 39 | For example, given the four strings above, the total number of 40 | characters of string code `(2 + 5 + 10 + 6 = 23)` minus the total number 41 | of characters in memory for string values `(0 + 3 + 7 + 1 = 11)` is `23 - 42 | 11 = 12`. 43 | 44 | Your puzzle answer was **`1342`**. 45 | 46 | ## Part Two 47 | 48 | Now, let's go the other way. In addition to finding the number of 49 | characters of code, you should now encode each code representation as 50 | a new string and find the number of characters of the new encoded 51 | representation, including the surrounding double quotes. 52 | 53 | For example: 54 | 55 | `""` encodes to `"\"\""`, an increase from 2 characters to 6. 56 | 57 | `"abc"` encodes to `"\"abc\""`, an increase from 5 characters to 9. 58 | 59 | `"aaa\"aaa"` encodes to `"\"aaa\\\"aaa\""`, an increase from 10 characters to 16. 60 | 61 | `"\x27"` encodes to `"\"\\x27\""`, an increase from 6 characters to 11. 62 | 63 | Your task is to find the total number of characters to represent the 64 | newly encoded strings minus the number of characters of code in each 65 | original string literal. For example, for the strings above, the total 66 | encoded length `(6 + 9 + 16 + 11 = 42)` minus the characters in the 67 | original code representation (23, just like in the first part of this 68 | puzzle) is `42 - 23 = 19`. 69 | 70 | Your puzzle answer was **`2074`**. -------------------------------------------------------------------------------- /doc/2015/13.md: -------------------------------------------------------------------------------- 1 | # Day 13: Knights of the Dinner Table 2 | 3 | In years past, the holiday feast with your family hasn't gone so well. 4 | Not everyone gets along! This year, you resolve, will be different. 5 | You're going to find the optimal seating arrangement and avoid all 6 | those awkward conversations. 7 | 8 | You start by writing up a list of everyone invited and the amount 9 | their happiness would increase or decrease if they were to find 10 | themselves sitting next to each other person. You have a circular 11 | table that will be just big enough to fit everyone comfortably, and so 12 | each person will have exactly two neighbors. 13 | 14 | For example, suppose you have only four attendees planned, and you 15 | calculate their potential happiness as follows: 16 | 17 | ``` 18 | Alice would gain 54 happiness units by sitting next to Bob. 19 | Alice would lose 79 happiness units by sitting next to Carol. 20 | Alice would lose 2 happiness units by sitting next to David. 21 | Bob would gain 83 happiness units by sitting next to Alice. 22 | Bob would lose 7 happiness units by sitting next to Carol. 23 | Bob would lose 63 happiness units by sitting next to David. 24 | Carol would lose 62 happiness units by sitting next to Alice. 25 | Carol would gain 60 happiness units by sitting next to Bob. 26 | Carol would gain 55 happiness units by sitting next to David. 27 | David would gain 46 happiness units by sitting next to Alice. 28 | David would lose 7 happiness units by sitting next to Bob. 29 | David would gain 41 happiness units by sitting next to Carol. 30 | ``` 31 | 32 | Then, if you seat Alice next to David, Alice would lose 2 happiness 33 | units (because David talks so much), but David would gain 46 happiness 34 | units (because Alice is such a good listener), for a total change of 35 | 44. 36 | 37 | If you continue around the table, you could then seat Bob next to 38 | Alice (Bob gains 83, Alice gains 54). Finally, seat Carol, who sits 39 | next to Bob (Carol gains 60, Bob loses 7) and David (Carol gains 55, 40 | David gains 41). The arrangement looks like this: 41 | 42 | ``` 43 | +41 +46 44 | +55 David -2 45 | Carol Alice 46 | +60 Bob +54 47 | -7 +83 48 | ``` 49 | 50 | After trying every other seating arrangement in this hypothetical 51 | scenario, you find that this one is the most optimal, with a total 52 | change in happiness of 330. 53 | 54 | What is the total change in happiness for the optimal seating 55 | arrangement of the actual guest list? 56 | 57 | Your puzzle answer was **`733`**. 58 | 59 | ## Part Two 60 | 61 | In all the commotion, you realize that you forgot to seat yourself. At 62 | this point, you're pretty apathetic toward the whole thing, and your 63 | happiness wouldn't really go up or down regardless of who you sit next 64 | to. You assume everyone else would be just as ambivalent about sitting 65 | next to you, too. 66 | 67 | So, add yourself to the list, and give all happiness relationships 68 | that involve you a score of 0. 69 | 70 | What is the total change in happiness for the optimal seating 71 | arrangement that actually includes yourself? 72 | 73 | Your puzzle answer was **`725`**. -------------------------------------------------------------------------------- /doc/2015/19.md: -------------------------------------------------------------------------------- 1 | # Day 19: Medicine for Rudolph 2 | 3 | Rudolph the Red-Nosed Reindeer is sick! His nose isn't shining very 4 | brightly, and he needs medicine. 5 | 6 | Red-Nosed Reindeer biology isn't similar to regular reindeer biology; 7 | Rudolph is going to need custom-made medicine. Unfortunately, 8 | Red-Nosed Reindeer chemistry isn't similar to regular reindeer 9 | chemistry, either. 10 | 11 | The North Pole is equipped with a Red-Nosed Reindeer nuclear 12 | fusion/fission plant, capable of constructing any Red-Nosed Reindeer 13 | molecule you need. It works by starting with some input molecule and 14 | then doing a series of replacements, one per step, until it has the 15 | right molecule. 16 | 17 | However, the machine has to be calibrated before it can be used. 18 | Calibration involves determining the number of molecules that can be 19 | generated in one step from a given starting point. 20 | 21 | For example, imagine a simpler machine that supports only the 22 | following replacements: 23 | 24 | ``` 25 | H => HO 26 | H => OH 27 | O => HH 28 | ``` 29 | 30 | Given the replacements above and starting with `HOH`, the following 31 | molecules could be generated: 32 | 33 | ``` 34 | HOOH (via H => HO on the first H). 35 | HOHO (via H => HO on the second H). 36 | OHOH (via H => OH on the first H). 37 | HOOH (via H => OH on the second H). 38 | HHHH (via O => HH). 39 | ``` 40 | 41 | So, in the example above, there are 4 distinct molecules (not five, 42 | because `HOOH` appears twice) after one replacement from `HOH`. Santa's 43 | favorite molecule, `HOHOHO`, can become 7 distinct molecules (over nine 44 | replacements: six from `H`, and three from `O`). 45 | 46 | The machine replaces without regard for the surrounding characters. 47 | For example, given the string `H2O`, the transition `H => OO` would 48 | result in `OO2O`. 49 | 50 | Your puzzle input describes all of the possible replacements and, at 51 | the bottom, the medicine molecule for which you need to calibrate the 52 | machine. How many distinct molecules can be created after all the 53 | different ways you can do one replacement on the medicine molecule? 54 | 55 | Your puzzle answer was **`535`**. 56 | 57 | ## Part Two 58 | 59 | Now that the machine is calibrated, you're ready to begin molecule 60 | fabrication. 61 | 62 | Molecule fabrication always begins with just a single electron, e, and 63 | applying replacements one at a time, just like the ones during 64 | calibration. 65 | 66 | For example, suppose you have the following replacements: 67 | 68 | ``` 69 | e => H 70 | e => O 71 | H => HO 72 | H => OH 73 | O => HH 74 | ``` 75 | 76 | If you'd like to make `HOH`, you start with e, and then make the 77 | following replacements: 78 | 79 | ``` 80 | e => O to get O 81 | O => HH to get HH 82 | H => OH (on the second H) to get HOH 83 | ``` 84 | 85 | So, you could make `HOH` after 3 steps. Santa's favorite molecule, 86 | `HOHOHO`, can be made in 6 steps. 87 | 88 | How long will it take to make the medicine? Given the available 89 | replacements and the medicine molecule in your puzzle input, what is 90 | the fewest number of steps to go from e to the medicine molecule? 91 | 92 | Your puzzle answer was **`212`**. -------------------------------------------------------------------------------- /src/advent-2016/day21.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day21 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def instr-data 7 | (->> (slurp (io/resource "2016/day21")) 8 | (string/split-lines) 9 | (map #(read-string (str "[" % "]"))))) 10 | 11 | ;; operations 12 | (defn swap-letter [s x y] (replace {x y y x} s)) 13 | 14 | (defn swap-position [s x y] (swap-letter s (nth s x) (nth s y))) 15 | 16 | (defn rotate-left [s n] (take (count s) (drop n (cycle s)))) 17 | 18 | (defn rotate-right [s n] (reverse (rotate-left (reverse s) n))) 19 | 20 | (defn move-position [s x y] 21 | (let [l (nth s x) 22 | res (remove #(= l %) s)] 23 | (concat (take y res) (cons l (drop y res))))) 24 | 25 | (defn reverse-positions [s x y] 26 | (let [part-size (inc (- y x))] 27 | (concat (take x s) 28 | (reverse (take part-size (drop x s))) 29 | (drop (+ x part-size) s)))) 30 | 31 | (defn rotate-based [s l] 32 | (let [i (.indexOf s l)] 33 | (rotate-right s (+ (inc i) (if (>= i 4) 1 0))))) 34 | 35 | ;; parse args 36 | (def get-numbers (partial filter integer?)) 37 | 38 | (defn get-letters [instr] 39 | (->> (map str instr) 40 | (filter #(= 1 (count %))) 41 | (map first))) 42 | 43 | ;; interpret 44 | (defn scramble-apply-instr [s instr] 45 | (let [s (vec s)] 46 | (condp = (take 2 instr) 47 | '[swap position] (apply swap-position s (get-numbers instr)) 48 | '[swap letter] (apply swap-letter s (get-letters instr)) 49 | '[move position] (apply move-position s (get-numbers instr)) 50 | '[rotate left] (apply rotate-left s (get-numbers instr)) 51 | '[rotate right] (apply rotate-right s (get-numbers instr)) 52 | '[rotate based] (apply rotate-based s (get-letters instr)) 53 | '[reverse positions] (apply reverse-positions s (get-numbers instr))))) 54 | 55 | (defn scramble [s instrs] 56 | (reduce scramble-apply-instr s instrs)) 57 | 58 | ;; part 1 59 | #_(apply str (scramble "abcdefgh" instr-data)) 60 | ;; => gbhafcde 61 | 62 | ;; not invertable so search 63 | (defn inv-rotate-based [s l] 64 | (->> (map #(rotate-left s %) (range (count s))) 65 | (filter #(= (rotate-based % l) s)) 66 | first)) 67 | 68 | (defn un-scramble-apply-instr [s instr] 69 | (let [s (vec s)] 70 | (condp = (take 2 instr) 71 | '[swap position] (apply swap-position s (reverse (get-numbers instr))) 72 | '[swap letter] (apply swap-letter s (reverse (get-letters instr))) 73 | '[move position] (apply move-position s (reverse (get-numbers instr))) 74 | '[rotate left] (apply rotate-right s (get-numbers instr)) 75 | '[rotate right] (apply rotate-left s (get-numbers instr)) 76 | '[rotate based] (apply inv-rotate-based s (get-letters instr)) 77 | '[reverse positions] (apply reverse-positions s (get-numbers instr))))) 78 | 79 | (defn un-scramble [s instrs] 80 | (reduce un-scramble-apply-instr s (reverse instrs))) 81 | 82 | ;; part 2 83 | #_(apply str (un-scramble "fbgdceah" instr-data)) 84 | ;; => "bcfaegdh" 85 | -------------------------------------------------------------------------------- /src/advent-2017/day24.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day24 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data 7 | (->> (io/resource "2017/day24") 8 | slurp)) 9 | 10 | (defn make-index [raw-data] 11 | (->> (string/split-lines raw-data) 12 | (map #(string/replace % "/" " ")) 13 | (map #(format "[%s]" %)) 14 | (mapv read-string) 15 | (reduce (fn [accum [h t :as part]] 16 | (-> accum 17 | (update h (fnil conj #{}) part) 18 | (update t (fnil conj #{}) part))) 19 | {}))) 20 | 21 | ;; an indexed version of the data for constant time look ups 22 | (def index (make-index data)) 23 | 24 | (defn remove-part [parts-index [h t :as part]] 25 | (-> parts-index 26 | (update h disj part) 27 | (update t disj part))) 28 | 29 | (defn strength [parts] 30 | (reduce + 0 (flatten parts))) 31 | 32 | (defn other-member [h? [h t]] 33 | (if (= h? h) t h)) 34 | 35 | ;; ignores partial briges as they don't matter for solution 36 | (defn all-bridges [parts-index main-part tail-part] 37 | (if (empty? (parts-index tail-part)) 38 | [[main-part]] 39 | (->> (parts-index tail-part) 40 | (mapcat #(all-bridges (remove-part parts-index %) % (other-member tail-part %))) 41 | (mapv #(cons main-part %))))) 42 | 43 | ;; part 1 44 | #_(with-redefs [all-bridges (memoize all-bridges)] 45 | (time (->> (all-bridges index [0 0] 0) 46 | (map strength) 47 | (reduce max)))) 48 | ;; => 1906 49 | ;; Elapsed time: 21145.979859 msecs 50 | 51 | ;; part 2 52 | #_(with-redefs [all-bridges (memoize all-bridges)] 53 | (time 54 | (let [bridges (all-bridges index [0 0] 0) 55 | max-length (reduce max (map count bridges))] 56 | (->> bridges 57 | (filter #(= (count %) max-length)) 58 | (map strength) 59 | (reduce max))))) 60 | ;; => 1824 61 | ;; Elapsed time: 3697.887612 msec 62 | 63 | 64 | 65 | ;; A tree-seq based solution 66 | ;; it collects the needed totals as it travels 67 | 68 | (defn branch? [[parts-index available-pin strength-total length]] 69 | (parts-index available-pin)) 70 | 71 | (defn children [[parts-index available-pin strength-total length]] 72 | (when-let [childs (parts-index available-pin)] 73 | (map 74 | (fn [next-part] 75 | [(remove-part parts-index next-part) 76 | (other-member available-pin next-part) 77 | (+ strength-total (apply + next-part)) 78 | (inc length)]) 79 | childs))) 80 | 81 | ;; part 1 82 | #_(->> (tree-seq branch? children [index 0 0 0]) 83 | (map #(nth % 2)) 84 | (reduce max) 85 | time) 86 | ;; => 1906 87 | ;; Elapsed time: 4472.040553 msecs 88 | 89 | ;; part 2 90 | #_(time 91 | (let [bridges (tree-seq branch? children [index 0 0 0]) 92 | max-length (reduce max (map last bridges))] 93 | (->> bridges 94 | (filter #(= (last %) max-length)) 95 | (map #(nth % 3)) 96 | (reduce max)))) 97 | ;; => 1824 98 | ;; Elapsed time: 6435.686022 msecs 99 | 100 | -------------------------------------------------------------------------------- /src/advent-2018/day07.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day07 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [medley.core :as med])) 6 | 7 | #_(remove-ns 'advent-2018.day07) 8 | 9 | (defn parse [s] 10 | (->> (string/split-lines s) 11 | (mapv #(vec (map (comp char first) (rest (re-seq #"[A-Z]" %))))))) 12 | 13 | (def ex (parse "Step C must be finished before step A can begin. 14 | Step C must be finished before step F can begin. 15 | Step A must be finished before step B can begin. 16 | Step A must be finished before step D can begin. 17 | Step B must be finished before step E can begin. 18 | Step D must be finished before step E can begin. 19 | Step F must be finished before step E can begin.")) 20 | 21 | (def data (parse (slurp (io/resource "2018/day07")))) 22 | 23 | (defn relation-map [d] 24 | (apply 25 | merge-with 26 | conj 27 | (into {} (map (juxt first (constantly #{}))) d) 28 | (map #(apply hash-map %) d))) 29 | 30 | (def parents relation-map) 31 | 32 | (defn children [d] (relation-map (map reverse d))) 33 | 34 | (defn roots [data] 35 | (let [cm (children data)] 36 | (into (sorted-set-by #(< (int %1) (int %2))) 37 | (filter (complement cm) 38 | (distinct (flatten data)))))) 39 | 40 | (defn order [parents prereqs accum stack] 41 | (if (empty? stack) 42 | accum 43 | (let [next (->> stack 44 | (filter #(empty? (reduce disj (prereqs %) accum))) 45 | first) 46 | accum (conj accum next)] 47 | (recur parents prereqs accum 48 | (reduce disj (into stack (parents next)) accum))))) 49 | 50 | (defn solve-1 [d] 51 | (apply str (order (parents d) (children d) [] (set (roots d))))) 52 | 53 | #_(= (solve-1 data) 54 | "CHILFNMORYKGAQXUVBZPSJWDET") 55 | 56 | (def ^:dynamic *slots* 2) 57 | (def ^:dynamic *seconds-offset* 0) 58 | 59 | (defn seconds [c] 60 | (+ (- (int c) 64) 61 | *seconds-offset*)) 62 | 63 | (defn work-second [{:keys [prereqs available completed workers] :as state}] 64 | (let [next-workers (med/map-vals dec workers) 65 | complete (keys (med/filter-vals #(zero? %) next-workers)) 66 | next-workers (reduce dissoc next-workers complete) 67 | next-completed (concat completed complete) 68 | next-ones (take (- *slots* (count next-workers)) 69 | (filter 70 | #(empty? (reduce disj (prereqs %) next-completed)) 71 | available))] 72 | (assoc state 73 | :available (remove (set next-ones) available) 74 | :completed next-completed 75 | :workers (reduce #(assoc %1 %2 (seconds %2)) next-workers 76 | next-ones)))) 77 | 78 | (defn solve-2 [n-workers offset data] 79 | (binding [*slots* n-workers 80 | *seconds-offset* offset] 81 | (count (take-while 82 | (comp not-empty :workers) 83 | (rest (iterate work-second 84 | {:prereqs (children data) 85 | :available (solve-1 data) 86 | :completed [] 87 | :workers {}})))))) 88 | 89 | #_(solve-2 5 60 data) 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/advent-2016/day23.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day23 2 | (:require 3 | [advent-2016.utils :as u] 4 | [clojure.java.io :as io] 5 | [clojure.string :as string])) 6 | 7 | (defn parse-instructions [s] 8 | (->> s 9 | (string/split-lines) 10 | (map #(str "[" % "]")) 11 | (map read-string) 12 | vec)) 13 | 14 | (def input (parse-instructions (slurp (io/resource "2016/day23")))) 15 | 16 | (defn reg-or-val [s reg-val] (if (symbol? reg-val) (get s reg-val) reg-val)) 17 | 18 | (defn update-reg [s reg f] 19 | (-> s (update reg f) (update :pos inc))) 20 | 21 | (def reg? '#{a b c d}) 22 | (def reg-or-val? #(or (reg? %) (integer? %))) 23 | 24 | (defmulti trans (fn [_ b] (first b))) 25 | (defmethod trans 'inc [s [_ reg]] 26 | (assert (reg? reg)) 27 | (update-reg s reg inc)) 28 | 29 | (defmethod trans 'dec [s [_ reg]] 30 | (assert (reg? reg)) 31 | (update-reg s reg dec)) 32 | 33 | (defmethod trans 'cpy [s [_ reg-val reg]] 34 | (assert (and (reg-or-val? reg-val) (reg? reg))) 35 | (-> s (assoc reg (reg-or-val s reg-val)) (update :pos inc))) 36 | 37 | (defmethod trans 'jnz [s [_ reg-val steps]] 38 | (assert (and (reg-or-val? reg-val) (reg-or-val? steps))) 39 | (update s :pos + 40 | (if-not (zero? (reg-or-val s reg-val)) 41 | (reg-or-val s steps) 42 | 1))) 43 | 44 | (defn tgl-inst [inst] 45 | (update-in inst [0] 46 | #(if (= 1 (count (rest inst))) 47 | (if (= 'inc %) 'dec 'inc) 48 | (if (= 'jnz %) 'cpy 'jnz)))) 49 | 50 | (defmethod trans 'tgl [{:keys [pos instr] :as s} [_ reg-val]] 51 | (assert (reg-or-val? reg-val)) 52 | (let [pos-to-change (+ pos (reg-or-val s reg-val))] 53 | (if (get instr pos-to-change nil) 54 | (-> s 55 | (update-in [:instr pos-to-change] tgl-inst) 56 | (update :pos inc)) 57 | (update s :pos inc)))) 58 | 59 | (defn start-state [instructions] 60 | (assoc '{a 0 b 0 c 0 d 0 :pos 0} 61 | :instr (vec instructions))) 62 | 63 | ;; for part 2 64 | 65 | (defn multiply-instructions? [instructions] 66 | (= '[[inc a] 67 | [dec c] 68 | [jnz c -2] 69 | [dec d] 70 | [jnz d -5]] 71 | (take 5 instructions))) 72 | 73 | (defn multiply [st] 74 | (-> st 75 | (update 'a + (* (get st 'c) (get st 'd))) 76 | (assoc 'c 0) 77 | (assoc 'd 0) 78 | (update :pos + 5))) 79 | 80 | (defn run-prog [start-state] 81 | (take-while (comp not nil?) 82 | (iterate (fn [{:keys [pos instr] :as s}] 83 | (when-let [inst (get instr pos nil)] 84 | (try 85 | (if (multiply-instructions? (drop pos instr)) 86 | (multiply s) 87 | (trans s inst)) 88 | (catch Throwable e 89 | (println "Skipping " (pr-str inst)) 90 | (update s :pos inc) 91 | #_(throw (ex-info "error" {:inst inst :st s})))))) 92 | start-state))) 93 | 94 | ;; part 1 95 | #_ (time (last (run-prog (assoc (start-state input) 'a 7)))) 96 | ;; => 12654 97 | 98 | ;; part 2 99 | #_ (time (last (run-prog (assoc (start-state input) 'a 12)))) 100 | ;; => 479009214 101 | -------------------------------------------------------------------------------- /src/advent-2018/day06.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2018.day06 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string] 5 | [clojure.math.combinatorics :as combo] 6 | [medley.core :as med])) 7 | 8 | (defn parse [s] 9 | (->> (str "(" s ")") 10 | read-string 11 | (partition 2))) 12 | 13 | (def data (parse (slurp (io/resource "2018/day06")))) 14 | 15 | (def example (parse 16 | "1, 1 17 | 1, 6 18 | 8, 3 19 | 3, 4 20 | 5, 5 21 | 8, 9")) 22 | 23 | (def min-max (juxt #(apply min %) #(apply max %))) 24 | 25 | (defn bounds [points] 26 | (map vector 27 | (min-max (map first points)) 28 | (min-max (map second points)))) 29 | 30 | (defn distance [[x y] [a b]] 31 | (+ (Math/abs (- x a)) 32 | (Math/abs (- y b)))) 33 | 34 | (defn edge-positions [[x y] [x1 y1]] 35 | (distinct 36 | (concat (map vector 37 | (range x x1) 38 | (repeat y)) 39 | (map vector 40 | (range x x1) 41 | (repeat y1)) 42 | (map vector 43 | (repeat x) 44 | (range y y1)) 45 | (map vector 46 | (repeat x) 47 | (range y y1))))) 48 | 49 | (defn closest-point-or-tie [points point] 50 | (let [res (sort-by second (map (juxt identity #(distance point %)) 51 | points))] 52 | (if (apply = (map second (take 2 res))) 53 | :tie 54 | (ffirst res)))) 55 | 56 | (defn closest-map [nodes positions] 57 | (reduce (fn [accum p] 58 | (assoc accum p (closest-point-or-tie nodes p))) 59 | {} positions)) 60 | 61 | (defn solve-1 [nodes] 62 | (let [[[x1 y1] [x2 y2]] (bounds nodes) 63 | positions (combo/cartesian-product 64 | (range x1 (inc x2)) 65 | (range y1 (inc y2))) 66 | edge-points 67 | (edge-positions [(- x1 5) (- y1 6)] 68 | [(+ x2 5) (+ y2 6)]) 69 | result (closest-map nodes positions) 70 | edge-result (closest-map nodes edge-points)] 71 | (second 72 | (first (sort-by 73 | second > 74 | (apply dissoc 75 | (->> result vals frequencies) 76 | (-> edge-result vals set))))))) 77 | 78 | ;; part 1 79 | #_(time (solve-1 data)) 80 | 81 | (defn distance-to-all [point points] 82 | {:pre [point points]} 83 | (apply + (map (partial distance point) points))) 84 | 85 | (def directions [[0 -1] [0 1] [-1 0] [1 0]]) 86 | 87 | (defn direction-search [valid? seen-set next-set] 88 | (if (empty? next-set) 89 | seen-set 90 | (let [point (first next-set)] 91 | (if (and (not (seen-set point)) 92 | (valid? point)) 93 | (recur valid? 94 | (conj seen-set point) 95 | (into next-set 96 | (filter 97 | (complement seen-set) 98 | (mapv #(map + point %1) 99 | directions)))) 100 | (recur valid? seen-set (disj next-set point)))))) 101 | 102 | (defn solve2 [limit d] 103 | (let [pred? #(< (distance-to-all % d) limit)] 104 | (direction-search pred? #{} 105 | #{(first (filter pred? d))}))) 106 | 107 | ;; part 2 108 | #_(time (count (solve2 10000 data))) 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /resources/2016/day21: -------------------------------------------------------------------------------- 1 | rotate left 2 steps 2 | rotate right 0 steps 3 | rotate based on position of letter a 4 | rotate based on position of letter f 5 | swap letter g with letter b 6 | rotate left 4 steps 7 | swap letter e with letter f 8 | reverse positions 1 through 6 9 | swap letter b with letter d 10 | swap letter b with letter c 11 | move position 7 to position 5 12 | rotate based on position of letter h 13 | swap position 6 with position 5 14 | reverse positions 2 through 7 15 | move position 5 to position 0 16 | rotate based on position of letter e 17 | rotate based on position of letter c 18 | rotate right 4 steps 19 | reverse positions 3 through 7 20 | rotate left 4 steps 21 | rotate based on position of letter f 22 | rotate left 3 steps 23 | swap letter d with letter a 24 | swap position 0 with position 1 25 | rotate based on position of letter a 26 | move position 3 to position 6 27 | swap letter e with letter g 28 | move position 6 to position 2 29 | reverse positions 1 through 2 30 | rotate right 1 step 31 | reverse positions 0 through 6 32 | swap letter e with letter h 33 | swap letter f with letter a 34 | rotate based on position of letter a 35 | swap position 7 with position 4 36 | reverse positions 2 through 5 37 | swap position 1 with position 2 38 | rotate right 0 steps 39 | reverse positions 5 through 7 40 | rotate based on position of letter a 41 | swap letter f with letter h 42 | swap letter a with letter f 43 | rotate right 4 steps 44 | move position 7 to position 5 45 | rotate based on position of letter a 46 | reverse positions 0 through 6 47 | swap letter g with letter c 48 | reverse positions 5 through 6 49 | reverse positions 3 through 5 50 | reverse positions 4 through 6 51 | swap position 3 with position 4 52 | move position 4 to position 2 53 | reverse positions 3 through 4 54 | rotate left 0 steps 55 | reverse positions 3 through 6 56 | swap position 6 with position 7 57 | reverse positions 2 through 5 58 | swap position 2 with position 0 59 | reverse positions 0 through 3 60 | reverse positions 3 through 5 61 | rotate based on position of letter d 62 | move position 1 to position 2 63 | rotate based on position of letter c 64 | swap letter e with letter a 65 | move position 4 to position 1 66 | reverse positions 5 through 7 67 | rotate left 1 step 68 | rotate based on position of letter h 69 | reverse positions 1 through 7 70 | rotate based on position of letter f 71 | move position 1 to position 5 72 | reverse positions 1 through 4 73 | rotate based on position of letter a 74 | swap letter b with letter c 75 | rotate based on position of letter g 76 | swap letter a with letter g 77 | swap position 1 with position 0 78 | rotate right 2 steps 79 | rotate based on position of letter f 80 | swap position 5 with position 4 81 | move position 1 to position 0 82 | swap letter f with letter b 83 | swap letter f with letter h 84 | move position 1 to position 7 85 | swap letter c with letter b 86 | reverse positions 5 through 7 87 | rotate left 6 steps 88 | swap letter d with letter b 89 | rotate left 3 steps 90 | swap position 1 with position 4 91 | rotate based on position of letter a 92 | rotate based on position of letter a 93 | swap letter b with letter c 94 | swap letter e with letter f 95 | reverse positions 4 through 7 96 | rotate right 0 steps 97 | reverse positions 2 through 3 98 | rotate based on position of letter a 99 | reverse positions 1 through 4 100 | rotate right 1 step -------------------------------------------------------------------------------- /doc/2015/21.md: -------------------------------------------------------------------------------- 1 | # Day 21: RPG Simulator 20XX 2 | 3 | Little Henry Case got a new video game for Christmas. It's an RPG, and 4 | he's stuck on a boss. He needs to know what equipment to buy at the 5 | shop. He hands you the controller. 6 | 7 | In this game, the player (you) and the enemy (the boss) take turns 8 | attacking. The player always goes first. Each attack reduces the 9 | opponent's hit points by at least `1`. The first character at or below `0` 10 | hit points loses. 11 | 12 | Damage dealt by an attacker each turn is equal to the attacker's 13 | damage score minus the defender's armor score. An attacker always does 14 | at least 1 damage. So, if the attacker has a damage score of `8`, and 15 | the defender has an armor score of `3`, the defender loses `5` hit points. 16 | If the defender had an armor score of `300`, the defender would still 17 | lose `1` hit point. 18 | 19 | Your damage score and armor score both start at zero. They can be 20 | increased by buying items in exchange for gold. You start with no 21 | items and have as much gold as you need. Your total damage or armor is 22 | equal to the sum of those stats from all of your items. You have `100` 23 | hit points. 24 | 25 | Here is what the item shop is selling: 26 | 27 | ``` 28 | Weapons: Cost Damage Armor 29 | Dagger 8 4 0 30 | Shortsword 10 5 0 31 | Warhammer 25 6 0 32 | Longsword 40 7 0 33 | Greataxe 74 8 0 34 | 35 | Armor: Cost Damage Armor 36 | Leather 13 0 1 37 | Chainmail 31 0 2 38 | Splintmail 53 0 3 39 | Bandedmail 75 0 4 40 | Platemail 102 0 5 41 | 42 | Rings: Cost Damage Armor 43 | Damage +1 25 1 0 44 | Damage +2 50 2 0 45 | Damage +3 100 3 0 46 | Defense +1 20 0 1 47 | Defense +2 40 0 2 48 | Defense +3 80 0 3 49 | ``` 50 | 51 | You must buy exactly one weapon; no dual-wielding. Armor is optional, 52 | but you can't use more than one. You can buy 0-2 rings (at most one 53 | for each hand). You must use any items you buy. The shop only has one 54 | of each item, so you can't buy, for example, two rings of Damage +3. 55 | 56 | For example, suppose you have `8` hit points, `5` damage, and `5` armor, and 57 | that the boss has `12` hit points, `7` damage, and `2` armor: 58 | 59 | ``` 60 | The player deals 5-2 = 3 damage; the boss goes down to 9 hit points. 61 | The boss deals 7-5 = 2 damage; the player goes down to 6 hit points. 62 | The player deals 5-2 = 3 damage; the boss goes down to 6 hit points. 63 | The boss deals 7-5 = 2 damage; the player goes down to 4 hit points. 64 | The player deals 5-2 = 3 damage; the boss goes down to 3 hit points. 65 | The boss deals 7-5 = 2 damage; the player goes down to 2 hit points. 66 | The player deals 5-2 = 3 damage; the boss goes down to 0 hit points. 67 | ``` 68 | 69 | In this scenario, the player wins! (Barely.) 70 | 71 | You have **100 hit points**. The boss's actual stats are in your puzzle 72 | input. What is **the least amount of gold you can spend** and still win 73 | the fight? 74 | 75 | Your puzzle answer was **`111`**. 76 | 77 | ## Part Two 78 | 79 | Turns out the shopkeeper is working with the boss, and can persuade 80 | you to buy whatever items he wants. The other rules still apply, and 81 | he still only has one of each item. 82 | 83 | What is the **most** amount of gold you can spend and still **lose** the fight? 84 | 85 | Your puzzle answer was **`188`**. -------------------------------------------------------------------------------- /src/advent-2017/day22.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day22 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def data 7 | (->> (io/resource "2017/day22") 8 | io/reader 9 | line-seq 10 | vec)) 11 | 12 | (def test-data ["..#" "#.." "..."]) 13 | 14 | (defn start-board [data'] 15 | (assert (= (count data') (count (first data')))) 16 | {:board 17 | (into {} 18 | (for [y (range (count data')) 19 | x (range (count data'))] 20 | [[y x] (str (get-in data' [y x]))])) 21 | ;; initial position center 22 | :position 23 | (let [x (int (/ (count data') 2))] 24 | [x x]) 25 | ;; initial direction up 26 | :direction 0}) 27 | 28 | (def directions [[-1 0] [0 1] [1 0] [0 -1]]) 29 | 30 | (def turn-right (comp #(mod % 4) inc)) 31 | (def turn-left (comp #(mod % 4) dec)) 32 | 33 | (defn turn [{:keys [board position] :as state}] 34 | (->> (if (= "#" (get board position)) turn-right turn-left) 35 | (update state :direction))) 36 | 37 | (defn infect-node [{:keys [board position] :as state}] 38 | (if (= "#" (get board position)) 39 | (update state :board assoc position ".") 40 | (-> state 41 | (update :board assoc position "#") 42 | (update :infect-count (fnil inc 0))))) 43 | 44 | (defn move-forward [{:keys [direction] :as state}] 45 | (update state :position #(mapv + % (get directions direction)))) 46 | 47 | ;; we really have to render the board to verify that the state machine is working 48 | (defn render-board [{:keys [board position]}] 49 | (let [min-coord (apply min (flatten (cons position (keys board)))) 50 | max-coord (apply max (flatten (cons position (keys board))))] 51 | (->> (for [y (range min-coord (inc max-coord)) 52 | x (range min-coord (inc max-coord))] 53 | [y x]) 54 | (map #(if (= % position) 55 | (str "[" (board % ".") "]") 56 | (str " " (board % ".") " "))) 57 | (partition (- (inc max-coord) min-coord)) 58 | (map #(apply str %)) 59 | (mapv println)) 60 | nil)) 61 | 62 | ;; verify that everything looks right 63 | #_(render-board (nth (iterate (comp move-forward infect-node turn) (start-board test-data)) 7)) 64 | 65 | ;; part 1 66 | #_ (time (-> (iterate (comp move-forward infect-node turn) (start-board data)) 67 | (nth 10000) 68 | :infect-count)) 69 | ;; 5240 70 | ;; Elapsed time: 41.665846 msecs 71 | 72 | ;; well ... we have a whole new state machine for part 2 woohoo! 73 | 74 | (def state-transition 75 | {nil "W" 76 | "." "W" 77 | "W" "#" 78 | "#" "F" 79 | "F" "."}) 80 | 81 | (defn turn-2 [{:keys [board position] :as state}] 82 | (condp = (get board position ".") 83 | "." (update state :direction turn-left) 84 | "#" (update state :direction turn-right) 85 | "W" state 86 | "F" (update state :direction (comp turn-right turn-right)))) 87 | 88 | (defn update-node [{:keys [board position] :as state}] 89 | (cond-> state 90 | (= "W" (board position)) (update :infect-count (fnil inc 0)) 91 | :else (update-in [:board position] state-transition))) 92 | 93 | ;; render the board 94 | #_(render-board (nth (iterate (comp move-forward update-node turn-2) (start-board test-data)) 5)) 95 | 96 | ;; part 2 97 | #_(time (-> (iterate (comp move-forward update-node turn-2) (start-board start-data)) 98 | (nth n) 99 | :infect-count)) 100 | ;; => 2512144 101 | ;; Elapsed time: 45868.547871 msecs 102 | 103 | 104 | -------------------------------------------------------------------------------- /resources/2015/prob13: -------------------------------------------------------------------------------- 1 | Alice would gain 2 happiness units by sitting next to Bob. 2 | Alice would gain 26 happiness units by sitting next to Carol. 3 | Alice would lose 82 happiness units by sitting next to David. 4 | Alice would lose 75 happiness units by sitting next to Eric. 5 | Alice would gain 42 happiness units by sitting next to Frank. 6 | Alice would gain 38 happiness units by sitting next to George. 7 | Alice would gain 39 happiness units by sitting next to Mallory. 8 | Bob would gain 40 happiness units by sitting next to Alice. 9 | Bob would lose 61 happiness units by sitting next to Carol. 10 | Bob would lose 15 happiness units by sitting next to David. 11 | Bob would gain 63 happiness units by sitting next to Eric. 12 | Bob would gain 41 happiness units by sitting next to Frank. 13 | Bob would gain 30 happiness units by sitting next to George. 14 | Bob would gain 87 happiness units by sitting next to Mallory. 15 | Carol would lose 35 happiness units by sitting next to Alice. 16 | Carol would lose 99 happiness units by sitting next to Bob. 17 | Carol would lose 51 happiness units by sitting next to David. 18 | Carol would gain 95 happiness units by sitting next to Eric. 19 | Carol would gain 90 happiness units by sitting next to Frank. 20 | Carol would lose 16 happiness units by sitting next to George. 21 | Carol would gain 94 happiness units by sitting next to Mallory. 22 | David would gain 36 happiness units by sitting next to Alice. 23 | David would lose 18 happiness units by sitting next to Bob. 24 | David would lose 65 happiness units by sitting next to Carol. 25 | David would lose 18 happiness units by sitting next to Eric. 26 | David would lose 22 happiness units by sitting next to Frank. 27 | David would gain 2 happiness units by sitting next to George. 28 | David would gain 42 happiness units by sitting next to Mallory. 29 | Eric would lose 65 happiness units by sitting next to Alice. 30 | Eric would gain 24 happiness units by sitting next to Bob. 31 | Eric would gain 100 happiness units by sitting next to Carol. 32 | Eric would gain 51 happiness units by sitting next to David. 33 | Eric would gain 21 happiness units by sitting next to Frank. 34 | Eric would gain 55 happiness units by sitting next to George. 35 | Eric would lose 44 happiness units by sitting next to Mallory. 36 | Frank would lose 48 happiness units by sitting next to Alice. 37 | Frank would gain 91 happiness units by sitting next to Bob. 38 | Frank would gain 8 happiness units by sitting next to Carol. 39 | Frank would lose 66 happiness units by sitting next to David. 40 | Frank would gain 97 happiness units by sitting next to Eric. 41 | Frank would lose 9 happiness units by sitting next to George. 42 | Frank would lose 92 happiness units by sitting next to Mallory. 43 | George would lose 44 happiness units by sitting next to Alice. 44 | George would lose 25 happiness units by sitting next to Bob. 45 | George would gain 17 happiness units by sitting next to Carol. 46 | George would gain 92 happiness units by sitting next to David. 47 | George would lose 92 happiness units by sitting next to Eric. 48 | George would gain 18 happiness units by sitting next to Frank. 49 | George would gain 97 happiness units by sitting next to Mallory. 50 | Mallory would gain 92 happiness units by sitting next to Alice. 51 | Mallory would lose 96 happiness units by sitting next to Bob. 52 | Mallory would lose 51 happiness units by sitting next to Carol. 53 | Mallory would lose 81 happiness units by sitting next to David. 54 | Mallory would gain 31 happiness units by sitting next to Eric. 55 | Mallory would lose 73 happiness units by sitting next to Frank. 56 | Mallory would lose 89 happiness units by sitting next to George. -------------------------------------------------------------------------------- /src/advent-2017/day23.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2017.day23 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as string])) 5 | 6 | (def program 7 | (->> (io/resource "2017/day23") 8 | io/reader 9 | line-seq 10 | (map #(format "[%s]" %)) 11 | (mapv read-string))) 12 | 13 | ;; make sure that there are no errant registers 14 | (assert (= (set (filter symbol? (flatten (map rest program)))) 15 | '#{a b c d e f g h})) 16 | 17 | (defmulti instruct (fn [_ [cmd]] cmd)) 18 | 19 | (defn inc-program-counter [state] 20 | (update state :program-counter inc)) 21 | 22 | (defn reg-or-val [state Y] 23 | (if (number? Y) Y (get state Y 0))) 24 | 25 | (defmethod instruct 'set [state [_ X Y]] 26 | (inc-program-counter 27 | (assoc state X (reg-or-val state Y)))) 28 | 29 | (defmethod instruct 'sub [state [_ X Y]] 30 | (inc-program-counter 31 | (update state X (fnil - 0) (reg-or-val state Y)))) 32 | 33 | (defmethod instruct 'mul [state [_ X Y]] 34 | (-> state 35 | (update X (fnil * 0) (reg-or-val state Y)) 36 | (update :mul-counter (fnil inc 0)) 37 | inc-program-counter)) 38 | 39 | (defmethod instruct 'jnz [state [_ X Y]] 40 | (if (not= ^long (reg-or-val state X) 0) 41 | (update state :program-counter + (reg-or-val state Y)) 42 | (inc-program-counter state))) 43 | 44 | (defn transition [{:keys [program-counter program] :as state}] 45 | (when-let [instruction (get program program-counter)] 46 | (assoc (instruct state instruction) 47 | :inst instruction))) 48 | 49 | ;; part 1 50 | #_(->> (iterate transition {:program-counter 0 51 | :program program}) 52 | (take-while identity) 53 | (map :inst) 54 | (filter #(= 'mul (first %))) 55 | count 56 | time) 57 | ;; => 4225 58 | ;; Elapsed time: 74.587177 msecs 59 | 60 | 61 | ;; program analysis 62 | 63 | (def program-2 64 | '[[set b 67] 65 | [set c b] 66 | [jnz a 2] 67 | [jnz 1 5] 68 | [mul b 100] 69 | [sub b -100000] 70 | [set c b] 71 | [sub c -17000] 72 | ;; outer loop 73 | [set f 1] 74 | [set d 2] 75 | ;; second loop over values for d from 2 => b 76 | [set e 2] 77 | ;; inner loop over values for e from 2 => b 78 | [set g d] 79 | [mul g e] 80 | [sub g b] ;; g = (- (* d e) b) 81 | [jnz g 2] 82 | [set f 0] ;; f = 0 when b is divisible by e 83 | [sub e -1] ;; inc e 84 | [set g e] 85 | [sub g b] ;; g = (- e b) 86 | [jnz g -8] ;; jmp inner loop (exit when e == b) 87 | [sub d -1] ;; inc d 88 | [set g d] 89 | [sub g b] ;; g = (- d b) 90 | [jnz g -13] ;; jmp second loop (exit when d == b) 91 | ;; constants 92 | ;; g = 0, 93 | ;; d = 2, 94 | ;; c = 123700 95 | ;; at end of second loop these are our values 96 | 97 | ;; variables 98 | ;; b = 106700 increases by 17 every outer loop 99 | ;; so outer loop has to run 1000 times 100 | 101 | ;; f is only 0 when b has an integer divisor 102 | ;; h increments when f is 0 103 | [jnz f 2] 104 | [sub h -1] ;; inc h 105 | [set g b] 106 | [sub g c] ;; (- b c) 107 | [jnz g 2] ;; true until (= b c) or until this runs 1000 times 108 | [jnz 1 3] 109 | [sub b -17] ;; b changes by + 17 110 | [jnz 1 -23]]) ;; jmp outer loop 111 | 112 | ;; Analysis Conclusion 113 | 114 | ;; this program counts numbers that are not prime over the range 115 | ;; from b to c stepping by 17 116 | 117 | (defn not-prime? [n] 118 | (some #(= 0 (mod n %)) (range 2 n))) 119 | 120 | ;; part 2 121 | (->> (filter not-prime? (range 106700 (inc 123700) 17)) 122 | count 123 | time) 124 | ;; => 905 125 | ;; Elapsed time: 1752.15433 msecs 126 | -------------------------------------------------------------------------------- /src/advent-2016/day24.clj: -------------------------------------------------------------------------------- 1 | (ns advent-2016.day24 2 | (:require 3 | [advent-2016.utils :as u] 4 | [clojure.java.io :as io] 5 | [clojure.set :refer [difference]] 6 | [medley.core :refer [distinct-by]] 7 | [clojure.string :as string])) 8 | 9 | ;; travelling salesman problem 10 | 11 | (defn make-map [s] 12 | (->> 13 | (for [[y line] (map-indexed vector (string/split-lines s)) 14 | [x chr] (map-indexed vector line)] 15 | [[x y] chr]) 16 | (into {}))) 17 | 18 | (defn number-positions [m] 19 | (->> (filter #(re-matches #"\d" (str (second %))) m) 20 | (map (comp vec reverse)) 21 | (map #(update % 0 (comp u/to-int str))) 22 | (into {}))) 23 | 24 | (defn open-closed [m] 25 | (into {} 26 | (keep (fn [[k v]] (when (not= \# v) [k v])) m))) 27 | 28 | (defn make-map-state [s] 29 | (let [m (make-map s)] 30 | {:positions (open-closed m) 31 | :number-location (number-positions m) 32 | :location-number (into {} 33 | (map (comp vec reverse) 34 | (number-positions m)))})) 35 | 36 | (def input (make-map-state (slurp (io/resource "2016/day24")))) 37 | 38 | (defn possible-moves [{:keys [moves-so-far positions current-position]}] 39 | (let [nm (map #(mapv + current-position %) (shuffle [[0 1] [0 -1] [1 0] [-1 0]]))] 40 | (filter #(and (not (moves-so-far %)) (positions %)) nm))) 41 | 42 | (defn at-number? [{:keys [current-position location-number]}] 43 | (location-number current-position)) 44 | 45 | (defn make-move [st move] 46 | (let [r (-> st 47 | (update :moves-so-far conj (:current-position st)) 48 | (assoc :current-position move))] 49 | (assoc r :at-number (at-number? r)))) 50 | 51 | (defn next-level [sts] 52 | (->> (mapcat #(map (partial make-move %) (possible-moves %)) sts) 53 | (distinct-by :current-position) 54 | (sort-by #(if (at-number? %) 0 1)))) 55 | 56 | (defn breadth-first-search [st] 57 | (drop 1 (iterate next-level [st]))) 58 | 59 | (defn distances-from-position [st a] 60 | (->> (breadth-first-search (assoc st 61 | :current-position (get-in st [:number-location a]) 62 | :moves-so-far #{})) 63 | (mapcat #(filter :at-number %)) 64 | (distinct-by :at-number) 65 | (take (dec (count (:location-number st)))) 66 | (map #(vector #{a (:at-number %)} (count (:moves-so-far %)))) 67 | (into {}))) 68 | 69 | (defn get-all-distances [input] 70 | (->> (map (partial distances-from-position input) (range 8)) 71 | (reduce (partial merge-with min) {}))) 72 | 73 | (def all-distances (time (get-all-distances input))) 74 | 75 | (defn travelling-salesmen [so-far available distances] 76 | (if (= 8 (count so-far)) 77 | 0 78 | (let [lst (first so-far)] 79 | (reduce min 80 | (map (fn [x] 81 | (+ (get distances #{lst x}) 82 | (travelling-salesmen (cons x so-far) available distances))) 83 | (difference (set available) (set so-far))))))) 84 | 85 | ;; part 1 86 | #_(travelling-salesmen [0] (range 8) all-distances) 87 | ;; => 456 88 | 89 | (defn travelling-salesmen-part-2 [so-far available distances] 90 | (if (= 8 (count so-far)) 91 | (get distances #{(first so-far) 0}) 92 | (let [lst (first so-far)] 93 | (reduce min 94 | (map (fn [x] 95 | (+ (get distances #{lst x}) 96 | (travelling-salesmen-part-2 97 | (cons x so-far) available distances))) 98 | (difference (set available) (set so-far))))))) 99 | 100 | ;; part 2 101 | #_(travelling-salesmen-part-2 [0] (range 8) all-distances) 102 | ;; => 704 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /doc/2015/18.md: -------------------------------------------------------------------------------- 1 | # Day 18: Like a GIF For Your Yard 2 | 3 | After the million lights incident, the fire code has gotten stricter: 4 | now, at most ten thousand lights are allowed. You arrange them in a 5 | `100x100` grid. 6 | 7 | Never one to let you down, Santa again mails you instructions on the 8 | ideal lighting configuration. With so few lights, he says, you'll have 9 | to resort to **animation**. 10 | 11 | Start by setting your lights to the included initial configuration 12 | (your puzzle input). A `#` means "on", and a `.` means "off". 13 | 14 | Then, animate your grid in steps, where each step decides the next 15 | configuration based on the current one. Each light's next state 16 | (either on or off) depends on its current state and the current states 17 | of the eight lights adjacent to it (including diagonals). Lights on 18 | the edge of the grid might have fewer than eight neighbors; the 19 | missing ones always count as "off". 20 | 21 | For example, in a simplified 6x6 grid, the light marked A has the 22 | neighbors numbered `1` through `8`, and the light marked B, which is on an 23 | edge, only has the neighbors marked `1` through `5`: 24 | 25 | ``` 26 | 1B5... 27 | 234... 28 | ...... 29 | ..123. 30 | ..8A4. 31 | ..765. 32 | ``` 33 | 34 | The state a light should have next is based on its current state (on 35 | or off) plus the number of neighbors that are on: 36 | 37 | ``` 38 | A light which is on stays on when 2 or 3 neighbors are on, and turns off otherwise. 39 | A light which is off turns on if exactly 3 neighbors are on, and stays 40 | off otherwise. 41 | ``` 42 | 43 | All of the lights update simultaneously; they all consider the same 44 | current state before moving to the next. 45 | 46 | Here's a few steps from an example configuration of another 6x6 grid: 47 | 48 | 49 | ``` 50 | Initial state: 51 | .#.#.# 52 | ...##. 53 | #....# 54 | ..#... 55 | #.#..# 56 | ####.. 57 | 58 | After 1 step: 59 | ..##.. 60 | ..##.# 61 | ...##. 62 | ...... 63 | #..... 64 | #.##.. 65 | 66 | After 2 steps: 67 | ..###. 68 | ...... 69 | ..###. 70 | ...... 71 | .#.... 72 | .#.... 73 | 74 | After 3 steps: 75 | ...#.. 76 | ...... 77 | ...#.. 78 | ..##.. 79 | ...... 80 | ...... 81 | 82 | After 4 steps: 83 | ...... 84 | ...... 85 | ..##.. 86 | ..##.. 87 | ...... 88 | ...... 89 | ``` 90 | 91 | After `4` steps, this example has four lights on. 92 | 93 | In your grid of `100x100` lights, given your initial configuration, how 94 | many lights are on after `100` steps? 95 | 96 | Your puzzle answer was **`821`**. 97 | 98 | ## Part Two 99 | 100 | You flip the instructions over; Santa goes on to point out that this 101 | is all just an implementation of Conway's Game of Life. At least, it 102 | was, until you notice that something's wrong with the grid of lights 103 | you bought: four lights, one in each corner, are stuck on and can't be 104 | turned off. The example above will actually run like this: 105 | 106 | ``` 107 | Initial state: 108 | ##.#.# 109 | ...##. 110 | #....# 111 | ..#... 112 | #.#..# 113 | ####.# 114 | 115 | After 1 step: 116 | #.##.# 117 | ####.# 118 | ...##. 119 | ...... 120 | #...#. 121 | #.#### 122 | 123 | After 2 steps: 124 | #..#.# 125 | #....# 126 | .#.##. 127 | ...##. 128 | .#..## 129 | ##.### 130 | 131 | After 3 steps: 132 | #...## 133 | ####.# 134 | ..##.# 135 | ...... 136 | ##.... 137 | ####.# 138 | 139 | After 4 steps: 140 | #.#### 141 | #....# 142 | ...#.. 143 | .##... 144 | #..... 145 | #.#..# 146 | 147 | After 5 steps: 148 | ##.### 149 | .##..# 150 | .##... 151 | .##... 152 | #.#... 153 | ##...# 154 | ``` 155 | 156 | After 5 steps, this example now has `17` lights on. 157 | 158 | In your grid of `100x100` lights, given your initial configuration, but 159 | with the four corners always in the on state, how many lights are on 160 | after `100` steps? 161 | 162 | Your puzzle answer was **`886`**. 163 | -------------------------------------------------------------------------------- /doc/2015/25.md: -------------------------------------------------------------------------------- 1 | # Day 25: Let It Snow 2 | 3 | Merry Christmas! Santa is booting up his weather machine; looks like 4 | you might get a white Christmas after all. 5 | 6 | The weather machine beeps! On the console of the machine is a copy 7 | protection message asking you to enter a code from the instruction 8 | manual. Apparently, it refuses to run unless you give it that code. No 9 | problem; you'll just look up the code in the-- 10 | 11 | "Ho ho ho", Santa ponders aloud. "I can't seem to find the manual." 12 | 13 | You look up the support number for the manufacturer and give them a 14 | call. Good thing, too - that 49th star wasn't going to earn itself. 15 | 16 | "Oh, that machine is quite old!", they tell you. "That model went out 17 | of support six minutes ago, and we just finished shredding all of the 18 | manuals. I bet we can find you the code generation algorithm, though." 19 | 20 | After putting you on hold for twenty minutes (your call is very 21 | important to them, it reminded you repeatedly), they finally find an 22 | engineer that remembers how the code system works. 23 | 24 | The codes are printed on an infinite sheet of paper, starting in the 25 | top-left corner. The codes are filled in by diagonals: starting with 26 | the first row with an empty first box, the codes are filled in 27 | diagonally up and to the right. This process repeats until the 28 | infinite paper is covered. So, the first few codes are filled in in 29 | this order: 30 | 31 | ``` 32 | | 1 2 3 4 5 6 33 | ---+---+---+---+---+---+---+ 34 | 1 | 1 3 6 10 15 21 35 | 2 | 2 5 9 14 20 36 | 3 | 4 8 13 19 37 | 4 | 7 12 18 38 | 5 | 11 17 39 | 6 | 16 40 | ``` 41 | 42 | For example, the `12th` code would be written to row 4, column 2; the 43 | 15th code would be written to row `1`, column `5`. 44 | 45 | The voice on the other end of the phone continues with how the codes 46 | are actually generated. The first code is `20151125`. After that, each 47 | code is generated by taking the previous one, multiplying it by 48 | `252533`, and then keeping the remainder from dividing that value by 49 | `33554393`. 50 | 51 | So, to find the second code (which ends up in row 2, column 1), start 52 | with the previous value, `20151125`. Multiply it by `252533` to get 53 | `5088824049625`. Then, divide that by `33554393`, which leaves a remainder 54 | of `31916031`. That remainder is the second code. 55 | 56 | "Oh!", says the voice. "It looks like we missed a scrap from one of 57 | the manuals. Let me read it to you." You write down his numbers: 58 | 59 | ``` 60 | | 1 2 3 4 5 6 61 | ---+---------+---------+---------+---------+---------+---------+ 62 | 1 | 20151125 18749137 17289845 30943339 10071777 33511524 63 | 2 | 31916031 21629792 16929656 7726640 15514188 4041754 64 | 3 | 16080970 8057251 1601130 7981243 11661866 16474243 65 | 4 | 24592653 32451966 21345942 9380097 10600672 31527494 66 | 5 | 77061 17552253 28094349 6899651 9250759 31663883 67 | 6 | 33071741 6796745 25397450 24659492 1534922 27995004 68 | ``` 69 | 70 | "Now remember", the voice continues, "that's not even all of the first 71 | few numbers; for example, you're missing the one at `7,1` that would 72 | come before `6,2`. But, it should be enough to let your-- oh, it's time 73 | for lunch! Bye!" The call disconnects. 74 | 75 | Santa looks nervous. Your puzzle input contains the message on the 76 | machine's console. What code do you give the machine? 77 | 78 | Your puzzle answer was **`19980801`**. 79 | 80 | ## Part Two 81 | 82 | The machine springs to life, then falls silent again. It beeps. 83 | "Insufficient fuel", the console reads. "Fifty stars are required 84 | before proceeding. One star is available." 85 | 86 | ..."one star is available"? You check the fuel tank; sure enough, a 87 | lone star sits at the bottom, awaiting its friends. Looks like you 88 | need to provide 49 yourself. 89 | 90 | -------------------------------------------------------------------------------- /resources/2017/day21: -------------------------------------------------------------------------------- 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 | .#./###/... => .#../#.../.#.#/##.# 40 | ##./###/... => ##.#/#.#./#.../.#.. 41 | #.#/###/... => ..../#.../####/.#.. 42 | ###/###/... => .#../#..#/.#../.#.. 43 | ..#/.../#.. => .#.#/#.../..##/...# 44 | #.#/.../#.. => ####/####/###./...# 45 | .##/.../#.. => ####/.###/##.#/##.. 46 | ###/.../#.. => ..##/..../...#/#.#. 47 | .##/#../#.. => ###./..#./##.#/##.# 48 | ###/#../#.. => ##.#/...#/.##./.### 49 | ..#/.#./#.. => #.#./#.#./...#/#.#. 50 | #.#/.#./#.. => ###./.#.#/#.#./.#.. 51 | .##/.#./#.. => #.#./.##./.###/#.#. 52 | ###/.#./#.. => #.../#.../#.#./.### 53 | .##/##./#.. => .#.#/.##./..#./##.. 54 | ###/##./#.. => .###/.##./#.##/..## 55 | #../..#/#.. => #.#./#..#/###./.##. 56 | .#./..#/#.. => ###./.###/...#/..## 57 | ##./..#/#.. => ###./##../####/.#.# 58 | #.#/..#/#.. => ..#./.#../.##./.#.. 59 | .##/..#/#.. => ##.#/###./.##./#... 60 | ###/..#/#.. => ...#/..##/##.#/##.# 61 | #../#.#/#.. => #.../.##./.#.#/.### 62 | .#./#.#/#.. => #.##/...#/####/###. 63 | ##./#.#/#.. => .#../#.../.###/.... 64 | ..#/#.#/#.. => ####/###./.#.#/#... 65 | #.#/#.#/#.. => ###./..##/...#/#.## 66 | .##/#.#/#.. => ##.#/..#./..##/.#.# 67 | ###/#.#/#.. => #.#./..../##../.### 68 | #../.##/#.. => #..#/###./.#.#/##.# 69 | .#./.##/#.. => #.../.###/.##./.### 70 | ##./.##/#.. => .#../###./.#../##.# 71 | #.#/.##/#.. => .#../#.#./.#../#.## 72 | .##/.##/#.. => ##../###./.#.#/.### 73 | ###/.##/#.. => ..##/...#/#.../.#.. 74 | #../###/#.. => #.##/#..#/####/###. 75 | .#./###/#.. => .###/.#.#/#.#./..#. 76 | ##./###/#.. => ####/#.#./..##/#.## 77 | ..#/###/#.. => .###/##.#/.##./#.#. 78 | #.#/###/#.. => #.##/###./.###/.... 79 | .##/###/#.. => #.##/..../.#../#### 80 | ###/###/#.. => ##.#/###./.#../...# 81 | .#./#.#/.#. => ..#./##.#/.#../###. 82 | ##./#.#/.#. => ..##/###./..#./.#.# 83 | #.#/#.#/.#. => .#../..##/.#.#/.#.# 84 | ###/#.#/.#. => ##../#..#/.#../..#. 85 | .#./###/.#. => #.../#..#/.#.#/.... 86 | ##./###/.#. => ..../..##/..#./#### 87 | #.#/###/.#. => ..##/##.#/.###/...# 88 | ###/###/.#. => ##.#/#.##/..#./#.#. 89 | #.#/..#/##. => #.../####/#.##/.### 90 | ###/..#/##. => ###./...#/.#.#/#..# 91 | .##/#.#/##. => ..../.#.#/##.#/..## 92 | ###/#.#/##. => ###./.#../.#.#/###. 93 | #.#/.##/##. => ###./.#../.#../.#.# 94 | ###/.##/##. => .##./..../..../#.## 95 | .##/###/##. => ####/##../.###/##.# 96 | ###/###/##. => #..#/#.##/#.##/.#.. 97 | #.#/.../#.# => ####/#.#./#..#/.##. 98 | ###/.../#.# => .#../.#.#/.#../.#.# 99 | ###/#../#.# => ..#./..#./.###/#... 100 | #.#/.#./#.# => #.#./..../.##./#### 101 | ###/.#./#.# => #.../..##/.##./..#. 102 | ###/##./#.# => .#.#/##../#.#./..#. 103 | #.#/#.#/#.# => #.##/#.##/#.##/..## 104 | ###/#.#/#.# => .###/#.#./.##./..## 105 | #.#/###/#.# => ...#/#.#./..#./#..# 106 | ###/###/#.# => #.../#..#/#..#/.##. 107 | ###/#.#/### => .#.#/..##/##.#/#... 108 | ###/###/### => .###/#.#./#.../#... --------------------------------------------------------------------------------