From 5e91487466c150b345b4c848db6ef931f7f0d517 Mon Sep 17 00:00:00 2001 From: Parnic Date: Wed, 21 Dec 2022 23:12:50 -0600 Subject: [PATCH] Day 19 solution Cribbed from some posts on the subreddit. I don't know why this one was so difficult for me. --- advent-of-code-2022.csproj | 1 + inputs/19.txt | 886 ++----------------------------------- inputs/19a.txt | 2 + src/19.cs | 369 +++++++++++++++ 4 files changed, 402 insertions(+), 856 deletions(-) create mode 100644 inputs/19a.txt create mode 100644 src/19.cs diff --git a/advent-of-code-2022.csproj b/advent-of-code-2022.csproj index e5e5ba6..34c17b7 100644 --- a/advent-of-code-2022.csproj +++ b/advent-of-code-2022.csproj @@ -79,6 +79,7 @@ + diff --git a/inputs/19.txt b/inputs/19.txt index d8699df..743cc3b 100644 --- a/inputs/19.txt +++ b/inputs/19.txt @@ -1,856 +1,30 @@ ---- 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 +Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 3 ore and 8 obsidian. +Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 3 ore and 16 obsidian. +Blueprint 3: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 9 obsidian. +Blueprint 4: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 2 ore and 8 obsidian. +Blueprint 5: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 2 ore and 18 obsidian. +Blueprint 6: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 7 clay. Each geode robot costs 4 ore and 20 obsidian. +Blueprint 7: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 6 clay. Each geode robot costs 2 ore and 20 obsidian. +Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 10 clay. Each geode robot costs 4 ore and 10 obsidian. +Blueprint 9: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 4 ore and 16 obsidian. +Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 4 ore and 12 obsidian. +Blueprint 11: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 3 ore and 17 obsidian. +Blueprint 12: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 2 ore and 12 obsidian. +Blueprint 13: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 4 ore and 17 obsidian. +Blueprint 14: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 9 obsidian. +Blueprint 15: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 7 obsidian. +Blueprint 16: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 9 obsidian. +Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian. +Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 19: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian. +Blueprint 20: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 8 obsidian. +Blueprint 21: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 7 obsidian. +Blueprint 22: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 12 obsidian. +Blueprint 23: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 3 ore and 19 obsidian. +Blueprint 24: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 16 clay. Each geode robot costs 3 ore and 9 obsidian. +Blueprint 25: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 9 clay. Each geode robot costs 4 ore and 16 obsidian. +Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 2 ore and 10 obsidian. +Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 3 ore and 19 obsidian. +Blueprint 28: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 7 clay. Each geode robot costs 3 ore and 9 obsidian. +Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 4 ore and 11 obsidian. +Blueprint 30: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 2 ore and 20 obsidian. \ No newline at end of file diff --git a/inputs/19a.txt b/inputs/19a.txt new file mode 100644 index 0000000..4626ad9 --- /dev/null +++ b/inputs/19a.txt @@ -0,0 +1,2 @@ +Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian. \ No newline at end of file diff --git a/src/19.cs b/src/19.cs new file mode 100644 index 0000000..e00e7e3 --- /dev/null +++ b/src/19.cs @@ -0,0 +1,369 @@ +using System.Text.RegularExpressions; + +namespace aoc2022; + +internal partial class Day19 : Day +{ + private enum resource + { + ore = 1, + clay = 2, + obsidian = 3, + geode = 4, + } + + private class cost + { + public resource type; + public int amount; + + public override string ToString() => $"{amount} {type}"; + } + + private class blueprint + { + public int id; + public Dictionary> robots = new(); + + public override string ToString() => $"({robots.Count}) {string.Join("; ", robots)}"; + } + + private class miningSim + { + public miningSim(blueprint bp, int timeLimit = 24) + { + this.bp = bp; + this.timeLimit = timeLimit; + } + + public override string ToString() => $"{resources[resource.ore]}r {clayCount}c {obsidianCount}o {geodeCount}g @{timePassed}m with bots {robots[resource.ore]}r {clayRobotCount}c {obsidianRobotCount}o {geodeRobotCount}g"; + + private int? cachedUpperBound; + public readonly int timeLimit; + + public int GetFinalValueUpperBound() + { + cachedUpperBound ??= GetFinalGeodesUpperBound(this); + return cachedUpperBound.Value; + } + + private miningSim Clone() + { + var tmp = (miningSim) MemberwiseClone(); + tmp.cachedUpperBound = null; + tmp.robots = new Dictionary(tmp.robots); + tmp.resources = new Dictionary(tmp.resources); + tmp.shouldWait = false; + return tmp; + } + + public miningSim advance() + { + var copy = Clone(); + copy.internalAdvance(); + return copy; + } + + private void internalAdvance() + { + shouldWait = false; + timePassed++; + foreach (var r in robots) + { + resources[r.Key] += r.Value; + } + } + + public miningSim buildRobot(resource type) + { + var copy = Clone(); + copy.internalBuildRobot(type); + return copy; + } + + private static readonly cost freeCost = new() {type = resource.ore, amount = 0}; + + private (cost cost1, cost cost2) getCosts(resource r) + { + var robotDef = bp.robots[r]; + var cost1 = robotDef.First(); + var cost2 = (robotDef.Count() > 1 ? robotDef.Last() : freeCost); + return (cost1, cost2); + } + + private void internalBuildRobot(resource r) + { + var (cost1, cost2) = getCosts(r); + + resources[cost1.type] -= cost1.amount; + if (resources[cost1.type] < 0) + { + throw new Exception($"sim {cost1.type} amount too low"); + } + resources[cost2.type] -= cost2.amount; + if (resources[cost2.type] < 0) + { + throw new Exception($"sim {cost2.type} amount too low"); + } + + internalAdvance(); + + robots[r]++; + } + + private enum buildStatus + { + cantBuild, + canBuild, + buildableEventually, + } + + buildStatus getBuildStatus(resource r) + { + var (cost1, cost2) = getCosts(r); + + if (resources[cost1.type] >= cost1.amount && resources[cost2.type] >= cost2.amount) + { + return buildStatus.canBuild; + } + + if (robots[cost1.type] > 0 && robots[cost2.type] > 0) + { + return buildStatus.buildableEventually; + } + + return buildStatus.cantBuild; + } + + private IEnumerable>> getBotsRequiring(resource res) + { + return bp.robots.Where(bot => bot.Value.Any(r => r.type == res)); + } + + public IEnumerable GetBuildableRobots() + { + foreach (var robot in bp.robots) + { + var status = getBuildStatus(robot.Key); + if (status == buildStatus.canBuild) + { + yield return robot.Key; + } + else if (status == buildStatus.buildableEventually) + { + shouldWait = true; + } + } + } + + private readonly blueprint bp; + public int timePassed { get; private set; } + public int geodeCount => resources[resource.geode]; + public int geodeRobotCount => robots[resource.geode]; + + public int obsidianCount => resources[resource.obsidian]; + public int obsidianRobotCount => robots[resource.obsidian]; + public int geodeRobotObsidianCost => bp.robots[resource.geode][1].amount; + + public int clayCount => resources[resource.clay]; + public int clayRobotCount => robots[resource.clay]; + public int obsidianRobotClayCost => bp.robots[resource.obsidian][1].amount; + + public double geodesPerMinute => 1.0 * geodeCount / timePassed; + public bool shouldWait { get; private set; } + + private Dictionary robots = new() + { + {resource.ore, 1}, + {resource.clay, 0}, + {resource.obsidian, 0}, + {resource.geode, 0}, + }; + + private Dictionary resources = new() + { + {resource.ore, 0}, + {resource.clay, 0}, + {resource.obsidian, 0}, + {resource.geode, 0}, + }; + } + + private readonly List blueprints = new(); + + [GeneratedRegex( + "Blueprint (?\\d+): Each (?.+?) robot costs (?\\d+) (?.+?)\\. Each (?.+?) robot costs (?\\d+) (?.+?)\\. Each (?.+?) robot costs (?\\d+) (?.+?) and (?\\d+) (?.+?)\\. Each (?.+?) robot costs (?\\d+) (?.+?) and (?\\d+) (?.+?)\\.")] + private static partial Regex BlueprintRegex(); + + internal override void Parse() + { + Regex r = BlueprintRegex(); + foreach (var line in Util.Parsing.ReadAllLines("19")) + { + var match = r.Match(line); + + cost orecost = new() + { + type = Enum.Parse(match.Groups["costtype1"].Value), + amount = int.Parse(match.Groups["count1"].Value), + }; + + cost claycost = new() + { + type = Enum.Parse(match.Groups["costtype2"].Value), + amount = int.Parse(match.Groups["count2"].Value), + }; + + cost obsidiancost1 = new() + { + type = Enum.Parse(match.Groups["costtype3_1"].Value), + amount = int.Parse(match.Groups["count3_1"].Value), + }; + cost obsidiancost2 = new() + { + type = Enum.Parse(match.Groups["costtype3_2"].Value), + amount = int.Parse(match.Groups["count3_2"].Value), + }; + + cost geodecost1 = new() + { + type = Enum.Parse(match.Groups["costtype4_1"].Value), + amount = int.Parse(match.Groups["count4_1"].Value), + }; + cost geodecost2 = new() + { + type = Enum.Parse(match.Groups["costtype4_2"].Value), + amount = int.Parse(match.Groups["count4_2"].Value), + }; + + blueprint bp = new() + { + id = blueprints.Count + 1, + robots = new Dictionary> + { + {resource.ore, new List {orecost}}, + {resource.clay, new List {claycost}}, + {resource.obsidian, new List {obsidiancost1, obsidiancost2}}, + {resource.geode, new List {geodecost1, geodecost2}}, + }, + }; + + blueprints.Add(bp); + } + } + + private static int GetFinalGeodesUpperBound(miningSim sim) + { + int geodeRobotCount = sim.geodeRobotCount; + int obsidianRobotCount = sim.obsidianRobotCount; + int clayRobotCount = sim.clayRobotCount; + + int obsidianCount = sim.obsidianCount; + int obsidianCost = sim.geodeRobotObsidianCost; + + int clayCount = sim.clayCount; + int clayCost = sim.obsidianRobotClayCost; + + int geodeCount = sim.geodeCount; + for (int i = sim.timePassed; i < sim.timeLimit; i++) + { + var newClayRobotCount = clayRobotCount; + var newObsidianRobotCount = obsidianRobotCount; + var newGeodeRobotCount = geodeRobotCount; + + if (obsidianCount >= obsidianCost) + { + obsidianCount -= obsidianCost; + newGeodeRobotCount++; + } + + if (clayCount >= clayCost) + { + clayCount -= clayCost; + newObsidianRobotCount++; + } + + newClayRobotCount++; + + clayCount += clayRobotCount; + obsidianCount += obsidianRobotCount; + geodeCount += geodeRobotCount; + + geodeRobotCount = newGeodeRobotCount; + obsidianRobotCount = newObsidianRobotCount; + clayRobotCount = newClayRobotCount; + } + + return geodeCount; + } + + private int FindMaxGeodes(miningSim sim) + { + var queue = new PriorityQueue(); + queue.Enqueue(sim, + (0.0, 0, 0) + ); + + int bestGeodes = 0; + + while (queue.Count > 0) + { + var state = queue.Dequeue(); + if (state.timePassed > state.timeLimit) + { + continue; + } + + if (state.geodeCount > bestGeodes) + { + bestGeodes = state.geodeCount; + } + + if (state.timePassed == state.timeLimit) + { + continue; + } + + var finalGeodesUpperBound = state.GetFinalValueUpperBound(); + if (finalGeodesUpperBound <= bestGeodes) + { + continue; + } + + foreach (var toBuild in state.GetBuildableRobots()) + { + var nextState = state.buildRobot(toBuild); + queue.Enqueue(nextState, + (-nextState.geodesPerMinute, -nextState.timePassed, -nextState.GetFinalValueUpperBound()) + ); + } + + if (state.shouldWait) + { + var nextState = state.advance(); + queue.Enqueue(nextState, + (-nextState.geodesPerMinute, -nextState.timePassed, -nextState.GetFinalValueUpperBound()) + ); + } + } + + return bestGeodes; + } + + internal override string Part1() + { + var lst = blueprints.Select(sim => (sim.id, maxGeodes: FindMaxGeodes(new miningSim(sim)))); + + var qualitySum = lst.Select(x => x.id * x.maxGeodes).Sum(); + return $"Quality level of all blueprints for 24 minutes: <+white>{qualitySum}"; + } + + internal override string Part2() + { + var g1 = FindMaxGeodes(new miningSim(blueprints[0], 32)); + var g2 = FindMaxGeodes(new miningSim(blueprints[1], 32)); + var g3 = FindMaxGeodes(new miningSim(blueprints[2], 32)); + return $"Sum of geodes opened by first 3 blueprints after 32 minutes: <+white>{g1*g2*g3}"; + } +} \ No newline at end of file