Done day 19
authorNeil Smith <neil.git@njae.me.uk>
Tue, 21 Dec 2021 16:41:12 +0000 (16:41 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Tue, 21 Dec 2021 16:41:12 +0000 (16:41 +0000)
advent-of-code21.cabal
advent19/Main.hs [new file with mode: 0644]
data/advent19.txt [new file with mode: 0644]
data/advent19a.txt [new file with mode: 0644]
problems/day19.html [new file with mode: 0644]

index 3154f15be8763b4983fe3f18c5b790426ed82375..f92f871ae5f9d405d522578ced150d7ccdcd6f4d 100644 (file)
@@ -195,4 +195,9 @@ executable advent17
 executable advent18
   import: common-extensions, build-directives
   main-is: advent18/Main.hs
-  build-depends: text, attoparsec
\ No newline at end of file
+  build-depends: text, attoparsec
+
+executable advent19
+  import: common-extensions, build-directives
+  main-is: advent19/Main.hs
+  build-depends: linear, text, attoparsec, containers, multiset
diff --git a/advent19/Main.hs b/advent19/Main.hs
new file mode 100644 (file)
index 0000000..e33eaef
--- /dev/null
@@ -0,0 +1,159 @@
+-- Writeup at https://work.njae.me.uk/2021/12/19/advent-of-code-2021-day-17/
+
+import Data.Text ()
+import qualified Data.Text.IO as TIO
+import Data.Attoparsec.Text hiding (take, takeWhile)
+
+import Linear (V3(..), (^+^), (^-^))
+import qualified Data.Set as S
+import qualified Data.MultiSet as MS
+import Data.Monoid
+import Data.Semigroup
+import Data.Maybe
+import Data.List
+import Control.Monad
+
+type Coord = V3 Int
+
+data Scanner = Scanner 
+  { scannerName :: Int
+  , beacons :: [Coord]
+  , transformation :: Endo Coord
+  , signature :: MS.MultiSet Int
+  }
+  deriving (Show)
+
+instance Eq Scanner where
+  s1 == s2 = (scannerName s1) == (scannerName s2)
+
+data Reconstruction = Reconstruction 
+  { found :: [Scanner] -- these have had the transform applied to the beacons
+  , pending :: [Scanner] -- these have had the transform applied to the beacons
+  , waiting :: [Scanner] -- these are as discovered
+  }
+  deriving (Show)
+
+
+-- Transformations
+
+type Transform = Endo Coord
+
+instance Show Transform where
+  -- show c = show $ appEndo c (V3 1 2 3)
+  show c = show $ appEndo c (V3 0 0 0)
+
+nullTrans = Endo id
+rotX = Endo \(V3 x y z) -> V3    x (- z)   y
+rotY = Endo \(V3 x y z) -> V3    z    y (- x)
+rotZ = Endo \(V3 x y z) -> V3 (- y)   x    z
+translate v = Endo (v ^+^)
+
+rotations :: [Transform]
+rotations = [a <> b | a <- ras, b <- rbs]
+  where ras = [nullTrans, rotY, stimes 2 rotY, stimes 3 rotY, rotZ, stimes 3 rotZ]
+        rbs = [nullTrans, rotX, stimes 2 rotX, stimes 3 rotX]
+
+-- Main
+
+main :: IO ()
+main = 
+  do  text <- TIO.readFile "data/advent19.txt"
+      let scanners = successfulParse text
+      let rec0 = mkReconstruction scanners
+      let rec = reconstruct rec0
+      let transScanners = found rec
+      -- print scanners
+      -- print $ findCands scanners
+      -- print $ matchingTransform (scanners!!0) (scanners!!1)
+      -- let rc = mkReconstruction scanners
+      -- print $ reconstruct rc
+      print $ part1 transScanners
+      print $ part2 transScanners
+
+part1 scanners = S.size $ S.unions $ map (S.fromList . beacons) scanners
+
+part2 scanners = maximum [manhattan (a ^-^ b) | a <- origins, b <- origins]
+  where extractOrigin sc = appEndo (transformation sc) (V3 0 0 0)
+        origins = map extractOrigin scanners
+        manhattan (V3 x y z) = (abs x) + (abs y) + (abs z)
+
+
+sign :: [Coord] -> MS.MultiSet Int
+sign bcns = MS.fromList [pythag (a ^-^ b) | a <- bcns, b <- bcns, a < b]
+  where pythag (V3 x y z) = x^2 + y^2 + z^2
+
+vagueMatch :: Scanner -> Scanner -> Bool
+vagueMatch scanner1 scanner2 = s >= (12 * 11) `div` 2
+  where s = MS.size $ MS.intersection (signature scanner1) (signature scanner2)
+
+
+findCands scs = map onlyNames [(a, b) | a <- scs, b <- scs, a `vagueMatch` b]
+  where onlyNames (sa, sb) = (scannerName sa, scannerName sb)
+
+
+matchingTransform :: Scanner -> Scanner -> Maybe Transform
+matchingTransform s1 s2 = listToMaybe $ matchingTransformAll s1 s2
+
+matchingTransformAll :: Scanner -> Scanner -> [Transform]
+matchingTransformAll scanner1 scanner2 = 
+  do  let beacons1 = beacons scanner1
+      let beacons2 = beacons scanner2
+      rot <- rotations
+      b1 <- beacons1
+      b2 <- beacons2
+      let t = b1 ^-^ (appEndo rot b2)
+      let translation = translate t
+      let transB2 = map (appEndo (translation <> rot)) beacons2
+      guard $ (length $ intersect beacons1 transB2) >= 12
+      return (translation <> rot)
+
+
+mkReconstruction :: [Scanner] -> Reconstruction
+mkReconstruction (s:ss) = Reconstruction {found = [], pending = [s], waiting = ss}
+
+reconstruct r 
+  | null $ waiting r = Reconstruction { found = (found r) ++ (pending r), pending = [], waiting = []}
+  | null $ pending r = r
+  | otherwise = reconstruct $ reconstructStep r
+
+reconstructStep Reconstruction{..} = 
+  Reconstruction { found = current : found
+                 , pending = currents ++ newCurrents
+                 , waiting = waiting'
+                 }
+  where (current:currents) = pending
+        possMatches = filter (vagueMatch current) waiting
+        matches = filter (isJust . snd) $ zip possMatches $ map (matchingTransform current) possMatches
+        waiting' = waiting \\ (map fst matches)
+        newCurrents = map (transformScanner) matches
+
+transformScanner (Scanner{..}, trans) = 
+  Scanner { beacons = map (appEndo $ fromJust trans) beacons
+          , transformation = fromJust trans
+          , ..}
+
+
+-- Parse the input file
+
+scannersP = scannerP `sepBy` blankLines
+scannerP = scannerify <$> nameP <*> beaconsP
+  where 
+    scannerify name beacons = 
+      Scanner { scannerName = name
+              , beacons = beacons
+              , transformation = nullTrans
+              , signature = sign beacons
+              }
+
+nameP = ("--- scanner " *>) decimal <* " ---" <* endOfLine
+
+beaconsP = beaconP `sepBy` endOfLine
+beaconP = V3 <$> (signed decimal <* ",") <*> (signed decimal <* ",") <*> (signed decimal)
+
+blankLines = many1 endOfLine
+
+-- successfulParse :: Text -> (Integer, [Maybe Integer])
+successfulParse input = 
+  case parseOnly scannersP input of
+    Left  _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
+    Right scanners -> scanners
diff --git a/data/advent19.txt b/data/advent19.txt
new file mode 100644 (file)
index 0000000..e9a9013
--- /dev/null
@@ -0,0 +1,747 @@
+--- scanner 0 ---
+33,119,14
+386,794,-527
+847,-773,-432
+494,712,-428
+-435,-718,795
+-295,471,-487
+-816,-544,-567
+734,-774,473
+463,729,497
+-427,366,-518
+398,573,572
+128,-27,104
+-540,492,683
+-363,-696,767
+503,604,588
+685,-758,404
+939,-738,-439
+466,681,-536
+-506,516,563
+-419,574,648
+-762,-635,-608
+-342,-819,826
+825,-767,-571
+-685,-537,-490
+621,-854,416
+-409,412,-368
+
+--- scanner 1 ---
+-554,688,331
+10,136,-43
+595,428,514
+385,-521,-354
+477,401,460
+903,577,-479
+471,-295,450
+367,-400,-438
+-312,-437,350
+-749,501,-593
+-441,-615,-655
+-827,496,-560
+-513,-396,311
+598,-354,555
+-424,793,374
+587,-320,334
+870,378,-476
+881,576,-497
+-348,-580,-656
+501,427,383
+-853,527,-530
+348,-473,-387
+-374,-464,296
+-437,-463,-675
+-430,611,375
+
+--- scanner 2 ---
+577,283,810
+-462,405,-722
+-379,-690,-402
+-347,-574,-279
+527,677,-416
+-706,-632,694
+-369,-495,-312
+661,-789,902
+666,-736,970
+491,307,853
+341,-869,-607
+-562,729,576
+405,789,-428
+440,263,902
+-543,376,-567
+-29,-176,83
+-838,-690,725
+-685,750,553
+-802,-549,689
+-720,682,507
+-501,407,-553
+692,-726,964
+337,-755,-698
+408,604,-496
+93,-36,1
+405,-730,-676
+
+--- scanner 3 ---
+587,471,-462
+-509,-620,-660
+-653,741,-542
+-868,-562,313
+-836,-678,436
+418,-555,505
+466,-556,374
+-377,-678,-691
+-413,-537,-655
+596,486,-428
+298,-596,399
+10,-1,-72
+-753,417,756
+-72,-163,17
+-672,388,601
+-495,694,-473
+480,642,434
+604,715,470
+-714,419,587
+553,571,-592
+734,-907,-428
+737,-874,-656
+721,-831,-433
+-530,762,-519
+-846,-483,346
+486,788,573
+
+--- scanner 4 ---
+364,-582,469
+-750,-386,504
+-439,-535,-634
+-734,-429,727
+518,-428,-697
+496,-640,500
+-343,-614,-680
+-339,703,-535
+803,534,-662
+744,470,-753
+493,-540,-546
+-576,853,480
+502,554,402
+-611,799,331
+20,1,-135
+415,692,351
+849,636,-772
+-747,-353,732
+-574,726,496
+589,-589,-637
+-496,-569,-655
+-289,730,-701
+-289,644,-607
+464,590,390
+400,-723,505
+
+--- scanner 5 ---
+882,753,478
+94,9,-2
+730,-823,-830
+-702,-361,462
+826,807,-755
+793,-927,-804
+-510,639,305
+-395,548,-768
+875,820,672
+951,833,625
+763,-901,-835
+844,829,-754
+-561,-475,-945
+-437,450,-814
+-401,574,296
+451,-539,482
+453,-644,492
+660,-563,502
+8,-97,-149
+-618,-536,439
+-763,-565,476
+-414,-426,-968
+-538,-383,-865
+-411,727,410
+-385,387,-889
+847,796,-953
+
+--- scanner 6 ---
+-454,-374,430
+431,400,675
+673,-439,-701
+414,438,713
+541,718,-651
+-718,484,680
+441,-781,727
+-395,-265,494
+-828,752,-757
+-360,-585,-527
+538,837,-815
+615,686,-758
+343,465,536
+778,-420,-535
+-377,-484,453
+732,-530,-637
+24,103,141
+-708,735,-745
+-603,467,581
+384,-690,830
+-736,445,668
+-410,-657,-468
+-767,596,-696
+-360,-491,-441
+-133,3,75
+408,-680,583
+
+--- scanner 7 ---
+-581,-448,-593
+-251,804,-447
+-781,512,720
+-347,-720,518
+882,655,-638
+627,-442,480
+-465,-858,549
+64,-9,18
+-680,566,831
+-452,-879,493
+447,-759,-699
+421,762,528
+881,662,-478
+590,-699,-737
+916,697,-478
+-505,-395,-497
+-684,492,812
+741,-410,448
+-434,759,-412
+383,645,637
+-298,826,-332
+-529,-464,-418
+436,639,562
+811,-510,474
+608,-876,-689
+
+--- scanner 8 ---
+-758,376,-649
+348,349,-725
+564,-589,-806
+-396,-646,735
+-336,-561,673
+573,-598,639
+649,527,715
+792,-621,691
+-651,457,-569
+626,-713,665
+528,-681,-645
+-627,-483,-412
+-587,-432,-606
+-874,903,424
+-591,480,-629
+-617,-474,-469
+354,414,-653
+-889,832,502
+-872,868,306
+-45,39,-90
+-346,-617,799
+641,569,762
+538,525,799
+441,330,-548
+509,-799,-799
+
+--- scanner 9 ---
+643,-675,879
+-297,764,660
+779,465,-424
+-390,-723,882
+685,-645,-332
+689,-492,-311
+634,-788,959
+809,590,-549
+535,-706,851
+678,773,520
+103,35,21
+-863,-795,-607
+-481,-598,842
+539,779,498
+-309,860,724
+-526,423,-306
+546,744,406
+-813,-837,-702
+753,455,-625
+-22,-129,41
+-864,-878,-525
+663,-639,-336
+-465,-567,947
+-366,780,611
+-545,423,-348
+-34,59,174
+-577,524,-230
+
+--- scanner 10 ---
+-391,495,669
+582,758,-495
+723,530,865
+-99,-118,110
+-520,-520,711
+316,-654,637
+-616,-611,662
+469,-629,682
+475,-384,-729
+573,724,-480
+539,594,-580
+-544,667,-771
+720,758,898
+-677,-626,-740
+350,-501,-755
+-705,-739,-768
+432,-413,-756
+-427,531,528
+-667,644,-750
+-523,526,611
+-509,713,-703
+13,-12,-24
+-575,-678,-688
+412,-608,716
+707,753,822
+-545,-671,823
+
+--- scanner 11 ---
+705,-863,-676
+608,741,471
+385,295,-522
+-765,407,-738
+668,718,531
+713,-642,713
+501,822,551
+126,-39,-4
+626,-767,-722
+-612,-867,-821
+-731,396,379
+-698,421,-595
+724,-863,747
+840,-747,772
+-697,519,-795
+-776,524,371
+-323,-449,588
+-335,-569,571
+-639,-917,-655
+660,-710,-701
+-781,370,428
+-28,46,-161
+-553,-917,-749
+-384,-510,432
+387,330,-404
+370,366,-600
+
+--- scanner 12 ---
+-423,223,700
+-552,-912,-420
+924,418,603
+840,420,492
+-463,577,-770
+-435,751,-716
+764,-705,568
+671,-915,-647
+790,-820,515
+-528,307,787
+6,-115,-93
+-633,-906,-522
+689,589,-847
+704,599,-950
+-447,653,-737
+-600,242,793
+-572,-870,-470
+-681,-696,577
+-674,-906,632
+708,492,-905
+887,462,500
+665,-898,-406
+816,-728,349
+648,-871,-541
+-520,-788,613
+
+--- scanner 13 ---
+-425,501,-445
+728,-720,602
+-446,-436,810
+484,-596,-266
+-735,-587,-375
+82,32,86
+-703,-473,-407
+-287,619,-476
+603,875,-553
+731,977,-509
+-386,-293,772
+447,-570,-440
+-750,659,570
+-269,-454,762
+824,551,740
+799,591,908
+-635,-657,-401
+458,-443,-320
+693,550,788
+-266,606,-420
+627,905,-605
+-681,683,491
+-697,735,666
+764,-647,726
+625,-793,720
+
+--- scanner 14 ---
+542,-384,605
+-711,703,-638
+583,-273,691
+-653,-503,341
+-634,-620,430
+-782,643,-799
+-51,104,-103
+253,506,-758
+-871,-683,-374
+-622,575,792
+-752,636,712
+705,386,563
+-650,688,764
+494,-688,-762
+-654,-468,434
+-922,-610,-355
+474,-714,-799
+271,482,-871
+597,-346,754
+-955,-562,-392
+753,385,581
+374,404,-820
+540,-646,-851
+638,435,490
+-807,794,-687
+
+--- scanner 15 ---
+913,-860,-635
+-601,425,-479
+636,616,855
+929,836,-632
+-515,-516,950
+851,-914,-608
+712,-899,-676
+-364,-546,909
+628,658,808
+-769,586,676
+465,-717,941
+-580,327,-467
+923,771,-560
+836,855,-455
+739,660,892
+-814,479,672
+-410,-383,-380
+3,-100,46
+439,-842,824
+-343,-523,-413
+-711,489,657
+-277,-496,955
+-634,501,-495
+-437,-419,-366
+157,18,115
+438,-760,912
+
+--- scanner 16 ---
+-627,-424,478
+-380,962,-358
+786,887,592
+-637,-415,535
+-603,516,635
+481,-617,-601
+-663,539,695
+643,-360,821
+-858,-587,-669
+565,-686,-596
+-496,435,715
+530,-711,-541
+702,738,-631
+-382,927,-240
+703,836,-431
+781,733,535
+-137,132,175
+-908,-558,-733
+556,-515,784
+573,-508,741
+736,861,543
+28,25,61
+770,850,-574
+-365,891,-436
+-918,-502,-607
+-667,-373,672
+
+--- scanner 17 ---
+-903,557,938
+-532,-319,949
+308,691,657
+571,607,-543
+-777,613,948
+321,-739,-612
+-613,-403,-431
+651,755,-613
+281,-503,685
+-839,528,888
+-711,404,-500
+398,-487,844
+-771,498,-451
+-598,-511,985
+276,-673,-493
+-556,-500,-433
+502,742,697
+255,-466,773
+-409,-432,-469
+-486,-530,974
+614,600,-526
+-766,429,-535
+277,-705,-701
+-129,29,156
+365,700,667
+
+--- scanner 18 ---
+633,-271,-850
+-662,603,-547
+-545,-742,658
+786,450,-611
+610,744,448
+-616,396,752
+-637,450,-592
+593,-505,542
+-128,165,-28
+-2,27,121
+-771,-386,-518
+561,-579,435
+-782,446,725
+-710,396,666
+585,-238,-813
+627,864,436
+752,671,-600
+-655,-696,556
+811,566,-727
+-620,-411,-406
+471,803,497
+-683,546,-513
+-564,-637,492
+712,-502,378
+706,-322,-831
+-680,-482,-567
+
+--- scanner 19 ---
+-757,454,646
+377,477,598
+437,-682,325
+-690,-682,784
+-935,-636,-720
+-769,490,684
+-483,289,-561
+-867,-583,-715
+733,-617,-391
+684,359,-604
+520,402,-594
+-659,-740,652
+-654,-823,748
+621,341,-604
+-563,362,-428
+642,-503,-395
+-461,347,-480
+347,-877,315
+314,-798,293
+-3,-175,-172
+-929,-646,-746
+-135,-44,-134
+-808,592,733
+351,543,412
+711,-642,-459
+436,435,428
+
+--- scanner 20 ---
+-672,500,-758
+-545,662,764
+634,-808,-432
+-487,778,731
+-784,-808,716
+-646,-522,-377
+761,844,-380
+9,-104,45
+142,19,-30
+660,-648,522
+600,-708,499
+694,572,884
+624,-865,-441
+763,664,883
+779,780,-349
+-576,-602,-525
+664,-671,-390
+-575,485,-814
+493,-628,418
+-739,-800,844
+696,586,847
+-581,353,-738
+-789,-751,870
+-559,-559,-532
+855,827,-276
+-520,805,765
+
+--- scanner 21 ---
+-327,375,-825
+-709,-420,-666
+746,-882,512
+823,-973,-754
+373,660,469
+-596,-500,-657
+-45,-13,17
+-285,550,299
+-627,-528,-765
+-281,393,-675
+852,-859,-622
+788,-793,558
+-335,459,414
+622,651,-703
+-286,532,347
+720,728,-585
+858,-881,-761
+93,-97,-111
+629,782,-626
+-382,-902,781
+446,723,455
+-304,-851,678
+-406,-789,799
+484,574,510
+-386,261,-706
+814,-830,578
+
+--- scanner 22 ---
+-787,-425,-591
+423,419,-559
+-560,519,547
+734,-609,-665
+-588,919,-611
+483,562,-521
+-815,-352,721
+718,-557,-840
+787,-533,-761
+700,452,461
+605,-259,537
+-727,773,-605
+-691,846,-729
+-762,-465,-423
+596,-502,490
+91,-38,-174
+-574,550,589
+-17,94,-100
+665,549,362
+821,538,448
+-656,-424,-543
+-848,-431,743
+-405,548,628
+682,-365,445
+-725,-547,711
+306,580,-569
+
+--- scanner 23 ---
+-672,354,397
+610,-553,804
+-713,315,598
+-494,-651,526
+-588,-350,-300
+875,454,872
+-529,-652,433
+-755,559,-513
+659,491,-566
+617,-523,-707
+904,497,845
+-789,338,-502
+768,-498,-595
+-636,-383,-263
+787,372,871
+677,-594,-546
+-709,-434,-282
+-814,454,-386
+-646,-671,522
+634,338,-521
+-645,300,459
+-9,-42,-19
+662,-655,856
+680,434,-600
+549,-683,884
+
+--- scanner 24 ---
+456,801,550
+-636,674,571
+-857,263,-304
+441,-968,703
+827,-771,-846
+109,-183,97
+-584,-777,-601
+553,606,-797
+-859,228,-422
+664,604,-713
+379,-914,730
+-576,651,631
+-404,-814,872
+363,782,727
+854,-814,-817
+-743,755,651
+-539,-930,-576
+580,-953,771
+369,717,655
+-520,-930,847
+-23,-52,-36
+656,562,-760
+-531,-709,813
+-618,-834,-622
+-874,299,-500
+853,-896,-729
+
+--- scanner 25 ---
+-722,591,-518
+-802,-413,-781
+-89,91,135
+624,-444,-790
+-612,-837,578
+-866,527,867
+-632,-628,602
+-913,609,868
+590,410,543
+705,-525,940
+823,-441,-757
+513,366,667
+-921,709,826
+-608,521,-475
+-17,-72,52
+-755,-337,-794
+408,409,537
+774,418,-388
+625,-462,-768
+800,495,-364
+773,549,-482
+674,-495,966
+700,-558,862
+-622,-835,683
+-705,383,-514
+-608,-406,-714
+
+--- scanner 26 ---
+-952,-459,615
+-634,708,898
+764,559,-816
+-608,702,-316
+684,706,-747
+-713,692,-318
+562,-570,-265
+-688,-683,-423
+-983,-571,495
+403,-731,749
+570,879,645
+-30,-12,-53
+-605,745,753
+-733,-779,-468
+-869,-514,621
+516,-639,-381
+505,888,536
+658,774,546
+372,-628,642
+-430,722,837
+-632,682,-525
+-109,51,132
+-555,-803,-459
+351,-597,730
+551,-474,-295
+751,512,-740
\ No newline at end of file
diff --git a/data/advent19a.txt b/data/advent19a.txt
new file mode 100644 (file)
index 0000000..b596cc4
--- /dev/null
@@ -0,0 +1,136 @@
+--- scanner 0 ---
+404,-588,-901
+528,-643,409
+-838,591,734
+390,-675,-793
+-537,-823,-458
+-485,-357,347
+-345,-311,381
+-661,-816,-575
+-876,649,763
+-618,-824,-621
+553,345,-567
+474,580,667
+-447,-329,318
+-584,868,-557
+544,-627,-890
+564,392,-477
+455,729,728
+-892,524,684
+-689,845,-530
+423,-701,434
+7,-33,-71
+630,319,-379
+443,580,662
+-789,900,-551
+459,-707,401
+
+--- scanner 1 ---
+686,422,578
+605,423,415
+515,917,-361
+-336,658,858
+95,138,22
+-476,619,847
+-340,-569,-846
+567,-361,727
+-460,603,-452
+669,-402,600
+729,430,532
+-500,-761,534
+-322,571,750
+-466,-666,-811
+-429,-592,574
+-355,545,-477
+703,-491,-529
+-328,-685,520
+413,935,-424
+-391,539,-444
+586,-435,557
+-364,-763,-893
+807,-499,-711
+755,-354,-619
+553,889,-390
+
+--- scanner 2 ---
+649,640,665
+682,-795,504
+-784,533,-524
+-644,584,-595
+-588,-843,648
+-30,6,44
+-674,560,763
+500,723,-460
+609,671,-379
+-555,-800,653
+-675,-892,-343
+697,-426,-610
+578,704,681
+493,664,-388
+-671,-858,530
+-667,343,800
+571,-461,-707
+-138,-166,112
+-889,563,-600
+646,-828,498
+640,759,510
+-630,509,768
+-681,-892,-333
+673,-379,-804
+-742,-814,-386
+577,-820,562
+
+--- scanner 3 ---
+-589,542,597
+605,-692,669
+-500,565,-823
+-660,373,557
+-458,-679,-417
+-488,449,543
+-626,468,-788
+338,-750,-386
+528,-832,-391
+562,-778,733
+-938,-730,414
+543,643,-506
+-524,371,-870
+407,773,750
+-104,29,83
+378,-903,-323
+-778,-728,485
+426,699,580
+-438,-605,-362
+-469,-447,-387
+509,732,623
+647,635,-688
+-868,-804,481
+614,-800,639
+595,780,-596
+
+--- scanner 4 ---
+727,592,562
+-293,-554,779
+441,611,-461
+-714,465,-776
+-743,427,-804
+-660,-479,-426
+832,-632,460
+927,-485,-438
+408,393,-506
+466,436,-512
+110,16,151
+-258,-428,682
+-393,719,612
+-211,-452,876
+808,-476,-593
+-575,615,604
+-485,667,467
+-680,325,-822
+-627,-443,-432
+872,-547,-609
+833,512,582
+807,604,487
+839,-516,451
+891,-625,532
+-652,-548,-490
+30,-46,-14
\ No newline at end of file
diff --git a/problems/day19.html b/problems/day19.html
new file mode 100644 (file)
index 0000000..f34b7cf
--- /dev/null
@@ -0,0 +1,466 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 19 - Advent of Code 2021</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'/>
+<link rel="stylesheet" type="text/css" href="/static/style.css?26"/>
+<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
+<link rel="shortcut icon" href="/favicon.png"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  The best surprises don't
+even appear in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not a massive company, and I can
+only take so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, social media), I
+built the whole thing myself, including the design, animations, prose, and all
+of the puzzles.
+
+The puzzles are most of the work; preparing a new calendar and a new set of
+puzzles each year takes all of my free time for 4-5 months. A lot of effort
+went into building this thing - I hope you're enjoying playing it as much as I
+enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2021/about">[About]</a></li><li><a href="/2021/events">[Events]</a></li><li><a href="https://teespring.com/stores/advent-of-code" target="_blank">[Shop]</a></li><li><a href="/2021/settings">[Settings]</a></li><li><a href="/2021/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2021/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">38*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">0xffff&amp;</span><a href="/2021">2021</a><span class="title-event-wrap"></span></h1><nav><ul><li><a href="/2021">[Calendar]</a></li><li><a href="/2021/support">[AoC++]</a></li><li><a href="/2021/sponsors">[Sponsors]</a></li><li><a href="/2021/leaderboard">[Leaderboard]</a></li><li><a href="/2021/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2021/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://www.twilio.com/quest" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">TwilioQuest</a> - Learn to code and lead your intrepid crew on a mission to save The Cloud in TwilioQuest, a PC role-playing game inspired by classics of the 16-bit era. Free forever, and available now for Windows, Mac, and Linux.</div></div>
+</div><!--/sidebar-->
+
+<main>
+<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script>
+<article class="day-desc"><h2>--- Day 19: Beacon Scanner ---</h2><p>As your <a href="17">probe</a> drifted down through this area, it released an assortment of <em>beacons</em> and <em>scanners</em> into the water. It's difficult to navigate in the pitch black open waters of the ocean trench, but if you can build a map of the trench using data from the scanners, you should be able to safely reach the bottom.</p>
+<p>The beacons and scanners float motionless in the water; they're designed to maintain the same position for long periods of time. Each scanner is capable of detecting all beacons in a large cube centered on the scanner; beacons that are at most 1000 units away from the scanner in each of the three axes (<code>x</code>, <code>y</code>, and <code>z</code>) have their precise position determined relative to the scanner. However, scanners cannot detect other scanners. The submarine has automatically summarized the relative positions of beacons detected by each scanner (your puzzle input).</p>
+<p>For example, if a scanner is at <code>x,y,z</code> coordinates <code>500,0,-500</code> and there are beacons at <code>-500,1000,-1500</code> and <code>1501,0,-500</code>, the scanner could report that the first beacon is at <code>-1000,1000,-1000</code> (relative to the scanner) but would not detect the second beacon at all.</p>
+<p>Unfortunately, while each scanner can report the positions of all detected beacons relative to itself, <em>the scanners do not know their own position</em>. You'll need to determine the positions of the beacons and scanners yourself.</p>
+<p>The scanners and beacons map a single contiguous 3d region. This region can be reconstructed by finding pairs of scanners that have overlapping detection regions such that there are <em>at least 12 beacons</em> that both scanners detect within the overlap. By establishing 12 common beacons, you can precisely determine where the scanners are relative to each other, allowing you to reconstruct the beacon map one scanner at a time.</p>
+<p>For a moment, consider only two dimensions. Suppose you have the following scanner reports:</p>
+<pre><code>--- scanner 0 ---
+0,2
+4,1
+3,3
+
+--- scanner 1 ---
+-1,-1
+-5,0
+-2,1
+</code></pre>
+<p>Drawing <code>x</code> increasing rightward, <code>y</code> increasing upward, scanners as <code>S</code>, and beacons as <code>B</code>, scanner <code>0</code> detects this:</p>
+<pre><code>...B.
+B....
+....B
+S....
+</code></pre>
+<p>Scanner <code>1</code> detects this:</p>
+<pre><code>...B..
+B....S
+....B.
+</code></pre>
+<p>For this example, assume scanners only need 3 overlapping beacons. Then, the beacons visible to both scanners overlap to produce the following complete map:</p>
+<pre><code>...B..
+B....S
+....B.
+S.....
+</code></pre>
+<p>Unfortunately, there's a second problem: the scanners also don't know their <em>rotation or facing direction</em>. Due to magnetic alignment, each scanner is rotated some integer number of 90-degree turns around all of the <code>x</code>, <code>y</code>, and <code>z</code> axes. That is, one scanner might call a direction positive <code>x</code>, while another scanner might call that direction negative <code>y</code>. Or, two scanners might agree on which direction is positive <code>x</code>, but one scanner might be upside-down from the perspective of the other scanner. In total, each scanner could be in any of 24 different orientations: facing positive or negative <code>x</code>, <code>y</code>, or <code>z</code>, and considering any of four directions "up" from that facing.</p>
+<p>For example, here is an arrangement of beacons as seen from a scanner in the same position but in different orientations:</p>
+<pre><code>--- scanner 0 ---
+-1,-1,1
+-2,-2,2
+-3,-3,3
+-2,-3,1
+5,6,-4
+8,0,7
+
+--- scanner 0 ---
+1,-1,1
+2,-2,2
+3,-3,3
+2,-1,3
+-5,4,-6
+-8,-7,0
+
+--- scanner 0 ---
+-1,-1,-1
+-2,-2,-2
+-3,-3,-3
+-1,-3,-2
+4,6,5
+-7,0,8
+
+--- scanner 0 ---
+1,1,-1
+2,2,-2
+3,3,-3
+1,3,-2
+-4,-6,5
+7,0,8
+
+--- scanner 0 ---
+1,1,1
+2,2,2
+3,3,3
+3,1,2
+-6,-4,-5
+0,7,-8
+</code></pre>
+<p>By finding pairs of scanners that both see at least 12 of the same beacons, you can assemble the entire map. For example, consider the following report:</p>
+<pre><code>--- scanner 0 ---
+404,-588,-901
+528,-643,409
+-838,591,734
+390,-675,-793
+-537,-823,-458
+-485,-357,347
+-345,-311,381
+-661,-816,-575
+-876,649,763
+-618,-824,-621
+553,345,-567
+474,580,667
+-447,-329,318
+-584,868,-557
+544,-627,-890
+564,392,-477
+455,729,728
+-892,524,684
+-689,845,-530
+423,-701,434
+7,-33,-71
+630,319,-379
+443,580,662
+-789,900,-551
+459,-707,401
+
+--- scanner 1 ---
+686,422,578
+605,423,415
+515,917,-361
+-336,658,858
+95,138,22
+-476,619,847
+-340,-569,-846
+567,-361,727
+-460,603,-452
+669,-402,600
+729,430,532
+-500,-761,534
+-322,571,750
+-466,-666,-811
+-429,-592,574
+-355,545,-477
+703,-491,-529
+-328,-685,520
+413,935,-424
+-391,539,-444
+586,-435,557
+-364,-763,-893
+807,-499,-711
+755,-354,-619
+553,889,-390
+
+--- scanner 2 ---
+649,640,665
+682,-795,504
+-784,533,-524
+-644,584,-595
+-588,-843,648
+-30,6,44
+-674,560,763
+500,723,-460
+609,671,-379
+-555,-800,653
+-675,-892,-343
+697,-426,-610
+578,704,681
+493,664,-388
+-671,-858,530
+-667,343,800
+571,-461,-707
+-138,-166,112
+-889,563,-600
+646,-828,498
+640,759,510
+-630,509,768
+-681,-892,-333
+673,-379,-804
+-742,-814,-386
+577,-820,562
+
+--- scanner 3 ---
+-589,542,597
+605,-692,669
+-500,565,-823
+-660,373,557
+-458,-679,-417
+-488,449,543
+-626,468,-788
+338,-750,-386
+528,-832,-391
+562,-778,733
+-938,-730,414
+543,643,-506
+-524,371,-870
+407,773,750
+-104,29,83
+378,-903,-323
+-778,-728,485
+426,699,580
+-438,-605,-362
+-469,-447,-387
+509,732,623
+647,635,-688
+-868,-804,481
+614,-800,639
+595,780,-596
+
+--- scanner 4 ---
+727,592,562
+-293,-554,779
+441,611,-461
+-714,465,-776
+-743,427,-804
+-660,-479,-426
+832,-632,460
+927,-485,-438
+408,393,-506
+466,436,-512
+110,16,151
+-258,-428,682
+-393,719,612
+-211,-452,876
+808,-476,-593
+-575,615,604
+-485,667,467
+-680,325,-822
+-627,-443,-432
+872,-547,-609
+833,512,582
+807,604,487
+839,-516,451
+891,-625,532
+-652,-548,-490
+30,-46,-14
+</code></pre>
+<p>Because all coordinates are relative, in this example, all "absolute" positions will be expressed relative to scanner <code>0</code> (using the orientation of scanner <code>0</code> and as if scanner <code>0</code> is at coordinates <code>0,0,0</code>).</p>
+<p>Scanners <code>0</code> and <code>1</code> have overlapping detection cubes; the 12 beacons they both detect (relative to scanner <code>0</code>) are at the following coordinates:</p>
+<pre><code>-618,-824,-621
+-537,-823,-458
+-447,-329,318
+404,-588,-901
+544,-627,-890
+528,-643,409
+-661,-816,-575
+390,-675,-793
+423,-701,434
+-345,-311,381
+459,-707,401
+-485,-357,347
+</code></pre>
+<p>These same 12 beacons (in the same order) but from the perspective of scanner <code>1</code> are:</p>
+<pre><code>686,422,578
+605,423,415
+515,917,-361
+-336,658,858
+-476,619,847
+-460,603,-452
+729,430,532
+-322,571,750
+-355,545,-477
+413,935,-424
+-391,539,-444
+553,889,-390
+</code></pre>
+<p>Because of this, scanner <code>1</code> must be at <code>68,-1246,-43</code> (relative to scanner <code>0</code>).</p>
+<p>Scanner <code>4</code> overlaps with scanner <code>1</code>; the 12 beacons they both detect (relative to scanner <code>0</code>) are:</p>
+<pre><code>459,-707,401
+-739,-1745,668
+-485,-357,347
+432,-2009,850
+528,-643,409
+423,-701,434
+-345,-311,381
+408,-1815,803
+534,-1912,768
+-687,-1600,576
+-447,-329,318
+-635,-1737,486
+</code></pre>
+<p>So, scanner <code>4</code> is at <code>-20,-1133,1061</code> (relative to scanner <code>0</code>).</p>
+<p>Following this process, scanner <code>2</code> must be at <code>1105,-1205,1229</code> (relative to scanner <code>0</code>) and scanner <code>3</code> must be at <code>-92,-2380,-20</code> (relative to scanner <code>0</code>).</p>
+<p>The full list of beacons (relative to scanner <code>0</code>) is:</p>
+<pre><code>-892,524,684
+-876,649,763
+-838,591,734
+-789,900,-551
+-739,-1745,668
+-706,-3180,-659
+-697,-3072,-689
+-689,845,-530
+-687,-1600,576
+-661,-816,-575
+-654,-3158,-753
+-635,-1737,486
+-631,-672,1502
+-624,-1620,1868
+-620,-3212,371
+-618,-824,-621
+-612,-1695,1788
+-601,-1648,-643
+-584,868,-557
+-537,-823,-458
+-532,-1715,1894
+-518,-1681,-600
+-499,-1607,-770
+-485,-357,347
+-470,-3283,303
+-456,-621,1527
+-447,-329,318
+-430,-3130,366
+-413,-627,1469
+-345,-311,381
+-36,-1284,1171
+-27,-1108,-65
+7,-33,-71
+12,-2351,-103
+26,-1119,1091
+346,-2985,342
+366,-3059,397
+377,-2827,367
+390,-675,-793
+396,-1931,-563
+404,-588,-901
+408,-1815,803
+423,-701,434
+432,-2009,850
+443,580,662
+455,729,728
+456,-540,1869
+459,-707,401
+465,-695,1988
+474,580,667
+496,-1584,1900
+497,-1838,-617
+527,-524,1933
+528,-643,409
+534,-1912,768
+544,-627,-890
+553,345,-567
+564,392,-477
+568,-2007,-577
+605,-1665,1952
+612,-1593,1893
+630,319,-379
+686,-3108,-505
+776,-3184,-501
+846,-3110,-434
+1135,-1161,1235
+1243,-1093,1063
+1660,-552,429
+1693,-557,386
+1735,-437,1738
+1749,-1800,1813
+1772,-405,1572
+1776,-675,371
+1779,-442,1789
+1780,-1548,337
+1786,-1538,337
+1847,-1591,415
+1889,-1729,1762
+1994,-1805,1792
+</code></pre>
+<p>In total, there are <code><em>79</em></code> beacons.</p>
+<p>Assemble the full map of beacons. <em>How many beacons are there?</em></p>
+</article>
+<p>Your puzzle answer was <code>355</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>Sometimes, it's a good idea to appreciate just how <span title="The deepest parts of the ocean are about as deep as the altitude of a normal commercial aircraft, roughly 11 kilometers or 36000 feet.">big</span> the ocean is. Using the <a href="https://en.wikipedia.org/wiki/Taxicab_geometry" target="_blank">Manhattan distance</a>, how far apart do the scanners get?</p>
+<p>In the above example, scanners <code>2</code> (<code>1105,-1205,1229</code>) and <code>3</code> (<code>-92,-2380,-20</code>) are the largest Manhattan distance apart. In total, they are <code>1197 + 1175 + 1249 = <em>3621</em></code> units apart.</p>
+<p><em>What is the largest Manhattan distance between any two scanners?</em></p>
+</article>
+<p>Your puzzle answer was <code>10842</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p>
+<p>At this point, you should <a href="/2021">return to your Advent calendar</a> and try another puzzle.</p>
+<p>If you still want to see it, you can <a href="19/input" target="_blank">get your puzzle input</a>.</p>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Beacon+Scanner%22+%2D+Day+19+%2D+Advent+of+Code+2021&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2021%2Fday%2F19&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Beacon+Scanner%22+%2D+Day+19+%2D+Advent+of+Code+2021+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2021%2Fday%2F19'}else{return false;}" target="_blank">Mastodon</a
+></span>]</span> this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('set', 'anonymizeIp', true);
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file