diff --git a/.circleci/config.yml b/.circleci/config.yml index 856542b..5628a6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -70,11 +70,11 @@ jobs: # nix-instantiate --eval 09/9.nix > /tmp/output9 # diff /tmp/output9 09/output - # - run: - # name: Day10 - # command: | - # nix-instantiate --eval 10/10.nix > /tmp/output10 - # diff /tmp/output10 10/output + - run: + name: Day10 + command: | + nix-instantiate --eval 10/10.nix > /tmp/output10 + diff /tmp/output10 10/output workflows: diff --git a/10/10.nix b/10/10.nix new file mode 100755 index 0000000..53bb39d --- /dev/null +++ b/10/10.nix @@ -0,0 +1,108 @@ +#!/usr/bin/nix-instantiate --eval + +let lib = import ; + inherit (builtins) readFile length split elem getAttr attrNames filter trace; + inherit (lib.lists) head last remove findFirst reverseList tail concatLists unique elemAt sort; + inherit (lib.strings) splitString stringToCharacters; + inherit (lib.attrsets) mapAttrs' genAttrs filterAttrs; + + inherit (import ../string-extra.nix) trim splitAndMap; + inherit (import ../math-extra.nix) maximum maximumBy manhattanDistance atan2 pseudoangle rad2def; + inherit (import ../lazy-extra.nix) strict; + inherit (import ../lists-extra.nix) enumerate uniqueBy removeMany rotateUntil; + inherit (import ../advent-utils.nix) splitStringAndMapFromTrimmedFile; + vector = import ../vector2.nix; + + input = splitStringAndMapFromTrimmedFile ./input "\n" stringToCharacters; + coordinateGrid = ( + let enumeratedLines = enumerate input; + coordinateGrid = + map (elines: + map (ecolumns: + genAttrs ["x" "y" "obj"] (name: + if name == "x" then + ecolumns.fst + else if name == "y" then + elines.fst + else + ecolumns.snd + ) + ) (enumerate elines.snd) + ) enumeratedLines; + in concatLists coordinateGrid + ); + + asteroidCoordinates = + map (filterAttrs (n: v: n != "obj")) + (filter (grid: grid.obj == "#") coordinateGrid); + + preprocessAsteroids = (originAsteroid: targetAsteroid: + let unit = vector.unit (vector.fromPoints originAsteroid targetAsteroid); + in {x1 = toString unit.x1; x2 = toString unit.x2;} + ); + + countVisibleAsteroid = + allAsteroids: + initialAsteroid: ( + let + asteroids = remove initialAsteroid allAsteroids; + preprocessedAsteroids = map (preprocessAsteroids initialAsteroid) asteroids; + nVisibleAsteroids = length (unique preprocessedAsteroids); + in nVisibleAsteroids + ); + + + idealPosition = maximumBy (countVisibleAsteroid asteroidCoordinates) asteroidCoordinates; + part1 = countVisibleAsteroid asteroidCoordinates idealPosition; + + listVisibleAsteroid = + allAsteroids: + initialAsteroid: ( + let + asteroids = remove initialAsteroid allAsteroids; + visibleAsteroids = uniqueBy (preprocessAsteroids initialAsteroid) (sort (a: b: manhattanDistance initialAsteroid a < manhattanDistance initialAsteroid b) asteroids); + in visibleAsteroids + ); + + laserFullRotation = (originAsteroid: allAsteroids: + removeMany (listVisibleAsteroid allAsteroids originAsteroid) allAsteroids + ); + + laserOrderedRotation = (originAsteroid: allAsteroids: + let rotateF = rotateUntil (a: a.x >= originAsteroid.x && a.y < originAsteroid.y); + sortF = sort (fst: snd: + let v1 = vector.unit (vector.fromPoints originAsteroid fst); + v2 = vector.unit (vector.fromPoints originAsteroid snd); + in atan2 v1.x1 v1.x2 > atan2 v2.x1 v2.x2 + ); + visibleAsteroids = listVisibleAsteroid allAsteroids originAsteroid; + in + rotateF (sortF visibleAsteroids) + ); + + nthAsteroidVaporized = (originAsteroid: allAsteroids: n: + let + nInitialAsteroids = length allAsteroids; + remainingAsteroids = laserFullRotation originAsteroid allAsteroids; + nRemainingAsteroids = length remainingAsteroids; + nVaporizedAsteroids = trace (nInitialAsteroids - nRemainingAsteroids) (nInitialAsteroids - nRemainingAsteroids); + in if nVaporizedAsteroids == 0 then + abort "Never got to n." + else if nVaporizedAsteroids >= n then + # laserOrderedRotation originAsteroid allAsteroids + elemAt (laserOrderedRotation originAsteroid allAsteroids) n + # else if nVaporizedAsteroids != countVisibleAsteroid allAsteroids originAsteroid then + # abort "Wrong" + else + nthAsteroidVaporized originAsteroid remainingAsteroids (n - nVaporizedAsteroids) + ); + + # pos = {x = 4; y = 4;}; + # bet = nthAsteroidVaporized pos asteroidCoordinates 9; + bet = nthAsteroidVaporized idealPosition asteroidCoordinates 200; + part2 = bet.x * 100 + bet.y; + + # abc = listVisibleAsteroid asteroidCoordinates pos; + +# in strict { inherit abc; } +in strict { inherit part1 part2; } diff --git a/10/aaaa b/10/aaaa new file mode 100644 index 0000000..82f82da --- /dev/null +++ b/10/aaaa @@ -0,0 +1,19 @@ +MyAsteroid: + 3,4 + +AllAsteroids +(Coordinates, AxisDistances, ManhattanDistance, Slope, Quadrant): + 4,4 (+1, +0) 1 null + 4,3 (+1, -1) 2 -1 + 3,2 (+0, -2) 2 +0 + 4,2 (+1, -2) 3 -2 + 1,2 (-2, -2) 4 +1 + 4,0 (+1, +4) 5 +4 + 0,2 (-3, -2) 5 +2/3 3 + 2,2 (-1, -2) 3 +2 3 + 5,6 (+1, +2) 3 +2 1 # Do Not Ignore! Reasons: Multiple of (-1, -2) + Multipicity factor < 0 (== -1) + 1,0 (-2, -4) 6 +2 # Ignore! Reasons: Multiple of (-1, -2) + Multipicity factor > 0 (== 2) + +X can see Y if: diff --git a/10/input b/10/input new file mode 100644 index 0000000..e5deb23 --- /dev/null +++ b/10/input @@ -0,0 +1,41 @@ +.#....#.###.........#..##.###.#.....##... +...........##.......#.#...#...#..#....#.. +...#....##..##.......#..........###..#... +....#....####......#..#.#........#....... +...............##..#....#...##..#...#..#. +..#....#....#..#.....#.#......#..#...#... +.....#.#....#.#...##.........#...#....... +#...##.#.#...#.......#....#........#..... +....##........#....#..........#.......#.. +..##..........##.....#....#.........#.... +...#..##......#..#.#.#...#............... +..#.##.........#...#.#.....#........#.... +#.#.#.#......#.#...##...#.........##....# +.#....#..#.....#.#......##.##...#.......# +..#..##.....#..#.........#...##.....#..#. +##.#...#.#.#.#.#.#.........#..#...#.##... +.#.....#......##..#.#..#....#....#####... +........#...##...#.....#.......#....#.#.# +#......#..#..#.#.#....##..#......###..... +............#..#.#.#....#.....##..#...... +...#.#.....#..#.......#..#.#............# +.#.#.....#..##.....#..#..............#... +.#.#....##.....#......##..#...#......#... +.......#..........#.###....#.#...##.#.... +.....##.#..#.....#.#.#......#...##..#.#.. +.#....#...#.#.#.......##.#.........#.#... +##.........#............#.#......#....#.. +.#......#.............#.#......#......... +.......#...##........#...##......#....#.. +#..#.....#.#...##.#.#......##...#.#..#... +#....##...#.#........#..........##....... +..#.#.....#.....###.#..#.........#......# +......##.#...#.#..#..#.##..............#. +.......##.#..#.#.............#..#.#...... +...#....##.##..#..#..#.....#...##.#...... +#....#..#.#....#...###...#.#.......#..... +.#..#...#......##.#..#..#........#....#.. +..#.##.#...#......###.....#.#........##.. +#.##.###.........#...##.....#..#....#.#.. +..........#...#..##..#..##....#.........# +..#..#....###..........##..#...#...#..#.. diff --git a/10/input2 b/10/input2 new file mode 100644 index 0000000..ecf3f24 --- /dev/null +++ b/10/input2 @@ -0,0 +1,5 @@ +.#....#####...#.. +##...##.#####..## +##...#...#.#####. +..#.....X...###.. +..#.#.....#....## diff --git a/10/input3 b/10/input3 new file mode 100644 index 0000000..33437ba --- /dev/null +++ b/10/input3 @@ -0,0 +1,20 @@ +.#..##.###...####### +##.############..##. +.#.######.########.# +.###.#######.####.#. +#####.##.#.##.###.## +..#####..#.######### +#################### +#.####....###.#.#.## +##.################# +#####.##.###..####.. +..######..##.####### +####.##.####...##..# +.#####..#.######.### +##...#.##########... +#.##########.####### +.####.#.###.###.#.## +....##.##.###..##### +.#.#.###########.### +#.#.#.#####.####.### +###.##.####.##.#..## diff --git a/10/output b/10/output new file mode 100644 index 0000000..1688c6d --- /dev/null +++ b/10/output @@ -0,0 +1 @@ +{ part1 = 340; part2 = NaN; } diff --git a/bool-extra.nix b/bool-extra.nix new file mode 100644 index 0000000..dc8b680 --- /dev/null +++ b/bool-extra.nix @@ -0,0 +1,5 @@ +#!/usr/bin/nix-instantiate --eval + +let not = bool: if bool then false else true; + +in { inherit not; } diff --git a/lists-extra.nix b/lists-extra.nix index 9003dce..9bba688 100644 --- a/lists-extra.nix +++ b/lists-extra.nix @@ -1,8 +1,10 @@ #!/usr/bin/nix-instantiate --eval let lib = import ; - inherit (lib.lists) head tail take drop range length foldl elemAt count zipLists zipListsWith concatMap foldr; + inherit (builtins) elem; + inherit (lib.lists) head tail take drop range length foldl elemAt count zipLists zipListsWith concatMap foldr filter; inherit (import ./func-extra.nix) minBy maxBy; + inherit (import ./bool-extra.nix) not; replace = (xs: i: v: (take i xs) ++ [v] ++ (drop (i + 1) xs)); @@ -137,4 +139,38 @@ let lib = import ; in foldr (xs: concatMap (insertEverywhere xs)) [[]] ); -in { inherit allBy2 anyBy2 cartesianProduct chunks concat countEqual dropWhile enumerate groupIntoList groupIntoListBy maximumBy minimumBy permutations replace scanl takeWhile upTo zipManyListsWith; } + removeMany = deny: xs: ( + filter (x: not (elem x deny)) xs + ); + + uniqueBy = f: xs: ( + if xs == [] then [] else + + let x = head xs; + in [x] ++ uniqueBy f (filter (y: f y != f x) (tail xs)) + ); + + rotate = n: xs: ( + if length xs < 2 then xs else + if n == 0 then xs else + + let h = head xs; + t = tail xs; + in rotate (n - 1) (t ++ [h]) + ); + + rotateUntil = p: xs: ( + if length xs < 2 then xs else + + let succeeded = p (head xs); + in if succeeded then xs else rotateUntil p (rotate 1 xs) + ); + + rotateUntil2 = p: xs: ( + if length xs < 2 then xs else + + let succeeded = p (head xs) (head tail xs); + in if succeeded then xs else rotateUntil2 p (rotate 1 xs) + ); + +in { inherit allBy2 anyBy2 cartesianProduct chunks concat countEqual dropWhile enumerate groupIntoList groupIntoListBy maximumBy minimumBy permutations replace removeMany scanl takeWhile upTo uniqueBy zipManyListsWith rotate rotateUntil rotateUntil2; } diff --git a/math-extra.nix b/math-extra.nix index 501e36f..34abe0e 100644 --- a/math-extra.nix +++ b/math-extra.nix @@ -2,60 +2,91 @@ let lib = import ; inherit (lib.trivial) mod; - - sum = lib.lists.foldr (a: b: a + b) 0; + inherit (lib.lists) head foldr; abs = n: if n < 0 then -n else n; + odd = n: mod n 2 == 1; even = n: mod n 2 == 0; - slope = (fst: snd: + sum = foldr (a: b: a + b) 0; + + min = a: b: if a > b then b else a; + max = a: b: if a > b then a else b; + + minBy = f: a: b: if f a > f b then b else a; + maxBy = f: a: b: if f a > f b then a else b; + + minimum = list: foldr min (head list) list; + maximum = list: foldr max (head list) list; + + minimumBy = f: list: foldr (minBy f) (head list) list; + maximumBy = f: list: foldr (maxBy f) (head list) list; + + slope = fst: snd: ( let rise = snd.y - fst.y; run = snd.x - fst.x; in - if run != 0 then rise / run + if run != 0 then rise * 1.0 / run else null ); - manhattanDistance = (fst: snd: abs (snd.x - fst.x) + abs (snd.y - fst.y)); - - quadrant = (vec: - if vec.x > 0 && vec.y > 0 then - 1 - else if vec.x < 0 && vec.y > 0 then - 2 - else if vec.x < 0 && vec.y < 0 then - 3 - else if vec.x > 0 && vec.y < 0 then - 4 - # not really quadrant anymore - else if vec.x == 0 && vec.y == 0 then - 0 - else if vec.y == 0 && vec.x > 0 then - -1 - else if vec.x == 0 && vec.y > 0 then - -2 - else if vec.y == 0 && vec.x < 0 then - -3 - else if vec.x == 0 && vec.y < 0 then - -4 - else - abort "Aaaaaahhhh" + + manhattanDistance = fst: snd: ( + abs (snd.x - fst.x) + abs (snd.y - fst.y) ); - semiaxis = (vec: - if vec.x == 0 && vec.y == 0 then - 0 - else if vec.y == 0 && vec.x > 0 then - 1 - else if vec.x == 0 && vec.y > 0 then - 2 - else if vec.y == 0 && vec.x < 0 then - 3 - else if vec.x == 0 && vec.y < 0 then - 4 + sqrt = sqrtNewton 0.00001 4.0; + + sqrtNewton = epsilon: prev: num: ( + let next = (prev + (num * 1.0) / prev) / 2; + in + if abs (next - prev) < (epsilon * next) then next else + + sqrtNewton epsilon next num + ); + + pi = 3.14156; + + atan = z: ( + let n1 = 0.97239411; + n2 = -0.19194795; + in (n1 + n2 * z * z) * z + ); + + atan2 = x: y: ( + if x == 0 && y == 0 then 0 else + if x == 0 && y > 0 then pi / 2 else + if x == 0 && y < 0 then -pi / 2 else + + if abs x > abs y then + let z = 1.0 * y / x; + in + if x > 0 then + atan(z) + else if y >= 0 then + atan(z) + pi + else + atan(z) - pi else - null + let z = 1.0 * x / y; + in + if y > 0 then + (-atan(z)) + pi / 2 + else + (-atan(z)) - pi / 2 + ); + + rad2def = rad: rad * (180 / pi); + + + copysign = (x: y: + if y >= 0 then abs(x) else -abs(x) ); -in { inherit abs even mod odd sum slope manhattanDistance; } + pseudoangle = (x: y: + copysign (1.0 - 1.0 * x / (abs x + abs y)) y + ); + + +in { inherit abs even mod odd sum slope manhattanDistance min max minBy maxBy minimum maximum minimumBy maximumBy sqrt atan atan2 pi rad2def; } diff --git a/vector2.nix b/vector2.nix new file mode 100644 index 0000000..c92c42d --- /dev/null +++ b/vector2.nix @@ -0,0 +1,32 @@ +#!/usr/bin/nix-instantiate --eval + +let lib = import ; + inherit (import ./math-extra.nix) sqrt; + + new = x1: x2: ( + { x1 = x1; x2 = x2; } + ); + + zero = (fst: snd: + new 0 0 + ); + + fromPoints = (fst: snd: + new (fst.x - snd.x) (fst.y - snd.y) + ); + + unit = (vector: + let mag = magnitude vector; + in + new (vector.x1 / mag) (vector.x2 / mag) + ); + + magnitude = (v: + sqrt (v.x1 * v.x1 + v.x2 * v.x2) + ); + + crossProduct = v1: v2: ( + (v1.x1*v2.x2) - (v1.x2*v2.x1) + ); + +in { inherit new zero fromPoints unit magnitude crossProduct; }