├── .gitignore ├── src ├── _CoqProject ├── aoc23_input.txt.prep ├── aoc17_input.txt ├── aoc14_input.txt.prep ├── aoc20_input.txt.prep ├── aoc25_input.txt.prep ├── aoc12_input.txt.prep ├── aoc08_input.txt.prep ├── aoc10_input.txt.prep ├── aoc16_input.txt.prep ├── aoc21_input.txt ├── aoc23_input.txt ├── aoc11_input.txt ├── aoc12_input.txt ├── runall.sh ├── aoc06_input.txt ├── a.sh ├── aoc16_input.txt ├── aoc14_input.txt ├── aoc06.v ├── aoc01.v ├── aoc17.v ├── aoc05.v ├── aoc02.v ├── aoc24_input.txt ├── aoc13.v ├── aoc25.v ├── aoc18_input.txt ├── aoc03.v ├── aoc07_input.txt ├── aoc18.v ├── aoc14.v ├── aoc04.v ├── aoc20.v ├── aoc21.v ├── aoc12.v ├── aoc16.v ├── aoc11.v ├── aoc09.v ├── aoc08.v ├── aoc10_input.txt ├── aoc15.v ├── aoc09_input.txt ├── aoc15_input.txt ├── aoc20_input.txt ├── aoc04_input.txt ├── aoc05_input.txt ├── aoc07.v ├── aoc19_input.txt └── aoc10.v └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | src/build/ 2 | -------------------------------------------------------------------------------- /src/_CoqProject: -------------------------------------------------------------------------------- 1 | -R build/ aoc 2 | -------------------------------------------------------------------------------- /src/aoc23_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sed -f 2 | s/\./ /g 3 | -------------------------------------------------------------------------------- /src/aoc17_input.txt: -------------------------------------------------------------------------------- 1 | target area: x=143..177, y=-106..-71 2 | -------------------------------------------------------------------------------- /src/aoc14_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sed -f 2 | s/[A-Z]\+/"\0"/g 3 | -------------------------------------------------------------------------------- /src/aoc20_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sed -f 2 | s/^/"/ 3 | s/$/"/ 4 | -------------------------------------------------------------------------------- /src/aoc25_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sed -f 2 | s/^/"/ 3 | s/$/"/ 4 | -------------------------------------------------------------------------------- /src/aoc12_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sed -f 2 | s/^/"/ 3 | s/$/"/ 4 | s/-/"-"/ 5 | -------------------------------------------------------------------------------- /src/aoc08_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo -n '"' 3 | cat - 4 | echo -n '"' 5 | -------------------------------------------------------------------------------- /src/aoc10_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo -n '"' 3 | cat - 4 | echo -n '"' 5 | -------------------------------------------------------------------------------- /src/aoc16_input.txt.prep: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo -n '"' 3 | cat - 4 | echo -n '"' 5 | -------------------------------------------------------------------------------- /src/aoc21_input.txt: -------------------------------------------------------------------------------- 1 | Player 1 starting position: 2 2 | Player 2 starting position: 10 3 | -------------------------------------------------------------------------------- /src/aoc23_input.txt: -------------------------------------------------------------------------------- 1 | ############# 2 | #...........# 3 | ###A#D#B#C### 4 | #B#C#D#A# 5 | ######### 6 | -------------------------------------------------------------------------------- /src/aoc11_input.txt: -------------------------------------------------------------------------------- 1 | 4112256372 2 | 3143253712 3 | 4516848631 4 | 3783477137 5 | 3746723582 6 | 5861358884 7 | 4843351774 8 | 2316447621 9 | 6643817745 10 | 6366815868 11 | -------------------------------------------------------------------------------- /src/aoc12_input.txt: -------------------------------------------------------------------------------- 1 | xx-xh 2 | vx-qc 3 | cu-wf 4 | ny-LO 5 | cu-DR 6 | start-xx 7 | LO-vx 8 | cu-LO 9 | xx-cu 10 | cu-ny 11 | xh-start 12 | qc-DR 13 | vx-AP 14 | end-LO 15 | ny-DR 16 | vx-end 17 | DR-xx 18 | start-DR 19 | end-ny 20 | ny-xx 21 | xh-DR 22 | cu-xh 23 | -------------------------------------------------------------------------------- /src/runall.sh: -------------------------------------------------------------------------------- 1 | for i in $(seq -f "%02g" 1 25) ; do 2 | if [[ -e "aoc${i}.v" ]] ; then 3 | echo "Day ${i}" 4 | if [[ "24" = "${i}" ]] 5 | then echo "This might take 10 minutes." 6 | fi 7 | ./a.sh aoc${i}.v aoc${i}_input.txt solve12 8 | fi 9 | done 10 | -------------------------------------------------------------------------------- /src/aoc06_input.txt: -------------------------------------------------------------------------------- 1 | 4,5,3,2,3,3,2,4,2,1,2,4,5,2,2,2,4,1,1,1,5,1,1,2,5,2,1,1,4,4,5,5,1,2,1,1,5,3,5,2,4,3,2,4,5,3,2,1,4,1,3,1,2,4,1,1,4,1,4,2,5,1,4,3,5,2,4,5,4,2,2,5,1,1,2,4,1,4,4,1,1,3,1,2,3,2,5,5,1,1,5,2,4,2,2,4,1,1,1,4,2,2,3,1,2,4,5,4,5,4,2,3,1,4,1,3,1,2,3,3,2,4,3,3,3,1,4,2,3,4,2,1,5,4,2,4,4,3,2,1,5,3,1,4,1,1,5,4,2,4,2,2,4,4,4,1,4,2,4,1,1,3,5,1,5,5,1,3,2,2,3,5,3,1,1,4,4,1,3,3,3,5,1,1,2,5,5,5,2,4,1,5,1,2,1,1,1,4,3,1,5,2,3,1,3,1,4,1,3,5,4,5,1,3,4,2,1,5,1,3,4,5,5,2,1,2,1,1,1,4,3,1,4,2,3,1,3,5,1,4,5,3,1,3,3,2,2,1,5,5,4,3,2,1,5,1,3,1,3,5,1,1,2,1,1,1,5,2,1,1,3,2,1,5,5,5,1,1,5,1,4,1,5,4,2,4,5,2,4,3,2,5,4,1,1,2,4,3,2,1 2 | -------------------------------------------------------------------------------- /src/a.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ "$#" -ne 3 ]; then 6 | echo -e "Usage: $0 aocXX.v aocXX_input.txt solve" 7 | echo -e "where" 8 | echo -e "\taocXX.v\t\tSolution module" 9 | echo -e "\taocXX_input.txt\tInput file" 10 | echo -e "\tsolve\t\tSolution function name (usually solve or solve2 or solve12)" 11 | exit 1 12 | fi 13 | 14 | BUILD=build 15 | mkdir -p $BUILD 16 | 17 | SOLUTION=$1 18 | INPUT=$2 19 | FUNC=$3 20 | INPUT_=$BUILD/${INPUT%.*} 21 | 22 | cat <(echo -e "Require Import ${SOLUTION%.v}. Definition x := input") \ 23 | <(if [ -f $INPUT.prep ]; then ./$INPUT.prep < $INPUT ; else cat $INPUT ; fi) \ 24 | <(echo -e ".\nCompute $FUNC x.") > $INPUT_.v 25 | 26 | coqc -R $BUILD aoc $SOLUTION -o $BUILD/${SOLUTION%.v}.vo 27 | coqc -R $BUILD aoc $INPUT_.v -o $INPUT_.vo 28 | -------------------------------------------------------------------------------- /src/aoc16_input.txt: -------------------------------------------------------------------------------- 1 | E20D72805F354AE298E2FCC5339218F90FE5F3A388BA60095005C3352CF7FBF27CD4B3DFEFC95354723006C401C8FD1A23280021D1763CC791006E25C198A6C01254BAECDED7A5A99CCD30C01499CFB948F857002BB9FCD68B3296AF23DD6BE4C600A4D3ED006AA200C4128E10FC0010C8A90462442A5006A7EB2429F8C502675D13700BE37CF623EB3449CAE732249279EFDED801E898A47BE8D23FBAC0805527F99849C57A5270C064C3ECF577F4940016A269007D3299D34E004DF298EC71ACE8DA7B77371003A76531F20020E5C4CC01192B3FE80293B7CD23ED55AA76F9A47DAAB6900503367D240522313ACB26B8801B64CDB1FB683A6E50E0049BE4F6588804459984E98F28D80253798DFDAF4FE712D679816401594EAA580232B19F20D92E7F3740D1003880C1B002DA1400B6028BD400F0023A9C00F50035C00C5002CC0096015B0C00B30025400D000C398025E2006BD800FC9197767C4026D78022000874298850C4401884F0E21EC9D256592007A2C013967C967B8C32BCBD558C013E005F27F53EB1CE25447700967EBB2D95BFAE8135A229AE4FFBB7F6BC6009D006A2200FC3387D128001088E91121F4DED58C025952E92549C3792730013ACC0198D709E349002171060DC613006E14C7789E4006C4139B7194609DE63FEEB78004DF299AD086777ECF2F311200FB7802919FACB38BAFCFD659C5D6E5766C40244E8024200EC618E11780010B83B09E1BCFC488C017E0036A184D0A4BB5CDD0127351F56F12530046C01784B3FF9C6DFB964EE793F5A703360055A4F71F12C70000EC67E74ED65DE44AA7338FC275649D7D40041E4DDA794C80265D00525D2E5D3E6F3F26300426B89D40094CCB448C8F0C017C00CC0401E82D1023E0803719E2342D9FB4E5A01300665C6A5502457C8037A93C63F6B4C8B40129DF7AC353EF2401CC6003932919B1CEE3F1089AB763D4B986E1008A7354936413916B9B080 2 | -------------------------------------------------------------------------------- /src/aoc14_input.txt: -------------------------------------------------------------------------------- 1 | NBOKHVHOSVKSSBSVVBCS 2 | 3 | SN -> H 4 | KP -> O 5 | CP -> V 6 | FN -> P 7 | FV -> S 8 | HO -> S 9 | NS -> N 10 | OP -> C 11 | HC -> S 12 | NP -> B 13 | CF -> V 14 | NN -> O 15 | OS -> F 16 | VO -> V 17 | HK -> N 18 | SV -> V 19 | VC -> V 20 | PH -> K 21 | NH -> O 22 | SB -> N 23 | KS -> V 24 | CB -> H 25 | SS -> P 26 | SP -> H 27 | VN -> K 28 | VP -> O 29 | SK -> V 30 | VF -> C 31 | VV -> B 32 | SF -> K 33 | HH -> K 34 | PV -> V 35 | SO -> H 36 | NK -> P 37 | NO -> C 38 | ON -> S 39 | PB -> K 40 | VS -> H 41 | SC -> P 42 | HS -> P 43 | BS -> P 44 | CS -> P 45 | VB -> V 46 | BP -> K 47 | FH -> O 48 | OF -> F 49 | HF -> F 50 | FS -> C 51 | BN -> O 52 | NC -> F 53 | FC -> B 54 | CV -> V 55 | HN -> C 56 | KF -> K 57 | OO -> P 58 | CC -> S 59 | FF -> C 60 | BC -> P 61 | PP -> F 62 | KO -> V 63 | PC -> B 64 | HB -> H 65 | OB -> N 66 | OV -> S 67 | KH -> B 68 | BO -> B 69 | HV -> P 70 | BV -> K 71 | PS -> F 72 | CH -> C 73 | SH -> H 74 | OK -> V 75 | NB -> K 76 | BF -> S 77 | CO -> O 78 | NV -> H 79 | FB -> K 80 | FO -> C 81 | CK -> P 82 | BH -> B 83 | OH -> F 84 | KB -> N 85 | OC -> K 86 | KK -> O 87 | CN -> H 88 | FP -> K 89 | VH -> K 90 | VK -> P 91 | HP -> S 92 | FK -> F 93 | BK -> H 94 | KV -> V 95 | BB -> O 96 | KC -> F 97 | KN -> C 98 | PO -> P 99 | NF -> P 100 | PN -> S 101 | PF -> S 102 | PK -> O 103 | -------------------------------------------------------------------------------- /src/aoc06.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export List NArith. 2 | Import ListNotations. 3 | 4 | #[global] Open Scope N_scope. 5 | 6 | Notation "'input' x ',' .. ',' y" := (cons x .. (cons y nil) ..) (at level 200). 7 | 8 | Definition example : list N := input 9 | 3,4,3,1,2 10 | . 11 | 12 | Fixpoint zip_with {A B C} (f : A -> B -> C) (xs : list A) (ys : list B) : list C := 13 | match xs, ys with 14 | | x :: xs, y :: ys => f x y :: zip_with f xs ys 15 | | _, _ => nil 16 | end. 17 | 18 | Definition one_vector (x : N) : list N := 19 | repeat 0 (N.to_nat x) ++ 1 :: repeat 0 (8 - N.to_nat x). 20 | 21 | Fixpoint input_to_vector (xs : list N) : list N := 22 | match xs with 23 | | [] => [0; 0; 0; 0; 0; 0; 0; 0; 0] 24 | | x :: xs => zip_with N.add (one_vector x) (input_to_vector xs) 25 | end. 26 | 27 | Fixpoint add_at (n : nat) (c : N) (xs : list N) : list N := 28 | match n, xs with 29 | | _, [] => [] (* should not happen *) 30 | | O, x :: xs => x+c :: xs 31 | | S n, x :: xs => x :: add_at n c xs 32 | end. 33 | 34 | Definition step (v : list N) : list N := 35 | match v with 36 | | [] => [] (* should not happen *) 37 | | x0 :: v => add_at 6 x0 v ++ [x0] 38 | end. 39 | 40 | Fixpoint steps (n : nat) (v : list N) : list N := 41 | match n with 42 | | O => v 43 | | S n => steps n (step v) 44 | end. 45 | 46 | Definition sum (xs : list N) := fold_left N.add xs 0. 47 | 48 | Definition solve (xs : list N) : N := 49 | sum (steps 80 (input_to_vector xs)). 50 | 51 | (* Compute solve example. *) 52 | 53 | Definition solve2 (xs : list N) : N := 54 | sum (steps 256 (input_to_vector xs)). 55 | 56 | Definition solve12 (xs : list N) : N * N := 57 | (solve xs, solve2 xs). 58 | -------------------------------------------------------------------------------- /src/aoc01.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export List NArith. 2 | From Coq Require Import Lia. 3 | 4 | Import ListNotations. 5 | 6 | #[global] Open Scope N_scope. 7 | 8 | Notation "'input' x .. y" := (cons x .. (cons y nil) ..) (at level 200, x at level 0, only parsing). 9 | 10 | Definition example : list N := input 11 | 199 12 | 200 13 | 208 14 | 210 15 | 200 16 | 207 17 | 240 18 | 269 19 | 260 20 | 263 21 | . 22 | 23 | (* Part 1 *) 24 | 25 | (* Count the number of consecutive increasing pairs *) 26 | Fixpoint count_increases_ (xs : list N) (acc : N) : N := 27 | match xs with 28 | | [] | _ :: [] => acc 29 | | x :: (y :: _) as xs => 30 | count_increases_ xs (if x N := count_increases. 36 | 37 | (* Compute solve example. (* 7 *) *) 38 | 39 | (* Seems as simple as could be. *) 40 | 41 | (* Part 2 *) 42 | 43 | (* Count the number of consecutive increasing sums in a sliding window of length 3 *) 44 | Fixpoint count_increases2_ (xs : list N) (acc : N) : N := 45 | match xs with 46 | | x :: (_ :: _ :: y :: _) as xs => 47 | count_increases2_ xs (if x acc 49 | end. 50 | 51 | Definition count_increases2 (xs : list N) : N := count_increases2_ xs 0. 52 | 53 | Definition solve2 : list N -> N := count_increases2. 54 | 55 | (* Compute solve2 example. (* 5 *) *) 56 | 57 | Definition solve12 (i : list N) : N * N := (solve i, solve2 i). 58 | 59 | (* This solution avoids computing the sums. We can prove that it's equivalent to a more literal 60 | solution that does the sums. *) 61 | 62 | Fixpoint sum3 (xs : list N) : list N := 63 | match xs with 64 | | x :: (y :: z :: _) as xs => (x + y + z) :: sum3 xs 65 | | _ => [] 66 | end. 67 | 68 | Theorem count_increases2_correct xs : count_increases (sum3 xs) = count_increases2 xs. 69 | Proof. 70 | unfold count_increases, count_increases2. generalize 0. 71 | induction xs as [ | x xs IH]; cbn [sum3]; intros n; [ reflexivity | ]. 72 | destruct xs as [ | y [ | z [ | t xs_ ] ] ]; [ reflexivity .. | ]. 73 | change 74 | ( count_increases_ (sum3 (y :: z :: t :: xs_)) (if x + y + z = 0 *) 23 | Definition step '(((x, y), (vx, vy)) : point * point) : point * point := 24 | let vx' := if vx =? 0 then vx else vx - 1 in 25 | let vy' := vy - 1 in 26 | ((x + vx, y + vy), (vx', vy')). 27 | 28 | Definition req_fuel (vy : Z) (ymin : Z) : N := 29 | Z.to_N (2 + ((Z.sqrt (4 * vy ^ 2 - 4 * vy - 8 * ymin + 1) + 2 * vy) / 2)). 30 | 31 | Definition steps_for (fuel : N) (v : point) : list point := 32 | N.iter fuel (fun go y => fst y :: go (step y)) (fun x => fst x :: nil) ((0,0), v). 33 | 34 | Definition get_vy '((_, vy) : point) := vy. 35 | Definition get_ymin '((_, (ymin, _)) : point * point) := ymin. 36 | 37 | Definition on_target '(((xmin,xmax), (ymin,ymax)) : point * point) '((x, y) : point) : bool := 38 | (xmin <=? x) && (x <=? xmax) && (ymin <=? y) && (y <=? ymax). 39 | 40 | Definition trajectory (tgt : point * point) (v : point) : list point := 41 | let fuel := req_fuel (get_vy v) (get_ymin tgt) in 42 | steps_for fuel v. 43 | 44 | Definition hit (tgt : point * point) (traj : list point):= 45 | existsb (on_target tgt) traj. 46 | 47 | Definition Zseq (zmin zmax : Z) : list Z := 48 | Z.iter (zmax - zmin) (fun go i => i :: go (i + 1)) (fun i => i :: nil) zmin. 49 | 50 | Definition range '(((xmin,xmax), (ymin,ymax)) : point * point) : list point := 51 | list_prod (Zseq 0 xmax) (Zseq ymin (-ymin)). 52 | 53 | Definition max_of {A} (f : A -> Z) (xs : list A) : Z := 54 | fold_left (fun y x => Z.max y (f x)) xs (-42). 55 | 56 | Definition solve (tgt : point * point) : Z := 57 | max_of (max_of snd) (filter (hit tgt) (map (trajectory tgt) (range tgt))). 58 | 59 | (* 60 | Compute (trajectory example (6,9)). 61 | Compute solve example. 62 | *) 63 | 64 | Definition solve2 (tgt : point * point) : nat := 65 | length (filter (hit tgt) (map (trajectory tgt) (range tgt))). 66 | 67 | Definition solve12 tgt := 68 | let trajs := filter (hit tgt) (map (trajectory tgt) (range tgt)) in 69 | (max_of (max_of snd) trajs, length trajs). 70 | -------------------------------------------------------------------------------- /src/aoc05.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export List NArith. 2 | From stdpp Require Import base gmap. 3 | 4 | #[global] Open Scope N_scope. 5 | 6 | Declare Custom Entry line. 7 | 8 | Notation "'input' l1 .. ln" := (cons l1 .. (cons ln nil) ..) (at level 200, l1 custom line, only parsing). 9 | 10 | Notation "x1 ',' y1 '->' x2 ',' y2" := ((x1, y1), (x2, y2)) 11 | (in custom line at level 1, x1 constr at level 0, y1 constr at level 0, x2 constr at level 0, y2 constr at level 0). 12 | 13 | Notation Point := (N * N)%type. 14 | 15 | Notation Line := (Point * Point)%type. 16 | 17 | Definition Input : Type := list Line. 18 | 19 | Definition example : Input := input 20 | 0,9 -> 5,9 21 | 8,0 -> 0,8 22 | 9,4 -> 3,4 23 | 2,2 -> 2,1 24 | 7,0 -> 7,4 25 | 6,4 -> 2,0 26 | 0,9 -> 2,9 27 | 3,4 -> 1,4 28 | 0,0 -> 8,8 29 | 5,5 -> 8,2 30 | . 31 | 32 | Definition is_hline '(((_, y1), (_, y2)) : Line) : bool := 33 | y1 =? y2. 34 | 35 | Definition is_vline '(((x1, _), (x2, _)) : Line) : bool := 36 | x1 =? x2. 37 | 38 | Definition is_hvline (l : Line) : bool := 39 | is_hline l || is_vline l. 40 | 41 | Definition iter_line {A} (l : Line) (f : Point -> A -> A) (x : A) : A := 42 | let '((x1, y1), (x2, y2)) := l in 43 | if y1 =? y2 then 44 | let '(x1, x2) := if x1 <=? x2 then (x1, x2) else (x2, x1) in 45 | N.recursion x (fun i => f (x1+i, y1)) (x2 - x1 + 1) 46 | else if x1 =? x2 then 47 | let '(y1, y2) := if y1 <=? y2 then (y1, y2) else (y2, y1) in 48 | N.recursion x (fun i => f (x1, y1+i)) (y2 - y1 + 1) 49 | else if x1 f (x1+i, add y1 i)) (x2 - x1 + 1) 52 | else 53 | let add := if y2 <=? y1 then N.add else N.sub in 54 | N.recursion x (fun i => f (x2+i, add y2 i)) (x1 - x2 + 1). 55 | 56 | Definition add_line (l : Line) : gmap Point positive -> gmap Point positive := 57 | let incr o := Some match o with None => 1%positive | Some n => Pos.succ n end in 58 | iter_line l (partial_alter incr). 59 | 60 | Definition cover (l : list Line) : gmap Point positive := 61 | fold_left (fun m l => add_line l m) l empty. 62 | 63 | Definition overlapping (x : Point * positive) : Prop := 64 | (1 < snd x)%positive. 65 | 66 | Definition solve (ls : list Line) : nat := 67 | size $ filter overlapping $ cover $ filter is_hvline ls. 68 | 69 | (* Compute solve example. *) 70 | 71 | Definition sizeN {A} (xs : list A) : N := 72 | let fix s n xs := 73 | match xs with 74 | | [] => n 75 | | _ :: xs => s (N.succ n) xs 76 | end in 77 | s 0 xs. 78 | 79 | Definition solve2 (ls : list Line) : _ := 80 | length $ map_to_list $ filter overlapping $ cover ls. 81 | 82 | (* Compute solve2 example. *) 83 | 84 | Definition solve12 (ls : list Line) : _ := 85 | (solve ls, solve2 ls). 86 | -------------------------------------------------------------------------------- /src/aoc02.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export ZArith List. 2 | Import ListNotations. 3 | 4 | #[global] Open Scope Z_scope. 5 | 6 | Inductive cmd := 7 | | forward 8 | | up 9 | | down 10 | . 11 | 12 | Declare Custom Entry aoc02. 13 | 14 | Notation "'input' x .. y" := (cons x .. (cons y nil) ..) (at level 200, x custom aoc02, y custom aoc02, only parsing). 15 | Notation "x y" := (x, y) (in custom aoc02 at level 0, x constr at level 0, y constr at level 0). 16 | 17 | Definition example := input 18 | forward 5 19 | down 5 20 | forward 8 21 | up 3 22 | down 8 23 | forward 2 24 | . 25 | 26 | (* Part One *) 27 | 28 | Definition position : Type := Z * Z. 29 | 30 | Definition eval1 (c : cmd) (n : Z) '((hpos, zpos) : position) : position := 31 | match c with 32 | | forward => (hpos + n, zpos) 33 | | up => (hpos, zpos - n) 34 | | down => (hpos, zpos + n) 35 | end. 36 | 37 | Fixpoint eval (xs : list (cmd * Z)) (current : position) : position := 38 | match xs with 39 | | [] => current 40 | | (c, n) :: xs => eval xs (eval1 c n current) 41 | end. 42 | 43 | Definition solve (xs : list (cmd * Z)) : Z := 44 | let '(hpos, zpos) := eval xs (0, 0) in 45 | hpos * zpos. 46 | 47 | (* Compute solve example. *) 48 | 49 | (* Part Two *) 50 | 51 | Definition position_2 : Type := Z * Z * Z. 52 | 53 | Definition eval1_2 (c : cmd) (n : Z) '((hpos, zpos, aim) : position_2) : position_2 := 54 | match c with 55 | | forward => (hpos + n, zpos + n * aim, aim) 56 | | up => (hpos, zpos, aim - n) 57 | | down => (hpos, zpos, aim + n) 58 | end. 59 | 60 | Fixpoint eval_2 (xs : list (cmd * Z)) (current : position_2) : position_2 := 61 | match xs with 62 | | [] => current 63 | | (c, n) :: xs => eval_2 xs (eval1_2 c n current) 64 | end. 65 | 66 | Definition solve2 (xs : list (cmd * Z)) : Z := 67 | let '(hpos, zpos, _aim) := eval_2 xs (0, 0, 0) in 68 | hpos * zpos. 69 | 70 | Definition solve12 (i : list (cmd * Z)) : Z * Z := (solve i, solve2 i). 71 | 72 | (* Compute solve2 example. *) 73 | 74 | (* The second part generalizes the first: the [aim] in Part Two plays the role of 75 | depth ([zpos]) in Part One. *) 76 | 77 | (* We could prove this directly, but just to be fancy, let's make it explicit 78 | that it relies on a _simulation argument_: 79 | the single-step functions [eval1] and [eval1_2] preserve a relation [R] between [position] 80 | and [position_2], so the iterated-step functions [eval] and [eval_2] also preserve [R]. *) 81 | 82 | Lemma eval_sim : forall (R : position -> position_2 -> Prop), 83 | (forall c n p p2, R p p2 -> R (eval1 c n p) (eval1_2 c n p2)) -> 84 | forall xs p p2, 85 | R p p2 -> R (eval xs p) (eval_2 xs p2). 86 | Proof. 87 | intros R SIM; induction xs as [ | [c n] xs IH ]; cbn. 88 | - trivial. 89 | - intros * H; apply IH, SIM, H. 90 | Qed. 91 | 92 | Lemma eval1_fact : forall c n hpos zpos aim, 93 | eval1 c n (hpos, aim) = let '(hpos', _, aim') := eval1_2 c n (hpos, zpos, aim) in (hpos', aim'). 94 | Proof. 95 | destruct c; reflexivity. 96 | Qed. 97 | 98 | Theorem eval_fact : forall xs hpos zpos aim, 99 | eval xs (hpos, aim) = let '(hpos', _, aim') := eval_2 xs (hpos, zpos, aim) in (hpos', aim'). 100 | Proof. 101 | intros xs hpos zpos aim; apply eval_sim. 102 | - intros c n _ [[? ?] ?] ->. apply eval1_fact. 103 | - reflexivity. 104 | Qed. 105 | -------------------------------------------------------------------------------- /src/aoc24_input.txt: -------------------------------------------------------------------------------- 1 | inp w 2 | mul x 0 3 | add x z 4 | mod x 26 5 | div z 1 6 | add x 11 7 | eql x w 8 | eql x 0 9 | mul y 0 10 | add y 25 11 | mul y x 12 | add y 1 13 | mul z y 14 | mul y 0 15 | add y w 16 | add y 8 17 | mul y x 18 | add z y 19 | inp w 20 | mul x 0 21 | add x z 22 | mod x 26 23 | div z 1 24 | add x 14 25 | eql x w 26 | eql x 0 27 | mul y 0 28 | add y 25 29 | mul y x 30 | add y 1 31 | mul z y 32 | mul y 0 33 | add y w 34 | add y 13 35 | mul y x 36 | add z y 37 | inp w 38 | mul x 0 39 | add x z 40 | mod x 26 41 | div z 1 42 | add x 10 43 | eql x w 44 | eql x 0 45 | mul y 0 46 | add y 25 47 | mul y x 48 | add y 1 49 | mul z y 50 | mul y 0 51 | add y w 52 | add y 2 53 | mul y x 54 | add z y 55 | inp w 56 | mul x 0 57 | add x z 58 | mod x 26 59 | div z 26 60 | add x 0 61 | eql x w 62 | eql x 0 63 | mul y 0 64 | add y 25 65 | mul y x 66 | add y 1 67 | mul z y 68 | mul y 0 69 | add y w 70 | add y 7 71 | mul y x 72 | add z y 73 | inp w 74 | mul x 0 75 | add x z 76 | mod x 26 77 | div z 1 78 | add x 12 79 | eql x w 80 | eql x 0 81 | mul y 0 82 | add y 25 83 | mul y x 84 | add y 1 85 | mul z y 86 | mul y 0 87 | add y w 88 | add y 11 89 | mul y x 90 | add z y 91 | inp w 92 | mul x 0 93 | add x z 94 | mod x 26 95 | div z 1 96 | add x 12 97 | eql x w 98 | eql x 0 99 | mul y 0 100 | add y 25 101 | mul y x 102 | add y 1 103 | mul z y 104 | mul y 0 105 | add y w 106 | add y 4 107 | mul y x 108 | add z y 109 | inp w 110 | mul x 0 111 | add x z 112 | mod x 26 113 | div z 1 114 | add x 12 115 | eql x w 116 | eql x 0 117 | mul y 0 118 | add y 25 119 | mul y x 120 | add y 1 121 | mul z y 122 | mul y 0 123 | add y w 124 | add y 13 125 | mul y x 126 | add z y 127 | inp w 128 | mul x 0 129 | add x z 130 | mod x 26 131 | div z 26 132 | add x -8 133 | eql x w 134 | eql x 0 135 | mul y 0 136 | add y 25 137 | mul y x 138 | add y 1 139 | mul z y 140 | mul y 0 141 | add y w 142 | add y 13 143 | mul y x 144 | add z y 145 | inp w 146 | mul x 0 147 | add x z 148 | mod x 26 149 | div z 26 150 | add x -9 151 | eql x w 152 | eql x 0 153 | mul y 0 154 | add y 25 155 | mul y x 156 | add y 1 157 | mul z y 158 | mul y 0 159 | add y w 160 | add y 10 161 | mul y x 162 | add z y 163 | inp w 164 | mul x 0 165 | add x z 166 | mod x 26 167 | div z 1 168 | add x 11 169 | eql x w 170 | eql x 0 171 | mul y 0 172 | add y 25 173 | mul y x 174 | add y 1 175 | mul z y 176 | mul y 0 177 | add y w 178 | add y 1 179 | mul y x 180 | add z y 181 | inp w 182 | mul x 0 183 | add x z 184 | mod x 26 185 | div z 26 186 | add x 0 187 | eql x w 188 | eql x 0 189 | mul y 0 190 | add y 25 191 | mul y x 192 | add y 1 193 | mul z y 194 | mul y 0 195 | add y w 196 | add y 2 197 | mul y x 198 | add z y 199 | inp w 200 | mul x 0 201 | add x z 202 | mod x 26 203 | div z 26 204 | add x -5 205 | eql x w 206 | eql x 0 207 | mul y 0 208 | add y 25 209 | mul y x 210 | add y 1 211 | mul z y 212 | mul y 0 213 | add y w 214 | add y 14 215 | mul y x 216 | add z y 217 | inp w 218 | mul x 0 219 | add x z 220 | mod x 26 221 | div z 26 222 | add x -6 223 | eql x w 224 | eql x 0 225 | mul y 0 226 | add y 25 227 | mul y x 228 | add y 1 229 | mul z y 230 | mul y 0 231 | add y w 232 | add y 6 233 | mul y x 234 | add z y 235 | inp w 236 | mul x 0 237 | add x z 238 | mod x 26 239 | div z 26 240 | add x -12 241 | eql x w 242 | eql x 0 243 | mul y 0 244 | add y 25 245 | mul y x 246 | add y 1 247 | mul z y 248 | mul y 0 249 | add y w 250 | add y 14 251 | mul y x 252 | add z y 253 | -------------------------------------------------------------------------------- /src/aoc13.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export ZArith Ascii String. 2 | From Coq Require Import List. 3 | From stdpp Require Import gmap. 4 | 5 | #[global] Open Scope string_scope. 6 | 7 | Declare Custom Entry paper. 8 | Declare Custom Entry paperf. 9 | 10 | Notation "'input' d1 .. dn f1 .. fn" := (cons d1 .. (cons dn nil) .., cons f1 .. (cons fn nil) ..) 11 | (at level 200, d1 custom paper, f1 custom paperf, only parsing). 12 | 13 | Notation "x , y" := (x%Z,y%Z) 14 | (in custom paper at level 1, x constr at level 0, y constr at level 0). 15 | 16 | Notation "'fold' 'along' c '=' x" := (c x%Z) 17 | (in custom paperf at level 1, c constr at level 0, x constr at level 0). 18 | 19 | Inductive axis := 20 | | x (_ : Z) 21 | | y (_ : Z) 22 | . 23 | 24 | Definition point : Type := Z * Z. 25 | 26 | Definition Input : Type := (list point * list axis). 27 | 28 | Definition example := input 29 | 6,10 30 | 0,14 31 | 9,10 32 | 0,3 33 | 10,4 34 | 4,11 35 | 6,0 36 | 6,12 37 | 4,1 38 | 0,13 39 | 10,12 40 | 3,4 41 | 3,0 42 | 8,4 43 | 1,10 44 | 2,14 45 | 8,10 46 | 9,0 47 | 48 | fold along y=7 49 | fold along x=5 50 | . 51 | 52 | #[local] Open Scope Z_scope. 53 | 54 | Definition fold1_along_x (n : Z) '((i, j) : point) : point := 55 | (if n <=? i then 2 * n - i else i, j). 56 | 57 | Definition fold1_along_y (n : Z) '((i, j) : point) : point := 58 | (i, if n <=? j then 2 * n - j else j). 59 | 60 | Definition fold1_along (n : axis) : point -> point := 61 | match n with 62 | | x n => fold1_along_x n 63 | | y n => fold1_along_y n 64 | end. 65 | 66 | Definition fold_along (n : axis) : list point -> list point := 67 | map (fold1_along n). 68 | 69 | (* stdpp's is quadratic *) 70 | Definition list_to_set {A} `{Countable A} (xs : list A) : gset A := 71 | dom (M := gmap A unit) (gset A) (fold_right (fun x m => insert x tt m) empty xs). 72 | 73 | Definition solve '((dots, folds) : Input) : N := 74 | match folds with 75 | | nil => 0%N 76 | | f :: _ => N.of_nat (size (C := gset _) (list_to_set (fold_along f dots))) 77 | end. 78 | 79 | (* Compute solve example. *) 80 | 81 | Definition fold_all '((dots, folds) : Input) : list point := 82 | fold_left (fun dots f => fold_along f dots) folds dots. 83 | 84 | Definition matrix_of (imin imax jmin jmax : Z) {A} (f : Z * Z -> A) : list (list A) := 85 | N.recursion (fun x => x) (fun dj k nil_ => 86 | let j := jmin + Z.of_N dj in 87 | k (cons (N.recursion (fun x => x) (fun di k nil_ => 88 | let i := imin + Z.of_N di in 89 | k (cons (f (i, j)) nil_)) (Z.to_N (imax - imin + 1)) nil) 90 | nil_) 91 | ) (Z.to_N (jmax - jmin + 1)) nil. 92 | 93 | Infix "::" := String : string_scope. 94 | 95 | Definition display_matrix (xs : list (list ascii)) : string := 96 | fold_right (fun row s => 97 | "010" :: fold_right (fun c s => c :: s) s row) ""%string xs. 98 | 99 | Definition display (dots : list point) : string := 100 | let dots := list_to_set dots in 101 | let imax := fold_left (fun i '(i', _) => Z.max i i') (elements dots) 0 in 102 | let jmax := fold_left (fun j '(_, j') => Z.max j j') (elements dots) 0 in 103 | display_matrix (matrix_of 0 imax 0 jmax (fun ij => 104 | if decide (elem_of ij dots) then "#"%char else "."%char)). 105 | 106 | Definition solve2 (xs : Input) : string := 107 | display (fold_all xs). 108 | 109 | (* Compute solve2 example. *) 110 | 111 | Definition solve12 (xs : Input) := (solve xs, solve2 xs). 112 | -------------------------------------------------------------------------------- /src/aoc25.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export String Ascii NArith List. 2 | From stdpp Require Import list strings. 3 | 4 | Notation "'input' r0 .. rn" := (cons r0%string .. (cons rn%string nil) ..) 5 | (at level 200, r0 at level 0, rn at level 0, only parsing). 6 | 7 | Definition example := input 8 | "v...>>.vv>" 9 | ".vv>>.vv.." 10 | ">>.>v>...v" 11 | ">>v>>.>.v." 12 | "v>v.vv.v.." 13 | ">.>>..v..." 14 | ".vv..>.>v." 15 | "v.v..>>v.v" 16 | "....v..v.>" 17 | . 18 | 19 | Inductive cell := Right | Down | Empty. 20 | Definition parse (xs : list string) : list (list cell) := 21 | map (fun row => 22 | map (fun c => 23 | if (c =? "v")%char then Down else if (c =? ">")%char then Right else Empty) 24 | (list_ascii_of_string row)) 25 | xs. 26 | 27 | Fixpoint init {A} (xs : list A) : list A := 28 | match xs with 29 | | _ :: nil => nil 30 | | x :: xs => x :: init xs 31 | | nil => nil 32 | end. 33 | 34 | (* [xs] is a row extended with the last cell at the beginning and the first cell at the end. *) 35 | Fixpoint _move_right (xs : list cell) : list cell := 36 | match xs with 37 | | Right :: Empty :: xs => Empty :: Right :: _move_right xs 38 | | x :: xs => x :: _move_right xs 39 | | nil => nil 40 | end. 41 | 42 | Definition move_right : list (list cell) -> list (list cell) := 43 | map (fun row => init (List.tl (_move_right (List.last row Empty :: row ++ List.hd Empty row :: nil)))). 44 | 45 | Fixpoint zip_with {A B C} (f : A -> B -> C) (xs : list A) (ys : list B) : list C := 46 | match xs, ys with 47 | | x :: xs, y :: ys => f x y :: zip_with f xs ys 48 | | _, _ => nil 49 | end. 50 | 51 | Fixpoint transpose {A} (xs : list (list A)) : list (list A) := 52 | match xs with 53 | | x :: nil => map (fun y => cons y nil) x 54 | | x :: xs => zip_with cons x (transpose xs) 55 | | nil => nil 56 | end. 57 | 58 | Definition swap (c : cell) : cell := 59 | match c with 60 | | Down => Right 61 | | Right => Down 62 | | Empty => Empty 63 | end. 64 | 65 | Definition transpose' (xs : list (list cell)) : list (list cell) := 66 | transpose (map (map swap) xs). 67 | 68 | Definition move_down (xs : list (list cell)) : list (list cell) := 69 | transpose' (move_right (transpose' xs)). 70 | 71 | #[global] Instance EqDecision_cell : EqDecision cell. 72 | Proof. solve_decision. Defined. 73 | 74 | Fixpoint steps (fuel : nat) (xs : list (list cell)) : list (list cell) := 75 | match fuel with 76 | | O => xs 77 | | S fuel => 78 | let xs' := move_down (move_right xs) in 79 | steps fuel xs' 80 | end. 81 | 82 | Definition show_map (xs : list (list cell)) : string := 83 | let cell2ascii x := 84 | match x with 85 | | Down => "v" 86 | | Right => ">" 87 | | Empty => "." 88 | end%char in 89 | let nl := String "010" "" in 90 | nl ++ String.concat nl (map (fun row => string_of_list_ascii (map cell2ascii row)) xs). 91 | 92 | Fixpoint steps_to_stop (fuel : nat) (xs : list (list cell)) : N := 93 | match fuel with 94 | | O => 0 95 | | S fuel => 96 | let xs' := move_down (move_right xs) in 97 | if bool_decide (xs = xs') then 1 else N.succ (steps_to_stop fuel xs') 98 | end. 99 | 100 | Definition solve (xs : list string) : N := steps_to_stop 999 (parse xs). 101 | 102 | (* Compute solve example. *) 103 | 104 | #[global] Open Scope N_scope. 105 | #[global] Open Scope string_scope. 106 | 107 | Definition solve12 xs := (solve xs, "Merry Christmas"). 108 | -------------------------------------------------------------------------------- /src/aoc18_input.txt: -------------------------------------------------------------------------------- 1 | [[5,[[8,5],8]],[[9,3],[0,3]]] 2 | [[[8,[3,6]],[0,[1,2]]],[[[4,1],4],[7,[5,8]]]] 3 | [[[[2,0],6],[4,8]],[8,[3,0]]] 4 | [[[[8,2],[8,3]],[[0,9],5]],3] 5 | [[[[4,4],[2,3]],8],[[1,[3,8]],[8,4]]] 6 | [[[2,[1,0]],[[3,2],0]],[9,2]] 7 | [[[0,4],[[9,8],[6,6]]],3] 8 | [[[6,[6,2]],[[4,5],3]],[0,7]] 9 | [[[[2,8],4],[[1,2],[3,8]]],9] 10 | [[[3,[7,6]],[9,9]],[[8,9],[[6,2],[3,4]]]] 11 | [0,[4,[[4,1],8]]] 12 | [[[[3,3],[8,7]],[9,7]],[[7,6],4]] 13 | [[1,[[0,6],4]],[[5,[3,3]],6]] 14 | [[[0,4],7],4] 15 | [[[2,[1,7]],8],[6,[2,[8,7]]]] 16 | [[[9,7],[[2,5],[7,9]]],[1,[4,[8,6]]]] 17 | [[[[3,7],6],[[1,6],[5,4]]],[0,[6,2]]] 18 | [9,5] 19 | [[[[6,1],[4,5]],[[4,2],8]],[[5,[5,1]],[[7,3],6]]] 20 | [9,[9,[[7,4],[6,9]]]] 21 | [3,[[9,2],9]] 22 | [[[[1,7],6],[3,[9,7]]],[[6,[4,3]],[[5,6],5]]] 23 | [[[[0,6],[7,9]],[[2,8],2]],[5,[3,[4,9]]]] 24 | [0,[[[1,8],7],[9,4]]] 25 | [5,[0,[[4,5],6]]] 26 | [[[[7,9],[4,9]],[7,[7,5]]],[6,[[1,6],[8,7]]]] 27 | [[[4,[0,1]],[[9,0],[8,1]]],[[0,7],[5,[0,4]]]] 28 | [0,1] 29 | [[[[7,7],[0,7]],8],[[3,[4,2]],[6,6]]] 30 | [[[[7,8],[4,3]],[7,[7,0]]],[3,[2,3]]] 31 | [[[[6,9],[3,2]],[[4,7],2]],[[3,[7,5]],[[3,3],3]]] 32 | [7,[[[6,7],[1,3]],9]] 33 | [[[[2,9],[2,1]],[3,[9,9]]],[1,[[0,7],[2,4]]]] 34 | [[7,4],[[[0,0],5],[[2,4],5]]] 35 | [[[[2,9],8],[3,4]],[6,[[8,7],[4,3]]]] 36 | [[[8,3],0],[4,[[6,7],5]]] 37 | [[[6,[4,1]],[[1,1],[0,4]]],[[[6,2],[8,6]],[5,2]]] 38 | [9,[[[5,6],0],[[7,2],3]]] 39 | [7,[[[6,6],[1,7]],8]] 40 | [[1,[9,[6,2]]],[[4,0],[[7,7],[4,2]]]] 41 | [[[5,[5,9]],[0,[7,2]]],[[3,3],6]] 42 | [[5,[3,6]],[[0,[8,4]],[6,[5,5]]]] 43 | [[[0,5],[[8,7],[0,3]]],[[[4,1],[6,2]],[[3,2],[2,7]]]] 44 | [[[6,9],5],[[7,3],[[5,0],[2,2]]]] 45 | [[3,5],[[1,[3,4]],[2,[5,3]]]] 46 | [[9,9],[4,6]] 47 | [[[[6,4],[3,7]],[3,8]],[3,[2,[3,7]]]] 48 | [[4,[[1,1],6]],[7,[[1,1],6]]] 49 | [[[[6,4],3],9],2] 50 | [[[[8,1],3],7],[4,[9,1]]] 51 | [4,[[[7,7],6],8]] 52 | [[[7,5],[8,1]],[[6,[6,5]],[6,7]]] 53 | [[8,[3,[1,3]]],[2,[[6,1],[0,5]]]] 54 | [9,[[8,6],0]] 55 | [[8,[1,5]],[[[6,4],6],1]] 56 | [2,[[3,[4,6]],[[2,9],[6,4]]]] 57 | [[[[0,9],[2,0]],[[2,4],7]],[[[7,1],3],[7,9]]] 58 | [[[3,6],[[6,6],1]],[[[0,5],[6,8]],5]] 59 | [[[4,5],[[5,1],0]],[3,[[3,1],[2,8]]]] 60 | [[[[9,0],[7,6]],5],[6,[[0,3],1]]] 61 | [[[1,4],[5,7]],[[9,[3,8]],3]] 62 | [[[7,7],1],[[[5,0],[4,0]],8]] 63 | [[[[0,9],[0,6]],[[5,8],[7,4]]],2] 64 | [[[[0,2],1],[[4,8],0]],[4,[[8,7],[9,1]]]] 65 | [[[1,[2,0]],[[8,4],[0,0]]],5] 66 | [[[9,[8,1]],[[1,1],[4,2]]],[9,[7,[6,9]]]] 67 | [[[[0,2],[1,5]],[[9,2],[8,7]]],[[6,8],[6,0]]] 68 | [[[3,[6,7]],[[9,8],[6,9]]],[8,[[4,6],5]]] 69 | [[[9,[1,5]],[[4,8],9]],2] 70 | [[[0,[1,5]],0],0] 71 | [[[[4,1],4],[4,[7,4]]],[[[3,9],9],3]] 72 | [[[9,7],[[8,7],[0,0]]],[[[0,0],3],3]] 73 | [[9,[[2,0],6]],[[8,6],[5,4]]] 74 | [2,[6,1]] 75 | [[7,[1,[9,5]]],[[[7,8],[1,0]],[6,3]]] 76 | [[[[2,3],1],[7,3]],[[[1,5],[2,2]],[[6,3],7]]] 77 | [4,6] 78 | [[[[4,0],1],2],[[[0,5],8],[8,[0,4]]]] 79 | [[5,[7,0]],[[[4,5],[0,2]],5]] 80 | [[[5,[3,1]],[[8,4],[4,9]]],[2,[[4,8],9]]] 81 | [[[0,7],2],[[[2,5],8],[0,[5,3]]]] 82 | [[[[2,2],[8,1]],[8,[1,3]]],[6,7]] 83 | [[[9,2],[[4,8],[7,1]]],[[[5,2],7],[5,8]]] 84 | [[[2,8],[[3,6],[8,3]]],[[0,5],6]] 85 | [[[3,[7,6]],[4,[5,2]]],6] 86 | [[7,[[5,2],8]],[1,[8,[8,3]]]] 87 | [[[[8,9],7],[[1,1],0]],[[3,6],[[7,8],9]]] 88 | [[4,[[4,2],[7,9]]],[[8,9],[8,8]]] 89 | [[[5,5],[9,[0,7]]],[[[5,8],8],4]] 90 | [[8,[[4,4],[0,0]]],[[2,1],[[2,5],3]]] 91 | [[6,[[4,3],[1,6]]],0] 92 | [[[4,[1,6]],2],[[0,7],1]] 93 | [[[6,[9,9]],[4,8]],[[[1,1],9],[4,[1,7]]]] 94 | [[[[2,1],6],[[3,8],[2,2]]],[9,[7,6]]] 95 | [[0,[[1,0],9]],[8,[0,6]]] 96 | [[[8,[3,4]],[[6,7],[9,9]]],[[7,[6,8]],[[7,7],[6,8]]]] 97 | [4,[[[4,5],[4,4]],[5,[9,0]]]] 98 | [[[[8,2],7],[6,5]],2] 99 | [[9,7],[4,[[5,3],7]]] 100 | [[[[6,5],0],1],[[[5,8],[3,9]],[[9,4],[8,3]]]] 101 | -------------------------------------------------------------------------------- /src/aoc03.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export ZArith NArith List Number Decimal. 2 | 3 | Import ListNotations. 4 | 5 | Record bits := Mk_bits { unbits : list bool }. 6 | 7 | (* Reinterpret a decimal with only digits 0 and 1 in binary. *) 8 | Fixpoint bindec_to_bits_ (d : Decimal.uint) : list bool := 9 | match d with 10 | | D0 d => false :: bindec_to_bits_ d 11 | | D1 d => true :: bindec_to_bits_ d 12 | | Nil | _ => [] 13 | end. 14 | 15 | Definition bindec_to_bits (d : Number.uint) : option bits := 16 | match d with 17 | | UIntDecimal d => Some (Mk_bits (bindec_to_bits_ d)) 18 | | _ => None 19 | end. 20 | 21 | Definition dummy_bits_to (b : bits) : option Number.uint := None. 22 | 23 | Declare Scope bits_scope. 24 | Number Notation bits bindec_to_bits dummy_bits_to : bits_scope. 25 | 26 | Notation "'input' x .. y" := (cons (unbits x) .. (cons (unbits y) nil) ..) (at level 200, x at level 0). 27 | 28 | #[global] Open Scope bits_scope. 29 | 30 | Definition example : list _ := input 31 | 00100 32 | 11110 33 | 10110 34 | 10111 35 | 10101 36 | 01111 37 | 00111 38 | 11100 39 | 10000 40 | 11001 41 | 00010 42 | 01010 43 | . 44 | 45 | Fixpoint zip_with {A B C} (f : A -> B -> C) (xs : list A) (ys : list B) : list C := 46 | match xs, ys with 47 | | x :: xs, y :: ys => f x y :: zip_with f xs ys 48 | | _, _ => nil 49 | end. 50 | 51 | Fixpoint transpose {A} (xs : list (list A)) : list (list A) := 52 | match xs with 53 | | x :: [] => map (fun y => cons y nil) x 54 | | x :: xs => zip_with cons x (transpose xs) 55 | | [] => [] 56 | end. 57 | 58 | Definition sum_bool_Z (xs : list bool) : Z := 59 | fold_left (fun i (b : bool) => i + if b then 1 else -1)%Z xs 0%Z. 60 | 61 | Fixpoint bits_to_N_ (acc : N) (xs : list bool) : N := 62 | match xs with 63 | | [] => acc 64 | | x :: xs => bits_to_N_ (if x then acc * 2 + 1 else acc * 2) xs 65 | end. 66 | 67 | Definition bits_to_N := bits_to_N_ 0. 68 | 69 | Record PartOne := { gamma : list bool ; epsilon : list bool }. 70 | 71 | Definition part_one (xs : list (list bool)) : PartOne := 72 | let tmp := map (fun x => if (sum_bool_Z x option B) (xs : list A) : list B := 76 | match xs with 77 | | [] => [] 78 | | x :: xs => 79 | match f x with 80 | | None => map_filter f xs 81 | | Some y => y :: map_filter f xs 82 | end 83 | end. 84 | 85 | Definition solve (xs : list (list bool)) : N := 86 | let ans := part_one xs in 87 | bits_to_N (gamma ans) * bits_to_N (epsilon ans). 88 | 89 | (* Compute solve example. *) 90 | 91 | Definition head {A} (xs : list A) : option A := 92 | match xs with 93 | | x :: _ => Some x 94 | | [] => None 95 | end. 96 | 97 | Fixpoint brrr (n : nat) (switch : bool) (xs : list (list bool * list bool)) : list bool := 98 | match n with 99 | | O => [] 100 | | S n => 101 | let bit := xorb switch (0 <=? sum_bool_Z (map_filter (fun '(x, _) => head x) xs))%Z in 102 | match map_filter (fun '(x, y) => 103 | match x with 104 | | c :: x => if Bool.eqb bit c then Some (x, y) else None 105 | | _ => None 106 | end) xs 107 | with 108 | | [(_, x)] => x 109 | | xs => brrr n switch xs 110 | end 111 | end. 112 | 113 | Definition brr switch xs := brrr (length xs) switch (map (fun x => (x, x)) xs). 114 | 115 | Definition solve2 (xs : list (list bool)) : N := 116 | let ogr := brr false xs in 117 | let csr := brr true xs in 118 | bits_to_N ogr * bits_to_N csr. 119 | 120 | (* Compute solve2 example. *) 121 | 122 | Definition solve12 (i : list (list bool)) : N * N := 123 | (solve i, solve2 i). 124 | -------------------------------------------------------------------------------- /src/aoc07_input.txt: -------------------------------------------------------------------------------- 1 | 1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,76,50,481,307,723,1100,235,147,851,504,1068,780,490,126,771,831,358,711,68,281,645,644,862,705,372,217,679,1097,1005,728,1739,571,40,1293,782,378,802,245,1370,1512,9,372,448,64,36,1212,141,585,1468,278,286,476,239,285,664,277,43,665,1037,654,205,1238,36,41,276,945,624,47,91,1569,284,107,845,60,961,30,21,269,1091,304,364,339,169,430,176,156,1483,1510,111,146,447,590,1227,611,483,428,396,839,307,901,380,128,80,535,461,482,379,59,281,977,44,966,545,37,163,845,845,151,936,269,938,612,1284,863,516,927,511,825,125,599,101,394,1062,140,483,218,83,443,404,492,78,507,860,1741,43,128,60,566,181,5,554,937,163,280,655,184,480,408,127,935,613,766,46,312,770,697,275,13,84,600,168,83,281,599,607,1441,197,344,0,302,414,147,370,748,421,844,871,319,666,117,640,247,167,529,324,252,235,303,443,1305,796,109,20,364,532,1388,708,769,916,340,405,90,47,504,516,97,535,28,69,960,590,254,106,188,190,1388,698,246,264,98,229,1648,292,710,14,421,31,147,1493,552,1371,454,4,146,674,452,1267,1027,170,141,936,1341,884,558,276,631,68,39,2,464,1,839,318,881,413,2,452,352,34,89,323,884,1439,243,79,56,128,1273,1134,606,11,682,747,415,599,782,179,269,320,682,177,336,466,10,370,159,1636,367,888,573,171,682,60,9,59,332,10,1496,637,1029,413,186,1183,77,309,461,883,1079,699,233,69,259,108,1160,435,480,495,13,858,718,126,115,728,1008,133,442,7,598,1475,1156,226,162,415,3,151,72,527,792,494,763,144,64,490,273,1245,300,465,744,36,1465,251,8,494,1126,362,180,1263,175,141,1041,103,163,205,568,93,699,103,437,204,931,563,550,88,415,146,265,31,221,1123,835,375,1101,578,388,92,1417,845,308,343,499,158,293,242,4,509,574,254,1556,69,668,691,0,558,16,687,1210,166,748,400,863,66,600,771,1073,561,738,398,384,232,350,393,1113,1222,153,462,907,797,712,18,1463,1185,1055,994,57,130,265,131,52,463,902,453,38,132,783,1560,232,169,1162,173,311,5,1477,397,336,480,540,491,67,340,27,291,341,35,275,78,1525,387,218,63,79,533,4,569,1643,595,1508,851,39,1200,912,10,53,42,60,154,1174,155,275,137,677,367,1373,4,708,441,756,647,1054,872,1039,109,530,1179,939,429,567,866,1411,436,23,212,184,66,79,831,538,90,827,678,549,313,434,60,907,284,171,570,1091,603,447,122,1092,29,789,563,462,15,310,340,16,365,393,614,48,368,42,457,736,737,1008,513,61,764,366,400,525,1683,1177,909,908,112,734,16,79,917,541,127,107,79,1208,32,258,596,166,376,1313,735,1457,864,563,55,439,54,694,81,93,48,470,1028,689,1177,1331,155,412,847,250,405,387,8,456,18,619,533,729,1475,1182,935,210,55,355,958,15,32,598,85,175,471,1087,280,652,53,13,225,12,488,717,353,2,134,351,698,276,456,209,535,604,19,12,785,3,63,879,437,216,1,1275,811,786,417,33,51,733,1074,143,309,65,555,557,78,611,909,260,973,701,998,490,213,9,233,760,933,916,437,1369,1952,372,324,859,670,73,296,1391,127,407,230,52,16,547,803,883,258,308,710,343,1290,184,8,41,9,68,104,175,1034,1544,219,752,327,690,134,601,1574,214,385,1233,231,267,944,1533,349,431,97,632,278,1505,162,888,62,90,489,351,990,846,14,159,134,14,314,148,214,1153,513,114,6,49,10,14,957,219,16,204,954,863,50,482,90,696,99,253,252,433,57,385,54,343,106,154,78,1595,590,380,102,825,1933,191,1328,374,263,355,137,494,60,781,1113,391,274,325,326,14,965,269,15,32,742,81,393,730,892,982,103,890,499,58,816,292,29,480,173,831,132,1033,1511,1137,1511,22,1105,146,344,308,915,540,1371,1238,414,352,304,841,749,6,491,30,1322,415,293,1207,31,90,636,303,1551,354,23,275,18,32,623,1483,49,12,311,407,1551,296,252,647,778,1499,98,1220,264,1020,1440,377,1125,8,72,270,162,348,3,1023,965,719,62,1467,1176,663,439,557,654,85,1493,70,349,10,727,15,1173,387,529,608,1398,905,619,173,849,1493,49,88,4,708,1084,370,1007,285,4,530,770,561,26,669,1100,30,876,649,178,32,354,621,911,334,514,9,449,1019,107 2 | -------------------------------------------------------------------------------- /src/aoc18.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List. 2 | 3 | #[local] Open Scope N_scope. 4 | 5 | Inductive t := 6 | | Lf (_ : N) 7 | | Nd (_ _ : t) 8 | . 9 | 10 | Declare Custom Entry bin. 11 | 12 | Notation "'input' x .. y" := (cons x .. (cons y nil) ..) (at level 200, x custom bin, y custom bin). 13 | 14 | Notation "'[' x ',' y ']'" := (Nd x y) (in custom bin at level 1). 15 | Notation "n" := (Lf n) (in custom bin at level 0, n bigint). 16 | 17 | Definition example : list t := input 18 | [1,2] 19 | [[1,2],3] 20 | [9,[8,7]] 21 | [[1,9],[8,5]] 22 | [[[[1,2],[3,4]],[[5,6],[7,8]]],9] 23 | [[[9,[3,8]],[[0,9],6]],[[[3,7],[4,9]],3]] 24 | [[[[1,3],[5,3]],[[1,3],[8,7]]],[[[4,9],[6,9]],[[8,2],[7,3]]]] 25 | . 26 | 27 | Definition unLf (x : t) : N := 28 | match x with 29 | | Lf n => n 30 | | _ => 0 31 | end. 32 | 33 | Fixpoint add_left (x : t) (n : N) : t := 34 | match x with 35 | | Lf m => Lf (n + m) 36 | | Nd l r => Nd (add_left l n) r 37 | end. 38 | 39 | Fixpoint add_right (x : t) (n : N) : t := 40 | match x with 41 | | Lf m => Lf (n + m) 42 | | Nd l r => Nd l (add_right r n) 43 | end. 44 | 45 | Fixpoint explode (depth : N) (x : t) : option (N * t * N) := 46 | match x with 47 | | Lf _ => None 48 | | Nd l r => 49 | if depth =? 4 then Some (unLf l, Lf 0, unLf r) 50 | else match explode (N.succ depth) l with 51 | | None => 52 | match explode (N.succ depth) r with 53 | | None => None 54 | | Some (rl, r', rr) => Some (0, Nd (add_right l rl) r', rr) 55 | end 56 | | Some (ll, l', lr) => Some (ll, Nd l' (add_left r lr), 0) 57 | end 58 | end. 59 | 60 | Fixpoint split (x : t) : option t := 61 | match x with 62 | | Lf n => if n <=? 9 then None else Some (Nd (Lf (n / 2)) (Lf ((n+1) / 2))) 63 | | Nd l r => 64 | match split l with 65 | | None => 66 | match split r with 67 | | None => None 68 | | Some r => Some (Nd l r) 69 | end 70 | | Some l => Some (Nd l r) 71 | end 72 | end. 73 | 74 | Definition reduce1 (x : t) : option t := 75 | match explode 0 x with 76 | | None => split x 77 | | Some (_, x, _) => Some x 78 | end. 79 | 80 | Definition reduce (fuel : N) : t -> t := 81 | N.iter fuel (fun _reduce x => 82 | match reduce1 x with 83 | | None => x 84 | | Some x => _reduce x 85 | end) (fun x => x). 86 | 87 | Fixpoint magnitude (x : t) : N := 88 | match x with 89 | | Lf n => n 90 | | Nd l r => 3 * magnitude l + 2 * magnitude r 91 | end. 92 | 93 | Definition solve (i : list t) : N := 94 | match i with 95 | | nil => 0 96 | | cons x xs => magnitude (fold_left (fun x y => reduce 1000 (Nd x y)) xs x) 97 | end. 98 | 99 | Definition example2 := input 100 | [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] 101 | [[[5,[2,8]],4],[5,[[9,9],0]]] 102 | [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] 103 | [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] 104 | [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] 105 | [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] 106 | [[[[5,4],[7,7]],8],[[8,3],8]] 107 | [[9,3],[[9,9],[6,[4,9]]]] 108 | [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] 109 | [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]] 110 | . 111 | 112 | (* Compute solve example. *) 113 | (* Compute solve example2. *) 114 | 115 | Fixpoint pick {A} (xs : list A) : list (A * list A) := 116 | match xs with 117 | | nil => nil 118 | | x :: xs => (x, xs) :: map (fun '(y,ys) => (y,x::ys)) (pick xs) 119 | end. 120 | 121 | Definition pick2 {A} (xs : list A) : list (A * A) := 122 | concat (map (fun '(x, xs) => map (fun '(y, ys) => (x, y)) (pick xs)) (pick xs)). 123 | 124 | Definition maximum (xs : list N) : N := fold_left N.max xs 0. 125 | 126 | Definition solve2 (xs : list t) : N := 127 | maximum (map (fun '(x, y) => magnitude (reduce 1000 (Nd x y))) (pick2 xs)). 128 | 129 | (* Compute solve2 example2. *) 130 | 131 | Definition solve12 xs := (solve xs, solve2 xs). 132 | -------------------------------------------------------------------------------- /src/aoc14.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith Ascii String. 2 | From stdpp Require Import gmap. 3 | 4 | Declare Custom Entry arr. 5 | 6 | Notation "'input' i j1 .. jn" := (i%string, cons j1 .. (cons jn nil) ..) 7 | (at level 200, i at level 0, j1 custom arr, jn custom arr). 8 | 9 | Notation "p -> q" := (p%string, q%char) 10 | (in custom arr at level 1, p constr at level 0, q constr at level 0). 11 | 12 | Definition Input : Type := string * list (string * ascii). 13 | 14 | Definition example : Input := input 15 | "NNCB" 16 | 17 | "CH" -> "B" 18 | "HH" -> "N" 19 | "CB" -> "H" 20 | "NH" -> "C" 21 | "HB" -> "C" 22 | "HC" -> "B" 23 | "HN" -> "C" 24 | "NN" -> "C" 25 | "BH" -> "H" 26 | "NC" -> "B" 27 | "NB" -> "B" 28 | "BN" -> "B" 29 | "BB" -> "N" 30 | "BC" -> "B" 31 | "CC" -> "N" 32 | "CN" -> "C" 33 | . 34 | 35 | Infix "::" := String : string_scope. 36 | 37 | #[global] Open Scope N_scope. 38 | 39 | Definition pairmap (xs : list (string * ascii)) : gmap (ascii * ascii) ascii := 40 | fold_left (fun m '(x, y) => 41 | match x with 42 | | (x1 :: x2 :: "")%string => insert (x1,x2) y m 43 | | _ => m 44 | end) xs empty. 45 | 46 | Fixpoint _occs (z : list ascii) : gmap (ascii * ascii) N := 47 | match z with 48 | | nil | _ :: nil => empty 49 | | c1 :: (c2 :: _) as z => 50 | let incr o := match o with 51 | | None => Some 1%N 52 | | Some n => Some (N.succ n) 53 | end in 54 | partial_alter incr (c1, c2) (_occs z) 55 | end. 56 | 57 | Definition occ (s : string) : (list ascii * gmap (ascii * ascii) N) := 58 | let z := list_ascii_of_string s in 59 | let ends := match z with 60 | | c1 :: c2 :: z' => c1 :: List.last z' c2 :: nil 61 | | c1 :: nil => c1 :: nil 62 | | nil => nil 63 | end in 64 | (ends, _occs z). 65 | 66 | Definition Pairs : Type := gmap (ascii * ascii) N. 67 | 68 | Definition incrmap {A} `{Countable A} (a : A) (n : N) : gmap A N -> gmap A N := 69 | partial_alter (fun i => Some 70 | match i with 71 | | Some i => i + n 72 | | None => n 73 | end) a. 74 | 75 | Definition step_pairs (trans : gmap (ascii * ascii) ascii) (pairs : Pairs) : Pairs := 76 | let go m '((a, b), n) := 77 | match lookup (a, b) trans with 78 | | None => incrmap (a, b) n m 79 | | Some c => incrmap (a, c) n (incrmap (c, b) n m) 80 | end in 81 | fold_left go (map_to_list pairs) empty. 82 | 83 | Definition steps_pairs (n : N) (trans : gmap (ascii * ascii) ascii) : Pairs -> Pairs := 84 | N.iter n (step_pairs trans). 85 | 86 | Definition count (extra : list ascii) (pairs : Pairs) : gmap ascii N := 87 | let extra' := fold_left (fun m c => incrmap c 1 m) extra empty in 88 | let pairs' := 89 | fold_left (fun m '((a, b), n) => incrmap a n (incrmap b n m)) (map_to_list pairs) extra' in 90 | fmap N.div2 pairs'. 91 | 92 | Fixpoint max_by {A} (leb : A -> A -> bool) (a : A) (xs : list A) : A := 93 | match xs with 94 | | nil => a 95 | | x :: xs => max_by leb (if leb a x then x else a) xs 96 | end. 97 | 98 | Definition min_by {A} (leb : A -> A -> bool) := max_by (fun x y => leb y x). 99 | 100 | Definition min_max (z : gmap ascii N) : N * N := 101 | let z := map snd (map_to_list z) in 102 | match z with 103 | | n0 :: z => (min_by N.leb n0 z, max_by N.leb n0 z) 104 | | nil => (0, 0) 105 | end. 106 | 107 | Definition run (n : N) '((ini, trans) : Input) := 108 | let trans := pairmap trans in 109 | let '(extra, pairs) := occ ini in 110 | let pairs := steps_pairs n trans pairs in 111 | (extra, pairs). 112 | 113 | Definition _solve (n : N) (x : Input) : N := 114 | let '(extra, pairs) := run n x in 115 | let cc := count extra pairs in 116 | let '(mini, maxi) := min_max cc in 117 | maxi - mini. 118 | 119 | Definition solve := _solve 10. 120 | Definition solve2 := _solve 40. 121 | Definition solve12 x := (solve x, solve2 x). 122 | 123 | (* Compute solve example. *) 124 | -------------------------------------------------------------------------------- /src/aoc04.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List. 2 | Import ListNotations. 3 | 4 | #[global] Open Scope N. 5 | 6 | Declare Custom Entry bingo. 7 | Declare Custom Entry bingo1. 8 | 9 | Record Input := { rand : list N ; boards : list (list (list N)) }. 10 | 11 | Notation "'input' rand1 ',' .. ',' randn board1 .. boardn" := 12 | {| rand := cons rand1 .. (cons randn nil) .. 13 | ; boards := cons board1 .. (cons boardn nil) .. 14 | |} 15 | (at level 200, randn at level 0, board1 custom bingo, only parsing). 16 | 17 | Notation "a b c d e" := [a; b; c; d; e] 18 | (in custom bingo at level 1, a custom bingo1, b custom bingo1, c custom bingo1, d custom bingo1, e custom bingo1). 19 | 20 | Notation "a b c d e" := [a; b; c; d; e] 21 | (in custom bingo1 at level 1, a constr at level 0, b constr at level 0, c constr at level 0, d constr at level 0, e constr at level 0). 22 | 23 | Definition example : Input := input 24 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 25 | 26 | 22 13 17 11 0 27 | 8 2 23 4 24 28 | 21 9 14 16 7 29 | 6 10 3 18 5 30 | 1 12 20 15 19 31 | 32 | 3 15 0 2 22 33 | 9 18 13 17 5 34 | 19 8 7 25 23 35 | 20 11 10 24 4 36 | 14 21 16 12 6 37 | 38 | 14 21 17 24 4 39 | 10 16 15 9 19 40 | 18 8 23 26 20 41 | 22 11 13 6 5 42 | 2 0 12 3 7 43 | . 44 | 45 | Definition Board := list (list (option N)). 46 | 47 | Definition mkBoard : list (list N) -> Board := map (map Some). 48 | 49 | Definition call (n : N) : Board -> Board := 50 | map (map (fun x => match x with Some m => if N.eqb m n then None else x | None => x end)). 51 | 52 | Fixpoint zip_with {A B C} (f : A -> B -> C) (xs : list A) (ys : list B) : list C := 53 | match xs, ys with 54 | | x :: xs, y :: ys => f x y :: zip_with f xs ys 55 | | _, _ => nil 56 | end. 57 | 58 | Fixpoint transpose {A} (xs : list (list A)) : list (list A) := 59 | match xs with 60 | | x :: [] => map (fun y => cons y nil) x 61 | | x :: xs => zip_with cons x (transpose xs) 62 | | [] => [] 63 | end. 64 | 65 | Definition isNone {A} (x : option A) : bool := 66 | match x with 67 | | None => true 68 | | Some _ => false 69 | end. 70 | 71 | Definition cleared : list (option N) -> bool := 72 | forallb isNone. 73 | 74 | Definition winning (b : Board) : bool := 75 | existsb cleared b || existsb cleared (transpose b). 76 | 77 | Fixpoint fold_with {A B} (f : B -> B -> B) (y : B) (g : A -> B) (xs : list A) : B := 78 | match xs with 79 | | [] => y 80 | | x :: xs => f (g x) (fold_with f y g xs) 81 | end. 82 | 83 | Definition sum_with {A} : (A -> N) -> list A -> N := fold_with N.add 0%N. 84 | 85 | Definition score : Board -> N := 86 | sum_with (sum_with (fun x => match x with None => 0 | Some x => x end)). 87 | 88 | Fixpoint bingo (rs : list N) (bs : list Board) : N * Board := 89 | match rs with 90 | | [] => (0, []) (* must not happen *) 91 | | r :: rs => 92 | let bs := map (call r) bs in 93 | match find winning bs with 94 | | None => bingo rs bs 95 | | Some b => (r, b) 96 | end 97 | end. 98 | 99 | Definition solve (xs : Input) : N := 100 | let '(r, b) := bingo (rand xs) (map mkBoard (boards xs)) in 101 | r * score b. 102 | 103 | (* Compute solve example. *) 104 | 105 | Fixpoint unbingo (rs : list N) (bs : list Board) : N * Board := 106 | match rs with 107 | | [] => (0, []) (* must not happen *) 108 | | r :: rs => 109 | let bs0 := map (call r) bs in 110 | let bs := filter (fun b => negb (winning b)) bs0 in 111 | match bs with 112 | | [] => 113 | match bs0 with 114 | | b :: _ => (r, b) 115 | | _ => (0, []) (* must not happen *) 116 | end 117 | | _ => unbingo rs bs 118 | end 119 | end. 120 | 121 | Definition solve2 (xs : Input) : N := 122 | let '(r, b) := unbingo (rand xs) (map mkBoard (boards xs)) in 123 | r * score b. 124 | 125 | (* Compute solve2 example. *) 126 | 127 | Definition solve12 (xs : Input) : N * N := 128 | (solve xs, solve2 xs). 129 | -------------------------------------------------------------------------------- /src/aoc20.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export ZArith NArith List String Ascii. 2 | From stdpp Require Import gmap. 3 | Import ListNotations. 4 | 5 | Set Implicit Arguments. 6 | 7 | (* dirty preprocessing will insert an empty string *) 8 | Notation "'input' tbl _r0 r1 .. rn" := (tbl%string, cons r1%string .. (cons rn%string nil) ..) 9 | (at level 200, tbl at level 0, _r0 at level 0, r1 at level 0, rn at level 0, only parsing). 10 | 11 | Definition example := input 12 | "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..## 13 | #..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.### 14 | .######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#. 15 | .#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#..... 16 | .#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.. 17 | ...####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#..... 18 | ..##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#" 19 | "" 20 | "#..#." 21 | "#...." 22 | "##..#" 23 | "..#.." 24 | "..###" 25 | . 26 | 27 | Inductive cellstate := On | Off. 28 | 29 | Definition foldli {A B} (f : N -> A -> B -> B) (b : B) (xs : list A) : B := 30 | fold_right (fun x go i b => go (N.succ i) (f i x b)) (fun _ b => b) xs 0%N b. 31 | 32 | Definition _mk_table (s : string) : gmap N unit := 33 | foldli (fun i c => if (c =? "#")%char then insert i tt else fun m => m) empty 34 | (filter (fun c => (c =? "#") || (c =? "."))%bool%char (list_ascii_of_string s)). 35 | 36 | Definition mk_table (s : string) : N -> cellstate := 37 | let t := _mk_table s in 38 | fun i => match lookup i t with 39 | | None => Off 40 | | Some _ => On 41 | end. 42 | 43 | Definition point : Type := Z * Z. 44 | 45 | Definition mk_grid : list string -> list (list cellstate) := 46 | map (fun row => map (fun c => if (c =? "#")%char then On else Off) (list_ascii_of_string row)). 47 | 48 | Definition shifts0 {A} (x0 : A) : list (list A -> list A) := 49 | [fun x => x; fun x => x0 :: x; fun x => x0 :: x0 :: x]. 50 | 51 | Definition shifts {A} (x0 : A) : list (list (list A) -> list (list A)) := Eval cbn in 52 | List.rev' (map (fun '(f, g) x => f (g x)) 53 | (list_prod 54 | (shifts0 []) 55 | ((fun x => x) :: List.tl (map (@map _ _) (shifts0 x0))))). 56 | 57 | Definition snocbit (i : N) (b : cellstate) := 58 | match b with 59 | | On => N.succ_double i 60 | | Off => N.double i 61 | end. 62 | 63 | Fixpoint zip_with_extend {A B C} (f : A -> B -> C) (x0 : A) (y0 : B) 64 | (xs : list A) (ys : list B) : list C := 65 | match xs, ys with 66 | | x :: xs, y :: ys => f x y :: zip_with_extend f x0 y0 xs ys 67 | | [], _ => map (f x0) ys 68 | | _, [] => map (fun x => f x y0) xs 69 | end. 70 | 71 | Definition nine (def : cellstate) (g : list (list cellstate)) : list (list N) := 72 | let zz def' := zip_with_extend (zip_with_extend snocbit def' def) [] [] in 73 | snd (fold_left (fun '(def', g') z => (snocbit def' def, zz def' g' (z g))) (shifts def) (0%N, [])). 74 | 75 | Definition step (f : N -> cellstate) '((def, g) : cellstate * list (list cellstate)) 76 | : cellstate * list (list cellstate) := 77 | let newdef := 78 | match def with 79 | | Off => f 0%N 80 | | On => f 511%N 81 | end in 82 | (newdef, map (map f) (nine def g)). 83 | 84 | Definition sum_with {A} (f : A -> N) (xs : list A) : N := 85 | fold_left (fun i x => i + f x)%N xs 0%N. 86 | 87 | Definition count '((def, g) : cellstate * list (list cellstate)) : N := 88 | match def with 89 | | On => 9999999999%N (* Boo *) 90 | | Off => sum_with (sum_with (fun c => match c with On => 1 | Off => 0 end)%N) g 91 | end. 92 | 93 | Definition enhance (n : N) (f : N -> cellstate) 94 | : cellstate * list (list cellstate) -> cellstate * list (list cellstate) := 95 | N.iter n (step f). 96 | 97 | Definition solve '(t, g) := 98 | let t := mk_table t in 99 | let g := (Off, mk_grid g) in 100 | count (enhance 2 t g). 101 | 102 | (* Compute solve example. *) 103 | (* 104 | Compute 105 | let '(t, g) := example in 106 | let t := mk_table t in 107 | let g := (Off, mk_grid g) in 108 | step t (step t g). 109 | *) 110 | 111 | Definition solve2 '(t, g) := 112 | let t := mk_table t in 113 | let g := (Off, mk_grid g) in 114 | count (enhance 50 t g). 115 | 116 | (* Compute solve2 example. *) 117 | 118 | Definition solve12 '(t, g) := 119 | let t := mk_table t in 120 | let g := (Off, mk_grid g) in 121 | (count (enhance 2 t g), count (enhance 50 t g)). 122 | -------------------------------------------------------------------------------- /src/aoc21.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List. 2 | 3 | From stdpp Require Import gmap. 4 | 5 | Set Implicit Arguments. 6 | 7 | #[global] Open Scope N_scope. 8 | 9 | Notation "'input' 'Player' '1' 'starting' 'position' ':' n1 'Player' '2' 'starting' 'position' ':' n2" := (n1%N, n2%N) 10 | (at level 200, n1 at level 0, only parsing). 11 | 12 | Definition example := input 13 | Player 1 starting position: 4 14 | Player 2 starting position: 8 15 | . 16 | 17 | Record board := MkBoard 18 | { p1 : N 19 | ; p2 : N 20 | ; s1 : N 21 | ; s2 : N 22 | }. 23 | 24 | Definition mk_board '((p1,p2) : N * N) : board := 25 | {| p1 := p1 ; p2 := p2 ; s1 := 0 ; s2 := 0 |}. 26 | 27 | #[global] Instance EqDecision_board : EqDecision board. 28 | Proof. 29 | solve_decision. 30 | Defined. 31 | 32 | #[global] Instance Countable_board : Countable board. 33 | Proof. 34 | apply (inj_countable (A := N * N * N * N) (fun b => (p1 b, p2 b, s1 b, s2 b)) 35 | (fun '(p1,p2,s1,s2) => Some (MkBoard p1 p2 s1 s2))). 36 | intros []; reflexivity. 37 | Defined. 38 | 39 | Definition advance (b : board) (n : N) : board := 40 | let p1' := (p1 b + n - 1) mod 10 + 1 in 41 | {| p1 := p2 b 42 | ; p2 := p1' 43 | ; s1 := s2 b 44 | ; s2 := s1 b + p1' 45 | |}. 46 | 47 | Record board1 := MkBoard1 48 | { b1 : board 49 | ; rolls : N 50 | ; d : N 51 | }. 52 | 53 | Definition step1 (b : board1) : board1 := 54 | {| b1 := advance (b1 b) (3 * rolls b + 1) 55 | ; rolls := 3 + rolls b 56 | ; d := (d b + 3) mod 10 57 | |}. 58 | 59 | Definition play1 i : board1 := 60 | N.iter 2000 (fun go b => if 1000 <=? s2 (b1 b) then b else go (step1 b)) 61 | (fun b => b (* should not happen *)) 62 | {| b1 := mk_board i ; rolls := 0 ; d := 1 |}. 63 | 64 | Definition solve i : N := 65 | let b := play1 i in 66 | s1 (b1 b) * rolls b. 67 | 68 | (* Compute let '(p1,p2):= example in play p1 p2. *) 69 | (* Compute solve example. *) 70 | 71 | (* Recursion and memoization *) 72 | 73 | Definition endo (X : Type) : Type := (X -> X). 74 | 75 | Class Monad M : Type := 76 | { ret : forall {A}, A -> M A 77 | ; bind : forall {A B}, M A -> (A -> M B) -> M B 78 | }. 79 | 80 | Declare Scope monad_scope. 81 | #[global] Open Scope monad_scope. 82 | 83 | Notation "'let*' x ':=' u 'in' v" := (bind u (fun x => v)) (at level 200) : monad_scope. 84 | 85 | Fixpoint traverse {M} `{Monad M} {A B} (f : A -> M B) (xs : list A) : M (list B) := 86 | match xs with 87 | | [] => ret [] 88 | | x :: xs => 89 | let* y := f x in 90 | let* ys := traverse f xs in 91 | ret (y :: ys) 92 | end. 93 | 94 | Record identity (A : Type) : Type := Mk_identity { run_identity : A }. 95 | 96 | Instance Monad_identity : Monad identity := 97 | {| ret _ x := Mk_identity x 98 | ; bind _ _ u k := k (run_identity u) 99 | |}. 100 | 101 | Fixpoint naive_fix (fuel : nat) {A R} (r0 : R) (gf : endo (A -> identity R)) : A -> R := 102 | fun x => 103 | run_identity (gf (fun x => Mk_identity match fuel with 104 | | O => r0 105 | | S fuel => naive_fix fuel r0 gf x 106 | end) x). 107 | 108 | Record state (S A : Type) : Type := Mk_state { run_state : S -> S * A }. 109 | 110 | Instance Monad_state {S} : Monad (state S) := 111 | {| ret _ x := Mk_state (fun s => (s, x)) 112 | ; bind _ _ u k := Mk_state (fun s => 113 | let '(s, x) := run_state u s in 114 | run_state (k x) s) |}. 115 | 116 | Definition memom (A R : Type) `{Countable A} : Type -> Type := state (gmap A R). 117 | 118 | Fixpoint _memo_fix (fuel : nat) {A R} `{Countable A} 119 | (r0 : R) (gf : endo (A -> state (gmap A R) R)) : A -> state (gmap A R) R := 120 | fun x => Mk_state (fun s => 121 | match lookup x s with 122 | | Some y => (s, y) 123 | | None => 124 | let __memo_fix x := match fuel with O => ret r0 | S fuel => _memo_fix fuel r0 gf x end in 125 | let '(s, y) := run_state (gf __memo_fix x) s in 126 | (insert x y s, y) 127 | end). 128 | 129 | Definition memo_fix (fuel : nat) {A R} `{Countable A} 130 | (r0 : R) (gf : endo (A -> state (gmap A R) R)) : A -> R := 131 | fun x => snd (run_state (_memo_fix fuel r0 gf x) empty). 132 | 133 | Fixpoint addwave (xs ys : list N) := 134 | match xs, ys with 135 | | x :: xs, y :: ys => x + y :: addwave xs ys 136 | | nil, ys => ys 137 | | xs, nil => xs 138 | end. 139 | 140 | Definition microwave (xs : list N) : list N := 141 | addwave (addwave xs (0 :: xs)) (0 :: 0 :: xs). 142 | 143 | Definition threedice : list (N * N) := Eval cbv in 144 | combine (3 :: 4 :: 5 :: 6 :: 7 :: 8 :: 9 :: nil) (microwave (microwave (microwave (1 :: nil)))). 145 | 146 | Definition sum_worlds (xs : list (N * N)) : N * N := 147 | fold_left (fun '(x,y) '(x',y') => (x+x', y+y')) xs (0,0). 148 | 149 | (* Starting from board [b], numbers of worlds in which each player wins *) 150 | Definition __play2 {M} `{Monad M} : endo (board -> M (N * N)%type) := fun __play2 b => 151 | if 21 <=? s2 b then ret (0, 1) else 152 | (* Weight and flip *) 153 | let wflip w '(v1, v2) := (v2 * w, v1 * w) in 154 | let* rs := traverse (fun '(d, w) => let* r := __play2 (advance b d) in ret (wflip w r)) 155 | threedice in 156 | ret (sum_worlds rs). 157 | 158 | Definition _play2 : board -> N * N := memo_fix 42 (0, 0) __play2. 159 | Definition play2 i := _play2 (mk_board i). 160 | 161 | Definition solve2 i : N := 162 | let '(v1, v2) := play2 i in 163 | if v1 [y] | Some ys => (y :: ys) end in 41 | partial_alter alt x g. 42 | 43 | Definition get_edges (x : V) (g : graph) : list V := 44 | match lookup x g with 45 | | None => [] 46 | | Some ys => ys 47 | end. 48 | 49 | Definition adj_list (xs : list (V * V)) : graph := 50 | fold_left (fun g '(x, y) => add_edge x y (add_edge y x g)) xs empty. 51 | 52 | End G. 53 | 54 | Arguments graph : clear implicits. 55 | Arguments graph V {_ _}. 56 | 57 | (* Recursion and memoization *) 58 | 59 | Definition endo (X : Type) : Type := (X -> X). 60 | 61 | Class Monad M : Type := 62 | { ret : forall {A}, A -> M A 63 | ; bind : forall {A B}, M A -> (A -> M B) -> M B 64 | }. 65 | 66 | Declare Scope monad_scope. 67 | #[global] Open Scope monad_scope. 68 | 69 | Notation "'let*' x ':=' u 'in' v" := (bind u (fun x => v)) (at level 200) : monad_scope. 70 | 71 | Fixpoint traverse {M} `{Monad M} {A B} (f : A -> M B) (xs : list A) : M (list B) := 72 | match xs with 73 | | [] => ret [] 74 | | x :: xs => 75 | let* y := f x in 76 | let* ys := traverse f xs in 77 | ret (y :: ys) 78 | end. 79 | 80 | Record identity (A : Type) : Type := Mk_identity { run_identity : A }. 81 | 82 | Instance Monad_identity : Monad identity := 83 | {| ret _ x := Mk_identity x 84 | ; bind _ _ u k := k (run_identity u) 85 | |}. 86 | 87 | Fixpoint naive_fix (fuel : nat) {A R} (r0 : R) (gf : endo (A -> identity R)) : A -> R := 88 | fun x => 89 | run_identity (gf (fun x => Mk_identity match fuel with 90 | | O => r0 91 | | S fuel => naive_fix fuel r0 gf x 92 | end) x). 93 | 94 | Record state (S A : Type) : Type := Mk_state { run_state : S -> S * A }. 95 | 96 | Instance Monad_state {S} : Monad (state S) := 97 | {| ret _ x := Mk_state (fun s => (s, x)) 98 | ; bind _ _ u k := Mk_state (fun s => 99 | let '(s, x) := run_state u s in 100 | run_state (k x) s) |}. 101 | 102 | Definition memom (A R : Type) `{Countable A} : Type -> Type := state (gmap A R). 103 | 104 | Fixpoint _memo_fix (fuel : nat) {A R} `{Countable A} 105 | (r0 : R) (gf : endo (A -> state (gmap A R) R)) : A -> state (gmap A R) R := 106 | fun x => Mk_state (fun s => 107 | match lookup x s with 108 | | Some y => (s, y) 109 | | None => 110 | let __memo_fix x := match fuel with O => ret r0 | S fuel => _memo_fix fuel r0 gf x end in 111 | let '(s, y) := run_state (gf __memo_fix x) s in 112 | (insert x y s, y) 113 | end). 114 | 115 | Definition memo_fix (fuel : nat) {A R} `{Countable A} 116 | (r0 : R) (gf : endo (A -> state (gmap A R) R)) : A -> R := 117 | fun x => snd (run_state (_memo_fix fuel r0 gf x) empty). 118 | 119 | (* DFS *) 120 | 121 | Definition isSome {A} (x : option A) := 122 | match x with 123 | | Some _ => true 124 | | None => false 125 | end. 126 | 127 | (* [gset] insertion (as [fun x s => union (singleton x) s]) is slow, 128 | so we redefine our own sets from maps which have fast [insert]. *) 129 | Notation set X := (gmap X unit). 130 | Notation insert_set x s := (insert x tt s). 131 | Notation elem_set x s := (isSome (lookup x s)). 132 | 133 | Notation v := string (only parsing). 134 | 135 | Definition is_big (x : v) : bool := 136 | match x with 137 | | ""%string => false 138 | | String c _ => ((N_of_ascii "A" <=? N_of_ascii c) && (N_of_ascii c <=? N_of_ascii "Z")) 139 | end. 140 | 141 | Definition visit (x : v) (visited : set v) : option (set v) := 142 | if is_big x then Some visited 143 | else if elem_set x visited then None 144 | else Some (insert_set x visited). 145 | 146 | Definition start_from (x : v) : set v * v := 147 | (insert_set x empty, x). 148 | 149 | Definition sum_N (xs : list N) : N := 150 | fold_left N.add xs 0. 151 | 152 | Definition _count_paths {M} `{Monad M} {VISITED} (_visit : v -> VISITED -> option VISITED) 153 | (g : graph v) : endo (VISITED * v -> M N) := fun __count_paths '(visited, x) => 154 | if String.eqb x "end" then ret 1 else 155 | let search x := match _visit x visited with 156 | | None => ret 0 157 | | Some visited => __count_paths (visited, x) 158 | end in 159 | let* ns := traverse search (get_edges x g) in 160 | ret (sum_N ns). 161 | 162 | (* The maximum length can be up to twice the number of nodes, because we can revisit big nodes. 163 | An implicit assumption is that there are no adjacent big nodes, so a long path must consist 164 | of an alternation of big and small nodes, and each small node is visited once, hence the bound. *) 165 | Definition count_paths (g : graph v) : N := 166 | memo_fix (2 * size g) 0 (_count_paths visit g) (start_from "start"). 167 | 168 | Definition solve (xs : Input) : N := 169 | count_paths (adj_list xs). 170 | 171 | (* Compute solve example. *) 172 | 173 | Definition visit2 (x : v) '((may_revisit, visited) : bool * set v) : option (bool * set v) := 174 | if is_big x then Some (may_revisit, visited) 175 | else if elem_set x visited then 176 | if negb (String.eqb x "start") && may_revisit then Some (false, visited) else None 177 | else Some (may_revisit, insert_set x visited). 178 | 179 | Definition start_from2 (x : v) : ((bool * set v) * v) := 180 | ((true, insert_set x empty), x). 181 | 182 | Definition count_paths2 (g : graph v) : N := 183 | memo_fix (2 * S (size g)) 0 (_count_paths visit2 g) (start_from2 "start"). 184 | 185 | Definition solve2 (xs : Input) : N := 186 | count_paths2 (adj_list xs). 187 | 188 | (* Compute solve2 example. *) 189 | 190 | Definition solve12 xs := (solve xs, solve2 xs). 191 | -------------------------------------------------------------------------------- /src/aoc16.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export Ascii String NArith. 2 | From Coq Require Import List. 3 | Import ListNotations. 4 | 5 | Set Implicit Arguments. 6 | Set Contextual Implicit. 7 | 8 | #[global] Open Scope N_scope. 9 | 10 | Notation b0 := false. 11 | Notation b1 := true. 12 | 13 | Infix "::" := String : string_scope. 14 | 15 | Definition bits := list bool. 16 | 17 | Definition hex_N_to_bits (n : N) : bits := 18 | [ N.odd (n / 8) ; N.odd (n / 4) ; N.odd (n / 2) ; N.odd n ]. 19 | 20 | Definition hex_to_bits (c : ascii) : bits := hex_N_to_bits ( 21 | if c =? "0" then 0 else 22 | if c =? "1" then 1 else 23 | if c =? "2" then 2 else 24 | if c =? "3" then 3 else 25 | if c =? "4" then 4 else 26 | if c =? "5" then 5 else 27 | if c =? "6" then 6 else 28 | if c =? "7" then 7 else 29 | if c =? "8" then 8 else 30 | if c =? "9" then 9 else 31 | if c =? "A" then 10 else 32 | if c =? "B" then 11 else 33 | if c =? "C" then 12 else 34 | if c =? "D" then 13 else 35 | if c =? "E" then 14 else 36 | if c =? "F" then 15 else 0)%char. 37 | 38 | Fixpoint to_bits (s : string) : bits := 39 | match s with 40 | | "" => [] 41 | | c :: s => (hex_to_bits c ++ to_bits s)%list 42 | end%string. 43 | 44 | Notation input s := (to_bits s%string) (only parsing). 45 | 46 | Definition example := input "8A004A801A8002F478". 47 | Definition example2 := input "620080001611562C8802118E34". 48 | Definition example3 := input "C0015000016115A2E0802F182340". 49 | Definition example4 := input "A0016C880162017C3686B18A3D4780". 50 | 51 | Definition parser (A : Type) : Type := 52 | forall R, (A -> bits -> N -> option R) -> bits -> N -> option R. 53 | 54 | Definition run_parser {A} (p : parser A) (bs : bits) : option A := 55 | p A (fun x _ _ => Some x) bs 0. 56 | 57 | Definition onebit : parser bool := fun R k bs pos => 58 | match bs with 59 | | [] => None 60 | | b :: bs => k b bs (N.succ pos) 61 | end. 62 | 63 | Definition ret {A} (x : A) : parser A := fun R k bs => k x bs. 64 | 65 | Definition bind {A B} (u : parser A) (c : A -> parser B) : parser B := fun R k => 66 | u _ (fun x => c x _ k). 67 | 68 | Notation "'let*' x ':=' u 'in' c" := (bind u (fun x => c)) (at level 200, x binder). 69 | 70 | Definition fixed (n : N) : parser N := 71 | N.iter n (fun c acc => 72 | let* b := onebit in 73 | c (N.double acc + N.b2n b)) ret 0. 74 | 75 | Definition get_pos : parser N := fun R k bs p => k p bs p. 76 | 77 | Inductive packet := 78 | | Packet (ver : N) (typ : N) (pay : payload) 79 | with payload := 80 | | Literal (_ : N) 81 | | Operator (_ : list packet) 82 | . 83 | 84 | Definition repeat {A} (n : N) (p : parser A) : parser (list A) := 85 | N.iter n (fun ps => 86 | let* x := p in 87 | let* xs := ps in 88 | ret (x :: xs)) (ret []). 89 | 90 | Definition fail {A} : parser A := fun R _ _ _ => None. 91 | 92 | Definition while_bounded {A} (n : N) (p : parser (option A)) : parser (list A) := 93 | N.iter (N.succ n) (fun ps => 94 | let* ox := p in 95 | match ox with 96 | | None => ret [] 97 | | Some x => let* xs := ps in ret (x :: xs) 98 | end) fail. 99 | 100 | Fixpoint iter_list {A B} (n : list A) (f : B -> B) (x : B) : B := 101 | match n with 102 | | [] => x 103 | | _ :: n => f (iter_list n f x) 104 | end. 105 | 106 | Definition fix_consuming {A B} (f : (A -> parser B) -> (A -> parser B)) (x : A) : parser B := 107 | fun _ k bs p => 108 | iter_list bs f (fun _ => fail) x _ k bs p. 109 | 110 | Definition fix_consuming' {A} (f : parser A -> parser A) : parser A := 111 | fix_consuming (fun z _ => f (z tt)) tt. 112 | 113 | Section Lit. 114 | 115 | Context (__literal : N -> parser N). 116 | 117 | Definition _literal (acc : N) : parser N := 118 | let* b := onebit in 119 | let* h := fixed 4 in 120 | match b with 121 | | b0 => ret (acc * 16 + h) 122 | | b1 => __literal (acc * 16 + h) 123 | end. 124 | 125 | End Lit. 126 | 127 | Definition get_literal : parser N := fix_consuming _literal 0. 128 | 129 | Section Packets. 130 | 131 | Context (__packet : parser packet). 132 | 133 | Definition _packet : parser packet := 134 | let* ver := fixed 3 in 135 | let* typ := fixed 3 in 136 | if typ =? 4 then 137 | let* n := get_literal in 138 | ret (Packet ver typ (Literal n)) 139 | else 140 | let* b := onebit in 141 | let* packs := match b with 142 | | b0 => 143 | let* len := fixed 15 in 144 | let* pos := get_pos in 145 | while_bounded len 146 | (let* pos' := get_pos in 147 | match N.compare pos' (pos + len) with 148 | | Eq => ret None 149 | | Lt => let* x := __packet in ret (Some x) 150 | | Gt => fail 151 | end) 152 | | b1 => 153 | let* len := fixed 11 in 154 | repeat len __packet 155 | end in 156 | ret (Packet ver typ (Operator packs)). 157 | 158 | End Packets. 159 | 160 | Definition get_packet : parser packet := fix_consuming' _packet. 161 | 162 | (* Compute (run_parser get_packet example). *) 163 | 164 | Fixpoint sum_versions (p : packet) : N := 165 | match p with 166 | | Packet v _ pl => v + sum_versions_payload pl 167 | end 168 | with sum_versions_payload (pl : payload) : N := 169 | match pl with 170 | | Literal _ => 0 171 | | Operator ps => fold_left (fun acc p => acc + sum_versions p) ps 0 172 | end. 173 | 174 | Definition solve (bs : bits) : option N := 175 | option_map sum_versions (run_parser get_packet bs). 176 | 177 | (* 178 | Compute solve example. 179 | Compute solve example2. 180 | Compute solve example3. 181 | Compute solve example4. 182 | *) 183 | 184 | Module Import Ops. 185 | 186 | Definition sum (xs : list N) := 187 | fold_left N.add xs 0. 188 | 189 | Definition product (xs : list N) := 190 | fold_left N.mul xs 1. 191 | 192 | Definition minimum (xs : list N) := 193 | match xs with 194 | | [] => 0 195 | | x :: xs => fold_left N.min xs x 196 | end. 197 | 198 | Definition maximum (xs : list N) := 199 | match xs with 200 | | [] => 0 201 | | x :: xs => fold_left N.max xs x 202 | end. 203 | 204 | Definition gt (xs : list N) := 205 | match xs with 206 | | [x; y] => if y 0 208 | end. 209 | 210 | Definition lt (xs : list N) := 211 | match xs with 212 | | [x; y] => if x 0 214 | end. 215 | 216 | Definition eq (xs : list N) := 217 | match xs with 218 | | [x; y] => if x =? y then 1 else 0 219 | | _ => 0 220 | end. 221 | 222 | End Ops. 223 | 224 | Fixpoint eval (p : packet) : N := 225 | match p with 226 | | Packet _ _ (Literal n) => n 227 | | Packet _ t (Operator ps) => 228 | let args := map eval ps in 229 | let op := 230 | if t =? 0 then sum 231 | else if t =? 1 then product 232 | else if t =? 2 then minimum 233 | else if t =? 3 then maximum 234 | else if t =? 5 then gt 235 | else if t =? 6 then lt 236 | else (* t = 7 *) eq 237 | in op args 238 | end. 239 | 240 | Definition solve2 (bs : bits) : option N := 241 | option_map eval (run_parser get_packet bs). 242 | 243 | Definition solve12 (bs : bits) : option (N * N) := 244 | option_map (fun x => (sum_versions x, eval x)) (run_parser get_packet bs). 245 | 246 | Definition example5 := input "C200B40A82". 247 | Definition example6 := input "880086C3E88112". 248 | Definition example7 := input "CE00C43D881120". 249 | 250 | (* 251 | Compute solve2 example5. 252 | Compute solve2 example6. 253 | Compute solve2 example7. 254 | *) 255 | -------------------------------------------------------------------------------- /src/aoc11.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List Number Decimal. 2 | From Coq Require Import ZArith. 3 | 4 | From stdpp Require Import gmap sorting. 5 | 6 | Set Implicit Arguments. 7 | Set Contextual Implicit. 8 | 9 | Import ListNotations. 10 | 11 | #[local] Open Scope N_scope. 12 | 13 | Fixpoint decimal_to_digits (d : Decimal.uint) : list N := 14 | match d with 15 | | D0 d => 0 :: decimal_to_digits d 16 | | D1 d => 1 :: decimal_to_digits d 17 | | D2 d => 2 :: decimal_to_digits d 18 | | D3 d => 3 :: decimal_to_digits d 19 | | D4 d => 4 :: decimal_to_digits d 20 | | D5 d => 5 :: decimal_to_digits d 21 | | D6 d => 6 :: decimal_to_digits d 22 | | D7 d => 7 :: decimal_to_digits d 23 | | D8 d => 8 :: decimal_to_digits d 24 | | D9 d => 9 :: decimal_to_digits d 25 | | Nil => [] 26 | end. 27 | 28 | Record DIGITS := { unDIGITS : list N }. 29 | 30 | Definition decimal_to_DIGITS (d : Number.uint) := 31 | match d with 32 | | UIntDecimal d => Some {| unDIGITS := decimal_to_digits d |} 33 | | _ => None 34 | end. 35 | 36 | Definition dummy_from_DIGITS : DIGITS -> option Number.uint := fun _ => None. 37 | 38 | Declare Scope DIGITS_scope. 39 | Delimit Scope DIGITS_scope with DIGITS. 40 | 41 | Number Notation DIGITS decimal_to_DIGITS dummy_from_DIGITS : DIGITS_scope. 42 | 43 | Definition foldi {A B} (f : N -> A -> B -> B) (xs : list A) (b0 : B) : B := 44 | let fix _foldi (n : N) (xs : list A) := 45 | match xs with 46 | | x :: xs => f n x (_foldi (N.succ n) xs) 47 | | nil => b0 48 | end in _foldi 0 xs. 49 | 50 | Definition point : Type := Z * Z. 51 | 52 | (* N is awkward because of saturating subtraction, we use Z so going negative 53 | is a natural way to detect going "out of bounds". *) 54 | Definition map_of_grid (xs : list (list N)) : gmap point N := 55 | foldi (fun i => 56 | foldi (fun j h => insert (Z.of_N i, Z.of_N j) h)) 57 | xs empty. 58 | 59 | Definition Input : Type := gmap point N. 60 | 61 | Notation "'input' x .. y" := (map_of_grid (map unDIGITS (cons x%DIGITS .. (cons y%DIGITS nil) ..))) 62 | (at level 200, x at level 0, only parsing). 63 | 64 | Definition example : Input := input 65 | 5483143223 66 | 2745854711 67 | 5264556173 68 | 6141336146 69 | 6357385478 70 | 4167524645 71 | 2176841721 72 | 6882881134 73 | 4846848554 74 | 5283751526 75 | . 76 | 77 | (* Phase 1 *) 78 | Definition incr_all (g : gmap point N) : gmap point N := 79 | fmap N.succ g. 80 | 81 | Fixpoint map_filter {A B} (f : A -> option B) (xs : list A) : list B := 82 | match xs with 83 | | [] => [] 84 | | x :: xs => 85 | match f x with 86 | | None => map_filter f xs 87 | | Some y => y :: map_filter f xs 88 | end 89 | end. 90 | 91 | (* Phase 2.a: Find the first ones to reach 10 *) 92 | Definition first_flash (g : gmap point N) : list point := 93 | let flashy '(ij, energy) := if energy <=? 9 then None else Some ij in 94 | map_filter flashy (map_to_list g). 95 | 96 | (* Phase 2.b: Propagage the energy *) 97 | 98 | (* We only process each flashing point once, when it increases from 9 to 10. *) 99 | Definition radiate '(ij : point) (g : gmap point N) (todo : list point) 100 | : gmap point N * list point := 101 | match lookup ij g with 102 | | None => (g, todo) 103 | | Some energy => 104 | (insert ij (N.succ energy) g, if energy =? 9 then ij :: todo else todo) 105 | end. 106 | 107 | Definition neighbors '((i,j) : point) : list point := 108 | [(i+1,j+1); (i+1,j); (i+1,j-1); (i,j+1); (i,j-1); (i-1,j+1); (i-1,j); (i-1,j-1)]%Z. 109 | 110 | Definition flash (ij : point) (g : gmap point N) (todo : list point) 111 | : gmap point N * list point := 112 | fold_left (fun '(g, todo) ij => radiate ij g todo) (neighbors ij) (g, todo). 113 | 114 | Fixpoint _propagate (fuel : nat) (g : gmap point N) (ndone : N) (todo : list point) 115 | : gmap point N * N := 116 | match todo, fuel with 117 | | [], _ => (g, ndone) 118 | | _, O => (empty, 0) (* Should not happen *) 119 | | ij :: todo, S fuel => 120 | let '(g, todo) := flash ij g todo in 121 | _propagate fuel g (N.succ ndone) todo 122 | end. 123 | 124 | (* Phase 2 *) 125 | Definition propagate (g : gmap point N) : gmap point N * N := 126 | _propagate (size g) g 0 (first_flash g). 127 | 128 | (* Phase 3 *) 129 | Definition exhaust (g : gmap point N) : gmap point N := 130 | fmap (fun energy => if energy <=? 9 then energy else 0)%N g. 131 | 132 | Definition step (g : gmap point N) : gmap point N * N := 133 | let g := incr_all g in 134 | let '(g, n) := propagate g in 135 | let g := exhaust g in 136 | (g, n). 137 | 138 | Fixpoint _steps (n : nat) (g : gmap point N) (nflashes : N) : gmap point N * N := 139 | match n with 140 | | O => (g, nflashes) 141 | | S n => 142 | let '(g, more) := step g in 143 | _steps n g (nflashes + more) 144 | end. 145 | 146 | Definition steps (n : nat) (g : gmap point N) : N := snd (_steps n g 0). 147 | 148 | Definition solve := steps 100. 149 | 150 | (* Compute solve example. *) 151 | 152 | Definition steps2 (fuel : N) (g : gmap point N) : N := 153 | let sz := N.of_nat (size g) in 154 | N.iter fuel 155 | (fun self '(g, n) => 156 | let n := N.succ n in 157 | let '(g, flashes) := step g in 158 | if flashes =? sz then n else self (g, n)) 159 | (fun _ => 0%N (* should not happen with enough fuel *)) 160 | (g, 0). 161 | 162 | Definition solve2 := steps2 1000. 163 | 164 | (* Compute solve2 example. *) 165 | 166 | Definition solve12 g := (solve g, solve2 g). 167 | 168 | (* Spec (no proofs) *) 169 | 170 | Definition isSome {A} (x : option A) := 171 | match x with 172 | | Some _ => true 173 | | None => false 174 | end. 175 | 176 | (* [gset] insertion (as [fun x s => union (singleton x) s]) is slow, 177 | so we redefine our own sets from maps which have fast [insert]. *) 178 | Notation set X := (gmap X unit). 179 | Notation insert_set x s := (insert x tt s). 180 | Notation elem_set x s := (isSome (lookup x s)). 181 | 182 | Definition radiate' '(ij : point) (g : gmap point N) : gmap point N := 183 | match lookup ij g with 184 | | None => g 185 | | Some energy => insert ij (N.succ energy) g 186 | end. 187 | 188 | Definition flash' (ij : point) (g : gmap point N) : gmap point N := 189 | fold_left (fun g ij => radiate' ij g) (neighbors ij) g. 190 | 191 | Record state : Type := MkState 192 | { energies : gmap point N (* current levels *) 193 | ; flashed : set point (* points that already flashed *) 194 | }. 195 | 196 | Definition lookup0 (ij : point) (m : gmap point N) : N := 197 | match lookup ij m with 198 | | Some n => n 199 | | None => 0 200 | end. 201 | 202 | Definition one_flash : state -> state -> Prop := fun s s' => 203 | exists ij, 9 one_flash s s2 -> 208 | s1 = s2 \/ exists s3, one_flash s1 s3 /\ one_flash s2 s3. 209 | Proof. 210 | Abort. 211 | 212 | Inductive star {A} (r : A -> A -> Prop) : A -> A -> Prop := 213 | | star_zero x : star r x x 214 | | star_succ x y z : r x y -> star r y z -> star r x z 215 | . 216 | 217 | Definition all_flash : state -> state -> Prop := fun s s' => 218 | star one_flash s s' /\ forall s'', ~ one_flash s' s''. 219 | 220 | Theorem step_correct g 221 | : exists s', all_flash (MkState g empty) s' 222 | /\ step g = (energies s', N.of_nat (size (flashed s'))). 223 | Proof. 224 | Abort. 225 | -------------------------------------------------------------------------------- /src/aoc09.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List Number Decimal. 2 | 3 | From stdpp Require Import gmap sorting. 4 | 5 | Set Implicit Arguments. 6 | Set Contextual Implicit. 7 | 8 | Import ListNotations. 9 | 10 | Record DIGITS := { unDIGITS : list N }. 11 | 12 | Fixpoint decimal_to_digits (d : Decimal.uint) : list N := 13 | match d with 14 | | D0 d => 0 :: decimal_to_digits d 15 | | D1 d => 1 :: decimal_to_digits d 16 | | D2 d => 2 :: decimal_to_digits d 17 | | D3 d => 3 :: decimal_to_digits d 18 | | D4 d => 4 :: decimal_to_digits d 19 | | D5 d => 5 :: decimal_to_digits d 20 | | D6 d => 6 :: decimal_to_digits d 21 | | D7 d => 7 :: decimal_to_digits d 22 | | D8 d => 8 :: decimal_to_digits d 23 | | D9 d => 9 :: decimal_to_digits d 24 | | Nil => [] 25 | end%N. 26 | 27 | Definition decimal_to_DIGITS (d : Number.uint) := 28 | match d with 29 | | UIntDecimal d => Some {| unDIGITS := decimal_to_digits d |} 30 | | _ => None 31 | end. 32 | 33 | Definition dummy_from_DIGITS : DIGITS -> option Number.uint := fun _ => None. 34 | 35 | Declare Scope DIGITS_scope. 36 | Delimit Scope DIGITS_scope with DIGITS. 37 | 38 | Number Notation DIGITS decimal_to_DIGITS dummy_from_DIGITS : DIGITS_scope. 39 | 40 | Definition Input : Type := list (list N). 41 | 42 | Notation "'input' x .. y" := (map unDIGITS (cons x%DIGITS .. (cons y%DIGITS nil) ..)) 43 | (at level 200, x at level 0, only parsing). 44 | 45 | Definition example : Input := input 46 | 2199943210 47 | 3987894921 48 | 9856789892 49 | 8767896789 50 | 9899965678 51 | . 52 | 53 | #[local] Open Scope bool_scope. 54 | #[local] Open Scope N_scope. 55 | 56 | (* Add sentinel values *) 57 | Definition pad (xs : Input) : Input := 58 | let sentinel_row := 59 | match xs with 60 | | [] => [] 61 | | x :: _ => 10 :: 10 :: map (fun _ => 10) x 62 | end in 63 | sentinel_row :: map (fun x => 10 :: x ++ [10])%N xs ++ [sentinel_row]. 64 | 65 | Fixpoint find_local_min_row (r1 r2 r3 : list N) : list N := 66 | match r1, r2, r3 with 67 | | _11 :: (x12 :: _13 :: _) as r1, 68 | x21 :: (x22 :: x23 :: _) as r2, 69 | _31 :: (x32 :: _33 :: _) as r3 => 70 | if (x22 [] 75 | end. 76 | 77 | Fixpoint find_local_min (xs : Input) : list N := 78 | match xs with 79 | | r1 :: (r2 :: r3 :: _) as xs => 80 | find_local_min_row r1 r2 r3 ++ find_local_min xs 81 | | _ => [] 82 | end. 83 | 84 | Definition sum_N : list N -> N := fold_right N.add 0. 85 | 86 | Definition solve (xs : Input) : N := 87 | let ys := find_local_min (pad xs) in 88 | sum_N (map N.succ ys). 89 | 90 | (* Compute solve example. *) 91 | 92 | Module St. 93 | 94 | Section St. 95 | 96 | Context (S : Type). 97 | 98 | Record m (A : Type) : Type := Mk { run : S -> S * A }. 99 | 100 | Definition pure {A} (a : A) : m A := Mk (fun s => (s, a)). 101 | 102 | Definition bind {A B} (u : m A) (k : A -> m B) : m B := 103 | Mk (fun s => 104 | let sa := run u s in 105 | run (k (snd sa)) (fst sa)). 106 | 107 | Fixpoint concat_for {A B} (cat : B -> B -> B) (dog : B) (xs : list A) (f : A -> m B) : m B := 108 | match xs with 109 | | nil => pure dog 110 | | x :: xs => 111 | bind (f x) (fun y => 112 | bind (concat_for cat dog xs f) (fun ys => 113 | pure (cat y ys))) 114 | end. 115 | 116 | Fixpoint for_ {A} (xs : list A) (f : A -> m unit) : m unit := 117 | match xs with 118 | | nil => pure tt 119 | | x :: xs => bind (f x) (fun _ => for_ xs f) 120 | end. 121 | 122 | End St. 123 | End St. 124 | 125 | Notation "'let*' a ':=' u 'in' v" := (St.bind u (fun a => v)) (at level 200, a binder). 126 | 127 | Definition isSome {A} (x : option A) := 128 | match x with 129 | | Some _ => true 130 | | None => false 131 | end. 132 | 133 | (* [gset] insertion (as [fun x s => union (singleton x) s]) is slow, 134 | so we redefine our own sets from maps which have fast [insert]. *) 135 | Notation set X := (gmap X unit). 136 | Notation insert_set x s := (insert x tt s). 137 | Notation elem_set x s := (isSome (lookup x s)). 138 | 139 | Section CC. 140 | 141 | Context (V : Type) `{Countable V}. 142 | 143 | Record graph : Type := 144 | { nodes : list V 145 | ; neighbors : V -> list V 146 | }. 147 | 148 | Record CC_state : Type := 149 | { visited : set V 150 | ; cur_component : list V 151 | }. 152 | 153 | Definition check_visited (v : V) : St.m CC_state bool := 154 | St.Mk (fun s => (s, elem_set v (visited s))). 155 | 156 | Definition visit (v : V) : St.m CC_state unit := 157 | St.Mk (fun s => 158 | ( {| visited := insert_set v (visited s) 159 | ; cur_component := v :: cur_component s |} 160 | , tt)). 161 | 162 | Definition reset_cur_component : St.m CC_state unit := 163 | St.Mk (fun s => 164 | ( {| visited := visited s ; cur_component := nil |} 165 | , tt)). 166 | 167 | Definition get_cur_component : St.m CC_state (list V) := 168 | St.Mk (fun s => (s, cur_component s)). 169 | 170 | Fixpoint create_component (g : graph) (fuel : nat) (v : V) : St.m CC_state unit := 171 | let* bvisited := check_visited v in 172 | if bvisited then 173 | St.pure tt 174 | else match fuel with | O => St.pure tt | S fuel => 175 | let* _ := visit v in 176 | St.for_ (neighbors g v) (create_component g fuel) 177 | end. 178 | 179 | Fixpoint _connected_components (g : graph) (fuel : nat) (vs : list V) (cc : list (list V)) 180 | : St.m CC_state (list (list V)) := 181 | match vs with 182 | | nil => St.pure cc 183 | | v :: vs => 184 | let* _ := reset_cur_component in 185 | let* _ := create_component g fuel v in 186 | let* c := get_cur_component in 187 | let cc := 188 | match c with 189 | | nil => (* Already visited *) cc 190 | | _ :: _ => c :: cc 191 | end in 192 | _connected_components g fuel vs cc 193 | end. 194 | 195 | Definition connected_components (g : graph) : list (list V) := 196 | snd (St.run 197 | (_connected_components g (length (nodes g)) (nodes g) nil) 198 | {| visited := empty ; cur_component := nil |}). 199 | 200 | End CC. 201 | 202 | Definition foldi {A B} (f : N -> A -> B -> B) (xs : list A) (b0 : B) : B := 203 | let fix _foldi (n : N) (xs : list A) := 204 | match xs with 205 | | x :: xs => f n x (_foldi (N.succ n) xs) 206 | | nil => b0 207 | end in _foldi 0 xs. 208 | 209 | Definition map_of_grid (xs : list (list N)) : set (N * N) := 210 | foldi (fun i => 211 | foldi (fun j h m => if h option B) (xs : list A) : list B := 215 | match xs with 216 | | [] => [] 217 | | x :: xs => 218 | match f x with 219 | | None => map_filter f xs 220 | | Some y => y :: map_filter f xs 221 | end 222 | end. 223 | 224 | Definition fourneighbors (m : set (N * N)) '((i,j) : N * N) : list (N * N) := 225 | filter (fun x => elem_set x m) [(i+1,j);(i-1,j);(i,j+1);(i,j-1)]. 226 | 227 | (* Assumes padding on the sides *) 228 | Definition graph_of_map (m : set (N * N)) : graph (N * N) := 229 | {| nodes := elements (dom (gset _) m) 230 | ; neighbors := fourneighbors m 231 | |}. 232 | 233 | Definition graph_of_grid (m : list (list N)) : graph (N * N) := 234 | graph_of_map (map_of_grid (pad m)). 235 | 236 | (* Compute connected_components (graph_of_grid example). *) 237 | 238 | Definition solve2 (m : Input) : N := 239 | let ccs := connected_components (graph_of_grid m) in 240 | let sizes := merge_sort N.ge (map (fun cc => N.of_nat (length cc)) ccs) in 241 | match sizes with 242 | | a :: b :: c :: _ => a * b * c 243 | | _ => 0 244 | end. 245 | 246 | (* Compute solve2 example. *) 247 | 248 | Definition solve12 (xs : Input) : N * N := (solve xs, solve2 xs). 249 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Advent of Code 2021 in Coq 2 | ========================== 3 | 4 | Solutions for [Advent of Code 2021](https://adventofcode.com/2021) written in Coq, 5 | a purely functional programming language where we can also prove theorems about 6 | functions. Some of the solutions include proofs. 7 | 8 | ## Run code 9 | 10 | Dependencies: 11 | - Coq (tested with Coq 8.13) 12 | - coq-stdpp 13 | 14 | ```shell 15 | # Install dependencies 16 | opam install coq-stdpp 17 | 18 | # Run 19 | 20 | cd src/ 21 | 22 | # Run Day 01 23 | ./a.sh aoc01.v aoc01_input.txt solve12 # Pair of answers for Day 1: Part One and Part Two 24 | 25 | # Run all days (this will take a big few minutes) 26 | sh ./runall.sh 27 | ``` 28 | 29 | ## Notes 30 | 31 | ### Execution 32 | 33 | All answers are computed by direct evaluation, with `Compute solve x.`, 34 | no extraction. 35 | 36 | ### Parsing 37 | 38 | Where possible, the input is just included within a Coq file: 39 | 40 | ``` 41 | Definition x := input 42 | 43 | . 44 | ``` 45 | 46 | This leverages *notations*, user-defined extensions of Coq's grammar. 47 | 48 | When this is not possible (9 days out of 25), we preprocess the input---with 49 | scripts named `src/aocXX_input.txt.prep`, in various way: 50 | 51 | - Quote the whole input, inserting `"` at the beginning and end: days 8, 10, 16. 52 | - Quote the input line-by-line: days 20, 25. 53 | - Quote alphanumeric substrings: days 12, 14. 54 | - Remove periods (conflicts with Coq syntax): day 23. 55 | 56 | ### Proving 57 | 58 | A few of the solutions have some associated specifications and proofs. 59 | 60 | #### Day 1 61 | 62 | Part 2 involves computing sums in a sliding window `x[i]+x[i+1]+x[i+2]` over 63 | the input sequence `x` and counting how many times the sums increase. This 64 | algorithm can be fused to avoid computing each sum, by instead comparing every 65 | element `x[i]` with `x[i+3]`. 66 | `aoc01.v` contains a proof that these two methods produce the same result. 67 | 68 | #### Day 2 69 | 70 | The "aim" in Part 2 behaves the same as the "depth" in Part 1. 71 | This is "obvious" from looking at the code, since each Part's respective functions 72 | involve the same operations. `aoc02.v` makes that correspondence formal using 73 | the concept of ["simulation"](https://en.wikipedia.org/wiki/Simulation_(computer_science)), and it occurred to me that only formal methods 74 | people know what that means. 75 | 76 | #### Day 7 77 | 78 | `aoc07.v` contains a proof that Part 2 finds the minimum-cost 79 | solution in the range `[0,xmax]` where `xmax` is the maximum position in the input 80 | (theorem `solve2_correct`). 81 | This result could be further improved to show that the solution is a global minimum. 82 | 83 | Part 2 is about finding the minimum of a convex function, which we do by 84 | binary search. The proof is decomposed as follows: 85 | 86 | 1. The cost function is convex (theorem `Convex_fuel2`). 87 | 2. Convex functions are V-shaped ("down then up", theorem `VShaped_Conves`). 88 | 3. Binary search (defined in that file) finds the minimum of V-shaped 89 | functions in a given range (`searchMin_correct`). 90 | 91 | #### Day 8 92 | 93 | `aoc08.v` contains a correctness specification (a formal statement but no 94 | proof; it's probably missing some conditions but it does its job of looking scary) 95 | of the core function in the solution, `decipher_line`: 96 | if an input line `l` is obtained from scrambling some initial string of digits (`outs ls`), 97 | then `decipher_line` computes the value of that string (reading the digits as a whole number). 98 | 99 | That specification says nothing about applying the function to an invalid input 100 | (one that is not obtained from scrambling some initial value). The solution is currently 101 | "garbage in, garbage out"; it could be improved to detect ill-formed inputs, 102 | and this could be specified accordingly. 103 | 104 | #### Day 10 105 | 106 | `aoc10.v` contains a full correctness theorem for the parser `check`. 107 | 108 | - If the parser succeeds on an input `s`, it produces a stack `z` which can be 109 | used to complete `s` into a well-bracketed string (theorem `check_sound`). 110 | 111 | - If the parser fails on an input `s`, it produces the first mismatched character `c`, 112 | which is characterized by the property that prefixes of `s` **not** including `c` 113 | can be completed into a well-bracketed string, while no prefix that **does** include 114 | `c` can be so completed (theorem `check_complete`). 115 | 116 | #### Day 11 117 | 118 | This problem relies on the property that it does not matter in what order 119 | octopuses flash, the resulting state after each step (after resolving all 120 | flashes) is uniquely determined. This property is called confluence. 121 | 122 | Specifications only, no proofs. `aoc11.v` contains: 123 | 124 | - a relation `one_flash` describing the effect of one octopus flashing, 125 | chosen non-deterministically. 126 | - a specification that `one_flash` is *strongly confluent*: intuitively, 127 | if octopus A flashed then octopus B flashed, the resulting state is the same 128 | as if B flashed then A flashed. 129 | - the above implies that the normal form of `one_flash` is uniquely determined 130 | (this is not stated), then the theorem `step_correct` says that the `step` 131 | function finds that normal form. 132 | 133 | #### Day 19 134 | 135 | Basically an exhaustive search. The solution uses an optimization: when trying 136 | to match two scanners, while trying a given orientation, we want to find 137 | a matching translation, and rather than testing each candidate translation for a match, 138 | we can enumerate the candidate translation vectors (all possible pairwise 139 | differences between the two sets of beacons) and pick the one that occurs at least 12 times. 140 | 141 | `aoc19.v` contains a specification for this optimization, i.e., 142 | it doesn't affect functional behavior (theorem `try_match_correct`, 143 | specification only, with an incomplete proof). 144 | 145 | Specifying and verifying this is especially tricky because there might be 146 | multiple matches. The problem statement guarantees uniqueness, but it's still 147 | a pain to formally reason about. 148 | 149 | #### Day 22 150 | 151 | Efficiency is achieved by only manipulating cubes, as an implicit representation 152 | of the huge space of individual points with on-off states. `aoc22.v` contains 153 | a (mostly complete) proof of the correspondence between these implicit and 154 | explicit representations. 155 | 156 | - Top-level theorem (`vol_add_spec`): the solution (left-hand side) computes 157 | the number of on-switches after applying every operation (right-hand side). 158 | 159 | - The main invariant for the core algorithm is that it maintains a list of cubes 160 | which represents an "inclusion-exclusion formula" (`inclexcl`) equivalent to 161 | the set operations applied so far (set union for "switch on" and set 162 | difference for "switch off"). In particular, that formula guarantees that 163 | set differences `A \ B` only occur when `B` is a subset of `A` 164 | (`nested_cubes` invariant), so their cardinal is simply the difference `|A| - |B|`. 165 | The preservation of those invariants by the step function `add_cube` is given 166 | by the two theorems `add_cube_nested` and `add_cube_spec`. 167 | 168 | - The proof is mostly complete, missing the lemma that the volume of a cuboid 169 | is the product of its three sides. 170 | 171 | #### Day 24 172 | 173 | This solution relies on the observation that the input actually consists of 14 174 | iterations of the same sequences of instruction differing only in three parameters, 175 | These parameters are easily extracted ("decompiled") by pattern-matching. 176 | Then they can be interpreted directly with a small arithmetic expression (`step`). 177 | `aoc24.v` contains a proof that those parameters can be "compiled" back into 178 | the original sequence, and also that `step` computes the same function as the 179 | original ALU instructions. (This "decompilation" doesn't actually change 180 | the asymptotic complexity of the solution but I only realized that later, 181 | and the constant factor reduction is probably worthwhile anyway.) 182 | 183 | A specification (no proof) of the final search algorithms is also given: we 184 | find the lexicographically greatest/smallest input accepted by the program. 185 | 186 | #### Extra comments 187 | 188 | Among the days with no spec formalized, some I think are either easy or interesting are: 189 | 190 | - Days 6, 12, 21: Your typical dynamic programming problems. 191 | 192 | - Day 14: A simple enough but not-too-trivial change of representation. 193 | 194 | - Day 15: Verify Dijkstra's algorithm. 195 | 196 | - Day 18: Is snailfish addition guaranteed to terminate? 197 | -------------------------------------------------------------------------------- /src/aoc08.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export String Ascii List NArith Arith. 2 | From Coq Require Import Permutation. 3 | 4 | Set Implicit Arguments. 5 | 6 | Import ListNotations. 7 | 8 | #[global] Open Scope string_scope. 9 | #[global] Open Scope N_scope. 10 | 11 | Infix "::" := String.String. 12 | 13 | Fixpoint _rev_string (r s : string) : string := 14 | match s with 15 | | "" => r 16 | | c :: s => _rev_string (c :: r) s 17 | end. 18 | 19 | Definition rev_string : string -> string := _rev_string "". 20 | 21 | Definition is_empty (w : string) : bool := 22 | match w with 23 | | "" => true 24 | | _ => false 25 | end. 26 | 27 | Fixpoint _split_on (c0 : ascii) (w s : string) : list string := 28 | match s with 29 | | "" => if is_empty w then [] else [rev_string w] 30 | | c :: s => 31 | if Ascii.eqb c0 c then 32 | if is_empty w then _split_on c0 w s else rev_string w :: _split_on c0 "" s 33 | else 34 | _split_on c0 (c :: w) s 35 | end. 36 | 37 | (* Drops empty words! *) 38 | Definition split_on (c0 : ascii) : string -> list string := _split_on c0 "". 39 | 40 | Definition words : string -> list string := split_on " ". 41 | Definition lines : string -> list string := split_on "010". 42 | 43 | Definition raw_signal : Type := string. 44 | Definition signal : Type := list bool. (* length 7 *) 45 | 46 | Fixpoint char_of (c : ascii) (w : string) : bool := 47 | match w with 48 | | "" => false 49 | | cw :: w => Ascii.eqb c cw || char_of c w 50 | end. 51 | 52 | Definition word_to_signal (w : raw_signal) : signal := 53 | map (fun c => char_of c w) ["a"; "b"; "c"; "d"; "e"; "f"; "g"]%char. 54 | 55 | Definition Line : Type := (list raw_signal * list raw_signal). 56 | 57 | Definition input (s : string) : list Line := 58 | let input_line l := 59 | match words l with 60 | | [s0; s1; s2; s3; s4; s5; s6; s7; s8; s9; vbar; t0; t1; t2; t3] => 61 | if String.eqb "|" vbar then 62 | ([s0; s1; s2; s3; s4; s5; s6; s7; s8; s9], [t0; t1; t2; t3]) 63 | else ([],[]) 64 | | _ => ([],[]) 65 | end in 66 | map input_line (lines s). 67 | 68 | Definition example := Eval cbv in input 69 | "be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe 70 | edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc 71 | fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg 72 | fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb 73 | aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea 74 | fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb 75 | dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe 76 | bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef 77 | egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb 78 | gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce". 79 | 80 | Definition sum_with {A} (f : A -> N) : list A -> N := 81 | fold_right (fun x => N.add (f x)) 0. 82 | 83 | Definition count_1478 : list Line -> N := 84 | sum_with (fun '(_, y) => 85 | sum_with (fun s => 86 | if ((String.length s =? 2) || (String.length s =? 3) || 87 | (String.length s =? 4) || (String.length s =? 7))%nat%bool 88 | then 1 else 0) y). 89 | 90 | Definition solve := count_1478. 91 | 92 | (* Compute solve example. *) 93 | 94 | 95 | (* 96 | aaaa 97 | b c 98 | b c 99 | dddd 100 | e f 101 | e f 102 | gggg 103 | 104 | Number of digits where segment is active: 105 | a 8 106 | b 6 107 | c 8 108 | d 7 109 | e 4 110 | f 9 111 | g 7 112 | 113 | c occurs in the digit 1, and a doesn't 114 | d occurs in the digit 4, and g doesn't 115 | *) 116 | 117 | Definition count (c : ascii) (xs : list raw_signal) : N := 118 | sum_with (fun s => if char_of c s then 1 else 0) xs. 119 | 120 | Definition occurs_in_1 (c : ascii) (xs : list raw_signal) : bool := 121 | existsb (fun s => (String.length s =? 2)%nat && char_of c s)%bool xs. 122 | 123 | Definition occurs_in_4 (c : ascii) (xs : list raw_signal) : bool := 124 | existsb (fun s => (String.length s =? 4)%nat && char_of c s)%bool xs. 125 | 126 | Definition decode (xs : list raw_signal) : list (ascii * ascii) := 127 | map (fun c => 128 | (c, let n := count c xs in 129 | if n =? 4 then "e" 130 | else if n =? 6 then "b" 131 | else if n =? 9 then "f" 132 | else if n =? 7 then 133 | if occurs_in_4 c xs then "d" else "g" 134 | else if n =? 8 then 135 | if occurs_in_1 c xs then "c" else "a" 136 | else "?")%N%char) ["a"; "b"; "c"; "d"; "e"; "f"; "g"]%char. 137 | 138 | Definition lookup_char {A} (def : A) (c : ascii) (xs : list (ascii * A)) : A := 139 | match List.find (fun w => c =? fst w)%char xs with 140 | | Some y => snd y 141 | | None => def 142 | end. 143 | 144 | Fixpoint map_string (f : ascii -> ascii) (s : string) : string := 145 | match s with 146 | | "" => "" 147 | | c :: s => f c :: map_string f s 148 | end. 149 | 150 | Definition decipher (d : list (ascii * ascii)) (xs : raw_signal) : raw_signal := 151 | map_string (fun c => lookup_char "?"%char c d) xs. 152 | 153 | Notation t := true (only parsing). 154 | Notation f := false (only parsing). 155 | 156 | Definition raw_signal_to_digit (s : raw_signal) : N := 157 | match word_to_signal s with 158 | | [t;t;t;f;t;t;t] => 0 159 | | [f;f;t;f;f;t;f] => 1 160 | | [t;f;t;t;t;f;t] => 2 161 | | [t;f;t;t;f;t;t] => 3 162 | | [f;t;t;t;f;t;f] => 4 163 | | [t;t;f;t;f;t;t] => 5 164 | | [t;t;f;t;t;t;t] => 6 165 | | [t;f;t;f;f;t;f] => 7 166 | | [t;t;t;t;t;t;t] => 8 167 | | [t;t;t;t;f;t;t] => 9 168 | | _ => 10000000 (* Blow up if wrong *) 169 | end. 170 | 171 | Fixpoint _from_decimal (d : N) (s : list N) : N := 172 | match s with 173 | | [] => d 174 | | c :: s => _from_decimal (d * 10 + c) s 175 | end%list. 176 | 177 | Definition from_decimal : list N -> N := _from_decimal 0. 178 | 179 | Definition outsig_to_num (s : list raw_signal) : N := 180 | from_decimal (map raw_signal_to_digit s). 181 | 182 | Definition decipher_line '((x,y) : Line) : N := 183 | let d := decode x in 184 | let y := map (decipher d) y in 185 | outsig_to_num y. 186 | 187 | Definition example1 := input "acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf". 188 | 189 | (* Compute map decipher_line example1. *) 190 | 191 | Definition solve2 : list Line -> N := 192 | sum_with decipher_line. 193 | 194 | (* Compute solve2 example. *) 195 | 196 | Definition solve12 (xs : list Line) : N * N := 197 | (solve xs, solve2 xs). 198 | 199 | (* Spec, no proofs *) 200 | 201 | Definition digits : list raw_signal := 202 | ["cf"; "acdeg"; "acdfg"; "bcdf"; "abdfg"; "abdefg"; "acf"; "abcdefg"; "abcdfg"]%string. 203 | 204 | (* The seven segments *) 205 | Definition segs : list ascii := ["a"; "b"; "c"; "d"; "e"; "f"; "g"]%char. 206 | 207 | Definition mapping {A B} (xs : list A) (ys : list B) (x : A) (y : B) := 208 | List.In (x, y) (List.combine xs ys). 209 | 210 | Fixpoint Forall2_string (F : ascii -> ascii -> Prop) (s1 s2 : string) : Prop := 211 | match s1, s2 with 212 | | "", "" => True 213 | | c1 :: s1, c2 :: s2 => F c1 c2 /\ Forall2_string F s1 s2 214 | | _, _ => False 215 | end. 216 | 217 | Definition Permutation_string (s1 s2 : string) : Prop := 218 | Permutation (list_ascii_of_string s1) (list_ascii_of_string s2). 219 | 220 | Definition index {A} (xs : list A) (n : nat) (x : A) : Prop := 221 | (n < length xs)%nat /\ nth n xs x = x. 222 | 223 | (* A well-formed input line [l] is related to the "canonical" representation of segments 224 | [segs] and [digits] as follows. *) 225 | Record LineSpec (l : Line) : Type := 226 | { (* (1) The display segments are scrambled *) 227 | ssegs : list ascii (* scrambled display lines *) 228 | ; ssegs_P : Permutation segs ssegs 229 | 230 | (* (2) We apply the segment scrambling to the digits *) 231 | ; sdigits : list raw_signal 232 | ; sdigits_P : Forall2 (Forall2_string (mapping segs ssegs)) digits sdigits 233 | 234 | (* (3) The digits are shuffled *) 235 | ; ssdigits : list raw_signal 236 | ; ssdigits_P : Permutation sdigits ssdigits 237 | 238 | (* (4) The order of segments in each digit is shuffled, 239 | this yields the first half of our input. *) 240 | ; sssdigits : list raw_signal := fst l 241 | ; sssdigits_P : Forall2 Permutation_string ssdigits sssdigits 242 | 243 | (* (5) The second half of the input is 4 digits *) 244 | ; outs : list nat 245 | ; outs_length : length outs = 4%nat 246 | 247 | (* (6) The digits are mapped to their 7-segment display 248 | (this implies the elements of [outs] are actually digits) *) 249 | ; douts : list raw_signal 250 | ; douts_X : Forall2 (index digits) outs douts 251 | 252 | (* (7) Apply the segment scrambling (like (2)) *) 253 | ; sdouts : list raw_signal 254 | ; sdouts_P : Forall2 (Forall2_string (mapping segs ssegs)) douts sdouts 255 | 256 | (* (8) The segments are shuffled, that's the second half of the input. *) 257 | ; ssdouts : list raw_signal := snd l 258 | ; ssdouts_P : Forall2 Permutation_string sdouts ssdouts 259 | }. 260 | 261 | (* [decipher_line] reconstructs the 4 digits in [outs]. *) 262 | Theorem decipher_correct (l : Line) (ls : LineSpec l) 263 | : decipher_line l = from_decimal (map N.of_nat (outs ls)). 264 | Proof. 265 | (* Good luck *) 266 | Abort. 267 | -------------------------------------------------------------------------------- /src/aoc10_input.txt: -------------------------------------------------------------------------------- 1 | ([(<<<{({([{{{{}[]}<[]<>>}<{()()}{{}()}>}{((()()))([[]<>]<{}()>)}]({((<>{})[<>()])<{()<>}<<>( 2 | {<{{<[[[(<<<([{}{}](()()))(([][])<()<>>)>>({([[]]<{}<>>)[{[]{}}{[]()}]}[(([]{})){([]<>)}])>((({{<>[]} 3 | [[{<<[{{<[(<[<()<>}[{}[]]]((()()))>{[([]<>)([]())]<([])[{}[]]>})<<<[{}[]]((){})>(<<>[]>[[]<>])> 4 | ({[{[<([{((((<{}()><<>()>))[<{[]<>}<{}()>>({<>[]}(<><>>)])([[<()<>>({}<>)]({[]()}[[]{}])]))} 5 | (<<({{{{({[[(<{}{}>{{}<>}){<<>>}]<(<{}()>{(){}}){[{}()]([]<>}}>][([((){})<[]<>>]<<<>{}>{[]}>)( 6 | {(((([{([<[[<[(){}]<()()>>{[[]{}]{{}[]}}]([<<><>>{[]{}}]<{[]()}[()()]>)]((({[]}[<><>]))<<[{}[]][<>()]>([{}[] 7 | ([({[[<{[{{[{<{}{}>[<>[]]}(([]()){<><>})]{<<<>()>(()())>{{<>[]}[<>{}]}}}(([(<><>){[][]}][{[]}[[][]]])<([{ 8 | <[<{[(([<[([<<()()>{{}{}}>[[<>][{}()]]]({(<>{})}<(<>{}){<><>}>))(<{[{}<>][()()]}<([]())<<>[]>>>)]>< 9 | <[([<<{{[(((<[(){}}{(){}}>{[()[]]<[]{}>}))){[[[[<>()](<>())]]]}]{<{(<<{}[]>[<>]><[[]()]<{}[]>>)({[()<>] 10 | (({[<([<<([{{{()[]}{[]{}}}{{<>[]}{()[]}}}<<(()){<>[]}>[(<><>]{(){}}]>]([[({}{})((){})][[<><>]((){})]][{( 11 | {{((<<<{[({[{{()<>}{[][]}}](<([][])[{}{}]>[{(){}}<[]{}>])}<[{{{}{}}(()<>)}[(()<>)[<><>]]]>)(<<[[[][]][{}<> 12 | [({[[{[{[{<((([])){<{}()>{[]{}}})>{<[{()<>>({})][{(){}}<()[]>]>{[{<>{}}(<>{})][<()[]><<>()>]}} 13 | <<{[(<<{{{(<{{[]()}<<>[]>}>{<<{}{}>{[]{}}><[{}{}]{{}[]}>})}{<{[<{}{}>({}())]}{[([]())[[]<>]]<{<><>} 14 | ((<[[[([{(({({()()}[{}()])(<{}()>[[][]])}((<[]{}>(<>()))([<><>][<>{}]]))<{([[]{}][[][]])}> 15 | <[<<<<{(((<{[{(){}}{<>()}]}{{{{}()}}<<<>()>>}>{({{<>()}}{<[]<>>[()()]}]}){<(<({}<>){[]<>}>({{}()}(<>())))> 16 | (([[[{{{{<<{<[[]()]{()[]}><[<>[]]({}<>)>}<<{[]{}}<<>>><[{}[]](<><>)>>>[({<{}[]>[(){}]}[{(){} 17 | {[{[({{({<<([({}[])][{()<>}{<>()}])<{<[]()>{()<>}}>>[(<<[]{}>{()()}>)]>})<{[{({<<>[]>{{}()} 18 | <([{[[<[([<(<<<>()><[][]>>)[[[<>()]<<>{}>]]>{<(<{}<>><[]()>)<(<>)[[][]]>>}])]{[[((<({}())[[]{}]><<{} 19 | [([[([{[<({(<({}{})[<><>]>){{({}{})(()())}[([]<>)<[][]>]}}}[[([[[][]]]<({}{})(<>[])>)(([[]()]{<><>})[[[]() 20 | {[[<[<(({<[{<[()[]>{<><>}>([[]<>]{[][]})}([{<><>}<<>{}>][{(){}}[{}<>]])][<(<()<>>(<>()))[{()<>} 21 | (<<<<({[{<[[({()<>}(()()))][({()}[<><>])]]<<[(<>[]){{}()}][([]{})({}{})]>{<[[]<>]<<>()>><[{}()][<> 22 | [({<<{{(<{<<{<()()>(()<>)}<{<><>}>>(([()<>][()<>])[(()<>)(()<>)])>[<(<()<>>{{}()}){[[]{}]{<>{}}}>]}[(<[({}( 23 | ({([([[{{[{{{<<><>>{()()}}[[<>[]][()()]]}({{<><>}{<>()}}<({}())>)}<[{[{}()](<>[])}(<(){}>)] 24 | (<{[[[{((<([[<[]{}>([]<>)]{{()()}}]({[{}[]](()<>)}{{{}}[<>()]}))>))}([{(([(<{}[]>[<>()])]({< 25 | ([{{<([<{{<[{(()]([][])}][{([])<{}{}>}<([]<>)<{}[]>>]>{<[[[]{}]<{}[]>]<{()}({}<>)>>}}}{<{<<[(){}](()()) 26 | {{<<<[{<([<<([{}[]])([()()][()<>>)><({[]()}[()<>])>>]<{[([{}{}]({}[]))]{(({}{}))(<<>()>({}[]))}}{{[[{}{}]<[]< 27 | {[([({[[<{{[{[[][]][<>()]}<<[]()>>]{<{[][]}(<>{})>}}{<[[<><>](<>())](<(){}>({}<>))>[<<[]{}><[]()>>[{[]{} 28 | [{{{([{([[[<{{{}()}{<>[]}}[{<>{}}[[]<>]]>]<([{{}{}]<[]()>]){{{{}()}[<>[]]}(<{}[]>{[]<>})}>][{{[<<>{}><()[]>] 29 | [<[(<(<([(({({{}<>})[{{}<>}{{}[]}]}{[<[]<>><{}[]>][[{}<>)<()<>>]}){{<<(){}>[{}()]><<()>([]<>)>}}) 30 | <(([<(([([{([({})][<{}[]><[]()>]){{{[]{}}[[]<>]}<(<>())[{}()]>}}])](<[({(({})(<>()))}{{<[]>}{<<>{}>[()()] 31 | [<{[[{([<{[<(({}{})(<>()))><{{{}<>}<()()>}(<<>()>(<><>))>][[[[()<>]<[]{}>]]{({{}[]}<()<>>)}]}([<<[()()] 32 | ([<{{(<(([<{<(<>{})<<>[]>><{{}[]}<[]{}}>}{(((){}){<>()})[<(){}>{<><>}]}>{<([[]()](()<>)){<()>[<>< 33 | <(<([({<(([[[[<><>]([]{})]({[]()})](({[]}({}[]))[({}<>)(()())])]<{({[]{}}([]())){<()<>>({}<>)}} 34 | [<(<{(<<<([{<[()<>][<>{}]>{[<>{}][()<>]}}{{<<>{}>[<>{}]}[{(){}}[[][]]]}][{[<[]()>(<>())][<<>[] 35 | [<[[([[[([([[[<><>]({}())][[<>()]]](([[]]({}))[{()[]}({}<>)]))(([{()[]}{{}}][{()[]}[<>[]]])({{<>{}}{ 36 | [<[([<<{{{[[[({}{})<()[]>]]]<(({(){}}{(){}})<[{}[]][[][]]>)>}({{([[]{}][[][]])<[<>[]][(){}]>}<[ 37 | <[<[({{<(<<[{{<>[]}}[(()())<[]<>>]][{{{}<>}<<>[]]}]>>)<{<(((<>[]))[([])]){(<[]()>({}()))[{{}< 38 | ({([<<<<[<{(((<>[])<()()>))<<[<>[]][<>[]]][{[][]}]>}((([[][]])({{}[]}[<><>]))({[[]<>](<>[]) 39 | {(<{((({[{({<<()[]>(<>())>{<{}{}><<><>>}}(([[]<>][()[]]){[{}()]}))[<<<<>()}[{}[]]>(<{}{}>{<>[] 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 | -------------------------------------------------------------------------------- /src/aoc15.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List Number Decimal. 2 | From Coq Require Import ZArith. 3 | 4 | From stdpp Require Import gmap sorting. 5 | 6 | Set Implicit Arguments. 7 | Set Contextual Implicit. 8 | 9 | Import ListNotations. 10 | 11 | #[global] Open Scope N_scope. 12 | 13 | Fixpoint decimal_to_digits (d : Decimal.uint) : list N := 14 | match d with 15 | | D0 d => 0 :: decimal_to_digits d 16 | | D1 d => 1 :: decimal_to_digits d 17 | | D2 d => 2 :: decimal_to_digits d 18 | | D3 d => 3 :: decimal_to_digits d 19 | | D4 d => 4 :: decimal_to_digits d 20 | | D5 d => 5 :: decimal_to_digits d 21 | | D6 d => 6 :: decimal_to_digits d 22 | | D7 d => 7 :: decimal_to_digits d 23 | | D8 d => 8 :: decimal_to_digits d 24 | | D9 d => 9 :: decimal_to_digits d 25 | | Nil => [] 26 | end. 27 | 28 | Record DIGITS := { unDIGITS : list N }. 29 | 30 | Definition decimal_to_DIGITS (d : Number.uint) := 31 | match d with 32 | | UIntDecimal d => Some {| unDIGITS := decimal_to_digits d |} 33 | | _ => None 34 | end. 35 | 36 | Definition dummy_from_DIGITS : DIGITS -> option Number.uint := fun _ => None. 37 | 38 | Declare Scope DIGITS_scope. 39 | Delimit Scope DIGITS_scope with DIGITS. 40 | 41 | Number Notation DIGITS decimal_to_DIGITS dummy_from_DIGITS : DIGITS_scope. 42 | 43 | Definition foldi {A B} (f : N -> A -> B -> B) (xs : list A) (b0 : B) : B := 44 | let fix _foldi (n : N) (xs : list A) := 45 | match xs with 46 | | x :: xs => f n x (_foldi (N.succ n) xs) 47 | | nil => b0 48 | end in _foldi 0 xs. 49 | 50 | (* N is awkward because of saturating subtraction, we use Z so going negative 51 | is a natural way to detect going "out of bounds". *) 52 | Definition point : Type := Z * Z. 53 | 54 | Definition map_of_grid (xs : list (list N)) : gmap point N := 55 | foldi (fun j => 56 | foldi (fun i h => insert (Z.of_N i, Z.of_N j) h)) 57 | xs empty. 58 | 59 | Record Input : Type := MkInput 60 | { input_grid : gmap point N 61 | ; input_dim : N * N 62 | }. 63 | 64 | Definition input_of_grid (xs : list (list N)) : Input := 65 | {| input_grid := map_of_grid xs 66 | ; input_dim := match xs with 67 | | [] => (0, 0) 68 | | row ::_ => (N.of_nat (length row), N.of_nat (length xs)) 69 | end |}. 70 | 71 | Notation "'input' x .. y" := (input_of_grid (map unDIGITS (cons x%DIGITS .. (cons y%DIGITS nil) ..))) 72 | (at level 200, x at level 0, only parsing). 73 | 74 | Definition example : Input := input 75 | 1163751742 76 | 1381373672 77 | 2136511328 78 | 3694931569 79 | 7463417111 80 | 1319128137 81 | 1359912421 82 | 3125421639 83 | 1293138521 84 | 2311944581 85 | . 86 | 87 | (* Priority queue with a heap à la Lampropoulos (Ode on a random urn) *) 88 | Module Q. 89 | 90 | Inductive t (K : Type) (leK : K -> K -> Prop) (V : Type) : Type := 91 | | Node : K -> V -> t leK V -> t leK V -> t leK V 92 | (* invariant: the right tree is bigger than the left tree *) 93 | | Leaf : t leK V 94 | . 95 | 96 | Section Q. 97 | 98 | Context {K : Type} {leK : K -> K -> Prop} {V : Type} `{!RelDecision leK}. 99 | 100 | Definition empty : t leK V := Leaf. 101 | 102 | Fixpoint push (k : K) (v : V) (q : t leK V) : t leK V := 103 | match q with 104 | | Leaf => Node k v Leaf Leaf 105 | | Node k' v' l r => 106 | if decide_rel leK k k' then Node k v r (push k' v' l) else Node k' v' r (push k v l) 107 | end. 108 | 109 | Fixpoint unsnoc (q : t leK V) : option (K * V * t leK V) := 110 | match q with 111 | | Leaf => None 112 | | Node k v l r => 113 | match unsnoc r with 114 | | None => Some (k, v, Leaf) 115 | | Some (k', v', r') => Some (k', v', Node k v r' l) 116 | end 117 | end. 118 | 119 | (* Remove the root of [q] and push [(k, v)]. This looks awkward but seems necessary 120 | to make the function structurally recursive. *) 121 | Fixpoint sift (k : K) (v : V) (q : t leK V) : t leK V := 122 | match q with 123 | | Leaf => Node k v Leaf Leaf 124 | | Node _ _ l r => 125 | match l, r with 126 | | Leaf, Node k' v' _ _ => 127 | if decide_rel leK k k' then Node k v l r else Node k' v' Leaf (Node k v Leaf Leaf) 128 | | _, Leaf => Node k v l r (* If r = Leaf then l = Leaf *) 129 | | Node kl vl _ _, Node kr vr _ _ => 130 | if decide_rel leK kl kr then 131 | if decide_rel leK k kl then 132 | Node k v l r 133 | else 134 | Node kl vl (sift k v l) r 135 | else 136 | if decide_rel leK k kr then 137 | Node k v l r 138 | else 139 | Node kr vr l (sift k v r) 140 | end 141 | end. 142 | 143 | Definition pop (q : t leK V) : option (K * V * t leK V) := 144 | match q with 145 | | Leaf => None 146 | | Node k v l r => 147 | let q := 148 | match unsnoc r with 149 | | None => Leaf 150 | | Some (k', v', r') => sift k' v' (Node k v r' l) 151 | end in 152 | Some (k, v, q) 153 | end. 154 | 155 | Fixpoint pops (n : nat) (q : t leK V) : list (K * V) := 156 | match n with 157 | | O => [] 158 | | S n => 159 | match pop q with 160 | | None => [] 161 | | Some (k, v, q) => (k, v) :: pops n q 162 | end 163 | end. 164 | 165 | End Q. 166 | End Q. 167 | 168 | (* Compute Q.pops 5 (Q.push (leK := N.le) 3 tt (Q.push 2 tt (Q.push 7 tt (Q.push 4 tt Q.empty)))). *) 169 | 170 | Definition isSome {A} (x : option A) := 171 | match x with 172 | | Some _ => true 173 | | None => false 174 | end. 175 | 176 | (* [gset] insertion (as [fun x s => union (singleton x) s]) is slow, 177 | so we redefine our own sets from maps which have fast [insert]. *) 178 | Notation set X := (gmap X unit). 179 | Notation insert_set x s := (insert x tt s). 180 | Notation elem_set x s := (isSome (lookup x s)). 181 | 182 | Section Dijkstra. (* This is really A* now *) 183 | 184 | Context (V : Type) `{Countable V}. 185 | 186 | Record graph : Type := 187 | { max_edges : N (* upper bound on the number of edges, as fuel *) 188 | ; neighbors : V -> list (N * V) 189 | ; heuristic : V -> N (* Upper bound on the remaining distance *) 190 | }. 191 | 192 | Definition no_fuel : N. Proof. exact 0. Qed. 193 | 194 | Definition _dijkstra (g : graph) (goal : V) (__dijkstra : _) 195 | (q : Q.t N.le (N * V)) (visited : set V) : N := 196 | match Q.pop q with None => 0 | Some (_, (d, v), q) => 197 | if decide (v = goal) then d (* REACHED GOAL *) else 198 | if elem_set v visited then __dijkstra q visited (* SKIP *) else 199 | let visited := insert_set v visited in 200 | let push q '(dd, v) := Q.push (d + dd + heuristic g v) (d + dd, v) q in 201 | let q := fold_left push (neighbors g v) q in 202 | __dijkstra q visited 203 | end. 204 | 205 | Definition dijkstra (g : graph) (goal start : V) : N := 206 | N.iter (N.succ (max_edges g)) (_dijkstra g goal) (fun _ _ => 0) 207 | (Q.push 0 (* don't need the heuristic for the first point *) (0, start) Q.empty) 208 | empty. 209 | 210 | End Dijkstra. 211 | 212 | Definition grid_neighbors '((i,j) : point) : list point := 213 | [(i+1,j); (i-1,j); (i,j+1); (i,j-1)]%Z. 214 | 215 | Fixpoint map_filter {A B} (f : A -> option B) (xs : list A) : list B := 216 | match xs with 217 | | [] => [] 218 | | x :: xs => 219 | match f x with 220 | | None => map_filter f xs 221 | | Some y => y :: map_filter f xs 222 | end 223 | end%list. 224 | 225 | Definition neigh (m : gmap point N) (ij : point) : list (N * point) := 226 | map_filter (fun ij => 227 | match lookup ij m with 228 | | None => None 229 | | Some d => Some (d, ij) 230 | end) (grid_neighbors ij). 231 | 232 | Definition heuristic_to '((igoal, jgoal) : point) '((i, j) : point) : N := 233 | (Z.abs_N (igoal - i) + Z.abs_N (jgoal - j)). 234 | 235 | Definition graph_of_input (i : Input) (goal : point) : graph point := 236 | let '(x, y) := input_dim i in 237 | {| max_edges := 4 * x * y 238 | ; neighbors := neigh (input_grid i) 239 | ; heuristic := heuristic_to goal 240 | |}. 241 | 242 | Definition solve (i : Input) : N := 243 | let '(x, y) := input_dim i in 244 | let goal := (Z.of_N (x - 1), Z.of_N (y - 1)) in 245 | let g := graph_of_input i goal in 246 | let start := (0, 0)%Z in 247 | dijkstra g goal start. 248 | 249 | (* Compute solve example. *) 250 | 251 | Module Part2. 252 | Section Part2. 253 | 254 | Context (ii : Input). 255 | 256 | Definition REPEAT := 5. 257 | 258 | Definition goal := 259 | let '(x, y) := input_dim ii in 260 | (Z.of_N (REPEAT * x - 1), Z.of_N (REPEAT * y - 1)). 261 | 262 | Definition decompose_point '((i, j) : point) : N * point := 263 | let '(x, y) := input_dim ii in 264 | ( ((Z.to_N i `div` x) + (Z.to_N j `div` y))%N 265 | , (i `mod` Z.of_N x, j `mod` Z.of_N y)%Z). 266 | 267 | Definition out_of_bounds '((i, j) : point) : bool := 268 | let '(x, y) := input_dim ii in 269 | (i 273 | if out_of_bounds ij then None else 274 | let '(s, ij') := decompose_point ij in 275 | let wrap x := ((x - 1) `mod` 9) + 1 in 276 | match lookup ij' m with 277 | | None => None 278 | | Some d => Some (wrap (d + s), ij) 279 | end) (grid_neighbors ij). 280 | 281 | Definition graph_of_input : graph point := 282 | {| max_edges := let '(x, y) := input_dim ii in 100 * x * y (* 4 * REPEAT * REPEAT *) 283 | ; neighbors := neigh (input_grid ii) 284 | ; heuristic := heuristic_to goal 285 | |}. 286 | 287 | Definition solve : N := 288 | let g := graph_of_input in 289 | let start := (0, 0)%Z in 290 | dijkstra g goal start. 291 | 292 | End Part2. 293 | End Part2. 294 | 295 | Definition solve2 := Part2.solve. 296 | 297 | (* 298 | Section Test. 299 | 300 | Let g := Part2.graph_of_input example. 301 | 302 | Compute neighbors g (11,0)%Z. 303 | 304 | End Test. 305 | *) 306 | 307 | (* Time Compute solve2 example. *) 308 | 309 | Definition solve12 i := (solve i, solve2 i). 310 | -------------------------------------------------------------------------------- /src/aoc09_input.txt: -------------------------------------------------------------------------------- 1 | 0197653456789987679545987978921245689901497654212455689767899878999979653246892123569876467899212346 2 | 9989542349899986578959976557890134599892398943201234678956789467989867932135789012398764345678923456 3 | 8679931298999765459898765445921247987689459865432345889345892399876546899013894123459976569799634577 4 | 6567895497998764345789543239895456797535967976545467891234989989865434598954993248969987678999545798 5 | 8456897986539975234568955398789967998212899597676578910395678979996423987895789356798698799997656789 6 | 7357899765624987356979967997678899876323795498789789929989989968989219876789998767986569899998867899 7 | 6479998654012998487899879886456799985434589349899897898879899757878929865699989878987461939879878989 8 | 7989876532129876598967998754347899876545679299965945977569798436569197654389876989986320129865989778 9 | 8995987644234998679459899975456943987656798989654326965497656424459298796578965699875431234979998568 10 | 9424987654346789789348789986567892398767987878943219876989843212348999887679873579987549345698976457 11 | 5313598789556999893245679987679921299899656667894398989878964301237899998995432123597698996987665376 12 | 2102459898967898987656799998789992989998943456789497898957896324356789449789521012398987989976554245 13 | 3213456997998967899878978969899789978997432347899986787545697534458891234689942123789976879876432156 14 | 4323569876899756799989569956987698766986421566789995631234789947669910123799893454569895366999943018 15 | 5444567985679534789991349899996569645977310145679864320123456898978954394569789965698789245987894236 16 | 6565979874599323567890198798989459759864321236799998432335679999989796989998679796987679123976789345 17 | 8989898765678901378932987567868969898765462347899876543479895695395689879876534599876568999435899456 18 | 9998719876789323489649876476457890949976574456789987687568996989987899965432123489985389987645998767 19 | 2987624989898754599656975324348991234989675778892399898978989878998999996542014678976498998757899898 20 | 1298545699999865987999764210235689946798776799999567999989879767899998987843124789998567899969999919 21 | 0987656789989986976889754321347999899989987898898998999997665456789987698764434999987689921399989101 22 | 1398777899874197975678965432456789678976898987686889989876556345999876549978556789998995439978976992 23 | 2349889999963098984568977949767894569865789997575679764986433235794989998989678997899986598867895889 24 | 9456992198742129799679989898979913598754657896434768992096520145693199877898789245999999987656954678 25 | 8967921098653245698789998767892102987653235789123456789989321238789098965459890129878998654347893557 26 | 7898943459854756999895987658943213498732126789012567999878932456896987654323991298765579543238912345 27 | 6799854598769867899954398769654324596543245899923456898969896577945698763212679987573498764369543467 28 | 5679767699989998999863239878965735987654376799899767987756797689434997853101598765432349878456976568 29 | 3568979987899769998943143989876896798765797895798979765645989995319876543213459898543556997567898679 30 | 2389998976598643987521012398997997999897898954687997654236978894201998765325578987656789698689998789 31 | 3567897895498656799432123567898998988999969543456789894399769799213459876736789998967896569799999894 32 | 7678976789329767987993544679999999976987654312398999975987654568924599987858998999989999678998989943 33 | 8799235699901989876789795889989988665398979103456789989999543457895987698969987894595698999987867932 34 | 9890123988892398965678976999869876543239898919767896799988651367939876459878976943203497899876756891 35 | 9921299876793987834779998998754989654198787998998924999977520179923984369989645894312986789765347799 36 | 7549987975899875324567999989965999965987676797899212398765421467899865458999786797324975678963235678 37 | 8998975986921965434678999878899899878986555656899404459875432348954986567899897896439864567942124579 38 | 9397654599899876645889889756789789989299434346798912346986545699843298789921998999598963878921023459 39 | 3298943498765987856795679847679678990198621234567895487987659789765109899910139998997654989542434678 40 | 9099894598654398967894599934533467799986532345998987579298767999953212999891239997549765698656547789 41 | 8989789999763219878962378921012345678987543456789598690129899459895629989789398876839876789767656896 42 | 7677679899972102989754569532133469789098658597999439789436943245789798765679987654324987999898867997 43 | 8564576789989743499895678943544678993129867998998929896545692134567999954399999976786798956999999898 44 | 6432345894398654899998789654665689943248978969987899987657789029989898899498763987997899235689988789 45 | 4321434899298776789359898765887799894356989653656789898767892198898756798979942199998989957899975678 46 | 5210123678929898995498979876798988789987996542345896789878954987668645987668893267999777898998654589 47 | 7491234579012999976987567987899576699999876431556965432999979876557539875456789346789656899998785699 48 | 8989955689129899897896456798954324598999765432369994321023498767432129654321239997894347912989898789 49 | 9979896793298766798989399899765945987899976545498789432344987654321098768732997899965456899876989899 50 | 8765799975987654899878989939879869876789899876987687993656798765534129879549876799989567899765674999 51 | 7654567899998432398765779019989998765456798987899456789767929876656434999656965689997698969874323478 52 | 8652089998998657989874568998999879876789897798998767898979213987767849878969854569998789754985412567 53 | 7643578997899869876543457897998765998995965679349879937698923998878997667898773237899997642195423456 54 | 8654689976879878988764598976899654959123987890199995326457899879989986456899632126789999654987689587 55 | 9869789865767989899875789655698969843234899989987654215345989768999965345798543234567898767998789678 56 | 7989897654656798797976789434987998764345678978998754301234569654569874237997656346678999898959898789 57 | 5496987643235897656987894324996889875456789867929865456345978943349752146789866457789999929234999893 58 | 4345695432124569547898989209875679876568997657813987678456989432198643256789987667899989910126798912 59 | 6456789643097697667969679213986789987689598543101299899568996543398764469899999788999876899437987893 60 | 7767998764989899878954598929987891298795349959212349998699569756459895678978999899998765698948976789 61 | 8998939875978999989543987898998992999894239898923598979789459867968998799567987999765984567959865990 62 | 9769323989865989995432496787899989799930199796899987869894324989899879899979876898754323678999754891 63 | 7653212399754779996531985656799877679321987645678975456965455798799864999899985789543210989988966789 64 | 8874309987653656789699764545689954578939998437899986345896596987678972989768994898764439899877899891 65 | 9986498767321247899987653434599843467998992123789997956789989876567899767957989959765998765656789910 66 | 6598987653210345929876432125987656567897789035679989898899976995459998951345679349879876543234898923 67 | 5329998654328456913998521016798767878976578997799878789999895976599987530123489219989998932123567899 68 | 6910989865987667899876543223569899989895456789912965689998754698679987621238999998994987543234589998 69 | 9899878997898898945987956334689991398774346999899754678987543549989986532357898897892198656357678947 70 | 5798769898999959321398967456789889987653234987678943789995432125798998754588987646789098765458789435 71 | 3987656799986543210179878997995679876543129876567965699864321013457999885678996535899199876768997623 72 | 9886545678999654322457989598933598765431098965459899789765532134567892976989987323988989997879789794 73 | 8765434567998768473578992349212399979532987653217678999898643246789921987896795439976578998997678989 74 | 9876323458999898764679874459323989998754987632104569632987654356896439898945987698765489899989539878 75 | 9988434567899999989789765598994978999875698544323689541098765467989597659139898987654346789878910167 76 | 9876575878999888999899877987689767891986987698765678932129876579768987543298769499874234679967892345 77 | 5987689999998767999910998976598756990197898789879889543234987678957897654369754398765645698856789756 78 | 4398794599987656789999999896432646789298989990989997654345798999348998976456963219879896897645679877 79 | 3239895989876543498987798754321434567999876421299598766987899621298999986569876323989999982123899998 80 | 6345999876987432567975649865410124567899996542998439987898999542456789998998765456899998765236789439 81 | 5456899865697643778954234987521234679988889959886724398999997663968997899129976568999899874345689321 82 | 6667897654987654567892123498435345898767767898765410279899989789899466789298799789998776965456797452 83 | 7979999743598775799954294999545456998656656999874321456789878998791245679989578999886565978967896543 84 | 8999898995679896987968989899876569876535345789975432357899869876589387889875465789765434989878999964 85 | 9988757989789997896899876789997879854321236789997549456798756982468998998753234898954326499989198895 86 | 9876545678992198975798765679998997653210147999989698967898743210178959769942102457893212389991096796 87 | 2997626789999019424597654568939298764321256899978987998987654321389543457943212967894345678992985689 88 | 1459739899898929013698742379029109885454345998765676899998765434499872129874567898965566989989864578 89 | 0296547998767898924797653489198999996965456789653235789999876595578953298765678999899789899876943456 90 | 2987656789248567895679854579987689999876787995432123567899987989989875459876789989789898679875432345 91 | 3498779893123468976789765678966578899989898954321012345678998979899976569987899876678987598765320156 92 | 4999889954564567897899897889656466789999979765432125767889219856789989878999998534567895459876431345 93 | 9876998795778678998999998996542345678999865986544234579995439767998799989998996545698954346997532666 94 | 8965345696889789129989329986421234899999754397655655678976546978945679999986989676789876234598754598 95 | 7844236789994998998778939765410125679989653298786769889999656989234567899975879989893986356798768789 96 | 5432125679553456986567799877321236798979790129897878999998987993123458998764567993912995467899989899 97 | 6594034689432349987434567986432347897857989245998989988877999899012367899653467892199876878901498967 98 | 7689125678944498975412798987685498986546679956789899876456997688975457998762345993987989989892397756 99 | 8794234789656987654323689999886579873234567897896797984349876567896569874321235689976492198789976546 100 | 9895345998767899875454568923987689764356678998965986543212987678987698765210123498654321013567894324 101 | -------------------------------------------------------------------------------- /src/aoc15_input.txt: -------------------------------------------------------------------------------- 1 | 8656175343119439947311919179279377257689197682985752287249881788527977345924133329967132199899199876 2 | 4281288396984115627338957853913949146812568775798196289991176529889498798259196976277683981565984526 3 | 8169838335918963371547591999342191683995972519179929683978126291855319511168245582651697938949414963 4 | 9911589184911198759466719191189995157885898771177913669999436998997781742478168921196176418888127932 5 | 2332856729917591158935782911513226531793881992469468248251991718456991551657621249229316797949388969 6 | 6488738222981127824819626661531168733698299313631126969162927725778914183239351484699921454131481322 7 | 3456499223985116399353928681116846939429849384129296119943791119497551946593566977823982927391143399 8 | 9297612841849646148511299569971197927971682598351883892842936977227795411959211782251399118676896328 9 | 1685688918999598249622886442487951289969917848948815999749154287969297396481891239821819247914959943 10 | 2855192597719945162116189119381795158862162959133647579913886639586438893695967226719685616432291318 11 | 3893139873964939791913261811173979825213968972939996181992593113695976322782892995939891783998623789 12 | 5964671772545917912328949994999514157618987654288269789931394913375316999489275494179994919117119365 13 | 3216339828898396212733674969295762442389789119366989996931919596282992864471192938639162947919972647 14 | 7879826444123912118829914949989194219763533694839431198212319893181151696157671388992581982743988967 15 | 7876122492176935838133394839673532581399474449569117478121989273123412313151952891988698552384251637 16 | 8786999269197821985731819155537259938991261919979365751539876866146174376911518943778479997131942722 17 | 7239919942299391891898171771589178983916281118889294494829292752139999754571391999826947791975394972 18 | 2727617215141959982544247383138498917281833932371546394891963994434638187617528821379728933335772342 19 | 6712949984729176138535147942577311588399869767114795759883948915177671474313191789814718292236422124 20 | 8689792116597916131779139899373471282726812338914773516383771158691551851991689929199689197212298649 21 | 6228175894997691471313338136819712699979449476188196729899628851391971728199959981585798691881191415 22 | 9491157288112631922166642933446197292729817888649185515198768537925149995158353829229269894798938589 23 | 5199389142294542461535132814487861987422485947698739199748986652229272998164982399192268248929567161 24 | 6881119581991538187539159493621999896486112182779617795198955921614753699796171837819179999654231813 25 | 6996595113784151975521879415898217119639999975184518599369743127684295298268259495226623211591871888 26 | 1779949977648145993713949919359399998812143513534984334127763318649997689919849157137418761137512977 27 | 9223292971993981422528813498119387921238194638215641911218326517839287886478991147999899894724396962 28 | 7451983891767995938972123465939918261682281929689989464297789895588752221375859586787938391672994381 29 | 1579954176878141996516584483611183926131694919877929897576151469657864935819598781814826881644187861 30 | 8934595321937914584995177237653199951582515953621782173159453287575529819242531191989113518599339361 31 | 3214791137819868237121897913928328682928239268681975567994149694512799167598489194267554981611157817 32 | 3161289322443822496458312797912957538349962328948955764669152944278622928929944477635195993465821714 33 | 3769985892295265479971729196428585411214871889139731131516448815999122871374996159138497416978598848 34 | 4926877381218811127939655759733739111889455359949289979523168797571871445191441719179859376969393872 35 | 7159871151274214979637977982939997337182139971896511115912187982698278842961545125121242636339621282 36 | 8423118867997391616931374681582965659184916625321536161483641999294114251928796446618889979683993218 37 | 6824788915976897879897933391998341399228914119912289149511515799142181679965255395897688149876629889 38 | 4794395837416911945432167619882718499181629123717219977896911277339851349162195299228963994667691947 39 | 1465122112768881153591399679274839985297692314947884169719151181986711822112796246416415955915718319 40 | 7114797833579933611249299912348294873921288555119486979959982462111791467394161781467316779796883775 41 | 9767795467854144194712742294766968549329117618283754959873952489784997597669593796889571883816748771 42 | 1759974879458746414925558868197241214751687661841649999221178613679929261984417289292556869111324941 43 | 9557955429999672993612951916598187741611893112948813816999484953994151249931191942493691497559992158 44 | 1469791219499218437828194894539893191199115998162227659757698173867329816328599398544492677817272998 45 | 6696472832532492295279572315976884291727999732161858916985514872395367168971969865959582923387918951 46 | 9722652752119479169481198119314728131429449798379179119171791999189878174319864498112912224658495939 47 | 9581794449119116165418178711351481129242636919987948291451161695541253977174231393582734959682898495 48 | 4757727865924728111221629983989222587789999361791192917315287219922119718827676188689966872358484669 49 | 1982319969915242121935864989286462118395187369193933592791414764965279817872197863615512262358899223 50 | 1811379712999278717898361849316989959114612857179582117839285399618929182259624916911439331479239488 51 | 1377519658968884779897799292198595917148591218821239614925192183128211371959295299959221257811239131 52 | 2627929612263297913663198357736594275199769318118546371628241929618769991214845296132728799271417791 53 | 7576972138942696587693261199467749912936563131454674591315468112333812659454789393699615918167338715 54 | 1778985995949591574849625759667137792111923771976687288498928179271746938986792658149697999719931492 55 | 1497174992519427759719169714342998311421419197412331399469329847692794191181111339933357161599799597 56 | 7158163932199423259572847121198873491117119999919996985599149129919588579223518511588378639685891315 57 | 6219361855573892912131718991998196749251949481814844299182119621344738991784149679694476483378729929 58 | 1398599388779918861183115593522489331874978727922373471991219247115944295163699192776967648639268659 59 | 8246143812623927544154898631717811662213981175534335932638718171969421398421692892399791789186618487 60 | 4457134139841167885881924949364884427839314973843366971997383189398399657998961185159781215111619878 61 | 2889934549617841969369167119338852267887359654637229634658717722728239549585928482358431813296859898 62 | 9968328746979669249145999585143117898196251944175462877716129989773292878848966999379983436559934934 63 | 6493994193996595991299891992438695916166928199197254269991979292986895799985938128881229638182945947 64 | 7266928918675112795879219714929968471352931229592623394713393869269941181318972192169271548316892574 65 | 2174196776119149368951321419512925818641848291921584561885586189445194773817792112569311611884895234 66 | 5617593683181229369984148191819568774125471789395181874847932736429929334265516997661987796259692831 67 | 7882228973393795938729341656949619511272988446634311621871394678132831899299832311614174939261965429 68 | 1131881592984545192978449637151892697525357924197922698921549791127287595929496515499876251183628176 69 | 9922954913893559597663824459627321943979599969474976998899879429185892995511392872381956558981867119 70 | 5166385448694129439797196837181355547743133114829285275149516986685925813416161972979872853196155916 71 | 3292899922794159291851551956738911971988929383861879921354871787791695284999126375594873179426338749 72 | 3971894752927483651131869717199971871964396958991799413921821198121691265888799954912311963139425236 73 | 5778565318498395151591219315499879273943817921588123199611531989674238272218198865913747444419629892 74 | 1148956123134785152496887782841669964225944272953163717879528194631986997718971481186872943816456591 75 | 5982998155291779554662769986899318991622943125199743569463317913185991442772122148595119965486877247 76 | 1592622221626611159996955945922614981222438358385913259412688295754161193293194979914999974739594393 77 | 1735995389872189896282749844299933869588931688619645726996959149185997128397635694766944945458588326 78 | 8969839951998899979864239155832982419271118982882915197745124695321464198748765361499779978719441246 79 | 6625484228731161195646227911299498172947526327866775111148173468799729895761595437743769876911891521 80 | 6742199381937628999297557371399872217983581247138899399239252389649491949578491998528132446741686888 81 | 9212328164223895178547771855976415127193137191217188318191949238429129518281919843229126971963111111 82 | 8589368771155989697277997492471969978917117589192916193887975787949771588121551699971132275182798898 83 | 1321997349438946615383211392181979153964221243634922639112684529286794272849757186396714797832698913 84 | 5499455959999492339698359789213323519479768626457859213487938838995348379392231623595879353861382977 85 | 4612129999347379911982695394862437936254989311441326295994617191963497895691479282499959828989987571 86 | 3953949985681978999897341375236798381973326952579319464522624134872231113676167279146985521828793431 87 | 2547232255918288952326674861524529119719429148626615319818611241832868529862499874951986568635799957 88 | 2181959929952711246913363617991144311613441799129546223661433628933579819732979148127949974997119951 89 | 1369158892917379123998253242599392893199998853969933983592129813969821127281951849151627687114757833 90 | 9629699176294886577773394197932998769278865351155516385519239971147785457838922269188195227329168368 91 | 1788912961677399663173822433232514884848179868666798987368382881226468481869127998236137881926332779 92 | 4811241997249159619241887142461943467819366815858371379792287198271563986876852729186927761281942192 93 | 2121993996798639492562961751217922319969898368461919218459919713413366292171628639922554153774327219 94 | 3489591127775295131639799492971117993637992434115331278511281997587996291111198123428588991837368589 95 | 1283798883941983912985615991541417994114453747887836936186431822993881123911799962749981389292178586 96 | 8392631553657936578372199916912973193995216848776811924799769959318889717919172521769363698292447429 97 | 9587697134368994212916856845984875416273418561198913859115983139967143891991617853289936814265113512 98 | 9111571922348271733199797953979536915998195916688317991255916216419817129423728913622269119972958686 99 | 9959599568987335314713638999897919449512991684446347789183915679567141547281548619496728636288445972 100 | 8391247911139217869276338998734496391173478717461631572924754792241695917352991662734191814376765142 101 | -------------------------------------------------------------------------------- /src/aoc20_input.txt: -------------------------------------------------------------------------------- 1 | #..##...#...####.......#...###.#...#.##.#.#.###.##...#..#.....#..#.##..#.....#...###.......###.###...##..##.#.##.#.#.......##.#.#..#.#...##....#..#.###...#......#..##...##.#.##.##.###.##.#...#..###...###..###.##.#..#..#.#.#..########..#.#.#.####....##.##.#.##.##.#...#..###...###.###..#...##.##..###.##.##.#.###.#...#####.##.####.####.##...####.####...#.#.##..#.######.#..#...##.#.##..###.##.#..##.##....##.###.###..#..##.#.#...##.#.#####...##....#.##....####.#.####.#####.#....#...###.....#####.#...###..#.####. 2 | 3 | .##...##..####.##.##.#...######.#.#..#.#.#..#.#.#.##....##.#..#..#..####.#..########.##.###.#.##.### 4 | ####.....##.#...#.###...#.##.......##.#...#######.......#..#..#...#.#.....##.#.##.####.....#.###.#.. 5 | ........#.###.#..#####..#.##.###.#..#..#.#..##..#...#...#.....##..##.....##.#####.#..##.#..#.###...# 6 | ..#.#.#.####...........#...#.........#####.#.######..#...##..#.##.#..#.....###.##.##.......####.###. 7 | ..#.....###..#.####...#########.....#.#.####..##..###..####.#.##..####.#.###.##......#..#.#.#.#..... 8 | .#......#.....#..########.####....##....##..#...###...#.#####...#.#...#.#........##########.##.##.## 9 | ###..###.#.###....###.....##....##.#....###..#....###....####.##..#...#....########.##.#.#.#.......# 10 | #..####..######.#.###..###...#......#######..#..##.######..##.#####......###...#.#.##..##.##.#.#..#. 11 | #....###.#.##...##..#.######..#.##..##..###.##....#.#.#....#..####..#....#.#...##.##.....###.##..### 12 | .##.###..#..###..##.....#.#....##.###.#..#..##..######..##.##..##...#.###.#.#...#.####..#..#..###.#. 13 | ###..#.##..##.#.#......#####....##..##.#.#.#.##...#.##..###....##..###...#...###.########..#.#..###. 14 | .#...#.###..##..#..##.....##...#.#...##.#.###.##.#..#.#.#.###..#.###....##.....##...######....#.##.# 15 | #####..#####..##.#......#.#..#...#.##.##.#.....#.##.#..###.###.##..###.###.#......###.##..#.....#..# 16 | #.###..##..###..#..#..#.#..##.#.##.#..#....#..#....#.######..###.##....###.##..#.#..##.....#####.#.# 17 | ...#..#..##...#.####.###.....#...##.#.#.####.#...###....#..##...#......#######..##..##..#...#..#.### 18 | ...##.#.#######.#.#.#..#.####.##.##..###..#####.###..#.....##......#####.#.....##..##.#...###.##.### 19 | #.#...#.#.#.#....##.##...#...#.....#..###.##..#.#.#..#.##..#..#######.#.....###.######...#######..## 20 | ##.#.#.#..##...#.##.#.#..#...#.#.####.##.##..#.#.#.#...##.##..#....###..####.#..#.#....#....#######. 21 | #.....##....##.......##..#.##.#..#.##.....##.#.......##.###.###.#.##.#..#..#.#....####..#####.#.#.#. 22 | #..#...##..###......#.##....#.###..####.#..##..##.#.##.#.##.#..########....####.##.#######.##.###### 23 | ###...#####...#.###.#.#..#....#..#..#.....##.#.##.#...#.###.#.....##....#.##.#...###.#...#.#..#.#... 24 | ##..##...##..#.###.###..#..####..#...##.#.#.###.###..#####.##..##.#.##..###..#######.##....#.##.#..# 25 | .##..#...#####.####..###.#..###..##..#..#.##..#........#..###..#.#....#.#....##...#.#.####....#.##.# 26 | #...#.#.#####...##..####.###.#..#.##.#...#..##........#.#####...#####....###.#...#.##.######.##.#... 27 | #..#..#.#.#####.##.##.#..######..##.#######.#.#..#..#.......#..#.####.#...##..###..#####.###.#...#.. 28 | ..#.#.##.#.......#.#.#.#.##.##.#.#####..#.....####..#....#.#..########.#.#....#....#.####.#####.#.## 29 | #######.###..#...#####...#####...#.#.####.#......##.#..##.###.####..##..#######..#.##.####..###.##.. 30 | #..#....#.#..##.####.#..#.######......#.##..##...##........###.########..##.#####.#..#..######.#..## 31 | #######.###########..##...#.#....#.###..#..#...#..#.....#.##.##..#.#.....#..######.####..#.#.#....#. 32 | #.###.###...##.#..##....##..#..###..#...#.##.####.#####.#.#######.#.#....#....#...#.##...##..#..#... 33 | .#.####..#####..##....##.#.....#####..##.#.....#..#...##.##..#.######....#..##.######....#.#..###.#. 34 | #..##.#.##..##.#.....##.#...#.##.#######.###.###.##.#...#.##..#####...###.##.###.##.##..###.#..#..## 35 | #.#.#.#.....###...#.###...##.#..#..##...#.#....#.#.#.#.#.##.......#.#####........#######..##.#.....# 36 | #.#...#.#.##..#.##....#.##.#.#..###.#...#..#...###.##...#...###...###..###.#.#..##.#.#.#.##.#.###.#. 37 | ..#...#.#.#.#######...###.#.#...#..###...#.####..#..##..#.##......#...##..##.##..#...##....##..#.... 38 | ..#.##.##.#..##...#.#.#..##..###.#..####.#...#....#..##.#.#.....###.#.#...#.#.#.#.#..###.#.#.#.##.## 39 | ...#...#.#...###..##..##.#......#.....###..####...#.#####.###.##..#.#..#...###..#..#..#.#.##..###.## 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 | -------------------------------------------------------------------------------- /src/aoc04_input.txt: -------------------------------------------------------------------------------- 1 | 31,50,68,16,25,15,28,80,41,8,75,45,96,9,3,98,83,27,62,42,59,99,95,13,55,10,23,84,18,76,87,56,88,66,1,58,92,89,19,54,85,74,39,93,77,26,30,52,69,48,91,73,72,38,64,53,32,51,6,29,17,90,34,61,70,4,7,57,44,97,82,37,43,14,81,65,11,22,5,36,71,35,78,12,0,94,47,49,33,79,63,86,40,21,24,46,20,2,67,60 2 | 3 | 95 91 54 75 45 4 | 46 94 39 44 85 5 | 31 43 24 2 70 6 | 90 58 4 30 77 7 | 13 26 38 52 34 8 | 9 | 68 14 99 63 46 10 | 67 16 82 10 8 11 | 55 52 41 51 4 12 | 90 17 32 44 74 13 | 89 94 73 56 36 14 | 15 | 6 91 2 28 71 16 | 7 88 37 21 36 17 | 95 32 84 57 8 18 | 13 79 89 75 48 19 | 47 81 66 17 5 20 | 21 | 44 55 48 16 41 22 | 35 5 43 53 11 23 | 0 79 19 82 49 24 | 30 85 31 72 39 25 | 27 68 65 66 95 26 | 27 | 6 46 55 24 40 28 | 87 16 62 11 64 29 | 8 49 18 59 91 30 | 72 28 48 19 96 31 | 39 73 9 88 0 32 | 33 | 46 1 18 93 6 34 | 50 96 41 81 58 35 | 62 66 49 32 55 36 | 29 11 65 2 10 37 | 71 30 17 69 43 38 | 39 | 84 57 6 56 95 40 | 39 15 32 1 10 41 | 55 43 40 3 22 42 | 89 54 13 80 38 43 | 72 12 59 71 77 44 | 45 | 3 51 72 88 6 46 | 56 64 99 82 36 47 | 75 81 42 67 24 48 | 41 79 35 40 73 49 | 2 14 61 50 87 50 | 51 | 72 7 0 99 24 52 | 29 81 92 74 38 53 | 84 53 20 56 91 54 | 93 64 44 48 2 55 | 37 40 88 96 97 56 | 57 | 39 87 99 75 38 58 | 45 81 46 72 62 59 | 40 8 24 67 79 60 | 96 1 77 73 70 61 | 34 13 55 83 59 62 | 63 | 18 38 55 84 58 64 | 35 97 31 26 44 65 | 80 1 28 71 85 66 | 45 46 10 32 99 67 | 60 48 72 11 53 68 | 69 | 53 44 6 30 82 70 | 65 64 10 0 86 71 | 81 50 5 21 60 72 | 16 19 97 66 73 73 | 20 24 96 68 69 74 | 75 | 33 85 88 58 20 76 | 19 2 99 40 70 77 | 69 10 17 67 23 78 | 48 9 29 34 3 79 | 89 30 43 41 94 80 | 81 | 30 83 37 14 78 82 | 57 42 98 90 28 83 | 5 82 51 15 55 84 | 77 79 96 67 53 85 | 22 76 0 59 47 86 | 87 | 10 93 84 54 11 88 | 59 30 6 94 75 89 | 9 62 68 37 24 90 | 61 3 66 58 74 91 | 64 0 83 32 13 92 | 93 | 24 77 15 5 49 94 | 23 11 70 17 10 95 | 62 33 38 36 12 96 | 3 61 0 26 65 97 | 63 47 54 50 9 98 | 99 | 34 28 24 55 38 100 | 69 37 36 32 72 101 | 91 85 9 64 68 102 | 94 22 96 90 82 103 | 30 20 97 19 56 104 | 105 | 35 90 58 93 2 106 | 72 8 27 88 16 107 | 25 54 69 60 61 108 | 1 15 9 71 78 109 | 89 42 46 57 91 110 | 111 | 43 38 47 1 82 112 | 19 32 2 95 51 113 | 78 74 91 10 22 114 | 80 77 33 60 14 115 | 0 98 70 54 50 116 | 117 | 71 94 3 84 31 118 | 10 59 12 28 46 119 | 68 69 13 48 36 120 | 37 49 24 26 61 121 | 72 65 38 16 25 122 | 123 | 68 78 10 90 29 124 | 40 14 45 43 44 125 | 27 75 72 39 87 126 | 96 93 53 12 11 127 | 37 64 56 59 76 128 | 129 | 19 78 84 68 41 130 | 36 96 87 15 55 131 | 47 33 10 91 85 132 | 11 94 31 49 35 133 | 83 63 86 4 76 134 | 135 | 5 89 55 46 96 136 | 67 22 95 82 56 137 | 61 94 84 99 28 138 | 71 70 16 57 63 139 | 98 92 86 73 83 140 | 141 | 56 24 93 88 29 142 | 74 89 50 44 79 143 | 97 49 87 31 8 144 | 70 6 57 3 82 145 | 20 25 99 48 78 146 | 147 | 80 20 45 22 57 148 | 43 35 48 44 52 149 | 29 98 38 27 11 150 | 64 49 84 60 31 151 | 7 97 17 85 74 152 | 153 | 21 1 18 41 62 154 | 76 38 13 46 27 155 | 0 16 43 28 53 156 | 54 42 22 83 20 157 | 4 25 50 11 56 158 | 159 | 21 71 73 30 51 160 | 92 27 14 16 11 161 | 89 43 38 62 31 162 | 65 4 36 84 94 163 | 56 13 59 22 6 164 | 165 | 46 28 45 57 6 166 | 16 67 33 20 44 167 | 36 86 92 3 11 168 | 98 27 26 84 31 169 | 5 76 13 65 25 170 | 171 | 49 55 99 31 73 172 | 80 0 83 26 65 173 | 3 96 60 37 50 174 | 57 34 7 20 23 175 | 70 52 93 13 71 176 | 177 | 78 41 81 32 76 178 | 37 36 16 99 48 179 | 3 93 33 85 35 180 | 60 38 74 80 56 181 | 86 29 87 20 7 182 | 183 | 98 24 4 9 82 184 | 22 37 52 81 30 185 | 51 70 17 23 8 186 | 60 61 75 35 85 187 | 33 48 88 13 57 188 | 189 | 49 52 91 21 46 190 | 90 51 70 5 35 191 | 57 68 31 86 87 192 | 42 36 25 95 3 193 | 73 64 17 96 80 194 | 195 | 6 42 13 16 24 196 | 51 72 55 78 47 197 | 67 28 7 97 64 198 | 44 77 98 71 25 199 | 82 8 31 76 73 200 | 201 | 63 79 18 80 27 202 | 57 66 47 89 14 203 | 15 61 94 38 29 204 | 21 53 73 17 76 205 | 65 7 23 36 3 206 | 207 | 93 22 8 52 4 208 | 63 31 90 46 68 209 | 51 14 95 50 23 210 | 17 34 60 75 36 211 | 88 55 7 0 73 212 | 213 | 42 67 91 15 83 214 | 1 37 76 12 25 215 | 29 82 50 70 86 216 | 74 66 39 90 16 217 | 31 71 47 5 92 218 | 219 | 98 48 27 87 2 220 | 60 0 25 30 14 221 | 44 61 94 82 16 222 | 17 19 53 49 59 223 | 15 85 50 63 8 224 | 225 | 63 12 52 81 97 226 | 87 68 44 31 41 227 | 39 24 99 27 6 228 | 1 21 35 59 51 229 | 4 92 3 90 62 230 | 231 | 66 43 98 25 47 232 | 59 16 75 44 82 233 | 40 58 48 60 37 234 | 13 81 61 45 83 235 | 24 89 93 19 67 236 | 237 | 8 86 47 81 83 238 | 1 91 57 59 68 239 | 0 52 25 93 95 240 | 27 84 63 45 36 241 | 39 62 20 99 88 242 | 243 | 67 28 65 4 17 244 | 44 33 12 99 84 245 | 27 36 34 5 10 246 | 38 63 97 82 64 247 | 94 19 58 41 6 248 | 249 | 28 41 96 16 39 250 | 93 78 56 69 75 251 | 74 60 9 30 7 252 | 12 81 35 84 94 253 | 45 20 6 49 2 254 | 255 | 33 7 5 43 9 256 | 97 65 50 2 1 257 | 26 86 76 47 98 258 | 83 31 30 58 52 259 | 93 51 34 63 12 260 | 261 | 65 81 10 46 59 262 | 51 89 85 2 52 263 | 13 54 18 70 4 264 | 37 94 75 92 56 265 | 58 99 91 32 41 266 | 267 | 44 23 18 16 75 268 | 5 3 45 76 90 269 | 20 71 69 37 99 270 | 49 91 43 32 82 271 | 4 79 51 2 39 272 | 273 | 54 80 71 61 76 274 | 81 52 6 89 34 275 | 58 14 20 26 40 276 | 25 60 45 0 3 277 | 36 33 65 41 94 278 | 279 | 53 23 56 55 92 280 | 3 81 59 0 35 281 | 32 30 93 70 40 282 | 45 91 24 65 6 283 | 95 88 16 47 8 284 | 285 | 24 23 10 47 63 286 | 38 79 18 77 62 287 | 13 88 72 68 36 288 | 96 27 12 69 89 289 | 28 94 6 98 20 290 | 291 | 70 1 61 77 28 292 | 92 22 30 48 96 293 | 66 3 34 29 45 294 | 85 6 17 87 5 295 | 97 89 14 80 20 296 | 297 | 40 86 97 5 54 298 | 91 57 12 19 7 299 | 62 88 92 20 32 300 | 50 77 11 39 22 301 | 33 2 21 95 35 302 | 303 | 51 79 64 24 28 304 | 95 19 82 58 76 305 | 69 30 9 14 42 306 | 27 16 56 80 83 307 | 52 5 49 43 45 308 | 309 | 26 65 68 18 55 310 | 58 83 30 48 4 311 | 69 42 78 96 22 312 | 91 13 82 38 41 313 | 67 33 10 98 53 314 | 315 | 74 97 43 1 18 316 | 49 30 28 10 15 317 | 42 12 80 20 96 318 | 41 92 67 22 36 319 | 5 26 13 47 4 320 | 321 | 85 60 72 19 48 322 | 61 21 43 34 83 323 | 51 75 94 11 78 324 | 27 89 45 49 79 325 | 97 15 5 28 50 326 | 327 | 69 99 97 77 98 328 | 37 80 86 7 34 329 | 85 28 31 23 16 330 | 32 47 8 40 4 331 | 46 91 71 54 74 332 | 333 | 23 43 29 7 21 334 | 58 34 42 4 38 335 | 64 96 16 73 49 336 | 36 92 52 81 31 337 | 85 71 78 13 5 338 | 339 | 65 71 46 5 11 340 | 24 4 6 0 23 341 | 13 17 76 15 34 342 | 27 79 10 56 85 343 | 90 19 30 94 78 344 | 345 | 81 40 65 12 35 346 | 23 93 24 96 53 347 | 27 60 87 59 33 348 | 76 56 4 17 6 349 | 78 49 90 3 80 350 | 351 | 7 25 42 85 39 352 | 40 6 26 11 63 353 | 48 20 62 61 89 354 | 78 15 18 21 53 355 | 69 4 87 47 5 356 | 357 | 38 65 87 72 26 358 | 88 75 10 30 3 359 | 89 58 7 20 32 360 | 85 2 97 63 15 361 | 28 77 82 57 64 362 | 363 | 16 89 6 31 27 364 | 45 69 61 5 15 365 | 40 75 64 94 98 366 | 36 18 26 58 90 367 | 10 44 59 13 67 368 | 369 | 80 13 39 49 42 370 | 50 94 12 14 88 371 | 97 48 15 68 69 372 | 21 18 51 99 91 373 | 89 64 35 63 84 374 | 375 | 81 96 26 43 30 376 | 5 74 9 93 60 377 | 63 41 1 14 22 378 | 4 77 33 53 3 379 | 38 90 50 25 10 380 | 381 | 58 66 17 0 16 382 | 5 67 41 48 40 383 | 43 93 76 95 68 384 | 4 13 14 51 8 385 | 56 74 23 57 94 386 | 387 | 18 15 92 4 20 388 | 69 26 84 23 2 389 | 72 35 56 96 9 390 | 61 41 85 91 25 391 | 13 70 1 14 77 392 | 393 | 15 20 77 80 47 394 | 45 34 63 55 75 395 | 65 12 66 44 22 396 | 74 3 25 38 93 397 | 9 31 68 87 67 398 | 399 | 54 95 79 50 75 400 | 18 36 20 34 43 401 | 17 65 55 98 61 402 | 27 46 56 6 52 403 | 91 31 30 40 0 404 | 405 | 25 30 24 64 98 406 | 8 72 53 45 3 407 | 27 77 0 33 44 408 | 89 39 34 71 38 409 | 54 21 20 80 23 410 | 411 | 69 38 63 60 4 412 | 55 37 83 68 61 413 | 67 25 86 24 18 414 | 22 59 65 28 70 415 | 84 46 44 91 96 416 | 417 | 35 27 65 31 0 418 | 46 97 44 74 4 419 | 56 61 7 49 88 420 | 5 38 50 20 26 421 | 62 9 45 64 51 422 | 423 | 3 28 43 97 7 424 | 88 57 17 82 73 425 | 16 94 74 22 39 426 | 84 99 31 1 47 427 | 92 91 55 38 78 428 | 429 | 60 31 29 49 72 430 | 89 41 5 79 22 431 | 58 28 90 76 95 432 | 93 45 14 47 37 433 | 65 25 7 59 62 434 | 435 | 58 1 73 30 55 436 | 95 46 5 80 63 437 | 52 16 70 20 71 438 | 84 60 15 0 77 439 | 99 89 17 72 31 440 | 441 | 83 21 68 18 42 442 | 1 28 97 31 35 443 | 2 38 67 63 74 444 | 77 27 48 90 86 445 | 12 52 26 29 60 446 | 447 | 81 53 80 85 96 448 | 19 32 31 15 88 449 | 91 92 66 37 34 450 | 74 75 33 39 78 451 | 42 40 30 83 58 452 | 453 | 40 41 80 69 67 454 | 24 63 97 33 5 455 | 28 84 34 72 11 456 | 36 79 91 14 92 457 | 55 89 59 10 44 458 | 459 | 0 51 49 24 60 460 | 48 65 28 70 66 461 | 86 58 78 77 18 462 | 6 44 50 37 36 463 | 4 73 91 97 43 464 | 465 | 66 42 76 12 48 466 | 77 83 35 18 50 467 | 30 87 95 99 11 468 | 0 52 92 16 51 469 | 26 56 39 64 62 470 | 471 | 83 89 52 61 45 472 | 74 77 66 59 30 473 | 85 17 38 10 8 474 | 97 67 54 21 26 475 | 34 63 11 94 40 476 | 477 | 93 91 14 49 38 478 | 77 53 29 36 39 479 | 12 52 0 48 92 480 | 95 82 71 76 37 481 | 19 70 75 9 74 482 | 483 | 80 49 59 67 27 484 | 43 66 97 81 12 485 | 10 77 24 75 68 486 | 16 57 14 28 85 487 | 41 52 23 15 2 488 | 489 | 39 89 66 27 11 490 | 63 84 21 44 69 491 | 56 51 58 70 83 492 | 14 0 8 41 31 493 | 98 18 61 97 74 494 | 495 | 97 18 63 29 24 496 | 75 73 80 8 7 497 | 81 37 46 93 68 498 | 57 32 2 41 5 499 | 4 65 88 45 54 500 | 501 | 87 26 81 12 50 502 | 19 9 68 23 71 503 | 74 38 4 34 16 504 | 18 99 86 45 7 505 | 35 8 11 98 57 506 | 507 | 13 31 78 59 58 508 | 51 61 96 68 44 509 | 41 85 26 55 92 510 | 11 62 30 7 64 511 | 18 19 73 27 17 512 | 513 | 48 85 71 39 29 514 | 33 79 24 0 72 515 | 95 52 12 77 40 516 | 70 31 46 44 43 517 | 61 88 73 49 65 518 | 519 | 60 81 51 24 27 520 | 23 28 47 85 67 521 | 35 57 45 76 84 522 | 19 48 30 37 74 523 | 15 78 56 87 16 524 | 525 | 12 5 45 26 21 526 | 1 71 51 10 25 527 | 37 68 73 46 56 528 | 55 20 63 87 91 529 | 22 32 66 90 19 530 | 531 | 20 59 12 29 97 532 | 92 30 77 27 49 533 | 14 98 23 50 6 534 | 11 47 61 34 36 535 | 55 82 13 22 21 536 | 537 | 29 37 0 40 71 538 | 2 43 97 18 59 539 | 32 72 89 99 24 540 | 58 90 73 60 85 541 | 69 53 95 78 27 542 | 543 | 58 28 32 52 55 544 | 86 33 1 41 60 545 | 8 53 42 92 5 546 | 43 69 96 54 24 547 | 74 10 17 89 85 548 | 549 | 51 74 99 21 64 550 | 54 27 60 32 37 551 | 14 45 50 81 94 552 | 28 11 77 17 23 553 | 93 95 53 57 79 554 | 555 | 16 5 80 45 71 556 | 22 57 9 90 43 557 | 3 52 47 59 84 558 | 28 53 14 15 7 559 | 50 76 46 56 34 560 | 561 | 83 62 77 56 26 562 | 82 35 11 6 51 563 | 96 97 15 1 78 564 | 92 45 55 84 94 565 | 20 8 70 21 31 566 | 567 | 4 47 68 81 12 568 | 66 23 35 8 39 569 | 73 94 27 69 22 570 | 59 11 53 26 99 571 | 7 20 87 60 88 572 | 573 | 90 0 88 81 43 574 | 47 54 42 29 97 575 | 60 13 85 51 71 576 | 56 14 94 80 41 577 | 75 8 35 69 61 578 | 579 | 51 38 40 17 42 580 | 19 26 92 64 67 581 | 33 66 82 27 55 582 | 62 2 68 59 31 583 | 7 24 20 91 79 584 | 585 | 21 83 45 35 88 586 | 85 11 5 86 72 587 | 78 3 58 0 89 588 | 67 1 39 59 63 589 | 79 87 19 4 57 590 | 591 | 25 16 40 17 27 592 | 96 72 29 32 87 593 | 50 63 35 81 66 594 | 7 11 92 68 69 595 | 54 83 12 51 95 596 | 597 | 64 98 67 54 75 598 | 8 10 31 5 57 599 | 89 23 25 34 47 600 | 72 74 37 48 94 601 | 39 59 15 55 87 602 | 603 | -------------------------------------------------------------------------------- /src/aoc05_input.txt: -------------------------------------------------------------------------------- 1 | 692,826 -> 692,915 2 | 914,338 -> 524,728 3 | 77,505 -> 77,912 4 | 31,484 -> 250,703 5 | 29,241 -> 313,241 6 | 381,70 -> 381,121 7 | 699,595 -> 641,595 8 | 69,989 -> 517,989 9 | 99,755 -> 99,687 10 | 205,77 -> 844,77 11 | 754,705 -> 754,720 12 | 739,884 -> 739,737 13 | 504,463 -> 854,113 14 | 85,386 -> 416,717 15 | 39,456 -> 449,46 16 | 900,469 -> 900,462 17 | 137,680 -> 137,713 18 | 797,792 -> 264,792 19 | 814,750 -> 86,22 20 | 252,644 -> 491,644 21 | 932,162 -> 932,615 22 | 42,71 -> 464,71 23 | 924,685 -> 755,685 24 | 729,610 -> 729,391 25 | 921,369 -> 921,649 26 | 833,241 -> 101,241 27 | 822,459 -> 507,459 28 | 739,74 -> 807,142 29 | 573,850 -> 573,619 30 | 888,60 -> 888,592 31 | 133,272 -> 339,66 32 | 882,662 -> 665,662 33 | 572,499 -> 959,112 34 | 631,173 -> 404,173 35 | 886,730 -> 470,730 36 | 116,435 -> 980,435 37 | 795,299 -> 886,390 38 | 321,464 -> 321,785 39 | 210,477 -> 210,880 40 | 215,191 -> 59,347 41 | 921,749 -> 363,191 42 | 598,962 -> 924,636 43 | 105,70 -> 105,411 44 | 617,221 -> 617,958 45 | 383,403 -> 383,208 46 | 763,129 -> 118,129 47 | 236,185 -> 236,57 48 | 608,592 -> 950,250 49 | 872,54 -> 761,54 50 | 542,49 -> 542,195 51 | 943,104 -> 59,988 52 | 800,709 -> 800,416 53 | 432,628 -> 947,113 54 | 396,169 -> 61,169 55 | 982,694 -> 611,323 56 | 500,381 -> 803,381 57 | 843,803 -> 101,61 58 | 529,76 -> 960,76 59 | 315,277 -> 315,82 60 | 396,916 -> 181,916 61 | 902,683 -> 902,713 62 | 762,40 -> 441,40 63 | 276,488 -> 219,488 64 | 584,803 -> 637,803 65 | 728,523 -> 728,230 66 | 794,60 -> 794,658 67 | 866,35 -> 866,142 68 | 552,689 -> 552,734 69 | 944,681 -> 944,606 70 | 203,187 -> 860,844 71 | 86,938 -> 957,67 72 | 789,703 -> 591,703 73 | 230,180 -> 230,458 74 | 306,404 -> 975,404 75 | 227,892 -> 935,184 76 | 220,102 -> 226,102 77 | 582,546 -> 645,546 78 | 565,466 -> 565,229 79 | 676,18 -> 123,571 80 | 422,815 -> 422,280 81 | 10,819 -> 10,395 82 | 307,137 -> 307,550 83 | 100,137 -> 903,940 84 | 769,399 -> 769,443 85 | 739,278 -> 201,816 86 | 980,916 -> 464,400 87 | 739,191 -> 222,191 88 | 467,360 -> 467,435 89 | 710,381 -> 126,965 90 | 106,483 -> 865,483 91 | 109,596 -> 388,596 92 | 382,953 -> 180,751 93 | 598,119 -> 189,528 94 | 205,981 -> 205,240 95 | 30,207 -> 742,919 96 | 422,672 -> 151,672 97 | 800,411 -> 800,490 98 | 619,174 -> 619,86 99 | 335,629 -> 335,325 100 | 143,301 -> 143,971 101 | 900,949 -> 900,838 102 | 625,201 -> 625,719 103 | 497,366 -> 497,200 104 | 252,67 -> 801,616 105 | 176,55 -> 160,39 106 | 292,164 -> 292,275 107 | 377,940 -> 320,883 108 | 984,985 -> 568,985 109 | 714,881 -> 714,71 110 | 360,728 -> 175,728 111 | 513,318 -> 160,671 112 | 192,726 -> 825,726 113 | 771,225 -> 771,541 114 | 693,424 -> 693,924 115 | 873,523 -> 603,523 116 | 205,525 -> 205,271 117 | 47,368 -> 253,368 118 | 631,381 -> 631,594 119 | 461,594 -> 461,807 120 | 51,220 -> 689,858 121 | 462,63 -> 462,175 122 | 193,943 -> 418,943 123 | 478,896 -> 650,896 124 | 160,527 -> 223,527 125 | 14,383 -> 812,383 126 | 410,830 -> 410,43 127 | 121,195 -> 121,211 128 | 274,284 -> 868,284 129 | 828,665 -> 828,559 130 | 478,373 -> 478,500 131 | 965,954 -> 73,62 132 | 370,867 -> 25,867 133 | 128,148 -> 128,566 134 | 135,843 -> 919,59 135 | 241,655 -> 400,814 136 | 133,270 -> 958,270 137 | 582,470 -> 582,318 138 | 545,624 -> 545,524 139 | 80,695 -> 80,306 140 | 184,926 -> 659,451 141 | 124,133 -> 389,133 142 | 395,829 -> 605,829 143 | 747,955 -> 237,445 144 | 697,62 -> 439,62 145 | 741,420 -> 741,215 146 | 907,848 -> 75,848 147 | 300,846 -> 333,813 148 | 278,458 -> 625,805 149 | 466,718 -> 466,400 150 | 408,974 -> 408,632 151 | 671,326 -> 340,326 152 | 646,615 -> 503,615 153 | 922,717 -> 922,392 154 | 302,195 -> 380,195 155 | 951,55 -> 28,978 156 | 272,196 -> 74,196 157 | 978,197 -> 978,538 158 | 836,737 -> 883,737 159 | 78,449 -> 30,449 160 | 489,799 -> 489,906 161 | 51,332 -> 51,965 162 | 295,173 -> 305,173 163 | 858,928 -> 257,327 164 | 291,935 -> 657,569 165 | 664,430 -> 284,430 166 | 731,831 -> 731,939 167 | 36,295 -> 36,311 168 | 693,696 -> 693,924 169 | 948,133 -> 311,770 170 | 881,34 -> 702,34 171 | 584,414 -> 584,451 172 | 52,470 -> 646,470 173 | 266,194 -> 527,194 174 | 758,207 -> 758,196 175 | 859,440 -> 540,440 176 | 752,307 -> 752,190 177 | 502,140 -> 502,798 178 | 391,472 -> 391,301 179 | 150,414 -> 835,414 180 | 234,842 -> 961,115 181 | 757,774 -> 935,952 182 | 402,342 -> 667,342 183 | 141,72 -> 433,72 184 | 154,779 -> 590,779 185 | 637,166 -> 311,492 186 | 387,330 -> 387,15 187 | 23,110 -> 95,110 188 | 667,651 -> 607,651 189 | 883,318 -> 733,318 190 | 449,149 -> 535,149 191 | 679,147 -> 522,304 192 | 472,99 -> 965,592 193 | 386,911 -> 148,673 194 | 540,720 -> 194,720 195 | 97,37 -> 236,37 196 | 319,66 -> 319,94 197 | 385,343 -> 385,601 198 | 180,799 -> 782,197 199 | 69,727 -> 69,686 200 | 117,290 -> 723,896 201 | 590,944 -> 736,798 202 | 174,860 -> 861,173 203 | 510,791 -> 488,791 204 | 837,261 -> 837,731 205 | 373,388 -> 373,471 206 | 810,844 -> 810,159 207 | 960,610 -> 610,960 208 | 786,264 -> 786,539 209 | 817,698 -> 572,453 210 | 388,113 -> 360,85 211 | 982,912 -> 982,720 212 | 716,155 -> 177,694 213 | 648,727 -> 931,727 214 | 764,850 -> 539,850 215 | 942,453 -> 942,620 216 | 47,746 -> 47,338 217 | 626,498 -> 76,498 218 | 341,420 -> 524,237 219 | 420,235 -> 732,547 220 | 598,452 -> 598,981 221 | 980,450 -> 980,103 222 | 526,652 -> 526,807 223 | 63,666 -> 512,217 224 | 137,452 -> 43,452 225 | 694,752 -> 252,752 226 | 652,346 -> 524,346 227 | 458,316 -> 640,316 228 | 597,503 -> 331,503 229 | 983,49 -> 79,953 230 | 358,847 -> 492,981 231 | 34,176 -> 34,269 232 | 169,482 -> 617,930 233 | 454,989 -> 454,436 234 | 572,292 -> 572,615 235 | 623,204 -> 125,702 236 | 960,332 -> 738,332 237 | 973,42 -> 25,42 238 | 349,974 -> 349,328 239 | 742,248 -> 111,248 240 | 784,766 -> 784,727 241 | 44,56 -> 973,985 242 | 651,740 -> 541,740 243 | 333,344 -> 834,845 244 | 769,256 -> 769,234 245 | 59,940 -> 832,167 246 | 414,500 -> 614,700 247 | 369,969 -> 347,969 248 | 18,983 -> 983,18 249 | 401,927 -> 579,749 250 | 752,102 -> 922,102 251 | 168,834 -> 442,560 252 | 78,213 -> 699,834 253 | 463,536 -> 463,222 254 | 819,393 -> 377,835 255 | 748,776 -> 122,776 256 | 668,127 -> 379,416 257 | 10,477 -> 477,10 258 | 271,474 -> 846,474 259 | 26,245 -> 26,720 260 | 916,184 -> 535,184 261 | 20,947 -> 857,110 262 | 185,506 -> 185,887 263 | 676,583 -> 676,779 264 | 453,650 -> 312,650 265 | 975,218 -> 538,655 266 | 21,856 -> 803,74 267 | 807,284 -> 807,186 268 | 803,732 -> 684,851 269 | 935,946 -> 573,946 270 | 818,904 -> 724,904 271 | 663,500 -> 291,872 272 | 871,327 -> 958,327 273 | 791,919 -> 791,895 274 | 635,112 -> 635,813 275 | 381,730 -> 585,934 276 | 256,759 -> 256,364 277 | 530,316 -> 330,316 278 | 30,931 -> 744,217 279 | 771,921 -> 771,445 280 | 169,132 -> 169,77 281 | 431,326 -> 91,326 282 | 674,537 -> 525,537 283 | 598,150 -> 249,150 284 | 902,974 -> 902,893 285 | 847,52 -> 71,52 286 | 944,330 -> 944,861 287 | 785,440 -> 785,716 288 | 747,200 -> 122,200 289 | 90,347 -> 90,270 290 | 705,986 -> 192,986 291 | 59,822 -> 59,502 292 | 554,196 -> 670,196 293 | 299,450 -> 299,555 294 | 285,793 -> 186,793 295 | 418,608 -> 418,297 296 | 928,183 -> 924,183 297 | 384,950 -> 384,265 298 | 979,61 -> 51,989 299 | 695,409 -> 695,797 300 | 976,988 -> 13,25 301 | 777,428 -> 777,558 302 | 199,983 -> 199,898 303 | 130,677 -> 130,282 304 | 128,975 -> 397,706 305 | 957,874 -> 358,874 306 | 331,121 -> 622,412 307 | 630,734 -> 171,734 308 | 129,260 -> 868,260 309 | 297,10 -> 794,507 310 | 610,632 -> 610,347 311 | 29,17 -> 989,977 312 | 220,663 -> 882,663 313 | 62,697 -> 62,465 314 | 906,851 -> 906,549 315 | 368,485 -> 46,485 316 | 20,616 -> 20,638 317 | 668,122 -> 953,122 318 | 849,140 -> 849,944 319 | 29,596 -> 29,859 320 | 324,95 -> 468,95 321 | 797,428 -> 389,836 322 | 258,381 -> 258,411 323 | 663,351 -> 73,351 324 | 852,436 -> 852,697 325 | 474,873 -> 474,53 326 | 413,786 -> 413,65 327 | 242,40 -> 210,72 328 | 173,585 -> 936,585 329 | 576,520 -> 576,359 330 | 958,376 -> 595,739 331 | 478,230 -> 809,230 332 | 817,743 -> 841,743 333 | 485,658 -> 233,406 334 | 937,708 -> 983,662 335 | 369,384 -> 340,413 336 | 189,277 -> 845,277 337 | 298,743 -> 157,743 338 | 414,938 -> 317,938 339 | 244,869 -> 244,788 340 | 280,148 -> 280,818 341 | 54,509 -> 146,509 342 | 387,579 -> 387,227 343 | 692,405 -> 545,405 344 | 522,325 -> 547,325 345 | 955,334 -> 955,495 346 | 575,199 -> 847,199 347 | 180,872 -> 917,872 348 | 131,816 -> 131,386 349 | 153,829 -> 29,829 350 | 487,869 -> 487,612 351 | 983,335 -> 695,623 352 | 119,755 -> 25,755 353 | 235,266 -> 938,969 354 | 710,965 -> 710,803 355 | 237,703 -> 472,938 356 | 326,900 -> 326,230 357 | 750,373 -> 809,373 358 | 910,961 -> 910,822 359 | 168,669 -> 168,360 360 | 437,284 -> 779,626 361 | 497,510 -> 245,762 362 | 920,130 -> 606,130 363 | 326,936 -> 851,411 364 | 985,654 -> 985,205 365 | 828,345 -> 828,176 366 | 810,192 -> 134,192 367 | 433,443 -> 956,443 368 | 360,215 -> 676,531 369 | 684,17 -> 684,419 370 | 430,431 -> 636,637 371 | 973,127 -> 973,156 372 | 68,893 -> 68,754 373 | 136,237 -> 541,237 374 | 867,799 -> 282,799 375 | 686,983 -> 829,983 376 | 92,30 -> 94,32 377 | 27,25 -> 977,975 378 | 947,262 -> 965,280 379 | 18,762 -> 294,762 380 | 538,99 -> 538,906 381 | 822,302 -> 175,949 382 | 17,499 -> 145,499 383 | 305,567 -> 171,701 384 | 592,389 -> 855,126 385 | 672,672 -> 312,312 386 | 971,859 -> 280,168 387 | 67,156 -> 558,156 388 | 710,109 -> 521,109 389 | 919,831 -> 705,831 390 | 573,975 -> 759,975 391 | 593,787 -> 82,276 392 | 880,169 -> 888,161 393 | 111,251 -> 474,251 394 | 61,240 -> 61,312 395 | 982,698 -> 982,38 396 | 916,759 -> 916,318 397 | 793,220 -> 947,220 398 | 772,655 -> 501,655 399 | 924,76 -> 924,449 400 | 955,573 -> 794,573 401 | 700,226 -> 739,226 402 | 86,147 -> 654,147 403 | 547,870 -> 159,482 404 | 578,813 -> 241,813 405 | 120,533 -> 587,533 406 | 160,56 -> 872,768 407 | 503,142 -> 916,142 408 | 709,248 -> 738,219 409 | 419,343 -> 374,343 410 | 756,489 -> 894,489 411 | 412,659 -> 649,659 412 | 159,472 -> 105,526 413 | 330,332 -> 330,764 414 | 432,292 -> 432,11 415 | 366,516 -> 524,674 416 | 744,937 -> 344,537 417 | 371,880 -> 277,880 418 | 773,260 -> 836,323 419 | 783,109 -> 595,109 420 | 414,463 -> 414,699 421 | 200,575 -> 155,575 422 | 105,743 -> 965,743 423 | 611,778 -> 238,405 424 | 986,419 -> 902,419 425 | 144,186 -> 251,186 426 | 398,491 -> 615,491 427 | 184,483 -> 251,483 428 | 569,932 -> 569,472 429 | 300,889 -> 300,16 430 | 402,681 -> 614,469 431 | 382,771 -> 382,940 432 | 469,206 -> 921,658 433 | 91,463 -> 91,578 434 | 708,168 -> 708,449 435 | 38,89 -> 804,855 436 | 958,976 -> 11,29 437 | 609,764 -> 609,705 438 | 139,161 -> 580,602 439 | 564,602 -> 564,869 440 | 292,257 -> 292,87 441 | 237,729 -> 695,271 442 | 331,57 -> 909,635 443 | 745,256 -> 745,47 444 | 504,914 -> 504,811 445 | 536,252 -> 650,252 446 | 398,765 -> 854,765 447 | 366,343 -> 419,396 448 | 10,919 -> 909,20 449 | 472,729 -> 11,268 450 | 931,299 -> 222,299 451 | 164,918 -> 404,918 452 | 860,77 -> 860,14 453 | 739,166 -> 359,166 454 | 323,220 -> 989,886 455 | 730,693 -> 248,693 456 | 106,56 -> 906,856 457 | 725,167 -> 725,45 458 | 907,290 -> 230,967 459 | 308,728 -> 308,340 460 | 731,671 -> 731,310 461 | 103,706 -> 584,706 462 | 819,42 -> 178,42 463 | 926,983 -> 753,983 464 | 985,912 -> 985,299 465 | 21,267 -> 477,267 466 | 355,582 -> 355,805 467 | 57,928 -> 663,928 468 | 76,523 -> 76,561 469 | 623,479 -> 17,479 470 | 15,715 -> 848,715 471 | 16,677 -> 671,22 472 | 307,231 -> 307,187 473 | 539,381 -> 179,21 474 | 144,101 -> 226,183 475 | 386,487 -> 745,487 476 | 979,171 -> 886,171 477 | 820,551 -> 820,811 478 | 205,970 -> 205,891 479 | 828,704 -> 136,704 480 | 187,338 -> 76,227 481 | 776,160 -> 473,463 482 | 989,578 -> 749,818 483 | 746,136 -> 746,370 484 | 659,964 -> 836,964 485 | 533,558 -> 907,558 486 | 231,786 -> 231,440 487 | 600,636 -> 133,636 488 | 746,361 -> 746,968 489 | 456,111 -> 679,111 490 | 283,638 -> 50,638 491 | 865,749 -> 753,637 492 | 798,33 -> 219,33 493 | 224,447 -> 444,667 494 | 941,845 -> 941,762 495 | 253,501 -> 152,501 496 | 90,287 -> 387,584 497 | 508,105 -> 532,105 498 | 90,128 -> 90,648 499 | 69,442 -> 69,675 500 | 872,108 -> 18,962 501 | 502 | -------------------------------------------------------------------------------- /src/aoc07.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export NArith List. 2 | From Coq Require Import Arith Sorting Orders OrdersEx Lia. 3 | Import ListNotations. 4 | 5 | Add Search Blacklist "N_as". 6 | 7 | #[global] Open Scope N_scope. 8 | 9 | Notation "'input' x ',' .. ',' y" := (cons x .. (cons y nil) ..) 10 | (at level 200, x constr at level 0). 11 | 12 | Definition example := input 13 | 16,1,2,0,4,2,7,1,2,14 14 | . 15 | 16 | Module NTotalOrder := OTF_to_TTLB N_as_OT. 17 | Module SortN := Sort NTotalOrder. 18 | 19 | Definition median (xs : list N) : N := 20 | match skipn (length xs / 2)%nat xs with 21 | | [] => 0 22 | | x :: _ => x 23 | end. 24 | 25 | Definition sum_N : list N -> N := fold_right N.add 0%N. 26 | 27 | (* |x-y| *) 28 | Definition dist (x y : N) : N := if x <=? y then y - x else x - y. 29 | 30 | Definition solve (xs : list N) : N := 31 | let xs := SortN.sort xs in 32 | sum_N (map (dist (median xs)) xs). 33 | 34 | (* Compute solve example. *) 35 | 36 | Definition dist2 (x y : N) : N := 37 | let d := dist x y in 38 | d * (d + 1) / 2. 39 | 40 | (* Cost to move everyone starting at positions [xs] to the same position [y]. *) 41 | Definition fuel2 (xs : list N) (y : N) : N := 42 | sum_N (map (dist2 y) xs). 43 | 44 | Fixpoint searchMin (n : nat) (f : N -> N) (low width : N) : N * N := 45 | match n with O => (0, 0) | S n => 46 | let il := width / 2 in 47 | let xl := low + il in 48 | let xr := low + il + 1 in 49 | let fl := f xl in 50 | let fr := f xr in 51 | match 1 53 | if fl <=? fr then searchMin n f low il 54 | else searchMin n f xr (width - il - 1) 55 | | false => 56 | if (0 =? width)%N || (fl <=? fr)%N then (xl, fl) else (xr, fr) 57 | end 58 | end. 59 | 60 | Fixpoint maximum (xs : list N) : N := 61 | match xs with 62 | | [] => 0 63 | | [x] => x 64 | | x :: xs => N.max x (maximum xs) 65 | end. 66 | 67 | Definition solve2 (xs : list N) : N := 68 | let f n := fuel2 xs n in 69 | let m := maximum xs in 70 | snd (searchMin (S (N.to_nat m)) f 0 m). 71 | 72 | (* Compute solve2 example. *) 73 | 74 | Definition solve12 (xs : list N) : N * N := (solve xs, solve2 xs). 75 | 76 | Definition Convex (f : N -> N) : Prop := 77 | forall i j k, (j+k) * f (i+j) <= k * f i + j * f (i+j+k). 78 | 79 | Definition LocallyConvex (f : N -> N) : Prop := 80 | forall i, 2 * f (i+1) <= f i + f (i+2). 81 | 82 | Definition Predecreasing (f : N -> N) : Prop := 83 | forall i j, i < j -> f j <= f i -> forall k, k <= i -> f i <= f k. 84 | 85 | Definition Postincreasing (f : N -> N) : Prop := 86 | forall i j, i < j -> f i <= f j -> forall k, j <= k -> f j <= f k. 87 | 88 | Definition VShaped (f : N -> N) : Prop := Predecreasing f /\ Postincreasing f. 89 | 90 | Lemma cancel_add_sub : forall a b c, c <= b -> (a + c) + (b - c) = a + b. 91 | Proof. 92 | intros; rewrite N.add_sub_assoc; lia. 93 | Qed. 94 | 95 | Ltac forward H := 96 | match type of H with 97 | | (?Y -> _) => let Z := fresh in assert (Z : Y); [ | specialize (H Z) ] 98 | end. 99 | 100 | Lemma searchMin_sound n f 101 | : forall low width, width < N.of_nat n -> 102 | let x := searchMin n f low width in 103 | low <= fst x <= low + width 104 | /\ snd x = f (fst x). 105 | Proof. 106 | induction n; cbn [searchMin]; intros; [ lia | ]. 107 | rewrite Nat2N.inj_succ in H. 108 | destruct (N.ltb_spec 1 width). 109 | - assert (HH : width / 2 < width). 110 | { apply N.div_lt_upper_bound; lia. } 111 | destruct (_ <=? _). 112 | { eapply Morphisms_Prop.and_impl_morphism; [ | exact (fun X => X) | apply IHn; lia ]. 113 | intros ?; lia. } 114 | { eapply Morphisms_Prop.and_impl_morphism; [ | exact (fun X => X) | apply IHn ]. 115 | { eapply Morphisms_Prop.and_impl_morphism. 116 | { red; apply N.le_trans. remember (width / 2). lia. } 117 | { refine (fun X => N.le_trans _ _ _ X _). lia. } } 118 | eapply N.le_lt_trans. 119 | { apply N.sub_le_mono_r. apply N.le_sub_l. } 120 | lia. } 121 | - destruct (N.eqb_spec 0 width). 122 | { subst width; cbn. rewrite N.add_0_r. split; [ split | ]; reflexivity. } 123 | destruct (_ <=? _) eqn:E; cbn; split; try reflexivity. 124 | all: apply N.le_1_r in H0; destruct H0 as [-> | ->]; cbn; lia. 125 | Qed. 126 | 127 | Lemma searchMin_correct n f (Hf : VShaped f) 128 | : forall low width, 129 | width < N.of_nat n -> 130 | forall i, i <= width -> snd (searchMin n f low width) <= f (low+i). 131 | Proof. 132 | induction n; [ (* contradiction *) lia | ]. intros; cbn [searchMin]. 133 | rewrite Nat2N.inj_succ in H. 134 | destruct (N.ltb_spec 1 width). 135 | - assert (HH : width / 2 < width). 136 | { apply N.div_lt_upper_bound; lia. } 137 | assert (coIH : width / 2 < N.of_nat n) by lia. 138 | destruct (N.leb_spec (f (low + width / 2)) (f (low + width / 2 + 1))). 139 | + specialize (IHn low (width / 2) coIH). 140 | destruct (N.leb_spec i (width / 2)). 141 | { apply IHn; assumption. } 142 | { etransitivity; [ apply IHn; reflexivity | ]. 143 | rewrite H2. 144 | eapply (proj2 Hf); [ | apply H2 | ]; lia. } 145 | + specialize (IHn (low + width / 2 + 1) (width - width / 2 - 1)). 146 | forward IHn. 147 | { eapply N.le_lt_trans. 148 | { apply N.sub_le_mono_r. apply N.le_sub_l. } 149 | lia. } 150 | destruct (N.ltb_spec i (width / 2 + 1)). 151 | { etransitivity; [ apply (IHn 0); lia | ]. 152 | rewrite N.add_0_r. 153 | apply N.lt_le_incl in H2. rewrite H2. 154 | eapply (proj1 Hf); [ | apply H2 | ]; lia. } 155 | { replace i with (width / 2 + 1 + (i - (width / 2 + 1))) by lia. 156 | rewrite 2 N.add_assoc. apply IHn. lia. } 157 | - destruct (N.eqb_spec 0 width); cbn. 158 | { subst width; cbn. apply N.le_0_r in H0. subst. reflexivity. } 159 | destruct (N.leb_spec (f (low + width / 2)) (f (low + width / 2 + 1))) as [e | e]; cbn. 160 | all: apply N.le_1_r in H1; destruct H1 as [-> | ->]; cbn; try contradiction. 161 | all: apply N.le_1_r in H0; destruct H0 as [-> | ->]; cbn. 162 | all: cbn in e; try rewrite N.add_0_r in *; try reflexivity; lia. 163 | Qed. 164 | 165 | Lemma Convex_additive f g : Convex f -> Convex g -> Convex (fun i => f i + g i). 166 | Proof. 167 | unfold Convex; intros Hf Hg i j k. specialize (Hf i j k). specialize (Hg i j k). lia. 168 | Qed. 169 | 170 | Lemma Convex_constant i : Convex (fun _ => i). 171 | Proof. 172 | unfold Convex; lia. 173 | Qed. 174 | 175 | Lemma Convex_summative {A} (f : A -> N -> N) 176 | : (forall z, Convex (f z)) -> forall xs, Convex (fun i => sum_N (map (fun x => f x i) xs)). 177 | Proof. 178 | intros Hf; induction xs; cbn. 179 | - apply Convex_constant. 180 | - apply Convex_additive; auto. 181 | Qed. 182 | 183 | Lemma div_mul : forall n m, n mod m = 0 -> n / m * m = n. 184 | Proof. 185 | intros. rewrite (N.div_mod' n m) at 2. rewrite H, N.add_0_r. lia. 186 | Qed. 187 | 188 | Lemma conseq_even : forall n, (n * (n+1)) mod 2 = 0. 189 | Proof. 190 | intros n. assert (H := N.mod_bound_pos n 2). destruct H as [_ H]; [lia ..| ]. 191 | apply N.lt_le_pred in H. 192 | apply N.le_1_r in H. 193 | rewrite <- N.mul_mod_idemp_l by lia. 194 | destruct H as [ H | H ]; rewrite H. 195 | - reflexivity. 196 | - rewrite N.mul_1_l. rewrite <- N.add_mod_idemp_l by lia. rewrite H. reflexivity. 197 | Qed. 198 | 199 | Lemma minus_minus m n p : n <= m -> p <= n -> m - n + p = m - (n - p). 200 | Proof. 201 | lia. 202 | Qed. 203 | 204 | Lemma LocallyConvex_dist2_2 : forall z, LocallyConvex (fun i => dist2 i z). 205 | Proof. 206 | unfold Convex, dist2, dist. intros z i. 207 | repeat lazymatch goal with 208 | | [ |- context [ ?x <=? ?y ] ] => destruct (N.leb_spec x y); cbn - [N.add N.sub N.mul] 209 | end. 210 | all: try lia. 211 | all: apply (N.mul_le_mono_pos_r _ _ 2); [ lia | ]. 212 | all: rewrite (N.mul_add_distr_r _ _ 2). 213 | all: rewrite <- !(N.mul_assoc _ _ 2). 214 | all: rewrite !div_mul by apply conseq_even. 215 | all: try lia. 216 | - rewrite minus_minus, N.add_sub by lia. 217 | replace (z - (i+1)) with ((z-i)-1) by lia. 218 | replace (z - (i+2) + 1) with ((z-i)-1) by lia. 219 | replace (z - (i+2)) with ((z-i)-2) by lia. 220 | rewrite ?(N.mul_add_distr_l (z-i)), ?(N.mul_add_distr_r (z-i)), ?(N.mul_sub_distr_l (z-i)), ?(N.mul_sub_distr_r (z-i)). 221 | remember ((z-i) * (z-i)) as ZZ. 222 | lia. 223 | - replace z with (i+1) by lia. lia. 224 | - replace z with i by lia. lia. 225 | Qed. 226 | 227 | Instance Proper_mul_le : Proper (N.le ==> N.le ==> N.le) N.mul. 228 | Proof. 229 | unfold Proper, respectful. auto using N.mul_le_mono. 230 | Qed. 231 | 232 | Instance Proper_add_le : Proper (N.le ==> N.le ==> N.le) N.add. 233 | Proof. 234 | unfold Proper, respectful. auto using N.add_le_mono. 235 | Qed. 236 | 237 | Lemma add_twice n : n + n = 2 * n. 238 | Proof. 239 | lia. 240 | Qed. 241 | 242 | Lemma Convex_LocallyConvex f : LocallyConvex f -> Convex f. 243 | Proof. 244 | unfold LocallyConvex, Convex. intros Hf. 245 | intros i j k; revert i j; induction k as [ | k IH ] using N.peano_ind; intros i j. 246 | - rewrite N.mul_0_l, !N.add_0_r. lia. 247 | - rewrite !N.add_succ_r, N.mul_succ_l. 248 | etransitivity; [ rewrite <- N.add_le_mono_r; apply IH | ]. 249 | enough (j * f (i + j + k) + f (i + j) <= f i + j * f (N.succ (i + j + k))) by lia. 250 | clear IH. 251 | revert i j; induction k as [ | k IH ] using N.peano_ind; intros i j. 252 | + rewrite N.add_0_r, <- N.mul_succ_l. 253 | induction j as [ | j IH] using N.peano_ind. 254 | * rewrite N.add_0_r, !N.mul_0_l. lia. 255 | * rewrite (N.add_le_mono_r _ _ (N.succ j * f (i + N.succ j))). 256 | rewrite N.mul_succ_l. rewrite N.add_shuffle0, add_twice, N.mul_shuffle3, N.add_succ_r, <- (N.add_1_r (i + j)). 257 | rewrite (Hf (i+j)). 258 | rewrite N.mul_add_distr_l, IH. rewrite <- N.add_1_r. 259 | replace (N.succ (i + j + 1)) with (i + j + 2) by lia. lia. 260 | + rewrite (N.add_le_mono_r _ _ (j * f (i + j + N.succ k))). 261 | rewrite N.add_shuffle0, add_twice, N.mul_shuffle3. 262 | replace (i + j + N.succ k) with (i + j + k + 1) by lia. 263 | rewrite Hf. 264 | replace (N.succ (i + j + k + 1)) with (i + j + k + 2) by lia. 265 | rewrite !N.mul_add_distr_l. 266 | rewrite N.add_shuffle0. 267 | rewrite IH. 268 | replace (N.succ (i + j + k)) with (i + j + k + 1) by lia. 269 | lia. 270 | Qed. 271 | 272 | Lemma Postincreasing_Convex f : Convex f -> Postincreasing f. 273 | Proof. 274 | unfold Convex, Postincreasing; intros Hf i j Eij Fij k Ejk. revert Fij. 275 | replace k with (j + (k - j)) in * by lia; generalize (k-j). 276 | replace j with (i + (N.pred (j - i) + 1)) in * by lia; generalize (N.pred (j-i)). 277 | clear j k Eij Ejk. intros j k. intros Fj. 278 | specialize (Hf i (j + 1) k). 279 | rewrite N.mul_add_distr_r in Hf. 280 | rewrite Fj in Hf. 281 | rewrite (N.add_comm (_ * _)) in Hf. 282 | rewrite <- N.add_le_mono_l in Hf. 283 | rewrite <- N.mul_le_mono_pos_l in Hf by lia. 284 | lia. 285 | Qed. 286 | 287 | Lemma Predecreasing_Convex f : Convex f -> Predecreasing f. 288 | Proof. 289 | unfold Convex, Predecreasing; intros Hf i j Eij Fij k Ejk. revert Fij. 290 | replace j with (i + (N.pred (j - i) + 1)) in * by lia; generalize (N.pred (j-i)). 291 | replace i with (k + (i - k)) in * by lia; generalize (i-k). 292 | clear i j Eij Ejk. intros i j. intros Fj. 293 | specialize (Hf k i (j+1)). 294 | rewrite N.mul_add_distr_r in Hf. 295 | rewrite Fj in Hf. 296 | rewrite (N.add_comm (_ * _)) in Hf. 297 | rewrite <- N.add_le_mono_r in Hf. 298 | rewrite <- N.mul_le_mono_pos_l in Hf by lia. 299 | lia. 300 | Qed. 301 | 302 | Lemma VShaped_Convex f : Convex f -> VShaped f. 303 | Proof. 304 | constructor. 305 | - apply Predecreasing_Convex; auto. 306 | - apply Postincreasing_Convex; auto. 307 | Qed. 308 | 309 | Lemma Convex_fuel2 : forall z, Convex (fuel2 z). 310 | Proof. 311 | intros z; apply Convex_summative. 312 | intros z'; apply Convex_LocallyConvex, LocallyConvex_dist2_2. 313 | Qed. 314 | 315 | Theorem solve2_correct xs 316 | : exists i, solve2 xs = fuel2 xs i /\ forall j, j <= maximum xs -> fuel2 xs i <= fuel2 xs j. 317 | Proof. 318 | unfold solve2. 319 | exists (fst (searchMin (S (N.to_nat (maximum xs))) (fuel2 xs) 0 (maximum xs))). 320 | assert (Hmax : forall i, i < N.of_nat (S (N.to_nat i))) by lia. 321 | refine ((fun I J => conj I (J I)) _ _). 322 | - apply (searchMin_sound _ _ _ _ (Hmax _)). 323 | - intros E j Hj. rewrite <- E. apply searchMin_correct with (low := 0). 324 | + apply VShaped_Convex, Convex_fuel2. 325 | + apply Hmax. 326 | + apply Hj. 327 | Qed. 328 | -------------------------------------------------------------------------------- /src/aoc19_input.txt: -------------------------------------------------------------------------------- 1 | --- scanner 0 --- 2 | 878,-830,-633 3 | -654,579,583 4 | -297,520,-671 5 | -288,418,-607 6 | 927,-707,-599 7 | 834,-770,492 8 | 65,-56,25 9 | 662,392,-584 10 | -635,672,759 11 | -286,-837,-550 12 | 943,-732,-680 13 | 868,-851,577 14 | 845,-735,422 15 | 757,441,-546 16 | 417,377,639 17 | -422,-920,-556 18 | -379,503,-529 19 | -358,-887,-535 20 | -557,695,590 21 | -469,-715,623 22 | 421,350,460 23 | 727,244,-543 24 | -524,-657,716 25 | 530,386,541 26 | -516,-654,485 27 | 28 | --- scanner 1 --- 29 | -576,568,-812 30 | 657,415,-415 31 | 697,-697,-764 32 | -768,-701,-757 33 | 133,21,23 34 | 660,-634,-685 35 | 531,764,612 36 | -693,-514,675 37 | 625,435,-393 38 | -505,429,-811 39 | -732,-827,-754 40 | -751,-553,759 41 | 585,424,-332 42 | 406,869,566 43 | -345,414,781 44 | -452,446,-773 45 | 437,881,577 46 | -667,-527,862 47 | 592,-509,865 48 | 572,-544,667 49 | 796,-712,-731 50 | -466,394,764 51 | -793,-859,-721 52 | -424,469,687 53 | 546,-522,796 54 | 55 | --- scanner 2 --- 56 | 496,419,871 57 | 517,-648,-341 58 | -373,-342,699 59 | 610,-470,865 60 | -405,433,-478 61 | 635,-489,683 62 | 591,-554,-342 63 | -523,457,-377 64 | 480,382,833 65 | -383,339,809 66 | 796,849,-470 67 | 576,-541,-376 68 | -529,382,821 69 | -359,-444,565 70 | -657,-489,-782 71 | -660,462,-493 72 | -701,-484,-738 73 | -444,333,689 74 | 736,800,-551 75 | 440,430,856 76 | -749,-542,-720 77 | 628,771,-522 78 | -84,45,31 79 | -354,-473,697 80 | 655,-447,812 81 | 82 | --- scanner 3 --- 83 | -585,-799,-407 84 | -8,3,-15 85 | -352,263,-798 86 | 648,-897,-545 87 | 807,594,858 88 | 949,398,-473 89 | -550,462,970 90 | 939,-728,848 91 | 923,450,-605 92 | -370,-983,687 93 | -320,-899,708 94 | -678,-623,-426 95 | -701,-792,-504 96 | 134,-80,61 97 | -425,479,834 98 | 651,-666,-537 99 | 906,-869,727 100 | 906,647,784 101 | -301,457,941 102 | 709,-759,-592 103 | -338,-971,589 104 | -326,308,-768 105 | -271,271,-719 106 | 957,-780,619 107 | 905,310,-592 108 | 902,471,898 109 | 110 | --- scanner 4 --- 111 | -344,-650,707 112 | -19,-55,-144 113 | -475,295,231 114 | -790,471,-694 115 | 634,400,-574 116 | -387,-696,643 117 | 526,-976,-868 118 | 737,-562,293 119 | -362,-790,-599 120 | 649,528,271 121 | 783,305,-610 122 | -348,-610,641 123 | 827,579,241 124 | 649,-550,431 125 | 20,-194,-1 126 | -548,230,315 127 | 726,671,262 128 | -513,246,239 129 | 699,-549,494 130 | 601,-874,-967 131 | 621,381,-566 132 | 600,-977,-919 133 | -756,576,-753 134 | -389,-745,-695 135 | -411,-777,-544 136 | -712,472,-707 137 | 138 | --- scanner 5 --- 139 | -736,-631,547 140 | 489,543,-764 141 | -658,-613,524 142 | -765,344,314 143 | 474,-482,585 144 | -588,530,-365 145 | -589,305,-401 146 | 443,401,516 147 | 376,-573,506 148 | 594,481,-777 149 | -688,-591,744 150 | -519,362,-375 151 | -728,347,358 152 | 442,-612,670 153 | -657,447,279 154 | 434,-736,-722 155 | 645,623,-783 156 | -13,-133,-116 157 | -758,-472,-812 158 | -651,-534,-759 159 | -805,-505,-654 160 | 418,-677,-730 161 | 407,437,584 162 | -149,-18,22 163 | 485,-643,-827 164 | 272,461,520 165 | 166 | --- scanner 6 --- 167 | 457,-689,-751 168 | 394,-366,777 169 | 7,-79,-26 170 | -346,-410,-447 171 | 492,343,394 172 | 64,50,92 173 | -432,487,345 174 | 328,-665,-703 175 | 329,-753,-802 176 | -568,-783,674 177 | -347,611,-432 178 | -361,477,-330 179 | 508,305,431 180 | -628,-604,616 181 | -504,-588,665 182 | 452,320,442 183 | -425,-374,-325 184 | 667,364,-435 185 | -465,-527,-427 186 | 647,493,-477 187 | 391,-438,763 188 | -517,355,394 189 | 345,-455,661 190 | -371,367,351 191 | 622,311,-458 192 | -342,479,-461 193 | 194 | --- scanner 7 --- 195 | 240,-368,494 196 | 553,641,-895 197 | -844,-774,775 198 | -158,152,27 199 | 604,463,-925 200 | -808,-665,694 201 | 257,746,637 202 | -582,876,794 203 | -564,874,680 204 | 295,-496,433 205 | 502,-255,-850 206 | -524,591,-672 207 | 336,-262,-791 208 | -887,-673,-732 209 | 496,-283,-694 210 | 276,755,723 211 | 233,780,826 212 | -537,896,707 213 | -16,-5,-83 214 | -869,-640,-763 215 | 292,-328,445 216 | -525,641,-735 217 | -817,-778,596 218 | -959,-707,-833 219 | -537,553,-873 220 | 696,564,-904 221 | 222 | --- scanner 8 --- 223 | -138,-81,-56 224 | 441,422,-748 225 | -613,-753,-567 226 | -711,-766,-679 227 | 471,430,517 228 | 469,-785,640 229 | -736,-746,-682 230 | -467,333,-521 231 | -837,485,476 232 | 574,-437,-615 233 | -838,-845,533 234 | 436,232,537 235 | 454,235,-722 236 | 630,-503,-471 237 | -869,-867,440 238 | -875,-814,670 239 | 449,301,491 240 | -942,531,351 241 | -487,316,-400 242 | 477,-764,674 243 | 480,338,-806 244 | 569,-466,-398 245 | -954,520,382 246 | -542,410,-479 247 | 539,-822,685 248 | 249 | --- scanner 9 --- 250 | 467,-625,-603 251 | -669,564,-709 252 | -847,-826,-623 253 | 652,-665,691 254 | -836,-756,-658 255 | 555,-658,807 256 | -738,641,-734 257 | -640,530,-730 258 | -532,-707,498 259 | 467,444,-799 260 | 261,397,458 261 | -419,-609,489 262 | -490,820,347 263 | 522,-532,-545 264 | 454,584,-817 265 | -557,750,437 266 | 586,532,-843 267 | -870,-671,-739 268 | 514,-763,-542 269 | -524,719,419 270 | -98,20,18 271 | -423,-788,462 272 | 340,405,377 273 | 291,442,432 274 | 633,-489,784 275 | 276 | --- scanner 10 --- 277 | 716,-305,-787 278 | 837,-330,-928 279 | 888,-497,410 280 | -835,-736,-589 281 | -726,396,-816 282 | 105,27,-108 283 | -269,644,397 284 | -783,-776,-540 285 | -719,467,-739 286 | -739,-842,696 287 | -8,-46,23 288 | 683,628,-464 289 | -579,-821,599 290 | -354,666,310 291 | 393,435,700 292 | 912,-501,603 293 | 714,514,-397 294 | 810,-320,-849 295 | 487,494,578 296 | -339,704,339 297 | 895,-524,455 298 | -704,404,-846 299 | 424,551,688 300 | -780,-608,-528 301 | 692,689,-364 302 | -573,-849,755 303 | 304 | --- scanner 11 --- 305 | -324,527,757 306 | 608,-702,-558 307 | 429,818,379 308 | 582,-495,715 309 | -341,737,-607 310 | -796,-621,820 311 | -880,-642,770 312 | -868,-740,802 313 | 597,-658,-369 314 | -453,503,805 315 | 572,409,-620 316 | 560,-388,839 317 | 565,-359,590 318 | -483,-797,-347 319 | 536,-739,-501 320 | -390,826,-723 321 | -387,754,-709 322 | 508,604,-611 323 | -41,-143,24 324 | -418,-868,-393 325 | -325,439,856 326 | 36,43,-57 327 | 469,665,481 328 | 350,782,501 329 | -394,-779,-323 330 | 632,588,-562 331 | 332 | --- scanner 12 --- 333 | -866,-426,-688 334 | 486,-659,807 335 | -935,-385,-780 336 | -686,-505,394 337 | 662,-480,-583 338 | 816,333,564 339 | 534,365,-598 340 | -696,619,400 341 | 767,325,526 342 | -694,783,523 343 | 757,-516,-732 344 | 391,356,-675 345 | -924,-312,-703 346 | -50,27,6 347 | 591,-600,841 348 | 590,-613,763 349 | -723,-341,410 350 | 483,335,-776 351 | -424,345,-345 352 | -685,728,577 353 | 681,-472,-570 354 | -557,-447,419 355 | 832,409,599 356 | -370,343,-406 357 | -382,333,-397 358 | 359 | --- scanner 13 --- 360 | -578,-856,613 361 | -609,-874,646 362 | 744,-939,-717 363 | 473,-481,439 364 | -508,-946,680 365 | 792,-836,-716 366 | 391,419,-696 367 | -38,-154,-175 368 | 499,-592,313 369 | -550,349,235 370 | -491,515,228 371 | -416,617,-490 372 | 382,488,294 373 | 399,438,-683 374 | -437,709,-591 375 | 435,343,-534 376 | -105,-7,-65 377 | 475,517,354 378 | -647,509,256 379 | -606,-512,-668 380 | -669,-511,-618 381 | 362,514,220 382 | 693,-938,-791 383 | -446,566,-668 384 | -468,-524,-580 385 | 556,-552,297 386 | 387 | --- scanner 14 --- 388 | -757,815,582 389 | -2,58,9 390 | -515,-401,595 391 | -371,445,-483 392 | 637,752,-662 393 | 8,-94,-131 394 | 723,-646,-779 395 | -582,817,681 396 | 655,514,402 397 | -453,-455,594 398 | -442,-349,665 399 | -521,-349,-553 400 | -393,472,-510 401 | -487,-325,-364 402 | 616,678,468 403 | 615,532,-632 404 | 746,593,500 405 | -391,490,-396 406 | 585,-819,511 407 | 597,555,-710 408 | -512,-368,-467 409 | 492,-714,460 410 | 551,-722,444 411 | 756,-804,-732 412 | -696,826,735 413 | 694,-751,-625 414 | 415 | --- scanner 15 --- 416 | -643,847,-354 417 | -766,752,-394 418 | 757,394,440 419 | 799,-393,-663 420 | -538,-714,742 421 | -634,-605,-282 422 | -165,88,-1 423 | -819,851,-468 424 | -629,-356,-311 425 | 727,-375,-544 426 | 256,-339,516 427 | -419,-694,859 428 | 749,586,347 429 | 811,-425,-565 430 | -498,-816,895 431 | 255,-438,604 432 | 697,851,-525 433 | 556,884,-404 434 | 788,442,416 435 | -651,-480,-418 436 | -923,489,752 437 | -970,419,912 438 | 608,902,-633 439 | -894,449,783 440 | -49,-39,90 441 | 384,-390,580 442 | 443 | --- scanner 16 --- 444 | 469,-678,693 445 | -644,-431,470 446 | -57,-144,57 447 | 392,324,928 448 | 553,371,-753 449 | -875,-821,-277 450 | 432,-606,750 451 | -621,243,-576 452 | -606,-460,455 453 | -906,725,820 454 | -682,343,-567 455 | -759,-809,-308 456 | 481,-761,-382 457 | 382,-776,-415 458 | -816,-699,-371 459 | -914,695,842 460 | 593,360,-814 461 | 374,413,904 462 | -159,-10,163 463 | -796,276,-598 464 | -666,-518,385 465 | 513,-667,882 466 | 303,348,858 467 | 518,-698,-461 468 | -843,618,835 469 | 521,351,-731 470 | 471 | --- scanner 17 --- 472 | 353,635,-713 473 | -771,-279,699 474 | -474,769,499 475 | -701,714,-588 476 | -643,-334,760 477 | -361,778,597 478 | -305,-533,-323 479 | -323,-424,-408 480 | 432,-395,549 481 | -74,22,-27 482 | 691,483,717 483 | -811,-331,748 484 | 708,-667,-556 485 | -671,911,-585 486 | 369,-410,442 487 | 361,-388,472 488 | -606,763,-626 489 | -365,805,418 490 | 710,576,541 491 | 435,652,-571 492 | -385,-573,-325 493 | 344,737,-649 494 | 682,-849,-596 495 | 739,-711,-666 496 | 613,460,548 497 | 498 | --- scanner 18 --- 499 | 630,-778,-377 500 | -642,806,-657 501 | 404,849,-563 502 | -504,-789,-498 503 | -659,778,-635 504 | 34,-62,148 505 | 347,-484,785 506 | -420,405,665 507 | -457,478,604 508 | 384,813,754 509 | -718,-667,757 510 | 468,755,793 511 | 263,852,-712 512 | -776,-678,695 513 | 653,-822,-405 514 | 476,-510,763 515 | -608,-880,-588 516 | 256,827,-572 517 | 278,-530,798 518 | -133,7,20 519 | -451,-884,-500 520 | -739,-633,765 521 | -391,622,660 522 | -640,591,-646 523 | 281,729,780 524 | 520,-823,-410 525 | 526 | --- scanner 19 --- 527 | -957,587,417 528 | 711,-510,-899 529 | -500,835,-796 530 | 348,583,-720 531 | 778,798,343 532 | 464,486,-727 533 | -414,-471,-425 534 | 499,-891,534 535 | 679,-608,-911 536 | -25,-50,-79 537 | 723,847,380 538 | -872,565,330 539 | 729,-629,-827 540 | -438,-453,-514 541 | -484,-382,-449 542 | -522,827,-826 543 | -507,764,-719 544 | -146,50,47 545 | -592,-511,505 546 | 371,505,-551 547 | 697,877,335 548 | -887,527,359 549 | -649,-548,577 550 | -460,-592,566 551 | 748,-862,529 552 | 624,-755,551 553 | 554 | --- scanner 20 --- 555 | -970,-446,-402 556 | 660,-629,-380 557 | 598,-630,-326 558 | -988,-361,-511 559 | 417,-770,901 560 | 601,432,-293 561 | -622,-623,933 562 | -592,-626,736 563 | -908,-363,-551 564 | -932,559,800 565 | 592,518,-274 566 | -138,98,149 567 | -144,-53,-3 568 | -687,-664,785 569 | 722,361,565 570 | 626,329,-250 571 | -650,722,-312 572 | -522,661,-257 573 | 356,-617,890 574 | -819,461,791 575 | 531,-716,892 576 | 671,-700,-274 577 | 720,475,547 578 | 742,448,520 579 | -928,380,827 580 | -482,710,-309 581 | 582 | --- scanner 21 --- 583 | -877,509,-750 584 | -613,-482,651 585 | 442,-680,-742 586 | 361,600,630 587 | -67,40,98 588 | -831,444,-821 589 | -901,420,-732 590 | 841,456,-531 591 | -662,-606,635 592 | 758,447,-603 593 | 416,-669,822 594 | 400,478,506 595 | 419,-795,786 596 | 362,461,559 597 | -617,367,784 598 | 452,-827,847 599 | -666,-582,-655 600 | -515,413,801 601 | 57,6,-81 602 | 488,-602,-606 603 | -855,-571,-611 604 | -501,416,873 605 | -604,-546,456 606 | 780,467,-571 607 | 409,-665,-643 608 | -723,-510,-692 609 | 610 | --- scanner 22 --- 611 | -11,-95,-104 612 | -767,-537,-778 613 | -624,512,-512 614 | 877,487,-759 615 | -686,495,624 616 | 595,-590,329 617 | -607,370,-430 618 | -837,-531,-869 619 | 609,-637,320 620 | -709,434,-421 621 | 551,-611,-783 622 | 602,-649,242 623 | 695,527,-785 624 | -400,-664,553 625 | -883,498,594 626 | 739,417,-816 627 | -517,-652,414 628 | -735,457,529 629 | 688,-605,-694 630 | 561,760,228 631 | -841,-389,-778 632 | -389,-727,337 633 | 601,758,308 634 | 671,-574,-878 635 | 452,675,246 636 | 637 | --- scanner 23 --- 638 | 843,466,-900 639 | 825,-466,237 640 | -918,-519,-987 641 | 823,-405,291 642 | 835,504,-949 643 | 833,-836,-616 644 | 835,-457,249 645 | -59,-106,-149 646 | -710,351,663 647 | -729,-553,-963 648 | 385,463,561 649 | 549,340,563 650 | -815,-544,-944 651 | -503,691,-666 652 | -732,450,730 653 | -539,-683,472 654 | 812,-735,-524 655 | 803,-658,-667 656 | 759,539,-965 657 | -546,-553,598 658 | -619,-530,502 659 | -657,662,-561 660 | -626,394,776 661 | 440,517,552 662 | -550,724,-508 663 | 664 | --- scanner 24 --- 665 | -80,-88,-25 666 | -862,-445,-663 667 | 803,-429,-392 668 | 396,465,-685 669 | -847,-416,-625 670 | 833,-844,438 671 | 682,683,480 672 | -421,422,649 673 | -462,-802,883 674 | 46,30,75 675 | -418,434,817 676 | -628,-861,890 677 | -366,483,777 678 | 373,634,-607 679 | 743,-774,505 680 | 748,-466,-343 681 | -482,633,-426 682 | 722,-421,-313 683 | 718,764,371 684 | 691,585,367 685 | -497,740,-363 686 | -475,710,-355 687 | 761,-743,472 688 | -622,-705,862 689 | 489,641,-704 690 | -932,-503,-603 691 | 692 | --- scanner 25 --- 693 | -711,-795,292 694 | 820,713,-588 695 | 682,725,-676 696 | 780,291,672 697 | -448,-881,-583 698 | 524,-765,493 699 | -489,-819,-650 700 | 710,381,605 701 | 494,-400,-461 702 | -423,-863,-611 703 | -828,406,739 704 | -796,-714,326 705 | -649,433,743 706 | -733,686,-909 707 | -866,-679,315 708 | -760,713,-931 709 | -847,668,-911 710 | -747,442,630 711 | 425,-473,-488 712 | 490,-786,522 713 | 679,363,638 714 | 601,-790,424 715 | 573,-463,-414 716 | 619,726,-626 717 | -3,-97,-140 718 | -------------------------------------------------------------------------------- /src/aoc10.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export Ascii String NArith. 2 | From Coq Require Import List Arith. 3 | 4 | Import ListNotations. 5 | 6 | Set Implicit Arguments. 7 | 8 | #[global] Open Scope string_scope. 9 | 10 | Infix "::" := String.String. 11 | 12 | Fixpoint _rev_string (r s : string) : string := 13 | match s with 14 | | "" => r 15 | | c :: s => _rev_string (c :: r) s 16 | end. 17 | 18 | Definition rev_string : string -> string := _rev_string "". 19 | 20 | Definition is_empty (w : string) : bool := 21 | match w with 22 | | "" => true 23 | | _ => false 24 | end. 25 | 26 | Fixpoint _split_on (c0 : ascii) (w s : string) : list string := 27 | match s with 28 | | "" => if is_empty w then [] else [rev_string w] 29 | | c :: s => 30 | if Ascii.eqb c0 c then 31 | if is_empty w then _split_on c0 w s else rev_string w :: _split_on c0 "" s 32 | else 33 | _split_on c0 (c :: w) s 34 | end. 35 | 36 | (* Drops empty words! *) 37 | Definition split_on (c0 : ascii) : string -> list string := _split_on c0 "". 38 | 39 | Definition words : string -> list string := split_on " ". 40 | Definition lines : string -> list string := split_on "010". 41 | 42 | Definition input : string -> list string := lines. 43 | 44 | Definition example := input 45 | "[({(<(())[]>[[{[]{<()<>> 46 | [(()[<>])]({[<{<<[]>>( 47 | {([(<{}[<>[]}>{[]{[(<()> 48 | (((({<>}<{<{<>}{[]{[]{} 49 | [[<[([]))<([[{}[[()]]] 50 | [{[{({}]{}}([{[{{{}}([] 51 | {<[[]]>}<{[{[{[]{()[[[] 52 | [<(<(<(<{}))><([]([]() 53 | <{([([[(<>()){}]>(<<{{ 54 | <{([{{}}[<[[[<>{}]]]>[]]". 55 | 56 | Inductive Result : Type := 57 | | Illegal (c : ascii) 58 | | Valid (z : list ascii) 59 | . 60 | 61 | Definition bra_cket (bra : ascii) : ascii := 62 | (if bra =? "(" then ")" 63 | else if bra =? "[" then "]" 64 | else if bra =? "{" then "}" 65 | else if bra =? "<" then ">" 66 | else "?")%char. 67 | 68 | Definition cket_bra (cket : ascii) : ascii := 69 | (if cket =? ")" then "(" 70 | else if cket =? "]" then "[" 71 | else if cket =? "}" then "{" 72 | else if cket =? ">" then "<" 73 | else "?")%char. 74 | 75 | Fixpoint _check (z : list ascii) (s : string) : Result := 76 | match s with 77 | | "" => Valid z 78 | | c :: s => 79 | if ((c =? "(") || (c =? "[") || (c =? "{") || (c =? "<"))%char%bool then 80 | _check (c :: z) s 81 | else 82 | match z with 83 | | (cz :: z)%list => if (cket_bra c =? cz)%char then _check z s else Illegal c 84 | | _ => Illegal c 85 | end 86 | end. 87 | 88 | Definition check := _check []. 89 | 90 | Definition sum_with {A} (f : A -> N) : list A -> N := 91 | fold_right (fun x => N.add (f x)) 0%N. 92 | 93 | Definition score (r : Result) : N := 94 | match r with 95 | | Valid _ => 0 96 | | Illegal c => 97 | if c =? ")" then 3 98 | else if c =? "]" then 57 99 | else if c =? "}" then 1197 100 | else if c =? ">" then 25137 101 | else 0 (* Should not happen *) 102 | end%char%N. 103 | 104 | Definition solve : list string -> N := 105 | sum_with (fun l => score (check l)). 106 | 107 | (* Compute solve example. *) 108 | 109 | Definition score2 (z : list ascii) : N := 110 | fold_left (fun a c => 111 | 5 * a 112 | + if c =? "(" then 1 113 | else if c =? "[" then 2 114 | else if c =? "{" then 3 115 | else if c =? "<" then 4 116 | else 0)%char%N z 0%N. 117 | 118 | Fixpoint minimum1 (x : N) (xs : list N) : N := 119 | match xs with 120 | | [] => x 121 | | y :: xs => minimum1 (if (x <=? y)%N then x else y) xs 122 | end%list. 123 | 124 | Definition minimum (xs : list N) : option N := 125 | match xs with 126 | | [] => None 127 | | x :: xs => Some (minimum1 x xs) 128 | end%list. 129 | 130 | Fixpoint _split (x : N) (l r xs : list N) : list N * list N := 131 | match xs with 132 | | [] => (l, r) 133 | | y :: xs => 134 | if (y <=? x)%N then _split x (y :: l) r xs else _split x l (y :: r) xs 135 | end%list. 136 | 137 | Definition split (x : N) (xs : list N) := _split x [] [] xs. 138 | 139 | Fixpoint kth (fuel : list N) (k : nat) (xs : list N) : option N := 140 | match fuel with 141 | | [] => None 142 | | _ :: fuel => 143 | match xs with 144 | | [] => None 145 | | x :: xs => 146 | let '(l, r) := split x xs in 147 | let nl := length l in 148 | match Nat.compare k nl with 149 | | Eq => Some x 150 | | Lt => kth fuel k l 151 | | Gt => kth fuel (k - nl - 1) r 152 | end 153 | end 154 | end%list. 155 | 156 | Definition median (xs : list N) : option N := 157 | kth xs (Nat.div2 (length xs)) xs. 158 | 159 | Definition dummydefault (x : option N) : N := 160 | match x with 161 | | Some x => x 162 | | None => 0 163 | end. 164 | 165 | Fixpoint map_filter {A B} (f : A -> option B) (xs : list A) : list B := 166 | match xs with 167 | | [] => [] 168 | | x :: xs => 169 | match f x with 170 | | None => map_filter f xs 171 | | Some y => y :: map_filter f xs 172 | end 173 | end%list. 174 | 175 | Definition unValid (r : Result) : option (list ascii) := 176 | match r with 177 | | Illegal _ => None 178 | | Valid z => Some z 179 | end. 180 | 181 | Definition solve2 (xs : list string) : N := 182 | dummydefault (median (map score2 (map_filter (fun l => unValid (check l)) xs))). 183 | 184 | (* Compute solve2 example. *) 185 | 186 | (* [solve12] factors the common logic of [check] in [solve] and [solve2]. *) 187 | Definition solve12 (xs : list string) : N * N := 188 | let xs := map check xs in 189 | (sum_with score xs, dummydefault (median (map score2 (map_filter unValid xs)))). 190 | 191 | (**) 192 | 193 | Lemma sum_with_map {A B} (f : A -> B) (g : B -> N) xs 194 | : sum_with g (map f xs) = sum_with (fun x => g (f x)) xs. 195 | Proof. 196 | unfold sum_with; generalize 0%N. 197 | induction xs; intros; cbn; congruence. 198 | Qed. 199 | 200 | Lemma map_filter_map {A B C} (f : A -> B) (g : B -> option C) xs 201 | : map_filter g (map f xs) = map_filter (fun x => g (f x)) xs. 202 | Proof. 203 | induction xs as [ | x xs IH ]; cbn; [ | destruct (g (f x))]; cbn; congruence. 204 | Qed. 205 | 206 | Lemma solve12Correct xs : solve12 xs = (solve xs, solve2 xs). 207 | Proof. 208 | unfold solve12; cbn. rewrite sum_with_map, map_filter_map. reflexivity. 209 | Qed. 210 | 211 | (**) 212 | 213 | (* Correctness of [check] *) 214 | 215 | (* 216 | Soundness and completeness. 217 | 218 | Soundness: If [check s] returns [Valid z], then the input [s] can be completed 219 | into a well-bracketed string, using the stack [z], [s ++ destack z]. 220 | 221 | Theorem check_sound s z : check s = Valid z -> wellbracketed (s ++ destack z). 222 | 223 | Completeness: If [check s] returns [Illegal c], then [c] is the earliest character of [s] 224 | such that the prefix before [c] is still completeable to a well-bracketed string, but not any 225 | completion after [c] (including [s] itself). 226 | 227 | Theorem check_complete s c 228 | : check s = Illegal c -> 229 | exists t u, s = t ++ c :: u 230 | /\ (exists v, wellbracketed (t ++ v)) 231 | /\ forall u', ~wellbracketed (t ++ c :: u'). 232 | *) 233 | 234 | Lemma append_assoc (s t u : string) : (s ++ t) ++ u = s ++ (t ++ u). 235 | Proof. 236 | induction s; cbn; congruence. 237 | Qed. 238 | 239 | Lemma append_empty_r (s : string) : (s ++ "") = s. 240 | Proof. 241 | induction s; cbn; congruence. 242 | Qed. 243 | 244 | Lemma append_cons_r (s : string) (c : ascii) (t : string) : (s ++ c :: "") ++ t = (s ++ c :: t). 245 | Proof. 246 | induction s; cbn; congruence. 247 | Qed. 248 | 249 | Create HintDb wb. 250 | 251 | Inductive brackets : ascii -> ascii -> Prop := 252 | | brackets_Par : brackets "(" ")" 253 | | brackets_Squ : brackets "[" "]" 254 | | brackets_Bra : brackets "{" "}" 255 | | brackets_Ang : brackets "<" ">" 256 | . 257 | #[global] Hint Constructors brackets : wb. 258 | 259 | Inductive wellbracketed : string -> Prop := 260 | | wellbracketed_empty : wellbracketed "" 261 | | wellbracketed_step bra cket s t 262 | : brackets bra cket -> wellbracketed s -> wellbracketed t -> wellbracketed (bra :: s ++ cket :: t) 263 | . 264 | #[global] Hint Constructors wellbracketed : wb. 265 | 266 | Lemma wellbracketed_app s t : wellbracketed s -> wellbracketed t -> wellbracketed (s ++ t). 267 | Proof. 268 | revert t; induction 1; intros; cbn; auto. 269 | rewrite append_assoc; constructor; auto. 270 | Qed. 271 | #[export] Hint Resolve wellbracketed_app : wb. 272 | 273 | Ltac spliteq := 274 | lazymatch goal with 275 | | [ |- context [ (?lhs =? ?rhs)%char ] ] => destruct (Ascii.eqb_spec lhs rhs) 276 | end. 277 | 278 | Lemma _check_adequate s : wellbracketed s -> forall t z, _check z (s ++ t) = _check z t. 279 | Proof. 280 | induction 1. 281 | - reflexivity. 282 | - cbn [_check]; intros; cbn; destruct H; cbn. 283 | all: rewrite append_assoc; cbn. 284 | all: rewrite IHwellbracketed1; cbn. 285 | all: apply IHwellbracketed2. 286 | Qed. 287 | 288 | Theorem check_adequate s : wellbracketed s -> check s = Valid []. 289 | Proof. 290 | rewrite <- (append_empty_r s) at 2. 291 | exact (fun H => _check_adequate H _ _). 292 | Qed. 293 | 294 | Inductive unstack : list ascii -> string -> Prop := 295 | | unstack_nil s : wellbracketed s -> unstack [] s 296 | | unstack_cons bra cket z t s 297 | : brackets bra cket -> unstack z t -> wellbracketed s -> unstack (bra :: z) (t ++ bra :: s) 298 | . 299 | #[export] Hint Constructors unstack : wb. 300 | 301 | Lemma extend_unstack z t s : unstack z t -> wellbracketed s -> unstack z (t ++ s). 302 | Proof. 303 | intros []. 304 | - constructor. apply wellbracketed_app; auto. 305 | - rewrite append_assoc. cbn; econstructor; eauto. apply wellbracketed_app; auto. 306 | Qed. 307 | 308 | Lemma cket_bra_cket bra cket 309 | : cket_bra cket = bra -> bra <> "?"%char -> bra_cket bra = cket. 310 | Proof. 311 | unfold cket_bra; repeat (spliteq; cbn); intros; subst; reflexivity + contradiction. 312 | Qed. 313 | 314 | Lemma _check_sound z z' t s : unstack z t -> _check z s = Valid z' -> unstack z' (t ++ s). 315 | Proof. 316 | revert z t. 317 | induction s; intros z t Hz. 318 | - rewrite append_empty_r; cbn; congruence. 319 | - cbn [_check]; repeat (spliteq; cbn [orb]); subst. 320 | 1,2,3,4: rewrite <- append_cons_r; apply IHs. 321 | 1,2,3,4: econstructor; eauto with wb. 322 | all: destruct Hz; try discriminate. 323 | all: destruct H; cbn; spliteq; cbn; try discriminate. 324 | all: apply cket_bra_cket in e; [ subst | discriminate ]. 325 | all: rewrite <- append_cons_r; apply IHs. 326 | all: rewrite append_assoc; cbn. 327 | all: apply extend_unstack; eauto with wb. 328 | Qed. 329 | 330 | Fixpoint destack (z : list ascii) : string := 331 | match z with 332 | | nil => "" 333 | | (c :: z)%list => bra_cket c :: destack z 334 | end. 335 | 336 | Definition destack_unstack z t : unstack z t -> forall s, wellbracketed s -> wellbracketed (t ++ s ++ destack z). 337 | Proof. 338 | induction 1; cbn; intros. 339 | - rewrite append_empty_r; apply wellbracketed_app; auto. 340 | - rewrite append_assoc; destruct H; cbn. 341 | all: rewrite <- (append_assoc s), <- (append_cons_r (s ++ _)); change (?c :: ?s ++ ?t) with ((c :: s) ++ t). 342 | all: apply IHunstack. 343 | all: eauto with wb. 344 | Qed. 345 | 346 | Theorem check_sound s z : check s = Valid z -> wellbracketed (s ++ destack z). 347 | Proof. 348 | intros H; eapply destack_unstack with (s := ""). 349 | - eapply _check_sound with (t := ""); eauto with wb. 350 | - eauto with wb. 351 | Qed. 352 | 353 | Lemma check_prefix s t z : check (s ++ t) = Valid z -> exists z', check s = Valid z'. 354 | Proof. 355 | unfold check; generalize (@nil ascii). 356 | induction s; cbn [check _check String.append]; [ eauto | ]. 357 | repeat (spliteq; cbn [orb]); subst; try auto. 358 | intros []; [ discriminate | ]. 359 | spliteq; [ | discriminate]. 360 | apply IHs. 361 | Qed. 362 | 363 | Lemma ex_f {A B} (f : A -> B) (P : B -> Prop) : ex (fun x => P (f x)) -> ex P. 364 | Proof. 365 | intros [x H]; exists (f x); exact H. 366 | Qed. 367 | 368 | Lemma _check_legit z s c 369 | : _check z s = Illegal c -> 370 | exists t u, s = t ++ c :: u /\ _check z (t ++ c :: "") = Illegal c /\ exists z', _check z t = Valid z'. 371 | Proof. 372 | revert z; induction s as [ | cs s IH ]; cbn; [ discriminate | ]. 373 | intros z Hz. 374 | lazymatch goal with 375 | | [ |- ex ?P ] => 376 | let P' := match eval pattern c in P with 377 | | (?P' _) => P' 378 | end in 379 | enough (HH : (exists t, P (cs :: t)) \/ (c = cs /\ P' cs "")) 380 | by (destruct HH as [[t HH] | [-> HH]]; [exists (cs :: t) | exists ""]; exact HH) 381 | end. 382 | cbn. revert Hz. 383 | repeat (spliteq; cbn [orb]). 384 | 1,2,3,4: left; specialize (IH _ Hz); destruct IH as (t & u & ? & ?); exists t, u; split; congruence. 385 | destruct z. 386 | - injection 1; intros <-; right; eauto 6. 387 | - spliteq; [ | injection 1; intros <-; right; eauto 6 ]. 388 | left; specialize (IH _ Hz). 389 | destruct IH as (t & u & ? & ?). exists t, u; split; congruence. 390 | Qed. 391 | 392 | Lemma check_legit s c 393 | : check s = Illegal c -> 394 | exists t u, s = t ++ c :: u /\ check (t ++ c :: "") = Illegal c /\ exists z', check t = Valid z'. 395 | Proof. 396 | apply _check_legit. 397 | Qed. 398 | 399 | Theorem check_complete s c 400 | : check s = Illegal c -> 401 | exists t u, s = t ++ c :: u 402 | /\ (exists v, wellbracketed (t ++ v)) 403 | /\ forall u', ~wellbracketed (t ++ c :: u'). 404 | Proof. 405 | intros H; destruct (check_legit _ H) as (t & u & Hs & Ht & z' & Hz'). 406 | exists t, u; split; [exact Hs | split ]. 407 | - eexists; revert Hz'; apply check_sound. 408 | - intros u' H'. 409 | apply check_adequate in H'. 410 | rewrite <- append_cons_r in H'. 411 | apply check_prefix in H'. 412 | destruct H' as [? H']; congruence. 413 | Qed. 414 | --------------------------------------------------------------------------------