diff --git a/advent-of-code-2021.csproj b/advent-of-code-2021.csproj index da056ec..d2794ff 100644 --- a/advent-of-code-2021.csproj +++ b/advent-of-code-2021.csproj @@ -72,6 +72,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/inputs/19.txt b/inputs/19.txt new file mode 100644 index 0000000..d8699df --- /dev/null +++ b/inputs/19.txt @@ -0,0 +1,856 @@ +--- scanner 0 --- +536,703,543 +-132,-41,-64 +-429,350,-809 +-477,567,455 +-369,-732,-732 +-806,-680,810 +502,729,469 +-417,400,-831 +497,-739,-564 +-545,-726,-743 +271,357,-605 +13,-26,94 +508,-654,-647 +-581,-685,774 +396,-908,355 +-481,568,418 +-634,-665,910 +306,410,-668 +540,739,539 +465,-656,-423 +-474,-628,-795 +-463,568,426 +254,306,-662 +358,-788,353 +-396,313,-691 +251,-873,452 + +--- scanner 1 --- +405,377,-919 +-471,604,350 +479,506,644 +495,326,707 +-407,-663,-846 +618,-537,318 +-584,506,-618 +-577,-375,640 +682,-442,283 +-579,-587,598 +612,361,-928 +-253,-680,-729 +512,382,-895 +531,379,751 +-468,-460,659 +-262,-699,-913 +974,-376,-550 +539,-333,326 +917,-437,-630 +-422,787,372 +48,7,-59 +-451,618,404 +-697,390,-626 +-766,485,-587 +971,-556,-663 + +--- scanner 2 --- +-652,-598,521 +680,708,-671 +401,-847,-328 +-666,588,522 +-629,-292,-571 +256,-750,-363 +-576,-428,-551 +-698,690,-828 +640,385,384 +698,679,-614 +-801,-392,-556 +490,-475,680 +-594,-543,549 +27,-15,66 +-878,546,524 +-703,476,-864 +741,661,-790 +-793,527,633 +506,-675,668 +-736,691,-860 +-646,-597,737 +650,579,455 +363,-849,-448 +-77,-44,-102 +636,387,485 +609,-565,657 + +--- scanner 3 --- +-694,-480,675 +-79,48,-39 +-713,754,292 +329,-686,-566 +352,-717,-653 +689,385,454 +-736,862,-562 +-619,615,350 +687,515,-478 +754,359,540 +-741,-551,707 +-416,-641,-826 +780,-406,714 +757,427,547 +-766,670,-548 +376,-703,-591 +-676,-675,645 +616,-364,628 +-413,-651,-750 +-645,601,324 +-837,864,-558 +618,546,-543 +651,-444,702 +-438,-700,-839 +735,493,-571 + +--- scanner 4 --- +-530,746,312 +786,-443,556 +-889,-559,548 +707,-625,-700 +-597,746,-565 +-695,733,324 +797,-456,613 +521,468,-520 +798,-448,530 +-820,-811,-882 +-905,-712,-989 +700,666,439 +759,795,432 +637,796,456 +-877,-533,314 +-887,-526,362 +671,-621,-704 +-575,696,330 +-940,-809,-844 +-478,699,-504 +-654,717,-547 +-56,111,-123 +529,444,-427 +618,407,-518 +697,-695,-738 + +--- scanner 5 --- +-622,-664,638 +91,56,-46 +-584,-588,503 +-597,-542,-844 +637,-732,382 +541,-389,-695 +608,849,773 +-824,472,329 +-715,664,-901 +-807,472,398 +696,824,658 +-748,513,423 +734,-704,553 +-603,-571,-996 +702,-641,519 +-564,648,-902 +-546,-560,-802 +529,757,-875 +-774,670,-893 +710,934,780 +-633,-647,616 +45,186,-187 +571,805,-747 +469,-300,-758 +548,722,-801 +470,-365,-800 + +--- scanner 6 --- +-63,90,49 +498,853,-791 +578,-569,-624 +-655,-638,533 +625,-555,-405 +612,-558,-546 +481,703,-791 +472,508,699 +-676,-594,581 +641,-783,554 +689,489,688 +-597,648,491 +-588,829,-432 +447,-795,466 +-611,-448,-552 +-628,702,-523 +517,666,-715 +-730,-425,-642 +-606,719,-512 +-714,-437,-442 +-537,611,499 +-462,665,425 +597,478,703 +460,-784,616 +-648,-556,677 + +--- scanner 7 --- +845,881,-301 +-501,-349,486 +-315,-608,-344 +-480,685,-388 +718,980,-308 +915,979,627 +-279,-529,-320 +749,-436,411 +-508,-323,638 +-557,-346,709 +744,-481,476 +738,-636,412 +-431,775,-306 +-486,759,-520 +378,-599,-409 +-575,569,537 +538,-579,-380 +94,37,37 +-656,696,463 +931,951,534 +931,865,728 +448,-570,-525 +-739,579,511 +-301,-469,-277 +782,925,-452 + +--- scanner 8 --- +-642,587,781 +449,768,-502 +-541,-248,454 +-652,688,-666 +-657,-301,345 +388,565,306 +-711,575,-617 +-597,592,716 +31,60,-133 +-705,-303,534 +-728,553,-628 +518,471,325 +-449,-629,-686 +-462,-608,-643 +399,395,424 +573,-579,-519 +-49,145,4 +485,-560,410 +365,-564,556 +408,793,-443 +-580,-592,-693 +542,-671,-541 +408,862,-426 +380,-463,470 +-442,598,780 +580,-773,-513 + +--- scanner 9 --- +511,-520,557 +831,490,487 +-549,-659,-680 +536,-615,-490 +165,-84,33 +652,-552,474 +-516,602,-544 +-439,-556,-691 +-267,-451,305 +-822,579,548 +-571,544,-572 +-16,-6,-106 +841,452,-616 +-517,596,-760 +-364,-306,340 +584,-594,-534 +820,314,481 +680,-622,-572 +883,419,585 +-722,751,533 +-639,-540,-703 +735,-563,559 +947,393,-650 +-686,526,528 +905,520,-588 +-265,-413,425 + +--- scanner 10 --- +-737,650,-388 +799,760,694 +-389,-453,768 +-667,-803,-543 +537,-419,977 +573,-564,910 +699,461,-254 +-644,698,-366 +-657,-874,-737 +556,-410,793 +-672,581,-419 +-653,-773,-735 +680,814,727 +78,-167,23 +-376,-475,827 +861,-734,-576 +649,-736,-534 +776,-625,-595 +-649,292,813 +860,817,614 +-624,339,830 +50,-20,162 +-465,-450,778 +-562,315,844 +903,382,-262 +794,525,-219 + +--- scanner 11 --- +99,76,34 +-676,680,608 +-416,-818,449 +-383,-733,-582 +-278,-673,-485 +-263,-587,-586 +-297,-719,373 +610,574,866 +544,-363,576 +743,689,-672 +-817,391,-552 +-607,706,535 +601,429,776 +-805,494,-602 +-779,332,-498 +699,-427,570 +703,798,-570 +759,-798,-323 +643,-689,-270 +-605,648,465 +648,653,-655 +-286,-837,543 +-21,-98,124 +581,458,936 +807,-609,-325 +744,-362,565 + +--- scanner 12 --- +-425,-551,749 +399,-500,-745 +621,-564,617 +458,551,789 +-771,404,712 +-635,-782,-410 +141,-60,-11 +-407,-500,691 +427,311,-461 +434,438,-362 +-786,391,773 +-533,-750,-406 +578,374,-417 +420,485,830 +376,378,782 +-602,225,-477 +535,-509,559 +-733,594,734 +652,-499,714 +-466,-660,638 +375,-461,-524 +-501,241,-363 +13,-15,-141 +392,-416,-592 +-585,-935,-464 +-408,225,-391 + +--- scanner 13 --- +-869,-562,284 +-626,-660,-761 +863,541,-592 +-615,-577,-676 +594,-454,-831 +-713,476,667 +915,554,-452 +621,-462,713 +528,750,450 +680,-516,627 +-640,407,641 +-783,478,609 +866,578,-609 +-705,797,-876 +-875,786,-758 +662,-561,828 +-658,-801,-678 +524,593,486 +-852,-619,335 +-799,667,-857 +-817,-556,388 +479,-362,-887 +490,705,572 +101,-76,-131 +-40,-1,16 +414,-474,-816 + +--- scanner 14 --- +441,817,-678 +-598,650,753 +371,-553,781 +-510,-749,-608 +9,-9,185 +364,-412,661 +-698,-767,-537 +-695,787,-546 +-93,144,106 +676,-367,-546 +-564,746,-667 +478,752,-535 +-588,-350,394 +565,773,-725 +-587,-306,537 +-678,698,-692 +-773,-762,-605 +-393,632,689 +597,749,893 +827,-282,-517 +-490,578,681 +380,-405,668 +808,-318,-662 +578,692,850 +579,917,825 +-578,-442,497 + +--- scanner 15 --- +711,434,636 +-814,919,616 +-367,796,-569 +667,-597,612 +637,-360,-736 +668,-381,618 +699,-371,-662 +-351,789,-562 +591,759,-398 +786,439,704 +128,62,-70 +-793,-527,-586 +722,-569,670 +-754,-553,694 +600,895,-438 +601,851,-295 +-796,-491,821 +-663,834,645 +-795,883,761 +-690,-470,-654 +-728,-676,-612 +-690,-525,762 +639,-287,-734 +-358,648,-682 +523,452,707 + +--- scanner 16 --- +509,-793,667 +878,553,565 +-582,760,-790 +-599,-400,-777 +581,-549,-837 +-498,-416,-891 +-405,-400,-863 +-530,575,-848 +769,655,525 +-8,-11,-79 +538,-953,687 +90,-139,81 +-529,308,461 +402,325,-509 +-282,-582,524 +-347,-587,569 +654,-883,658 +-718,306,509 +-609,253,625 +-283,-593,724 +-632,607,-844 +430,-486,-793 +395,241,-662 +437,-613,-892 +733,638,620 +378,286,-730 + +--- scanner 17 --- +754,602,-677 +-722,-580,-369 +-439,722,669 +-372,731,-647 +16,-1,-34 +164,118,125 +433,-796,-390 +474,-459,828 +943,619,739 +-765,-605,576 +-402,923,-633 +697,631,-695 +873,649,-738 +-700,-639,-356 +592,-518,899 +-756,-789,557 +566,-719,-309 +475,-540,761 +-725,-590,-445 +692,-807,-381 +-611,-722,593 +-550,783,796 +911,620,701 +-441,764,881 +-301,925,-637 +947,834,706 + +--- scanner 18 --- +113,-179,93 +-709,565,-575 +-585,-728,588 +812,527,-496 +-496,315,704 +-367,364,615 +939,-532,762 +727,472,-351 +701,704,557 +-312,-886,-799 +944,-633,873 +-779,594,-691 +-533,-891,548 +499,-602,-827 +-608,-769,451 +-375,-930,-648 +-619,574,-720 +829,432,-460 +460,-823,-851 +757,693,547 +415,-755,-834 +950,-664,733 +-439,-985,-792 +702,691,743 +-341,400,702 + +--- scanner 19 --- +765,-723,-476 +-795,553,792 +640,682,-495 +138,123,77 +648,-491,767 +617,736,-578 +-556,-542,581 +-679,-488,-787 +-738,-463,-828 +-755,-394,-828 +508,578,559 +779,-845,-366 +-638,-549,725 +489,795,570 +611,-431,759 +665,-356,833 +478,703,555 +80,10,-59 +-594,-570,677 +-783,747,704 +-705,828,-630 +677,-838,-451 +-784,566,642 +-495,837,-652 +598,810,-543 +-646,836,-636 + +--- scanner 20 --- +698,-671,896 +-629,-578,570 +882,-690,887 +633,-486,-344 +815,-654,742 +862,582,-466 +-307,396,-533 +-671,-366,572 +556,494,383 +-327,471,-605 +-403,796,727 +-526,-508,-812 +-690,-451,681 +-48,50,4 +595,399,452 +-741,-541,-816 +-435,627,698 +-381,613,678 +611,-348,-461 +-527,-546,-780 +587,515,565 +887,614,-414 +-361,524,-418 +552,-419,-343 +867,468,-504 + +--- scanner 21 --- +591,695,-643 +-461,-434,378 +876,-525,845 +447,688,-725 +-609,715,615 +858,-320,-565 +-724,-437,365 +752,-379,-599 +725,-496,760 +816,-447,-627 +413,806,524 +-598,737,632 +-528,629,-524 +-660,-471,-643 +-649,-505,360 +405,746,561 +-606,-523,-455 +-605,-529,-671 +-638,732,-535 +339,881,578 +-110,154,-71 +857,-380,809 +38,67,-3 +-518,755,742 +495,667,-681 +-728,613,-512 + +--- scanner 22 --- +417,869,-670 +-390,-523,-643 +668,-601,466 +-449,460,555 +-411,652,-704 +757,407,838 +-332,-429,-504 +-399,817,-717 +-14,26,-96 +-635,458,588 +549,-578,556 +-401,470,562 +-674,-468,562 +-687,-471,703 +-364,-497,-657 +460,693,-688 +508,-376,-588 +902,442,741 +478,750,-717 +518,-305,-394 +652,-589,666 +109,117,38 +-417,772,-667 +795,527,840 +-640,-457,484 +522,-406,-396 + +--- scanner 23 --- +-800,-816,-415 +486,376,-362 +-411,496,636 +260,419,326 +-938,-671,519 +1,-24,20 +359,-713,278 +-930,-835,-509 +-611,650,-431 +668,-637,-556 +429,325,-345 +-833,-731,616 +423,429,-397 +282,369,338 +-953,-585,620 +400,332,305 +296,-609,383 +-437,334,532 +-919,-717,-339 +348,-707,454 +527,-720,-588 +444,-635,-599 +-540,682,-574 +-186,11,-59 +-399,393,586 +-609,708,-501 + +--- scanner 24 --- +661,560,-615 +-838,-878,-425 +756,-980,519 +-430,-499,528 +-840,792,-299 +-891,-834,-389 +730,337,599 +-711,491,690 +-613,-477,577 +-835,768,-406 +-827,499,803 +792,592,-663 +-711,-771,-373 +656,286,631 +-856,801,-506 +-42,-81,88 +841,216,626 +-599,-531,557 +767,-854,387 +754,-461,-726 +-732,460,872 +859,-869,436 +668,-426,-620 +626,-548,-657 +802,511,-703 + +--- scanner 25 --- +871,758,-518 +-441,-709,335 +458,576,380 +704,-742,-632 +-721,571,786 +-803,-452,-835 +-752,658,763 +-711,565,-686 +828,638,-529 +-687,377,-660 +392,-542,358 +-686,530,-584 +818,761,-520 +-888,-342,-883 +480,483,428 +-798,-414,-880 +324,-535,361 +-399,-623,499 +-54,-43,48 +511,548,497 +350,-449,426 +807,-776,-756 +-738,596,739 +81,137,-43 +716,-700,-860 +-479,-697,464 + +--- scanner 26 --- +-901,-451,391 +-534,-435,-744 +-383,810,622 +-7,71,53 +474,684,458 +-861,602,-891 +-769,-567,440 +-571,-578,-679 +-457,735,676 +605,-576,840 +-920,-596,355 +417,-505,822 +680,-508,835 +384,612,-707 +471,-446,-673 +462,781,-698 +565,644,585 +-864,517,-869 +554,666,568 +-909,737,-873 +-658,-388,-700 +-449,675,639 +585,-421,-625 +602,-567,-714 +397,746,-782 + +--- scanner 27 --- +-490,-562,-654 +501,516,490 +-310,-612,762 +560,738,-569 +587,-506,-667 +-782,970,-551 +-729,935,-614 +-289,-544,-609 +424,433,614 +606,-412,-491 +-833,987,-608 +378,-468,689 +-404,-503,-708 +391,546,639 +487,738,-654 +-436,705,597 +451,-491,621 +-400,701,593 +-321,-555,775 +567,-397,668 +81,40,90 +582,667,-630 +-410,739,523 +-309,-529,770 +657,-413,-678 + +--- scanner 28 --- +69,84,-59 +-289,-502,-551 +595,-623,583 +-456,920,-639 +583,-423,567 +778,439,713 +-576,755,732 +714,-491,-517 +-307,-690,-480 +-693,808,704 +879,437,717 +739,598,-801 +-377,912,-843 +-645,786,797 +741,640,-589 +-544,-542,669 +742,-546,-575 +-520,955,-734 +606,-513,686 +526,-545,-569 +-671,-633,709 +-561,-553,691 +-294,-427,-483 +808,631,727 +630,579,-716 + +--- scanner 29 --- +554,-452,430 +712,317,-664 +554,-470,422 +-577,514,-619 +-735,-733,754 +-625,-635,-349 +419,547,547 +-441,819,564 +-504,514,-704 +-518,736,440 +809,-385,-687 +30,-54,-66 +722,-406,-827 +-599,585,-680 +772,-418,-805 +-123,-145,56 +765,282,-601 +-662,-695,652 +-660,-788,804 +383,551,543 +-650,-675,-301 +-723,-747,-314 +-408,706,589 +555,-466,459 +393,513,473 +-30,28,95 +816,265,-658 + +--- scanner 30 --- +648,439,-720 +-883,-704,-653 +760,676,623 +681,-717,482 +288,-461,-535 +739,-762,425 +752,755,827 +-682,-622,380 +-665,-711,526 +278,-470,-658 +-587,838,467 +-793,461,-725 +588,-655,448 +-850,825,464 +-702,588,-685 +-662,843,535 +-870,-779,-787 +795,612,718 +-796,-670,405 +595,556,-748 +5,-51,26 +235,-459,-538 +-131,33,-79 +-805,-695,-822 +-713,571,-707 +626,487,-813 \ No newline at end of file diff --git a/src/19.cs b/src/19.cs new file mode 100644 index 0000000..2d336cc --- /dev/null +++ b/src/19.cs @@ -0,0 +1,176 @@ +namespace aoc2021; + +internal class Day19 : Day +{ + internal override void Go() + { + var lines = Util.ReadAllLines("inputs/19.txt"); + var scanners = new List>(); + foreach (var line in lines) + { + if (line.StartsWith("--")) + { + scanners.Add(new()); + } + else if (string.IsNullOrEmpty(line)) + { + continue; + } + else + { + var points = line.Split(','); + scanners[^1].Add((Convert.ToInt32(points[0]), Convert.ToInt32(points[1]), Convert.ToInt32(points[2]))); + } + } + + var result = Part1(scanners); + Part2(result); + } + + record struct Vector3(int X, int Y, int Z) + { + public static implicit operator Vector3((int x, int y, int z) value) => new(value.x, value.y, value.z); + public static Vector3 operator+(Vector3 p, Vector3 v) => (p.X + v.X, p.Y + v.Y, p.Z + v.Z); + public static Vector3 operator-(Vector3 p1, Vector3 p2) => (p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z); + + public int DistanceTo(Vector3 other) => (int)(Math.Pow(other.X - X, 2) + Math.Pow(other.Y - Y, 2) + Math.Pow(other.Z - Z, 2)); + + public int ManhattanDistanceTo(Vector3 other) + { + var (dx, dy, dz) = this - other; + return Math.Abs(dx) + Math.Abs(dy) + Math.Abs(dz); + } + + public Vector3 Transform(Vector3 up, int rotation) + { + Vector3 reoriented = up switch + { + (0, +1, 0) => (X, Y, Z), + (0, -1, 0) => (X, -Y, -Z), + (+1, 0, 0) => (Y, X, -Z), + (-1, 0, 0) => (Y, -X, Z), + (0, 0, +1) => (Y, Z, X), + (0, 0, -1) => (Y, -Z, -X), + _ => throw new Exception("Invalid up vector") + }; + + return rotation switch + { + 0 => reoriented, + 1 => (reoriented.Z, reoriented.Y, -reoriented.X), + 2 => (-reoriented.X, reoriented.Y, -reoriented.Z), + 3 => (-reoriented.Z, reoriented.Y, reoriented.X), + _ => throw new Exception("Invalid rotation") + }; + } + } + + private static readonly (int, int, int)[] Axes = new[] + { + ( 0, +1, 0), + ( 0, -1, 0), + (+1, 0, 0), + (-1, 0, 0), + ( 0, 0, +1), + ( 0, 0, -1) + }; + + private static (IEnumerable alignedBeacons, Vector3 translation, Vector3 up, int rotation)? Align(ICollection beacons1, ICollection beacons2) + { + // Fix beacons1, rotate beacons2 + for (int axis = 0; axis < Axes.Length; axis++) + { + for (int rotation = 0; rotation < 4; rotation++) + { + var rotatedBeacons2 = new HashSet(beacons2.Select(b => b.Transform(Axes[axis], rotation))); + + foreach (var b1 in beacons1) + { + // Assume b1 matches some b2 + foreach (var matchingB1InB2 in rotatedBeacons2) + { + // Move all b2 so matchingB1InB2 matches b1, in scanner 1 coordinates + var delta = b1 - matchingB1InB2; + var transformedBeacons2 = rotatedBeacons2.Select(b => b + delta); + + // How many overlaps did we get? + var intersection = new HashSet(transformedBeacons2); + intersection.IntersectWith(beacons1); + if (intersection.Count >= 12) + { + // Found the right orientation + return (transformedBeacons2, delta, Axes[axis], rotation); + } + } + } + } + } + return null; + } + + private static (IEnumerable> scans, IEnumerable> scanners) Reduce(IEnumerable> scans, IEnumerable> scanners) + { + var toRemove = new HashSet(); + for (int i = 0; i < scans.Count() - 1; i++) + { + for (int j = i + 1; j < scans.Count(); j++) + { + if (toRemove.Contains(j)) + { + // Already merged + continue; + } + + var alignment = Align(scans.ElementAt(i), scans.ElementAt(j)); + if (alignment != null) + { + // Convert all scanners from j coordinates to i coordinates + foreach (var s in scanners.ElementAt(j)) + { + var scanner = alignment.Value.translation + s.Transform(alignment.Value.up, alignment.Value.rotation); + scanners.ElementAt(i).Add(scanner); + } + // Merge the scan sets + scans.ElementAt(i).UnionWith(alignment.Value.alignedBeacons); + toRemove.Add(j); + } + } + } + // Skip all scans and scanners that were merged + return (scans.Where((_, i) => !toRemove.Contains(i)), scanners.Where((_, i) => !toRemove.Contains(i))); + } + + private static ICollection Part1(List> input) + { + using var t = new Timer(); + + IEnumerable> scans = input; + IEnumerable> scanners = input.Select((_) => new HashSet { (0, 0, 0) }).ToList(); + while (scans.Count() > 1) + { + // Note that this will loop forever if there is no alignment + (scans, scanners) = Reduce(scans, scanners); + } + + var allBeacons = scans.ElementAt(0); + + t.Stop(); + Logger.Log($"<+black>> part1: <+white>{allBeacons.Count}"); + + return scanners.ElementAt(0); + } + + private static void Part2(ICollection scanners) + { + using var t = new Timer(); + + var scannerList = scanners.ToList(); + var farthest = + Enumerable.Range(0, scannerList.Count - 1) + .SelectMany(i => Enumerable.Range(i + 1, scannerList.Count - i - 1).Select(j => (i, j))) + .Max(pair => scannerList[pair.i].ManhattanDistanceTo(scannerList[pair.j])); + + t.Stop(); + Logger.Log($"<+black>> part2: <+white>{farthest}"); + } +} diff --git a/src/main.cs b/src/main.cs index e82507d..cdbdfa9 100644 --- a/src/main.cs +++ b/src/main.cs @@ -37,6 +37,7 @@ else "16" => new Day16(), "17"=> new Day17(), "18" => new Day18(), + "19" => new Day19(), _ => new Day20(), }; day.Go();