Compare commits

..
15 Commits
Author SHA1 Message Date
peterr 8062f0a2be Add code for day 16
Day 16: Chronal Classification
2019-01-09 20:05:32 -06:00
peterr 5531412a55 Add code for Day 15
Day 15: Beverage Bandits
2019-01-08 23:15:45 -06:00
peterr 14c93b8482 Add Code for Day 14
Day 14: Chocolate Charts
(brute forced part 2, not elegant)
2018-12-15 12:22:25 -06:00
peterr d511a8cd65 Finish Code for Day 13 2018-12-15 00:48:20 -06:00
peterr 944fad0f02 Make GridPoint support dictionaries
Add hashValue propertiy and Hashable protocol
2018-12-15 00:47:20 -06:00
peterr 3e711561fa Add Code for Day 13 (only the start)
Day 13: Mine Cart Madness
 - add the "Cart" struct to do everything "cart" related
2018-12-13 19:03:02 -06:00
peterr 949f3e7444 Move GridPoint to Tools
Make GridPoint available to all "days"
2018-12-13 19:01:54 -06:00
peterr eff0e909a1 Modified Day 11 - takes too long 2018-12-13 15:25:46 -06:00
peterr f373431d8e Add Code for Day 12
Day 12: Subterranean Sustainability
 - ended up looking for a repeating pattern
 - then figured out how many generation to repeat
 - calculated out 50000000000 generations
2018-12-13 15:23:15 -06:00
peterr 439760c9ec Added Code for Day 11
Day 11: Chronal Charge
(done, but I don't like my solution)
2018-12-13 11:24:28 -06:00
peterr 0ad73c41d9 Remove compile warnings 2018-12-13 11:23:13 -06:00
peterr 4ee98ff5fa Add Code for Day 10
Day 10: The Stars Align
2018-12-13 09:01:27 -06:00
peterr cb807de984 Add code for Day 9
Day 9: Marble Mania
2018-12-11 21:25:58 -06:00
peterr 96d9683eb2 Add code for Day 8
Day 8: Memory Maneuver
2018-12-09 18:56:35 -06:00
peterr 200555b6cb Finish Day 7 2018-12-08 16:23:10 -06:00
19 changed files with 7556 additions and 33 deletions
File diff suppressed because one or more lines are too long
+347
View File
@@ -0,0 +1,347 @@
position=< 10253, -50152> velocity=<-1, 5>
position=< 20314, 40332> velocity=<-2, -4>
position=<-19881, -30049> velocity=< 2, 3>
position=<-29940, 10166> velocity=< 3, -1>
position=<-40022, -40103> velocity=< 4, 4>
position=< 30403, 20217> velocity=<-3, -2>
position=< 20330, 10172> velocity=<-2, -1>
position=< 30397, -40102> velocity=<-3, 4>
position=< 10305, -50152> velocity=<-1, 5>
position=< 20347, 10167> velocity=<-2, -1>
position=< 30389, 50381> velocity=<-3, -5>
position=< 50485, -40103> velocity=<-5, 4>
position=< -9840, 40325> velocity=< 1, -4>
position=<-29951, 20217> velocity=< 3, -2>
position=< 40441, -30053> velocity=<-4, 3>
position=<-19906, 20217> velocity=< 2, -2>
position=< 40443, -50153> velocity=<-4, 5>
position=< 40446, -19991> velocity=<-4, 2>
position=< 30378, 40325> velocity=<-3, -4>
position=< 20359, 20226> velocity=<-2, -2>
position=<-50072, -30046> velocity=< 5, 3>
position=< 30370, 30271> velocity=<-3, -3>
position=< -9854, 20226> velocity=< 1, -2>
position=<-29948, 10168> velocity=< 3, -1>
position=<-19886, 50388> velocity=< 2, -5>
position=<-50062, 20222> velocity=< 5, -2>
position=<-29921, 30271> velocity=< 3, -3>
position=<-29929, 30276> velocity=< 3, -3>
position=< 30408, -30051> velocity=<-3, 3>
position=< 40422, -40099> velocity=<-4, 4>
position=<-50047, -9940> velocity=< 5, 1>
position=< 30392, -19995> velocity=<-3, 2>
position=<-39967, -40098> velocity=< 4, 4>
position=< 30371, 30275> velocity=<-3, -3>
position=<-19902, -30045> velocity=< 2, 3>
position=< 30388, 50380> velocity=<-3, -5>
position=< 30352, 10169> velocity=<-3, -1>
position=<-29940, 40333> velocity=< 3, -4>
position=<-50069, 30280> velocity=< 5, -3>
position=<-39978, 10168> velocity=< 4, -1>
position=<-39968, -9941> velocity=< 4, 1>
position=<-19918, -40102> velocity=< 2, 4>
position=< 10289, -50156> velocity=<-1, 5>
position=< 40419, -50161> velocity=<-4, 5>
position=<-50059, -40106> velocity=< 5, 4>
position=< 10281, -50157> velocity=<-1, 5>
position=< 40454, 50386> velocity=<-4, -5>
position=< 20298, -30044> velocity=<-2, 3>
position=< -9839, -9945> velocity=< 1, 1>
position=<-19858, 30271> velocity=< 2, -3>
position=<-50040, 40334> velocity=< 5, -4>
position=< -9819, -9936> velocity=< 1, 1>
position=< 10292, -30049> velocity=<-1, 3>
position=< 30409, 30271> velocity=<-3, -3>
position=< 40443, 30276> velocity=<-4, -3>
position=<-19918, -50157> velocity=< 2, 5>
position=< 10289, 30273> velocity=<-1, -3>
position=<-29914, 50388> velocity=< 3, -5>
position=< 20349, 50383> velocity=<-2, -5>
position=<-39969, -50161> velocity=< 4, 5>
position=< 50484, -40101> velocity=<-5, 4>
position=<-29931, 40330> velocity=< 3, -4>
position=< 50486, -50152> velocity=<-5, 5>
position=< 50508, 40327> velocity=<-5, -4>
position=< 30393, -50160> velocity=<-3, 5>
position=< 50464, -19990> velocity=<-5, 2>
position=< 30392, 50381> velocity=<-3, -5>
position=<-29915, -30044> velocity=< 3, 3>
position=< 50496, 30276> velocity=<-5, -3>
position=< 30370, 30280> velocity=<-3, -3>
position=< 40417, 10163> velocity=<-4, -1>
position=< 10264, 30271> velocity=<-1, -3>
position=< 30364, 40329> velocity=<-3, -4>
position=< -9819, -40099> velocity=< 1, 4>
position=< -9837, -50157> velocity=< 1, 5>
position=< 50496, -40102> velocity=<-5, 4>
position=<-39989, 10172> velocity=< 4, -1>
position=< 20330, -40098> velocity=<-2, 4>
position=<-50048, 20220> velocity=< 5, -2>
position=< 10246, 30275> velocity=<-1, -3>
position=< 10304, 20226> velocity=<-1, -2>
position=<-40023, 10172> velocity=< 4, -1>
position=<-19858, -50157> velocity=< 2, 5>
position=< 30400, 50380> velocity=<-3, -5>
position=<-40006, 50382> velocity=< 4, -5>
position=< 50497, 50382> velocity=<-5, -5>
position=< 30400, 20226> velocity=<-3, -2>
position=< -9861, -19999> velocity=< 1, 2>
position=<-29916, 10165> velocity=< 3, -1>
position=< 40409, 20221> velocity=<-4, -2>
position=<-40015, 30280> velocity=< 4, -3>
position=< 50494, -19999> velocity=<-5, 2>
position=< 10268, 40326> velocity=<-1, -4>
position=< -9821, 20217> velocity=< 1, -2>
position=<-29940, -30047> velocity=< 3, 3>
position=<-19870, 20221> velocity=< 2, -2>
position=< 20346, 20220> velocity=<-2, -2>
position=< 40456, -40103> velocity=<-4, 4>
position=<-19893, 10172> velocity=< 2, -1>
position=<-29960, -19993> velocity=< 3, 2>
position=<-50036, 30276> velocity=< 5, -3>
position=< -9840, -30046> velocity=< 1, 3>
position=<-19906, 20220> velocity=< 2, -2>
position=<-19860, 20217> velocity=< 2, -2>
position=<-29916, -40106> velocity=< 3, 4>
position=<-50061, -9936> velocity=< 5, 1>
position=<-29972, 30277> velocity=< 3, -3>
position=<-50048, -40104> velocity=< 5, 4>
position=< 20354, 20224> velocity=<-2, -2>
position=<-19866, 50383> velocity=< 2, -5>
position=< -9855, 20226> velocity=< 1, -2>
position=<-40023, -50152> velocity=< 4, 5>
position=< 10245, -50161> velocity=<-1, 5>
position=<-39997, -19999> velocity=< 4, 2>
position=< -9840, -19991> velocity=< 1, 2>
position=< 30394, 50379> velocity=<-3, -5>
position=< 20318, -50161> velocity=<-2, 5>
position=<-50024, 50379> velocity=< 5, -5>
position=<-29972, -50159> velocity=< 3, 5>
position=<-19878, 10168> velocity=< 2, -1>
position=< 30368, 10163> velocity=<-3, -1>
position=< 30371, 20226> velocity=<-3, -2>
position=<-19873, 50383> velocity=< 2, -5>
position=< 20351, 10164> velocity=<-2, -1>
position=< 40433, -9945> velocity=<-4, 1>
position=< 10248, 50379> velocity=<-1, -5>
position=<-50072, -9937> velocity=< 5, 1>
position=<-29960, -9938> velocity=< 3, 1>
position=< 50468, -30045> velocity=<-5, 3>
position=<-50024, 20224> velocity=< 5, -2>
position=< 50484, -9944> velocity=<-5, 1>
position=< 40451, 10165> velocity=<-4, -1>
position=< 40422, -19992> velocity=<-4, 2>
position=<-19886, 50387> velocity=< 2, -5>
position=< 10293, -9941> velocity=<-1, 1>
position=< 40418, -40105> velocity=<-4, 4>
position=< 10304, 50383> velocity=<-1, -5>
position=<-29960, 40330> velocity=< 3, -4>
position=<-39983, 50379> velocity=< 4, -5>
position=< 30389, -30047> velocity=<-3, 3>
position=<-40023, 50379> velocity=< 4, -5>
position=<-29916, 40334> velocity=< 3, -4>
position=<-19918, 30280> velocity=< 2, -3>
position=<-29948, 20221> velocity=< 3, -2>
position=<-39989, -30050> velocity=< 4, 3>
position=< 30394, -50161> velocity=<-3, 5>
position=< -9832, 30278> velocity=< 1, -3>
position=<-29923, 40325> velocity=< 3, -4>
position=< 20319, -40105> velocity=<-2, 4>
position=< 30353, 30275> velocity=<-3, -3>
position=< -9804, -50152> velocity=< 1, 5>
position=<-19905, -9945> velocity=< 2, 1>
position=< -9835, -50152> velocity=< 1, 5>
position=< 40406, 40326> velocity=<-4, -4>
position=< 50508, 10163> velocity=<-5, -1>
position=<-19865, 10165> velocity=< 2, -1>
position=< 10276, -50157> velocity=<-1, 5>
position=<-19870, -19996> velocity=< 2, 2>
position=<-19870, 30280> velocity=< 2, -3>
position=<-39970, 40332> velocity=< 4, -4>
position=< 40462, 50383> velocity=<-4, -5>
position=< 40451, 10170> velocity=<-4, -1>
position=< 40451, 50385> velocity=<-4, -5>
position=<-29924, 30279> velocity=< 3, -3>
position=< 30397, 30280> velocity=<-3, -3>
position=<-40014, 50380> velocity=< 4, -5>
position=<-19858, 50388> velocity=< 2, -5>
position=<-29927, 50387> velocity=< 3, -5>
position=<-29924, 40330> velocity=< 3, -4>
position=<-19918, -9940> velocity=< 2, 1>
position=< 50484, -19991> velocity=<-5, 2>
position=< 40432, -19999> velocity=<-4, 2>
position=<-50072, -9937> velocity=< 5, 1>
position=< 30396, -9944> velocity=<-3, 1>
position=<-19885, -50160> velocity=< 2, 5>
position=< 10273, -9936> velocity=<-1, 1>
position=< 50484, -9940> velocity=<-5, 1>
position=<-40002, 20226> velocity=< 4, -2>
position=<-50045, -50161> velocity=< 5, 5>
position=<-29960, 50385> velocity=< 3, -5>
position=<-29972, 20219> velocity=< 3, -2>
position=< -9837, -9945> velocity=< 1, 1>
position=< 30408, -50161> velocity=<-3, 5>
position=< 20298, -19997> velocity=<-2, 2>
position=<-39985, 10168> velocity=< 4, -1>
position=< 50496, 30272> velocity=<-5, -3>
position=<-29927, -50157> velocity=< 3, 5>
position=<-50076, 50383> velocity=< 5, -5>
position=< 30369, -9945> velocity=<-3, 1>
position=< 50517, 40334> velocity=<-5, -4>
position=<-29946, 10167> velocity=< 3, -1>
position=< 30368, -50161> velocity=<-3, 5>
position=< 50476, 30280> velocity=<-5, -3>
position=< 30373, -30044> velocity=<-3, 3>
position=< 10244, 50382> velocity=<-1, -5>
position=< 40418, 10167> velocity=<-4, -1>
position=<-50048, 50384> velocity=< 5, -5>
position=< 50487, -40103> velocity=<-5, 4>
position=< -9863, -19990> velocity=< 1, 2>
position=< -9836, 30280> velocity=< 1, -3>
position=<-50028, -19995> velocity=< 5, 2>
position=<-29944, -19990> velocity=< 3, 2>
position=< 20333, -9945> velocity=<-2, 1>
position=<-50024, 10166> velocity=< 5, -1>
position=<-40002, -40104> velocity=< 4, 4>
position=< 40424, -40102> velocity=<-4, 4>
position=< 10300, -9944> velocity=<-1, 1>
position=< -9864, 20218> velocity=< 1, -2>
position=<-50043, 20225> velocity=< 5, -2>
position=<-40006, -50158> velocity=< 4, 5>
position=<-50078, 30280> velocity=< 5, -3>
position=< 20318, 40334> velocity=<-2, -4>
position=< 40410, -9936> velocity=<-4, 1>
position=<-29955, -30047> velocity=< 3, 3>
position=<-50022, 30280> velocity=< 5, -3>
position=<-19894, 10165> velocity=< 2, -1>
position=<-19865, 50382> velocity=< 2, -5>
position=<-29924, 50388> velocity=< 3, -5>
position=<-39981, 50387> velocity=< 4, -5>
position=< 40407, 50388> velocity=<-4, -5>
position=<-29924, -40100> velocity=< 3, 4>
position=< -9816, -30049> velocity=< 1, 3>
position=<-50044, 10168> velocity=< 5, -1>
position=< 50493, 40326> velocity=<-5, -4>
position=< 30402, -9941> velocity=<-3, 1>
position=<-50043, 30277> velocity=< 5, -3>
position=< 50516, 30280> velocity=<-5, -3>
position=<-29972, -50157> velocity=< 3, 5>
position=< 40454, -30048> velocity=<-4, 3>
position=< -9853, -9936> velocity=< 1, 1>
position=< 40450, -19998> velocity=<-4, 2>
position=< 30355, 30280> velocity=<-3, -3>
position=<-39975, 30275> velocity=< 4, -3>
position=< 50516, 30277> velocity=<-5, -3>
position=< 40463, -50157> velocity=<-4, 5>
position=< 50497, 30276> velocity=<-5, -3>
position=<-29920, -9945> velocity=< 3, 1>
position=< 30393, -9944> velocity=<-3, 1>
position=< 30372, -19996> velocity=<-3, 2>
position=< 20324, -40103> velocity=<-2, 4>
position=< 40459, 30274> velocity=<-4, -3>
position=< 10268, 50387> velocity=<-1, -5>
position=<-50035, 20220> velocity=< 5, -2>
position=<-29927, 50386> velocity=< 3, -5>
position=<-50037, -30048> velocity=< 5, 3>
position=< 20346, 30273> velocity=<-2, -3>
position=< 40463, 10172> velocity=<-4, -1>
position=< 50465, -40098> velocity=<-5, 4>
position=<-19870, 10164> velocity=< 2, -1>
position=< 30354, -50157> velocity=<-3, 5>
position=< 30404, -19995> velocity=<-3, 2>
position=<-50036, -50160> velocity=< 5, 5>
position=< -9811, -9942> velocity=< 1, 1>
position=<-19897, -40098> velocity=< 2, 4>
position=<-19869, -19999> velocity=< 2, 2>
position=<-19901, 40325> velocity=< 2, -4>
position=<-19890, 30271> velocity=< 2, -3>
position=< 30379, -9941> velocity=<-3, 1>
position=< 40443, 20223> velocity=<-4, -2>
position=< 40416, 30280> velocity=<-4, -3>
position=< 40462, -50161> velocity=<-4, 5>
position=<-50061, 30271> velocity=< 5, -3>
position=<-19901, -30044> velocity=< 2, 3>
position=< 40407, -50152> velocity=<-4, 5>
position=<-39986, 20223> velocity=< 4, -2>
position=<-29927, -30051> velocity=< 3, 3>
position=< -9824, 50381> velocity=< 1, -5>
position=< 50519, 30280> velocity=<-5, -3>
position=< -9816, 30274> velocity=< 1, -3>
position=<-39989, -9942> velocity=< 4, 1>
position=<-29916, 10169> velocity=< 3, -1>
position=< 40440, 40330> velocity=<-4, -4>
position=< 20325, 50388> velocity=<-2, -5>
position=< -9839, 20221> velocity=< 1, -2>
position=<-19860, 20217> velocity=< 2, -2>
position=<-40014, -9937> velocity=< 4, 1>
position=< 50516, 30273> velocity=<-5, -3>
position=<-40014, -50153> velocity=< 4, 5>
position=< 30397, -19992> velocity=<-3, 2>
position=< 20338, -19992> velocity=<-2, 2>
position=< 20310, 30271> velocity=<-2, -3>
position=< 10272, 10163> velocity=<-1, -1>
position=<-39998, -40103> velocity=< 4, 4>
position=< 40454, 40332> velocity=<-4, -4>
position=<-29945, 50379> velocity=< 3, -5>
position=<-40014, 40328> velocity=< 4, -4>
position=< 50508, -40106> velocity=<-5, 4>
position=< 40438, 10170> velocity=<-4, -1>
position=< 10304, -9945> velocity=<-1, 1>
position=< 20338, 40331> velocity=<-2, -4>
position=<-19907, -19999> velocity=< 2, 2>
position=<-19915, -19999> velocity=< 2, 2>
position=<-29932, 40328> velocity=< 3, -4>
position=< 50520, 40329> velocity=<-5, -4>
position=< 20298, 10171> velocity=<-2, -1>
position=<-40007, -30044> velocity=< 4, 3>
position=< 30377, -30044> velocity=<-3, 3>
position=<-29972, 30276> velocity=< 3, -3>
position=< 10287, -30053> velocity=<-1, 3>
position=< 20330, 20225> velocity=<-2, -2>
position=<-50068, 20224> velocity=< 5, -2>
position=< 30352, 20220> velocity=<-3, -2>
position=< 40458, 50379> velocity=<-4, -5>
position=< 30352, -9941> velocity=<-3, 1>
position=<-29972, 50386> velocity=< 3, -5>
position=<-50059, -40106> velocity=< 5, 4>
position=<-50076, 10172> velocity=< 5, -1>
position=< 10268, -9942> velocity=<-1, 1>
position=< 30408, 50383> velocity=<-3, -5>
position=<-40024, -40107> velocity=< 4, 4>
position=< 50495, -50156> velocity=<-5, 5>
position=<-39984, 50384> velocity=< 4, -5>
position=< -9805, -9945> velocity=< 1, 1>
position=< 50460, -30050> velocity=<-5, 3>
position=< 30364, -30050> velocity=<-3, 3>
position=< 40432, -30053> velocity=<-4, 3>
position=< 10300, 50382> velocity=<-1, -5>
position=< 30364, -30047> velocity=<-3, 3>
position=<-19868, -40107> velocity=< 2, 4>
position=<-39976, 40329> velocity=< 4, -4>
position=<-29960, 40325> velocity=< 3, -4>
position=< 30392, -50156> velocity=<-3, 5>
position=< 10284, 50383> velocity=<-1, -5>
position=< 50509, -9945> velocity=<-5, 1>
position=<-29972, -30053> velocity=< 3, 3>
position=< 40424, -19994> velocity=<-4, 2>
position=<-40021, 20217> velocity=< 4, -2>
position=<-50045, 50384> velocity=< 5, -5>
position=< 10249, -30053> velocity=<-1, 3>
position=< 20322, 10170> velocity=<-2, -1>
position=< 20322, 10164> velocity=<-2, -1>
position=<-50043, -30045> velocity=< 5, 3>
position=< 30408, -19991> velocity=<-3, 2>
position=<-29928, 50384> velocity=< 3, -5>
position=< 10284, 30279> velocity=<-1, -3>
position=< 40440, 20222> velocity=<-4, -2>
position=< 20335, -9938> velocity=<-2, 1>
position=<-19857, -19999> velocity=< 2, 2>
position=<-40026, 50386> velocity=< 4, -5>
position=<-40021, 10163> velocity=< 4, -1>
position=< 30371, -50157> velocity=<-3, 5>
position=< 50500, -40104> velocity=<-5, 4>
position=<-29916, -19994> velocity=< 3, 2>
position=<-29924, 20223> velocity=< 3, -2>
position=<-39970, 20218> velocity=< 4, -2>
position=< 40465, 50383> velocity=<-4, -5>
position=<-29940, 40327> velocity=< 3, -4>
+150
View File
@@ -0,0 +1,150 @@
/----------------------\ /--------------------------\
| /+------------------------------------------------------------------------------+-------------\ |
| /--++--------------------------------------------------------\ | | |
| | /++--------------------------------------------------------+---------------------+-------\ | |
| /----------------+-+++--------\ /---------------------------------------------+---------------------+\ | | |
| | | ||| | | /+---------------------++------+-----+-----------\|
/----+-+-\ | ||| | | /----------------------------++---------------------++---\ | | ||
| | | |/-------------+-+++--------+-+---------------+--->------------------------++--\ /------------++---+--+-----+---------\ ||
| | | || /-------+-+++--------+-+---------------+----------------------------++--+-----+-----\ || | | | | ||
/+----+-+-++-----+-------+-+++--------+-+---------------+----------------------------++--+--\ | | || | | | | ||
|| |/+-++-----+-------+-+++--------+-+---------------+----------------------------++--+--+--+-----+-\ || | | | | ||
/-----++----+++\|| | | ||| | | | || | | | | | || | | /--+---------+-++----\
| || |||||| | | ||| | | /--+----------------------------++--+--+--+-----+-+----++---+--+--+--+------\ | || |
| || |||||| | | ||| | | /--------+\ | /---------------------++--+--+--+-----+-+----++---+--+--+--+------+--+-++---\|
| || ||||||/----+-------+-+++--------+-+---+--------++-+------+---------------------++--+--+--+-----+-+----++---+\ | | | | | || ||
| || |||||||/---+-------+-+++--------+-+---+--------++-+------+----------------\ || | | | | | || || | | | | | || ||
| || |||||||| | | ||| | | | || | | | || | | | | | /-++---++-+--+--+------+--+-++-\ ||
| /--++----++++++++---+-------+-+++--\ /-+-+---+--------++-+------+----------------+----++--+--+\ | | | | || || | | | | | || | ||
/+--+--++----++++++++---+-------+-+++--+---+-+-+---+--------++-+------+----------------+-\ || | || | | | | || || | | | | | || | ||
|| | || |||||||| | | ||| | | | | | || | | | | ||/-+--++-+-----+-+--+-++\ || | | | | | || | ||
|| | || |||||||| | | ||| | | | | | || | | /--------+-+--+++-+--++\| | | | ||| || | | | | | || | ||
|| | || |||||||| | | ||| | | | | | || | | | | | ||| | |||| | | | ||| || | | | | | || | ||
|| | || |||||^|| \-------+-+++--+---+-+-+---+--------++-+------+-------+--------+-+--+++-+--++++-----/ | | ||| || | | | | | || | ||
|| | \+-<--++++++++-----------+-+++--+---+-+-+---+--------++-+------+-------+--------+-+--+++-+--/||| | | ||| || | | | | | || | ||
|| | | |||||||| /----+-+++--+---+-+-+---+--------++-+----\ | | | | ||| | |||/------+--+-+++--++-+--+--+------+--+\|| | ||
|| | | |||||||| | | |||/-+---+-+-+---+--------++-+----+-+-------+--------+-+--+++-+---++++------+--+-+++--++-+--+--+------+-\|||| | ||
|| | | |||||||| | | |||| | /+-+-+---+--------++-+----+-+-------+--------+-+--+++-+---++++------+--+-+++--++-+--+--+--\ | ||||| | ||
|| | | |||||||| | | \+++-+--++-+-+---+--------++-+----+-+-------+--------+-+--+++-+---++++------+--+-+++--++-/ | | | | ||||| | ||
|| | | |||||||| | | ||| |/-++-+-+---+--------++-+----+\| | | | ||| | |||| | | ||| || | | | | ||||| | ||
|| |/--+----++++++++---->-+----+--+++-++-++-+-+---+--------++-+---\||| | | | ||| | |||| |/-+-+++--++----+--+\ | | ||||| | ||
|| || | |||||||| /+----+--+++-++-++-+-+---+--------++-+---++++-------+--------+-+--+++-+---++++------++-+-+++--++---\| || | | ||||| | ||
|| || | |||||||| || | /+++-++-++\| | | || ^ |||| | | | ||| | ||||/-----++-+-+++--++---++--++-+---+\||||| | ||
|| || |/---++++++++-----++----+-++++-++-++++-+---+--------++-+---++++-------+--------+-+--+++-+\/-+++++-----++-+-+++--++---++\ || | ||||||| | ||
|| || || |||||||| || | |||| || |||| | | || | |||| | | | ||| ||| ||||| || | ||| || ||| || | ||||||| | ||
|| || || |||||||| || | |||| || ||||/+---+--------++-+---++++-------+--------+-+\ ||| ||| ||||| || | ||| || ||| || | ||||||| | ||
|| || /++---++++++++-----++----+-++++-++-++++++---+--------++-+---++++-------+--------+-++-+++-+++-+++++\ || | ||| || ||| || | ||||||| | ||
|| || ||| |||||||| || |/++++-++-++++++---+--------++\| |||| | |/++-+++-+++-++++++--\ || | ||| || ||| || | ||||||| | ||
|| || ||| |||||||| || |||||| || |||||| | |||| |||| \--------++++-+++-+++-+/|||| | || | ||| || ||| || | ||||||| | ||
|\--++-+++---+++/|||| || |||||| || |||||| | |||| |||| /--------------++++-+++-+++-+-++++--+-++-+-+++--++---+++-++-+\ ||||||| | ||
| \+-+++---+++-++++-----++----++++++-/| |||||| | |||| |||| | |||| ||| ||| | |||| | || | ||| || ||| || || ||||||| | ||
| | ||| ||| |||| || |||||| /+-++++++---+--------++++---++++-+--------------++++-+++-+++-+-++++--+\|| | ||| || ||| || || ||||||| | ||
| | ||| |\+-++++-----++----++++++-++-++++++---+--------++++---++++-+--------------++++-+++-+++-+-++++--++/| | ||| || ||| || || ||||||| | ||
| | ||| | | |||| ||/---++++++-++-++++++---+--------++++---++++-+------------\ |||| ||| ||| | ||\+--++-+-+-+++--++---+++-++-++--+/||||| | ||
| | ||| | | |||| ||| |||||| || |||||| | /------++++---++++-+------------+-++++-+++-+++-+-++-+--++-+-+-+++--++--\||| || || | ||||| | ||
/+----+-+++---+\| |||| ||| |||||| || |||||| | | |||| |||| | | |||| ||| ||| | |\-+--++-+-+-+++--++--++++-++-++--+-++/|| | ||
|| | ||| ||| |||| ||| |||||| || |||||| \-+------+/|\---++++-+------------+-++++-+++-+++-+-+--+--++-+-+-+++--/| |||| || || | || || | ||
|| /-+-+++---+++-++++-\ ||| |||||| |\-++++++-----+------+-+----++/| | /----+-++++-+++-+++-+-+--+--++-+-+\||| | |||| || || | || || | ||
|| | | ||| ||| |||| | ||| |||||| | ||||\+-----+------+-+----++-+-+-------+----+-+++/ ||| ||| | |/-+--++-+-+++++--\| |||| || || | || || | ||
|| | | ||| ||| |||| | ||| |||||| | |||| | | | | || | | | | ||| ||| ||| | || | || | ||||| || |||| || || | || || | ||
|| |/+-+++---+++-++++-+---+++---++++++-+--++++-+-----+------+-+----++-+-+-------+---\| ||| ||\-+++-+-++-+--++-+-++++/ || |||| || || | || || | ||
|| ||| ||\---+++-++++-+---+++---++++++-+--++++-+-----+------+-+----++-+-+-------+---++-+++--++--+/| | \+-+--++-+-++++---++--++++-++-++--+-+/ || | ||
|| ||| ||/---+++-++++-+---+++---++++++-+--++++-+-----+------+-+----++-+-+-----<-+---++-+++--++-\| | | | | || | ||\+---++--++++-++-++--+-+--+/ | ||
|| ||| ||| ||| |||| | ||| |||||| | |||| | | | | || | | | || ||| ||/++-+-+--+-+--++-+-++-+---++\ |||| || || | | | | ||
|| ||| ||| \++-++++-+---+++---++++/| | ||||/+-<---+------+-+----++-+-+-------+---++-+++--+++++-+\| | | || | || | ||| |||| || || | | | | ||
|| ||| ||| || |||| | ||| |||| | | |||||| | | | /-++-+-+-------+---++-+++--+++++-+++--+-+-\|| | || | ||| |||| || || | | | | ||
|| ||| ||| || |||| | ||| |||| | | |||||| | | | | || | | | || |\+--+++++-+++--+-+-+/|/+-++-+---+++-++++-++-++--+-+\ | | ||
|| ||| ||| || |||| | ||| |||| | | |||||| | | | | || | | ^ || | | ||||| ||| | | | ||| || | ||| |||| || || | || | | ||
|| ||| ||| || |||| | ||| |||| | | |||||| /--+------+-+--+-++-+-+-------+---++-+-+--+++++-+++--+-+-+-+++-++-+---+++-++++-++-++\ | || | | ||
|| ||| ||| || |||| | ||| |||| | | |||||| | | | | | || | | \---++-+-+--+++++-+++--+-+-+-+++-+/ | ||| |||| || ||| | || | | ||
|\--+++-+++----++-++++-+---+++---++++-+-+--++++++--+--+------+-+--+-++-+-+-----------++-+-/ ||||| ||| | | | ||| | | ||| |||| || ||| | || | | ||
| ||| ||| || |||| | ||| |||| | | |||||| | /+------+\| | || | | || | ||||| ||| | | | ||| | | ||| |||| || ||| | || | | ||
| ||| ||| || |||| | ||| |||| | | |||||| | || ||| | || | |/----------++-+----+++++-+++--+-+-+-+++-+--+---+++-++++-++\||| | || | | ||
| ||\-+++----++-++++-+---+++---++++-+-+--++++++--+-++------+++--+-/| | || || | ||||| ||| | | | |||/+--+---+++-++++-++++++-+-++-+--+\||
|/--++--+++----++-++++-+\ ||| |||| | |/-++++++--+-++------+++--+--+-+-++----------++-+----+++++-+++--+-+-+-+++++--+---+++-++++<++++++-+-++-+\ ||||
|| || ||| /-++-++++-++--+++---++++-+-++-++++++--+-++------+++--+--+-+-++----------++-+----+++++-+++--+-+-+-+++++--+\ ||| |||| |||||| | || || ||||
|| || ||| | || ||||/++--+++---++++-+-++-++++++--+-++------+++--+--+-+-++----------++-+----+++++-+++--+-+-+\||||| || ||| |||| |||||| | || || ||||
||/-++--+++--+-++-+++++++--+++---++++-+\|| |||||\--+-++------+++--+--+-+-++----------++-+----+++++-+++--+-+-+++++++--/| ||| |||| |||||| | || || ||||
||| || ||| | || ||||||| ||| |||| |||| ||||| /-+-++------+++--+--+-+-++--------\ || | ||||| ||| | | ||||||| /+--+++-++++-++++++-+-++-++\||||
||| || ||| | || ||||||| ||| |||| |||| ||||| | | || ||| | | | || | || | ||||| ||| | | ||||||| || ||| |||| |||||| | || |||||||
||| || ||| | || ||||||| |\+---++++-++++-+++++-+-+-++------+++--+--/ | || /---+-++-+----+++++-+++--+-+-+++++++--++--+++-++++\|||||| | || |||||||
||| || ||| | || ||\++++--+-+---++++-++++-+++++-+-+-++------+++--+----+-++----+---+-++-+----+++++-+++--+-+-+++++++--++--+/| ||||||||||| | || |||||||
||| || ||| | || || |||| | | |||| |||| \++++-+-+-++------+++--+----+-++----+---+-++-+----+++++-+++--+-+-+++++++--++--+-+-++++++++/|| | || |||||||
||| || ||| | || || |v|| | | /++++-++++--++++-+-+-++------+++--+----+-++-\ | | || | ||||| ||| | | ||||||| || | | |||||||| || | || |||||||
||v || /+++--+-++-++-++++--+-+--+++++-++++--++++-+-+-++------+++--+----+-++-+--+---+-++-+----+++++-+++--+-+\||||||| || | | |||||||| || | || |||||||
||| || |||| | || || |||| | | ||||| |||| |||| | | || ||| |/---+-++-+-\| | || | ||||| ||| | ||||||||| || | | |||||||| || | || |||||||
||| || |||| | || || |||| | | ||||| |||| |||| | | || ||| || | || | ||/--+-++-+----+++++-+++--+-+++++++++\ || | | |||||||| || | || |||||||
||| || |||| | || || |||| | | |||\+-++++--+/|| | | || ||| || \-++-+-+++--+-++-+----+++++-+++--+-++++++++++-++--+-+-++++++++-++-+-++-+++++/|
||| || |||| | || || |||| | | ||| | |||| | || | | || ||| || || | ||| | || | ||||| ||| | |||||||||| \+--+-+-++++++++-++-+-++-++/|| |
||| || |||| \-++-++-++++--+-+--+++-+-++++--+-++-+-+-++------+++--++-----++-+-+++--+-++-+----+++++-+++--+-++++++++++--/ | | ||\+++++-++-+-++-++-++-/
||| || |||| || || |||| | | ||| | \+++--+-++-+-+-++------+++--++-----++-+-+++--+-++-+----+++++-+++--+-++++++++++-----+-+-++-+++++-++-+-/| || ||
||| || |||| ||/++-++++--+-+--+++-+--+++--+-++-+-+-++------+++--++-----++-+-+++--+-++-+----+++++-+++--+-++++++++++-----+-+\|| ||||| || | | || ||
||| || |||\----+++++-++++--+-+--+++-+--+++--+-++-+-+-++------+++--++-----++-+-+++--+-++-+----+++/| ||| | |||||||||| | |||| ||||| || | | || ||
||| || ||| ||||| |||| | | ||| | ||| | || | | || ||| || || | ||| | || | ||| | ||| \-++++++++++-----/ |||| ||||| || | | || ||
|\+-++-+++-----+++++-+++/ | | ||| | ||\--+-++-+-+-++------+++--++-----++-+-+++--+-++-+----+++-+-+++----++++++++++-------++++-+++++-++-+--+-+/ ||
| | || ||| ||||| ||| | | ||| | || | || | | || ||| || || | |||/-+-++-+----+++-+-+++----++++++++++-------++++-+++++-++-+\ | | ||
| | || ||| ||||| ||| /-+-+--+++-+--++\ | || | | || /----+++--++-----++-+-++++-+-++-+----+++-+-+++----++++++++++-------++++-+++++-++-++-+-+--++-\
| | || ||| ||||| ||| | | | ||| | ||| | || | | || | ||| || || | |||| | || | \++-+-+++----++++++++++-------++++-+++++-++-++-+-/ || |
| | || ||\-----+++/| ||| | | | ||| | ||| | || | | || | ||| || || | |||| | || | |\-+-+++----++++++++++-------/||| ||||| || || | || |
| | || || /---+++-+-+++-+-+-+--+++-+--+++--+-++-+-+-++-+----+++--++-----++-+-++++-+-++-+-----+--+-+++----++++++++++--\ ||| ||||| || || | || |
\-+-++-++--+---/|| | ||| | | | ||| | ||| | || | | || | ||| || || | |||| | || | | | \++----++++++++++--+-----+++-/|||| || || | || |
| || || | || | ||| | | | ||| | ||| | || | | || | ||| || || | |||| | || | | | || |||||||||| | ||| |||| || || | || |
| || || | \+-+-+++-+-+-+--+++-+--+++--+-/| | | || | ||| || || | |||| | || | | | ||/---++++++++++--+-----+++--++++-++-++-+\ || |
| || || /+-----+-+-+++-+-+-+--+++-+--+++--+--+-+-+-++-+----+++-\|| || | |||| | || | | | ||| |||||||||| | ||| ||^| || || || || |
| || || || | | ||| | | | ||| | ||| | | | | || | ||| ||| || | |||| | || | | | ||| |||||||||| | ||| |||| || || || || |
| || || || | | ||| | | | ||| | ||| | | | | || | ||| ||| || | ||||/+-++-+-----+--+-\||| |||||||||| | ||| |||| || || || || |
/-+-++-++-++-----+-+-+++-+-+-+--+++-+--+++--+--+-+-+-++\| ||| ||| || | |||\++-++-+-----+--+-++++---++++++++++--+-----+++--++++-++-+/ || || |
| | ||/++-++-----+-+-+++-+-+-+--+++-+--+++--+--+-+-+-++++----+++-+++\ || | ||| || || | | | |||| |||||||||| | ||| |||| || | || || |
| | ||||| || | | ||| | |/+--+++-+--+++--+--+-+-+-++++----+++-++++----++-+-+++-++-++-+-----+--+-++++---++++++++++--+-----+++-\|||| || | || || |
| | |||||/++-----+-+-+++\| ||| ||| \--+++--+--+-+-+-++++----+++-++++----++-+-+++-++-++-+-----+--+-++++---++++++++++--+-----+++-++/|| || | || || |
| | |||||||| | | ||||| ||| |\+----+++--+--+-+-+-++++----+++-++++----++-+-+++-++-++-+-----/ | |||| ||||||||\+--+-----+++-++-++-++-+--++---/| |
| | |||||||| | | ||||| ||| | | ||| | | | | |||| ||| |||| || | ||| || || | | |||| |||||||| | | ||| || || || | || | |
| | |||||||| | | ||||| ||| | | ||| | | | | |||| \++-++++--->++-+-+++-++-++-+--------+-++++---++++++++-+--+-----+++-++-++-++-/ || | |
| | |||||||| | | ||||| ||| | | /-+++--+--+-+-+-++++-----++-++++\ || | ||| || || | | |||| |||||||| | | ||| || || || || | |
| | |||||||| | | ||||| ||| | | | ||| | | | | |||| || ||||| || | ||| || || | | |||| |||||||| | | ||| || || || || | |
| | |||||||| | | ||||| ||| \-+--+-+++--+--+-+-+-++++-----++-+++++>--++-/ ||| || || | | |||| |||||||| | | ||| || || || || | |
| | |||||||| | | ||||| ||| /+--+-+++--+--+\| | |||| || ||||| || ||| || || | | |||\---++++++++-+--+-----+++-++-++-++----+/ | |
| \-++++++++-----+-+-+++++-+++---++--+-/|| | ||| | |||| || ||||| /++---+++-++-++-+--------+\||| |||||||| | | ||| || || || | | |
| |||||||| | | ||||| ||| || | || | \++-+-++++-----++-+++++--+++---+++-++-++-+--------+++/| |||||||| | | ||| || || || | | |
| ||||||\+-----+-+-+++++-+++---++--+--++--+---++-+-++++-----++-/|||| ||| ||| || ||/+--------+++-+----++++++++-+--+-----+++-++-++-++----+\ | |
| |||||| | | \-+++++-+++---++--+--++--+---++-+-++++-----++--++++--+++---+++-++-++++--------/|| | ||||||\+-+--+-----+++-++-/|/++----++\ | |
| |||||| | | ||||| ||| || | \+--+---++-+-++++-----++--++++--+++---+++-++-++++---------++-+----++++/| | | | ||| || |||| ||| | |
| |||||| | | ||||| ||| || | | | || | |||| || |||| |\+---+++-++-++++---------++-+----++++-+-+-+--+-----+++-++--++/| ||| | |
| |||||| | /+---+++++-+++---++--+---+--+---++-+-++++-----++--++++--+-+---+++-++-++++---------++-+----++++-+-+-+--+\ ||| || || | ||| | |
| |||||\-+----++---+++/| ||| || | | | || | |||| || |||| | | ||| || |||| || | |||| | | | || ||| || || | ||| | |
| ||||| | /-++---+++-+-+++---++--+---+--+---++-+-++++-----++--++++-\| \---+++-++-++++---------++-+----++++-+-+-+--++----+++-++--/| | ||| | |
| ||||| | | || ||| | ||\---++--+---+--+---++-+-++++-----++--++++-++-----+++-++-+/|| || | /-++++-+-+-+--++----+++-++---+-+----+++-\ | |
| ||||| | | || ||| | || \+--+---+--+---/| | |||| || |||| || ||| || | || || | | |||| | | | || /+++-++---+-+----+++-+-+\|
| ||||| | | || ||| | || | | | | | | |||| || |||| || ||| \+-+-++---------+/ | | |||| | | | || |||| || | | ||| | |||
| ||||| | | || ||| | |\-----+--+---+--+----+-+-++++-----++--++++-++-----+++--+-+-++---------+--+--+-++++-+-+-+--++---++++-/| | | ||| | |||
| ||||| | | || ||| | \------+--+---+--+----+-+-++++-----++--++++-++-----+++--+-+-++---------+--+--+-++++-+-+-+--++---+++/ | | | ||| | |||
| ||||| | | || \++-+--------+--+---+--+----+-+-++++-----++--++++-++-----+++--+-+-+/ | | | |||| |/+-+--++---+++---+--\| | ||| | |||
\---+++++--+--+-++----++-+--------+--+---+--+----+-+-++/| || |||| || ||| | | | | | | |||| ||| | || ||| | || | ||| | |||
||||| | | || || \--------+--+---/ | | | || | || |||| || ||| | | \----------+--+--+-++++-+++-+--++---+++---+--++-+----+/| | |||
||||| | | || /--++----------+--+--\ | | \-++-+-----++--++++-++-----+++--+-+------------+--+--+-++++-+++-+--++---+++---+--++-/ | | | |||
||||| | | || | || | | | \----+---++-+-----++--++++-++-----+++--+-+------------+--/ | |||| ||| | || ||| | || | | | |||
||||| | | || | || | | | | |\-+-----++--++++-++-----+++--+-+------------+-----+-++++-+++-+--++---++/ | || | | | |||
||||| \--+-++-+--++----------+--+--+--------+---+--+-----++--++++-++-----+++--+-+------------+-----+-++++-+++-+--/| || | || | | | |||
|\+++-----+-++-+--++----------+--+--+--------+---+--+-----++--++++-++-----+++--+-/ | | |||| ||| | | || | || | | | |||
| ||| /--+-++-+--++----------+--+--+--------+---+--+-----++--++++-++-----+++\ | | | |||| ||| | | || | || | | | |||
| ||| | | || | || | | | | | \-----++--++++-++-----++++-+--------------+-----+-++++-+++-+---+---++----+--++------+-+-+-++/
| ||| | | || |/-++----------+--+--+--------+---+----\ || |||| || |||| | | | |||| ||| | | || v || | | | ||
| ||| | | || || || | | | \---+----+---++--++++-++-----++++-/ | | |||| ||| | | || | || | | | ||
/--+-+++--+-\| || || || | | | | | || |||| || |||| | | |||| ||| | | || | || | | | ||
| | ||| | || || \+-++----------+->+--/ | | || |\++-++-----/||| | | |||| ||| | | || | || | | | ||
| | ||| | || || | || | | | | || | || || ||| /+-----+-++++-+++-+---+---++----+--++------+-+-+-++\
| | ||\--+-++-++--+-++--->------+--+---------------+----+---++--+-++-++------+++---------------++-----+-/||| ||| | | || | || | | | |||
| | || | || || | || \--+---------------+----+---+/ | || || ||| || | ||| |\+-+---+---++----+--/| | | | |||
| | || | || || | \+-------------+---------------+----+---+---+-++-++------+++---------------++-----+--++/ | | | | || | | | | | |||
| | || | |\-++--+--+-------------+---------------+----+---+---+-++-/| |\+---------------++-----+--++--+-+-/ | || | \------+-/ | |||
| | || | | || | | | | | | | || \------+-+---------------+/ | || | | | || | | | |||
| \-++---+-+--++--+--/ \---------------+----+---+---+-+/ | | | \--++--+-+-----+---++----+----------+---/ |||
| |\---+-+--++--+--------------------------------+----+---+---+-+----------+-+---------------+---------/| | \-----+---++----+----------+-----/||
\----+----+-/ || | \----+---/ | | | | | | | | || | | ||
| | || | | \-+----------+-+---------------+----------/ | | || | | ||
| | \+--+-------------------------------------+---------+----------+-+---------------+-------------+-------/ \+----+----------+------/|
| | \--+-------------------------------------+---------+----------+-+---------------+-------------+------------/ | | |
| \--------+-------------------------------------+---------+----------+-/ | | | | |
| \-------------------------------------/ | \-----------------+-------------+-----------------/ | |
| | | \----------------------------/ |
\-------------------------------------------------------------/ \--------------------------------------------------/
+32
View File
@@ -0,0 +1,32 @@
################################
#########################.G.####
#########################....###
##################.G.........###
##################.##.......####
#################...#.........##
################..............##
######..########...G...#.#....##
#####....######.G.GG..G..##.####
#######.#####G............#.####
#####.........G..G......#...####
#####..G......G..........G....##
######GG......#####........E.###
#######......#######..........##
######...G.G#########........###
######......#########.....E..###
#####.......#########........###
#####....G..#########........###
######.##.#.#########......#####
#######......#######.......#####
#######.......#####....E...#####
##.G..#.##............##.....###
#.....#........###..#.#.....####
#.........E.E...#####.#.#....###
######......#.....###...#.#.E###
#####........##...###..####..###
####...G#.##....E####E.####...##
####.#########....###E.####....#
###...#######.....###E.####....#
####..#######.##.##########...##
####..######################.###
################################
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-13
View File
@@ -4,19 +4,6 @@
import Foundation import Foundation
struct GridPoint: Equatable, Comparable {
var X = 0
var Y = 0
static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
return (lhs.X == rhs.X) && (lhs.Y == rhs.Y)
}
static func < (lhs: GridPoint, rhs: GridPoint) -> Bool {
return (lhs.X + lhs.Y) < (rhs.X + rhs.Y)
}
}
class Coordinates { class Coordinates {
var points: [GridPoint] = [] var points: [GridPoint] = []
var dimensions: GridPoint var dimensions: GridPoint
+195 -15
View File
@@ -17,12 +17,26 @@ struct Instruction: Equatable, Comparable {
} }
} }
struct Worker: Equatable, Comparable {
var job = Character(" ")
var duration = 0
static func == (lhs: Worker, rhs: Worker) -> Bool {
return (lhs.job == rhs.job) && (lhs.duration == rhs.duration)
}
static func < (lhs: Worker, rhs: Worker) -> Bool {
return lhs.duration < rhs.duration
}
}
class SumParts { class SumParts {
var instrList: [Instruction] = [] var instrList: [Instruction] = []
var inventoryComplete: [Character] = [] var workers: [Worker] = []
var masterClock = 0
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt' // Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt'
init(withFile filename: String) { init(withFile filename: String, numWorkers: Int) {
let instrString = Tools.readFile(fromPath: filename) let instrString = Tools.readFile(fromPath: filename)
var instrArray = instrString.components(separatedBy: "\n") var instrArray = instrString.components(separatedBy: "\n")
// This gurd statement is just an excuse to use guard // This gurd statement is just an excuse to use guard
@@ -30,12 +44,14 @@ class SumParts {
guard let lastStr = instrArray.last, lastStr.count == 0 else { return } guard let lastStr = instrArray.last, lastStr.count == 0 else { return }
instrArray.removeLast() // empty string instrArray.removeLast() // empty string
parseData(withInstructions: instrArray) parseData(withInstructions: instrArray)
workers = Array(repeating: Worker(), count: numWorkers)
} }
// Supply test data in the form of a String // Supply test data in the form of a String
init(withString instrString: String) { init(withString instrString: String, numWorkers: Int) {
let instrArray = instrString.components(separatedBy: "\n") let instrArray = instrString.components(separatedBy: "\n")
parseData(withInstructions: instrArray) parseData(withInstructions: instrArray)
workers = Array(repeating: Worker(), count: numWorkers)
} }
func parseData(withInstructions instr: [String]) { func parseData(withInstructions instr: [String]) {
@@ -45,6 +61,7 @@ class SumParts {
} }
func getNextAvailable() -> Character? { func getNextAvailable() -> Character? {
var retVal: Character?
var availDict: [Character : Bool] = [:] var availDict: [Character : Bool] = [:]
for index in 0..<instrList.count { for index in 0..<instrList.count {
if !instrList.contains(where: { $0.before == instrList[index].complete} ) { if !instrList.contains(where: { $0.before == instrList[index].complete} ) {
@@ -53,10 +70,22 @@ class SumParts {
} }
var available = Array(availDict.keys) var available = Array(availDict.keys)
available.sort() available.sort()
return available.first if workers.count == 0 {
retVal = available.first
} else {
// Exclude 'available' if already scheduled to a worker
for job in available {
// if workers.contains(where: { $0.job == job && $0.duration == 0} ) {
if !workers.contains(where: { $0.job == job} ) || workers.contains(where: { $0.job == job && $0.duration == 0} ) {
retVal = job
break
}
}
}
return retVal
} }
func completeInstructions() -> String { func completeAllInstructions() -> String {
var retVal = "" var retVal = ""
var last: Character = "*" var last: Character = "*"
while let instruction = getNextAvailable() { while let instruction = getNextAvailable() {
@@ -69,6 +98,77 @@ class SumParts {
retVal.append(last) retVal.append(last)
return retVal return retVal
} }
func complete(instruction: Character) {
if instrList.count == 1 && instrList[0].complete != " " {
instrList.append(Instruction(complete: instrList[0].before, before: Character(" ")))
}
instrList.removeAll(where: { $0.complete == instruction })
}
//-------------->> Code for Part 2 <<--------------
// We'll cheat here and assume the duration is 1 second + offset for One worker and 60 seconds + offset for more than one
func duration(forInstruction instr: Character) -> Int {
guard let val = instr.ascii else { return -1 }
let offset = Int(val) - 64
return (workers.count > 2) ? 60 + offset : offset
}
// Go through the list of workers and find the min() time-to-finish
func getTimeUntilWorkerFree() -> Int {
guard workers.count > 0 else { return 0 }
let sortedByDuration = workers.sorted(by: { $0.duration < $1.duration })
for worker in sortedByDuration {
if worker.duration != 0 {
return worker.duration
}
}
return 0
}
func advanceTime(by elapsedtime: Int) {
for index in 0..<workers.count {
if workers[index].duration > 0 {
workers[index].duration -= elapsedtime
}
}
masterClock += elapsedtime
}
// subtract XX seconds from the workers time and add that to the master-clock
// Since we advance until worker(s) done, we should complete the tasks finsished by the worker(s)
// return true if more work to do
func advanceClockAndCompleteInstructions() -> Bool {
guard workers.count > 0 else { return false }
let advTime = getTimeUntilWorkerFree()
if advTime == 0 {
let test = workers.contains(where: { $0.duration != 0} )
if !test {
return false
}
}
// subtract this time from all workers
// add this time to the Master-Clock
advanceTime(by: advTime)
// Complete the "finished" worker(s) instruction
for index in 0..<workers.count {
if workers[index].duration == 0 {
complete(instruction: workers[index].job)
}
}
return true
}
// Look for available workers and assign them instructions
func scheduleWorkers() {
for index in 0..<workers.count {
if workers[index].duration == 0 {
guard let job = getNextAvailable() else { return }
workers[index] = Worker(job: job, duration: duration(forInstruction: job))
}
}
}
} }
class Day07: AOCDay { class Day07: AOCDay {
@@ -86,16 +186,16 @@ class Day07: AOCDay {
""" """
func testSumPartsInit() { func testSumPartsInit() {
var instr = SumParts(withString: testData) var instr = SumParts(withString: testData, numWorkers: 0)
XCTAssertEqual(test: "testSumPartsInit string 0", withExpression: (instr.instrList[0].before == "A")) XCTAssertEqual(test: "testSumPartsInit string 0", withExpression: (instr.instrList[0].before == "A"))
XCTAssertEqual(test: "testSumPartsInit string 4", withExpression: (instr.instrList[4].complete == "B")) XCTAssertEqual(test: "testSumPartsInit string 4", withExpression: (instr.instrList[4].complete == "B"))
instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt") instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt", numWorkers: 0)
XCTAssertEqual(test: "testSumPartsInit file 0", withExpression: (instr.instrList[0].before == "X")) XCTAssertEqual(test: "testSumPartsInit file 0", withExpression: (instr.instrList[0].before == "X"))
XCTAssertEqual(test: "testSumPartsInit file 4", withExpression: (instr.instrList[4].complete == "O")) XCTAssertEqual(test: "testSumPartsInit file 4", withExpression: (instr.instrList[4].complete == "O"))
} }
func testGetNextAvailable() { func testGetNextAvailable() {
let instr = SumParts(withString: testData) let instr = SumParts(withString: testData, numWorkers: 0)
if let avail = instr.getNextAvailable() { if let avail = instr.getNextAvailable() {
XCTAssertEqual(test: "testGetNextAvailable", withExpression: (avail == "C")) XCTAssertEqual(test: "testGetNextAvailable", withExpression: (avail == "C"))
} else { } else {
@@ -104,22 +204,102 @@ class Day07: AOCDay {
} }
func testCompleteInstructions() { func testCompleteInstructions() {
let instr = SumParts(withString: testData) let instr = SumParts(withString: testData, numWorkers: 0)
let answer = instr.completeInstructions() let answer = instr.completeAllInstructions()
XCTAssertEqual(test: "testCompleteInstructions", withExpression: (answer == "CABDFE")) XCTAssertEqual(test: "testCompleteInstructions", withExpression: (answer == "CABDFE"))
} }
func testDuration() {
var instr = SumParts(withString: testData, numWorkers: 2)
var dur = instr.duration(forInstruction: "A")
XCTAssertEqual(test: "testDuration 1 worker A", withExpression: (dur == 1))
dur = instr.duration(forInstruction: "K")
XCTAssertEqual(test: "testDuration 1 worker K", withExpression: (dur == 11))
dur = instr.duration(forInstruction: "Z")
XCTAssertEqual(test: "testDuration 1 worker Z", withExpression: (dur == 26))
instr = SumParts(withString: testData, numWorkers: 5)
dur = instr.duration(forInstruction: "A")
XCTAssertEqual(test: "testDuration 5 worker A", withExpression: (dur == 60 + 1))
dur = instr.duration(forInstruction: "K")
XCTAssertEqual(test: "testDuration 5 worker K", withExpression: (dur == 60 + 11))
dur = instr.duration(forInstruction: "Z")
XCTAssertEqual(test: "testDuration 5 worker Z", withExpression: (dur == 60 + 26))
}
// Go through the list of workers and find the min() time-to-finish
func testGetTimeUntilWorkerFree() {
var instr = SumParts(withString: testData, numWorkers: 2)
var time = instr.getTimeUntilWorkerFree()
XCTAssertEqual(test: "testGetTimeUntilWorkerFree 1 worker", withExpression: (time == 0))
instr = SumParts(withString: testData, numWorkers: 5)
time = instr.getTimeUntilWorkerFree()
XCTAssertEqual(test: "testGetTimeUntilWorkerFree 5 workers", withExpression: (time == 0))
}
func testAdvanceTime() {
let instr = SumParts(withString: testData, numWorkers: 2)
let oldClock = instr.masterClock
let oldWorkers = instr.workers
instr.advanceTime(by: 0)
XCTAssertEqual(test: "testAdvanceTime by 0 seconds clock", withExpression: (oldClock == instr.masterClock))
XCTAssertEqual(test: "testAdvanceTime by 0 seconds workers", withExpression: (oldWorkers == instr.workers))
instr.advanceTime(by: 10)
XCTAssertEqual(test: "testAdvanceTime by 10 seconds clock", withExpression: (instr.masterClock == 10))
}
// subtract XX seconds from the workers time and add that to the master-clock
// Since we advance until worker(s) done, we should complete the tasks finsished by the worker(s)
func testAdvanceClockAndCompleteInstructions() {
let instr = SumParts(withString: testData, numWorkers: 2)
let oldWorkers = instr.workers
var done = instr.advanceClockAndCompleteInstructions()
XCTAssertEqual(test: "testAdvanceClockAndCompleteInstructions done=false before first schedule", withExpression: (!done))
XCTAssertEqual(test: "testAdvanceClockAndCompleteInstructions workers unchanged", withExpression: (oldWorkers == instr.workers))
XCTAssertEqual(test: "testAdvanceClockAndCompleteInstructions masterClock unchanged", withExpression: (instr.masterClock == 0))
instr.scheduleWorkers()
done = instr.advanceClockAndCompleteInstructions()
XCTAssertEqual(test: "testAdvanceClockAndCompleteInstructions done=true after first schedule", withExpression: (done))
}
// Look for available workers and assign them instructions
func testScheduleWorkers() {
let instr = SumParts(withString: testData, numWorkers: 2)
let oldWorkers = instr.workers
instr.scheduleWorkers()
XCTAssertEqual(test: "testScheduleWorkers workers changed", withExpression: (oldWorkers != instr.workers))
}
func testAnswerPart2() {
let instr = SumParts(withString: testData, numWorkers: 2)
instr.scheduleWorkers()
while instr.advanceClockAndCompleteInstructions() {
instr.scheduleWorkers()
}
XCTAssertEqual(test: "testAnswerPart2", withExpression: (instr.masterClock == 15))
}
func day07Tests() { func day07Tests() {
testSumPartsInit() testSumPartsInit()
testGetNextAvailable() testGetNextAvailable()
testCompleteInstructions() testCompleteInstructions()
testDuration()
testGetTimeUntilWorkerFree()
testAdvanceTime()
testAdvanceClockAndCompleteInstructions()
testScheduleWorkers()
testAnswerPart2()
} }
func day07Final() { func day07Final() {
let retVal = "None" var instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt", numWorkers: 0)
let instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt") let answerPart1 = instr.completeAllInstructions()
let answer = instr.completeInstructions() instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt", numWorkers: 5)
print("Answer to part 1 is: \(answer)") instr.scheduleWorkers()
print("Answer to part 2 is: \(retVal)") while instr.advanceClockAndCompleteInstructions() {
instr.scheduleWorkers()
}
let answerPart2 = instr.masterClock
print("Answer to part 1 is: \(answerPart1)")
print("Answer to part 2 is: \(answerPart2)")
} }
} }
+169
View File
@@ -0,0 +1,169 @@
//
// Advent of Code 2018 "Day 8: Memory Maneuver"
//
import Foundation
struct Header {
var nChildren = 0
var nMeta = 0
}
struct Node {
var header = Header(nChildren: 0, nMeta: 0)
var children: [Node] = []
var meta: [Int] = []
var length = 2 // Smallest node is only a header with no children or meta data
}
class Maneuver {
var treeData: [Int] = []
var sumMeta = 0
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day08.txt'
init(withFile filename: String) {
let tree = Tools.readFile(fromPath: filename)
let chars = tree.components(separatedBy: " ")
for char in chars {
treeData.append(Int(char) ?? -1)
}
}
// Supply test data in the form of a String
init(withString tree: String) {
let chars = tree.components(separatedBy: " ")
for char in chars {
treeData.append(Int(char) ?? -1)
}
}
// get length of node and sum th meta data for Part 1 as a by-product
func getLength(ofChild childData: ArraySlice<Int>) -> Int {
let nChildren = childData[childData.startIndex]
let nMetaIndex = childData.index(after: childData.startIndex)
let nMeta = childData[nMetaIndex]
var length = 2
if nChildren == 0 {
let start = childData.startIndex + 2
let metaData = Array(childData[start..<start+nMeta])
for meta in metaData {
sumMeta += meta
}
return length + nMeta
} else {
var childIndex = nMetaIndex + 1
for _ in 0..<nChildren {
let childLength = getLength(ofChild: childData[childIndex...])
childIndex += childLength
length += childLength
}
let metaData = Array(childData[childIndex..<childIndex+nMeta])
for meta in metaData {
sumMeta += meta
}
length += nMeta
}
return length
}
func getNode(withChild childData: ArraySlice<Int>) -> Node {
let nChildren = childData[childData.startIndex]
let nMetaIndex = childData.index(after: childData.startIndex)
let nMeta = childData[nMetaIndex]
var metaData: [Int] = []
let children: [Node] = []
var retVal = Node(header: Header(nChildren: nChildren, nMeta: nMeta), children: children, meta: metaData, length: 2)
if nChildren == 0 {
let start = childData.startIndex + 2
metaData = Array(childData[start..<start+nMeta])
} else {
var childIndex = nMetaIndex + 1
for _ in 0..<nChildren {
let childLength = getLength(ofChild: childData[childIndex...])
retVal.children.append(getNode(withChild: childData[childIndex...]))
childIndex += childLength
retVal.length += childLength
}
metaData = Array(childData[childIndex..<childIndex+nMeta])
}
retVal.meta = metaData
retVal.length += nMeta
return retVal
}
func getValue(forNode node: Node) -> Int {
var retVal = 0
if (node.header.nChildren == 0) {
for meta in node.meta {
retVal += meta
}
} else {
for meta in node.meta {
let childIndex = meta - 1
if (0..<node.children.count).contains(childIndex) {
let childNode = node.children[childIndex]
retVal += getValue(forNode: childNode)
}
}
}
return retVal
}
}
class Day08: AOCDay {
lazy var tests: (() -> ()) = day08Tests
lazy var final: (() -> ()) = day08Final
let testData = "2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2"
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
// A----------------16----------------
// B-----5----- C-----6-----
// D-3---
func testManeuverInit() {
var maneu = Maneuver(withString: testData)
XCTAssertEqual(test: "testManeuverInit string", withExpression: (maneu.treeData[3] == 3))
maneu = Maneuver(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day08.txt")
XCTAssertEqual(test: "testManeuverInit file [3]", withExpression: (maneu.treeData[3] == 2))
XCTAssertEqual(test: "testManeuverInit file last", withExpression: (maneu.treeData.last! == 1))
}
func testGetLength() {
let maneu = Maneuver(withString: testData)
let totalLen = maneu.getLength(ofChild: maneu.treeData[0...])
XCTAssertEqual(test: "testGetLength", withExpression: (totalLen == 16))
XCTAssertEqual(test: "testGetLength sum Meta", withExpression: (maneu.sumMeta == 138))
}
func testGetNode() {
let maneu = Maneuver(withString: testData)
let node = maneu.getNode(withChild: maneu.treeData[0...])
XCTAssertEqual(test: "testGetNode", withExpression: (node.length == 16))
}
func testGetValue() {
let maneu = Maneuver(withString: testData)
let node = maneu.getNode(withChild: maneu.treeData[0...])
let value = maneu.getValue(forNode: node)
XCTAssertEqual(test: "testGetValue", withExpression: (value == 66))
}
func day08Tests() {
testManeuverInit()
testGetLength()
testGetNode()
testGetValue()
}
func day08Final() {
var maneu = Maneuver(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day08.txt")
_ = maneu.getLength(ofChild: maneu.treeData[0...])
print("Answer to part 1 is: \(maneu.sumMeta)")
maneu = Maneuver(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day08.txt")
let node = maneu.getNode(withChild: maneu.treeData[0...])
let value = maneu.getValue(forNode: node)
print("Answer to part 2 is: \(value)")
}
}
+187
View File
@@ -0,0 +1,187 @@
//
// Advent of Code 2018 "Day 9: Marble Mania"
//
import Foundation
struct List {
var val = 0
var ptrNext = -1
var ptrPrev = -1
}
class Marble {
var player: [Int] = []
var lastMarble = 0
var circle: [List] = []
var circleCount = 1
var currentMarble = 0
var currentPlayer = 0
var PC = 0
init(numPlayers: Int, lastMarble last: Int) {
circle = Array(repeating: List(), count: last+1)
circleCount = 1
currentMarble = 0
currentPlayer = 0
PC = 0
circle[0].ptrNext = 0
circle[0].ptrPrev = 0
player = Array(repeating: 0, count: numPlayers)
for num in 0...last { circle[num].val = num }
lastMarble = last
}
func insert() {
circle[currentMarble].ptrNext = circle[PC].val
circle[currentMarble].ptrPrev = circle[PC].ptrPrev
circle[circle[PC].ptrPrev].ptrNext = circle[currentMarble].val
circle[PC].ptrPrev = circle[currentMarble].val
PC = currentMarble
circleCount += 1
}
func remove() {
circle[circle[PC].ptrPrev].ptrNext = circle[PC].ptrNext
circle[circle[PC].ptrNext].ptrPrev = circle[PC].ptrPrev
PC = circle[circle[PC].ptrPrev].ptrNext
circleCount -= 1
}
func incrPC() {
PC = circle[PC].ptrNext
}
func incrPC(by n: Int) {
for _ in 0..<n { incrPC() }
}
func decrPC() {
PC = circle[PC].ptrPrev
}
func decrPC(by n: Int) {
for _ in 0..<n { decrPC() }
}
func incrPlayer() {
currentPlayer += 1
if currentPlayer == player.count { currentPlayer = 0 }
}
func placeNextMarble() {
currentMarble += 1
if currentMarble % 23 == 0 {
player[currentPlayer] += currentMarble
decrPC(by: 7)
player[currentPlayer] += circle[PC].val
remove()
} else {
incrPC(by: 2)
insert()
}
incrPlayer()
}
}
class Day09: AOCDay {
lazy var tests: (() -> ()) = day09Tests
lazy var final: (() -> ()) = day09Final
let testData: [(Int, Int, Int)] = [
(9, 25, 32),
(13, 7999, 146373),
(17, 1104, 2764),
(21, 6111, 54718),
(30, 5807, 37305)
]
let finalData = (477, 70851)
func printCircle(circle: [List], withCount circleCount: Int) -> String {
var retVal = ""
var marble = circle[0]
for _ in 0..<circleCount {
retVal += "\(marble.val), "
marble = circle[marble.ptrNext]
}
return retVal
}
func testMarbleInit() {
let marb = Marble(numPlayers: 9, lastMarble: 15)
let result = printCircle(circle: marb.circle, withCount: marb.circleCount)
XCTAssertEqual(test: "testMarbleInit num", withExpression: (marb.player.count == 9))
XCTAssertEqual(test: "testMarbleInit last", withExpression: (marb.lastMarble == 15))
XCTAssertEqual(test: "testMarbleInit result", withExpression: (result == "0, "))
}
func testInsert() {
let marb = Marble(numPlayers: 9, lastMarble: 15)
for _ in 0...3 {
marb.currentMarble += 1
marb.insert()
marb.incrPC(by:2)
}
let result = printCircle(circle: marb.circle, withCount: marb.circleCount)
XCTAssertEqual(test: "testInsert result", withExpression: (result == "0, 4, 2, 1, 3, "))
}
func testRemove() {
let marb = Marble(numPlayers: 9, lastMarble: 15)
for _ in 0...3 {
marb.currentMarble += 1
marb.insert()
marb.incrPC(by:2)
}
marb.decrPC(by: 2)
marb.remove()
let result = printCircle(circle: marb.circle, withCount: marb.circleCount)
XCTAssertEqual(test: "testRemove result", withExpression: (result == "0, 2, 1, 3, "))
}
func testPlaceNextMarble() {
var result = ""
for data in testData {
let marb = Marble(numPlayers: data.0, lastMarble: data.1)
for _ in 0..<marb.lastMarble {
marb.placeNextMarble()
if data == (9, 25, 32) {
result = printCircle(circle: marb.circle, withCount: marb.circleCount)
}
}
let max = marb.player.max() ?? 0
if data == (9, 25, 32) {
XCTAssertEqual(test: "testPlaceMarble result", withExpression: (result == "0, 16, 8, 17, 4, 18, 19, 2, 24, 20, 25, 10, 21, 5, 22, 11, 1, 12, 6, 13, 3, 14, 7, 15, "))
}
XCTAssertEqual(test: "testPlaceMarble \(data)", withExpression: (max == data.2))
}
}
func day09Tests() {
testMarbleInit()
testInsert()
testRemove()
testPlaceNextMarble()
}
func day09Final() {
var marb = Marble(numPlayers: 477, lastMarble: 70851)
for _ in 0..<marb.lastMarble {
marb.placeNextMarble()
}
var max = marb.player.max() ?? 0
print("Answer to part 1 is: \(max)")
marb = Marble(numPlayers: 477, lastMarble: 7085100)
for i in 0..<marb.lastMarble {
marb.placeNextMarble()
if i % 1000000 == 0 { print("\(i)")}
}
max = marb.player.max() ?? 0
print("Answer to part 2 is: \(max)")
}
}
+173
View File
@@ -0,0 +1,173 @@
//
// Advent of Code 2018 "Day 10: The Stars Align"
//
import Foundation
class Align {
var pt: [(Int, Int)] = []
var vel: [(Int, Int)] = []
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day10.txt'
init(withFile filename: String) {
let starFile = Tools.readFile(fromPath: filename)
var starStrings = starFile.components(separatedBy: "\n")
// This gurd statement is just an excuse to use guard
// I'm assuming the last string is an empty string, if not DON'T remove the last string
guard let lastStr = starStrings.last, lastStr.count == 0 else { return }
starStrings.removeLast() // empty string
parseData(withStars: starStrings)
}
// Supply test data in the form of a String
init(withString starFile: String) {
let starStrings = starFile.components(separatedBy: "\n")
parseData(withStars: starStrings)
}
func parseData(withStars starArray: [String]) {
for star in starArray {
var line = star
line = line.replacingOccurrences(of: "position=<", with: "")
line = line.replacingOccurrences(of: "> velocity=<", with: ", ")
line = line.replacingOccurrences(of: ">", with: "")
line = line.replacingOccurrences(of: " ", with: "")
let data = line.components(separatedBy: ",")
guard data.count == 4 else { print("Error"); return }
pt.append((Int(data[0]) ?? 0, Int(data[1]) ?? 0))
vel.append((Int(data[2]) ?? 0, Int(data[3]) ?? 0))
}
}
func advanceTime(by n: Int) -> [(Int, Int)] {
var newpt: [(Int, Int)] = []
for index in 0..<pt.count {
let x = pt[index].0 + vel[index].0 * n
let y = pt[index].1 + vel[index].1 * n
newpt.append((x, y))
}
return newpt
}
func potentialMessage(withGrid grid: [(Int, Int)]) -> Int {
var xs: [Int] = []
var ys: [Int] = []
for point in grid {
xs.append(point.0)
ys.append(point.1)
}
var lineCount = 0
for point in grid {
lineCount += xs.filter{$0 == point.0}.count
lineCount *= ys.filter{$0 == point.1}.count
break
}
if lineCount > 123 {
printGrid(points: grid, minX: xs.min()!, maxX: xs.max()!, minY: ys.min()!, maxY: ys.max()!)
}
return lineCount
}
func printGrid(points: [(Int, Int)], minX: Int, maxX: Int, minY: Int, maxY: Int) {
for j in minY-1...maxY+1 {
for i in minX-1...maxX+1 {
if points.contains(where: { $0.0 == i && $0.1 == j }) {
print("XX", terminator: "")
} else {
print("..", terminator: "")
}
}
print("")
}
}
}
class Day10: AOCDay {
lazy var tests: (() -> ()) = day10Tests
lazy var final: (() -> ()) = day10Final
let testData = """
position=< 9, 1> velocity=< 0, 2>
position=< 7, 0> velocity=<-1, 0>
position=< 3, -2> velocity=<-1, 1>
position=< 6, 10> velocity=<-2, -1>
position=< 2, -4> velocity=< 2, 2>
position=<-6, 10> velocity=< 2, -2>
position=< 1, 8> velocity=< 1, -1>
position=< 1, 7> velocity=< 1, 0>
position=<-3, 11> velocity=< 1, -2>
position=< 7, 6> velocity=<-1, -1>
position=<-2, 3> velocity=< 1, 0>
position=<-4, 3> velocity=< 2, 0>
position=<10, -3> velocity=<-1, 1>
position=< 5, 11> velocity=< 1, -2>
position=< 4, 7> velocity=< 0, -1>
position=< 8, -2> velocity=< 0, 1>
position=<15, 0> velocity=<-2, 0>
position=< 1, 6> velocity=< 1, 0>
position=< 8, 9> velocity=< 0, -1>
position=< 3, 3> velocity=<-1, 1>
position=< 0, 5> velocity=< 0, -1>
position=<-2, 2> velocity=< 2, 0>
position=< 5, -2> velocity=< 1, 2>
position=< 1, 4> velocity=< 2, 1>
position=<-2, 7> velocity=< 2, -2>
position=< 3, 6> velocity=<-1, -1>
position=< 5, 0> velocity=< 1, 0>
position=<-6, 0> velocity=< 2, 0>
position=< 5, 9> velocity=< 1, -2>
position=<14, 7> velocity=<-2, 0>
position=<-3, 6> velocity=< 2, -1>
"""
func testAlignInit() {
let _ = Align(withString: testData)
let _ = Align(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day10.txt")
}
func testAdvanceTime() {
let algn = Align(withString: testData)
let newGrid = algn.advanceTime(by: 3)
algn.printGrid(points: newGrid, minX: 0, maxX: 9, minY: 0, maxY: 7)
}
func testPotentialMessage() {
let algn = Align(withString: testData)
var bestTime = 0
for time in 0...10 {
let newGrid = algn.advanceTime(by: time)
let mFactor = algn.potentialMessage(withGrid: newGrid)
if mFactor >= 10 {
bestTime = time
break
}
}
XCTAssertEqual(test: "testPotentialMessage", withExpression: (bestTime == 3))
}
func day10Tests() {
testAlignInit()
testAdvanceTime()
testPotentialMessage()
}
func day10Final() {
// let retVal = "None"
// print("Answer to part 1 is: \(retVal)")
var bestTime = 0
let algn = Align(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day10.txt")
for time in 0...100000 {
let newGrid = algn.advanceTime(by: time)
let mFactor = algn.potentialMessage(withGrid: newGrid)
if mFactor > 123 {
// print("mFactor [\(time)] = \(mFactor), time = \(time)")
bestTime = time
break
}
}
print("Answer to part 2 is: \(bestTime)")
}
}
+143
View File
@@ -0,0 +1,143 @@
//
// Advent of Code 2018 "Day 11: Chronal Charge"
//
import Foundation
class Charge {
var grid: [Int] = []
init(withSerialNumber num: Int) {
grid = Array(repeating: 0, count: 300 * 300)
for j in 0..<300 {
for i in 0..<300 {
// grid[j * 300 + i] =
let ID = i + 11
let power = (ID * (j + 1) + num) * ID
// print("power[\(i+1),\(j+1)] : \(power), \(power/1000)")
if power < 100 {
print("_____________________> WOW <__________________")
}
grid[j*300+i] = (power - (power/1000) * 1000 - (power % 100))/100 - 5
// print("\(power % 100), mynum = \(mynum)")
// if (i == 2) { break }
}
// if j == 4 { break }
}
}
func getVal(for pt: (Int, Int)) -> Int {
return grid[(pt.1 - 1) * 300 + (pt.0 - 1)]
}
func sum(for pt: (Int, Int, Int)) -> Int {
let x = pt.0 - 1
let y = pt.1 - 1
let size = pt.2 - 1
var sum = 0
for j in y...y+size {
for i in x...x+size {
sum += grid[j*300+i]
// print("\(grid[j*300+i])", terminator: " ")
}
// print("")
}
// for j in pt.1-2...pt.1+2 {
// for i in pt.0-2...pt.0+2 {
// // print("\(grid[j*300+i])", terminator: " ")
// print(NSString(format:"%4d", grid[j*300+i]), terminator: "")
// }
// print("")
// }
// print("sum:\(sum)")
return sum
}
}
class Day11: AOCDay {
lazy var tests: (() -> ()) = day11Tests
lazy var final: (() -> ()) = day11Final
func testInitCharge() {
let _ = Charge(withSerialNumber: 5093)
// let cha = Charge(withSerialNumber: 8)
}
func testPoint() {
var cha = Charge(withSerialNumber: 57)
var val = cha.getVal(for: (122, 79))
XCTAssertEqual(test: "testPoint (122,79)", withExpression: (val == -5))
cha = Charge(withSerialNumber: 39)
val = cha.getVal(for: (217, 196))
XCTAssertEqual(test: "testPoint (217,196)", withExpression: (val == 0))
cha = Charge(withSerialNumber: 71)
val = cha.getVal(for: (101, 153))
XCTAssertEqual(test: "testPoint (101,153)", withExpression: (val == 4))
}
func testSum() {
var cha = Charge(withSerialNumber: 18)
var sum = cha.sum(for: (33, 45, 3))
XCTAssertEqual(test: "testSum (33,45)", withExpression: (sum == 29))
cha = Charge(withSerialNumber: 42)
sum = cha.sum(for: (21, 61, 3))
XCTAssertEqual(test: "testSum (21,61)", withExpression: (sum == 30))
}
func day11Tests() {
testInitCharge()
testPoint()
testSum()
}
func day11Final() {
// let retVal = "None"
let cha = Charge(withSerialNumber: 5093)
var maxSum = 0
var maxCoord = (0,0)
for y in 1...298 {
for x in 1...298 {
let sum = cha.sum(for: (x, y, 3))
if sum > maxSum {
maxSum = sum
maxCoord = (x, y)
}
}
}
print("Answer to part 1 is: \(maxCoord)")
// var maxSize = 0
// var outerMaxSum = 0
// var outerMaxCoord = (0,0)
// for size in 1...300 {
// maxSum = 0
// maxCoord = (0,0)
// for y in 1...300 - size + 1 {
// for x in 1...300 - size + 1 {
// let sum = cha.sum(for: (x, y, size))
// if sum > maxSum {
// maxSum = sum
// maxCoord = (x, y)
// }
// }
// }
// if maxSum > outerMaxSum {
// outerMaxSum = maxSum
// outerMaxCoord = maxCoord
// maxSize = size
// }
// print("\(outerMaxCoord), \(maxSize)")
// }
// print("Answer to part 2 is: \(outerMaxCoord), \(maxSize)")
print("Answer to part 2 is: look for repeating cycle - takes too long to run as part of CI")
}
}
// RackID = X + 10
// Power = RackID * Y
// Power += SerialNumber
// Power *= Power * RackID
// Power = "hundreds digit"
// Power -= 5
+175
View File
@@ -0,0 +1,175 @@
//
// Advent of Code 2018 "Day 12: Subterranean Sustainability"
//
import Foundation
class Sustainability {
var condition = ""
var pattern: [String: String] = [:]
var keyLength = 0
var paddingLength = 0
// Supply test data in the form of a String
init(withString noteList: String, andInitialCondition initial: String, padding pad: Int) {
paddingLength = pad
let padding = String(Array(repeating: ".", count: paddingLength))
condition = padding + initial + padding
let noteStrings = noteList.components(separatedBy: "\n")
parseData(withNotes: noteStrings)
}
func parseData(withNotes noteArray: [String]) {
for oneNote in noteArray {
var line = oneNote
line = line.replacingOccurrences(of: " => ", with: " ")
let data = line.components(separatedBy: " ")
guard data.count == 2 else { print("Error"); return }
pattern[data[0]] = data[1]
keyLength = data[0].count
}
}
func nextGeneration(with previous: String) -> String {
var nextGen = String(Array(repeating: ".", count: keyLength/2))
for i in 0..<previous.count-keyLength {
let start = previous.index(previous.startIndex, offsetBy: i)
let end = previous.index(previous.startIndex, offsetBy: i + keyLength)
let range = start..<end
let substr = String(previous[range])
if pattern[substr] == nil {
nextGen += "."
} else {
nextGen = nextGen + pattern[substr]!
}
}
nextGen += String(Array(repeating: ".", count: keyLength/2+1))
return nextGen
}
func getValue(of plants: String) -> Int {
var value = 0
let start = -paddingLength
for i in 0..<plants.count {
let pot = start + i
value += plants[i] == "#" ? pot : 0
}
return value
}
}
class Day12: AOCDay {
lazy var tests: (() -> ()) = day12Tests
lazy var final: (() -> ()) = day12Final
func testSustainabilityInit() {
let _ = Sustainability(withString: testNotes, andInitialCondition: testInitialState, padding: 15)
}
func testNextGeneration() {
let sus = Sustainability(withString: testNotes, andInitialCondition: testInitialState, padding: 15)
var gen = sus.condition
print(" 0", terminator: ": ")
print("\(gen)")
for i in 1...20 {
print(NSString(format:"%2d", i), terminator: ": ")
gen = sus.nextGeneration(with: gen)
print("\(gen)")
}
}
func testGetVaue() {
let sus = Sustainability(withString: testNotes, andInitialCondition: testInitialState, padding: 15)
var gen = sus.condition
for _ in 1...20 {
gen = sus.nextGeneration(with: gen)
}
let value = sus.getValue(of: gen)
XCTAssertEqual(test: "testGetVaue", withExpression: (value == 325))
}
func day12Tests() {
testSustainabilityInit()
testNextGeneration()
testGetVaue()
}
func day12Final() {
let sus = Sustainability(withString: finalNotes, andInitialCondition: finalInitialState, padding: 200)
var gen = sus.condition
for _ in 1...20 {
gen = sus.nextGeneration(with: gen)
}
let value = sus.getValue(of: gen)
print("Answer to part 1 is: \(value)")
let limitCount = 150
var inc = 0 //40
gen = sus.condition
for _ in 1...limitCount {
let preValue = sus.getValue(of: gen)
gen = sus.nextGeneration(with: gen)
let postValue = sus.getValue(of: gen)
inc = postValue - preValue
}
let valLimit = sus.getValue(of: gen)
let generations = 50000000000 - limitCount
let answer = generations * inc + valLimit
print("Answer to part 2 is: \(answer)")
}
}
var testInitialState = "#..#.#..##......###...###"
var testNotes = """
...## => #
..#.. => #
.#... => #
.#.#. => #
.#.## => #
.##.. => #
.#### => #
#.#.# => #
#.### => #
##.#. => #
##.## => #
###.. => #
###.# => #
####. => #
"""
var finalInitialState = "##.......#.######.##..#...#.#.#..#...#..####..#.##...#....#...##..#..#.##.##.###.##.#.......###....#"
var finalNotes = """
.#### => .
....# => .
###.. => .
..#.# => .
##### => #
####. => .
#.##. => #
#.#.# => .
##.#. => #
.###. => .
#..#. => #
###.# => .
#.### => .
##... => #
.#.## => .
..#.. => .
#...# => #
..... => .
.##.. => .
...#. => .
#.#.. => .
.#..# => #
.#.#. => .
.#... => #
..##. => .
#..## => .
##.## => #
...## => #
..### => #
#.... => .
.##.# => #
##..# => #
"""
+380
View File
@@ -0,0 +1,380 @@
//
// Advent of Code 2018 "Day 13: Mine Cart Madness"
//
import Foundation
enum Sequence: Int {
case left
case straight
case right
}
enum Direction: Int {
case up
case right
case down
case left
}
struct Cart: Equatable, Comparable {
var loc = GridPoint(X: 0, Y: 0)
var dir = Direction.up
var intersection = Sequence.left
var removed = false
var dirValue: (Int, Int) {
get {
switch dir {
case .up : return (0, -1)
case .right: return (1, 0)
case .down : return (0, 1)
case .left : return (-1, 0)
}
}
}
mutating func move() {
loc.X = loc.X + dirValue.0
loc.Y = loc.Y + dirValue.1
}
mutating func changeDirection(with map: Character) {
func rotateRight() { dir = Direction(rawValue: dir.rawValue + 1) ?? Direction.up }
func rotateLeft() { dir = Direction(rawValue: dir.rawValue - 1) ?? Direction.left }
func increaseSequence() { intersection = Sequence(rawValue: intersection.rawValue + 1) ?? Sequence.left }
if map == "-" || map == "|" { return }
if map == "+" {
switch intersection {
case .left : rotateLeft()
case .straight: break
case .right : rotateRight()
}
increaseSequence()
return
}
switch dir {
case .up, .down :
if map == "/" { rotateRight() }
if map == "\\" { rotateLeft() }
case .left, .right :
if map == "/" { rotateLeft() }
if map == "\\" { rotateRight() }
}
}
static func == (lhs: Cart, rhs: Cart) -> Bool {
return (lhs.loc.X == rhs.loc.X) && (lhs.loc.Y == rhs.loc.Y)
}
static func < (lhs: Cart, rhs: Cart) -> Bool {
return lhs.loc.Y == rhs.loc.Y ? lhs.loc.X < rhs.loc.X : lhs.loc.Y < rhs.loc.Y
}
}
// Initialization:
// 1. read in the grid to get the size (width anf height)
// 2. convert to 2-dimensional grid of Character
// 3. scan for carts
// a. note the grid location
// b. note the direction
// c. initialize the "turning sequence" (count, direction)
// d. convert the cart to the appropriate track
// 1. '<' or '>' => '-'
// 2. '^' or 'v' => '|'
class Madness {
var track: [[Character]] = []
var width = 0
var height = 0
var carts: [Cart] = []
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day13.txt'
init(withFile filename: String) {
let trackFile = Tools.readFile(fromPath: filename)
var trackStrings = trackFile.components(separatedBy: "\n")
// This gurd statement is just an excuse to use guard
// I'm assuming the last string is an empty string, if not DON'T remove the last string
guard let lastStr = trackStrings.last, lastStr.count == 0 else { return }
trackStrings.removeLast() // empty string
parseData(withStars: trackStrings)
}
// Supply test data in the form of a String
init(withString trackFile: String) {
let trackStrings = trackFile.components(separatedBy: "\n")
parseData(withStars: trackStrings)
}
func parseData(withStars trackArray: [String]) {
guard trackArray.count > 0 else { print("Error Parsing"); return }
width = trackArray[0].count
height = trackArray.count
for line in trackArray {
track.append(Array(line))
}
func newCart(at loc: (Int, Int), with direction: Direction) {
carts.append(Cart(loc: GridPoint(X: loc.0, Y: loc.1), dir: direction, intersection: Sequence.left, removed: false))
switch direction {
case .up, .down : track[loc.1][loc.0] = "|"
case .left, .right: track[loc.1][loc.0] = "-"
}
}
for j in 0..<height {
for i in 0..<width {
switch track[j][i] {
case "^": newCart(at: (i, j), with: Direction.up)
case "v": newCart(at: (i, j), with: Direction.down)
case "<": newCart(at: (i, j), with: Direction.left)
case ">": newCart(at: (i, j), with: Direction.right)
default: break
}
}
}
}
func getTrack(at loc: GridPoint) -> Character {
guard loc.X >= 0 && loc.Y >= 0 && loc.X < width && loc.Y < height else { print("getTrack out of range"); return "#" }
return track[loc.Y][loc.X]
}
func collision(removeCrash: Bool) -> GridPoint? {
var retVal: GridPoint? = nil
var dupTest: [GridPoint : Int] = [:]
for index in 0..<carts.count {
if !carts[index].removed {
if dupTest[carts[index].loc] != nil {
if removeCrash {
carts[index].removed = true
carts[dupTest[carts[index].loc]!].removed = true
} else {
return carts[index].loc
}
} else {
dupTest[carts[index].loc] = index
}
}
}
let notRemoved = carts.filter { $0.removed == false }
if notRemoved.count == 1 {
retVal = notRemoved[0].loc
}
return retVal
}
// Start of Tick:
// 1. order carts by location
// 2. move cart one step in it's direction
// 3. Look to see where we landed
// a. other cart => CRASH
// b. '-' or '|' is a straight track => do nothing
// c. '\' => rotate right
// d. '/' => rotate left
// e. '+' => [Left, Straight, Right] sequense for this cart
func tick(andRemove remove: Bool) -> GridPoint? {
var collided: GridPoint? = nil
carts.sort()
for index in 0..<carts.count {
if !carts[index].removed {
carts[index].move()
collided = collision(removeCrash: remove)
if collided != nil && !remove {
break
}
let track = getTrack(at: carts[index].loc)
carts[index].changeDirection(with: track)
}
}
return collided
}
}
class Day13: AOCDay {
lazy var tests: (() -> ()) = day13Tests
lazy var final: (() -> ()) = day13Final
let testData =
"/->-\\ \n" +
"| | /----\\\n" +
"| /-+--+-\\ |\n" +
"| | | | v |\n" +
"\\-+-/ \\-+--/\n" +
" \\------/ "
let testData2 =
"/>-<\\ \n" +
"| | \n" +
"| /<+-\\\n" +
"| | | v\n" +
"\\>+</ |\n" +
" | ^\n" +
" \\<->/"
func testCartMove() {
var car = Cart(loc: GridPoint(X: 10, Y:10), dir: Direction.up, intersection: Sequence.left, removed: false)
car.move()
XCTAssertEqual(test: "testCartMove", withExpression: (car.loc.X == 10 && car.loc.Y == 9))
}
func testCartChangeDirection() {
var car = Cart(loc: GridPoint(X: 10, Y:10), dir: Direction.up, intersection: Sequence.left, removed: false)
car.move()
car.changeDirection(with: "-")
car.move()
XCTAssertEqual(test: "testCartChangeDirection '-'", withExpression: (car.loc.X == 10 && car.loc.Y == 8))
car.changeDirection(with: "|")
car.move()
XCTAssertEqual(test: "testCartChangeDirection '|'", withExpression: (car.loc.X == 10 && car.loc.Y == 7))
car.changeDirection(with: "/")
car.move()
XCTAssertEqual(test: "testCartChangeDirection '/'", withExpression: (car.loc.X == 11 && car.loc.Y == 7))
car.changeDirection(with: "\\")
car.move()
car.move()
XCTAssertEqual(test: "testCartChangeDirection '\\'", withExpression: (car.loc.X == 11 && car.loc.Y == 9))
car.changeDirection(with: "+")
car.move()
XCTAssertEqual(test: "testCartChangeDirection '+'", withExpression: (car.loc.X == 12 && car.loc.Y == 9))
car.changeDirection(with: "+")
car.move()
XCTAssertEqual(test: "testCartChangeDirection '+'", withExpression: (car.loc.X == 13 && car.loc.Y == 9))
car.changeDirection(with: "+")
car.move()
XCTAssertEqual(test: "testCartChangeDirection '+'", withExpression: (car.loc.X == 13 && car.loc.Y == 10))
}
func testCartSort() {
var cars: [Cart] = []
cars.append(Cart(loc: GridPoint(X: 10, Y:10), dir: Direction.up, intersection: Sequence.left, removed: false))
cars.append(Cart(loc: GridPoint(X: 5, Y:22), dir: Direction.up, intersection: Sequence.left, removed: false))
cars.append(Cart(loc: GridPoint(X: 22, Y:5), dir: Direction.up, intersection: Sequence.left, removed: false))
cars.append(Cart(loc: GridPoint(X: 2, Y:10), dir: Direction.up, intersection: Sequence.left, removed: false))
cars.sort()
let lastCar = cars.last!
XCTAssertEqual(test: "testCartSort last", withExpression: (lastCar.loc.X == 5 && lastCar.loc.Y == 22))
}
func testCartEquatable() {
var car1 = Cart(loc: GridPoint(X: 10, Y:10), dir: Direction.up, intersection: Sequence.left, removed: false)
car1.move()
car1.changeDirection(with: "-")
car1.move()
let car2 = Cart(loc: GridPoint(X: 10, Y:8), dir: Direction.up, intersection: Sequence.left, removed: false)
XCTAssertEqual(test: "testCartEquatable", withExpression: (car1 == car2))
}
func testMadnessInit() {
let mad = Madness(withString: testData)
printTrack(with: mad)
XCTAssertEqual(test: "testMadnessInit string", withExpression: (mad.width == 13 && mad.height == 6))
if mad.carts.count != 2 {
XCTAssertEqual(test: "testMadnessInit carts count", withExpression: (false))
} else {
XCTAssertEqual(test: "testMadnessInit carts count", withExpression: (mad.carts.count == 2))
XCTAssertEqual(test: "testMadnessInit cart X", withExpression: (mad.carts[0].loc.X == 2))
XCTAssertEqual(test: "testMadnessInit cart Y", withExpression: (mad.carts[0].loc.Y == 0))
XCTAssertEqual(test: "testMadnessInit cart direction", withExpression: (mad.carts[0].dir == Direction.right))
}
}
func testGetTrack() {
let mad = Madness(withString: testData)
var result = mad.getTrack(at: GridPoint(X: 4, Y: 2))
XCTAssertEqual(test: "testGetTrack (5, 3)", withExpression: (result == "+"))
result = mad.getTrack(at: GridPoint(X: 2, Y: 0))
XCTAssertEqual(test: "testGetTrack (3, 1) convert cart to track", withExpression: (result == "-"))
}
func testCollision() {
let mad = Madness(withString: testData)
mad.carts[1].loc = mad.carts[0].loc
XCTAssertEqual(test: "testCollision", withExpression: (mad.collision(removeCrash: false) != nil))
}
func testTick() {
let mad = Madness(withString: testData)
let oldcart = mad.carts[0]
let collided = mad.tick(andRemove: false)
let newcart = mad.carts[0]
XCTAssertEqual(test: "testTick", withExpression: (oldcart != newcart))
XCTAssertEqual(test: "testTick", withExpression: (collided == nil))
}
func printTrack(with mad: Madness) {
func cartLoc(at loc: GridPoint) -> (Bool, Character) {
var retVal: (Bool, Character) = (false, " ")
for cart in mad.carts {
if cart.loc == loc && !cart.removed{
switch cart.dir {
case .up : retVal = (true, "^")
case .down : retVal = (true, "v")
case .left : retVal = (true, "<")
case .right: retVal = (true, ">")
}
}
}
return retVal
}
for j in 0..<mad.height {
for i in 0..<mad.width {
let cartIcon = cartLoc(at: GridPoint(X: i, Y: j))
if cartIcon.0 {
print("\(cartIcon.1)", terminator: " ")
} else {
print("\(mad.getTrack(at: GridPoint(X: i, Y: j)))", terminator: " ")
}
}
print("")
}
print("")
}
func testRun() {
var mad = Madness(withString: testData)
printTrack(with: mad)
var crash: GridPoint?
repeat {
crash = mad.tick(andRemove: false)
} while crash == nil
// print("Collision location Part1: (\(crash!))")
XCTAssertEqual(test: "testRun Part 1", withExpression: (crash! == GridPoint(X: 7, Y: 3)))
mad = Madness(withString: testData2)
printTrack(with: mad)
repeat {
crash = mad.tick(andRemove: true)
} while crash == nil
// print("Last Cart location Part2: (\(crash!))")
XCTAssertEqual(test: "testRun Part 2", withExpression: (crash! == GridPoint(X: 6, Y: 4)))
}
func day13Tests() {
testCartMove()
testCartChangeDirection()
testCartSort()
testCartEquatable()
testMadnessInit()
testGetTrack()
testCollision()
testTick()
testRun()
}
func day13Final() {
var mad = Madness(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day13.txt")
var crash: GridPoint?
repeat {
crash = mad.tick(andRemove: false)
} while crash == nil
print("Answer to part 1 is: \(crash!)")
mad = Madness(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day13.txt")
repeat {
crash = mad.tick(andRemove: true)
} while crash == nil
print("Answer to part 2 is: \(crash!)")
}
}
+125
View File
@@ -0,0 +1,125 @@
//
// Advent of Code 2018 "Day 14: Chocolate Charts"
//
import Foundation
class Chocolate {
var score: [Int] = [3, 7, 1, 0]
var scoreStr = "3710"
var elf: [Int] = [0, 1]
var lf2 = 3
func moveForward() {
for index in 0..<elf.count {
let currentRecipe = elf[index]
let moveCount = score[elf[index]] + 1
elf[index] = moveCount + currentRecipe
if elf[index] >= score.count {
elf[index] -= score.count
}
}
}
func nextRecipe() {
var sum = 0
for index in 0..<elf.count {
sum += score[elf[index]]
}
let strsum = Array(String(sum))
for i in 0..<strsum.count {
let newScore = String(strsum[i])
score.append(Int(newScore)!)
scoreStr += newScore
}
}
func get10RecipeScore(after index: Int) -> String {
var retVal = ""
repeat {
nextRecipe()
moveForward()
} while score.count < index+10
for i in index..<index+10 {
retVal += String(score[i])
}
return retVal
}
func getNumBefore(pattern: String) -> Int {
var distance = 0
let range = scoreStr.range(of: pattern)
if let range = range {
distance = scoreStr.distance(from: scoreStr.startIndex, to: range.lowerBound)
}
return distance
}
}
class Day14: AOCDay {
lazy var tests: (() -> ()) = day14Tests
lazy var final: (() -> ()) = day14Final
func testNextRecipe() {
let cho = Chocolate()
cho.nextRecipe()
guard cho.score.count == 6 else {
XCTAssertEqual(test: "testNextRecipe fail count", withExpression: (false))
return
}
XCTAssertEqual(test: "testNextRecipe", withExpression: (cho.score[4] == 1 && cho.score[5] == 0))
}
func testMoveForward() {
let cho = Chocolate()
cho.nextRecipe()
cho.moveForward()
XCTAssertEqual(test: "testMoveForward", withExpression: (cho.elf[0] == 4 && cho.elf[1] == 3))
}
func testGet10RecipeScore() {
var cho = Chocolate()
var answer = cho.get10RecipeScore(after: 9)
XCTAssertEqual(test: "testGet10RecipeScore 9", withExpression: (answer == "5158916779"))
cho = Chocolate()
answer = cho.get10RecipeScore(after: 5)
XCTAssertEqual(test: "testGet10RecipeScore 5", withExpression: (answer == "0124515891"))
cho = Chocolate()
answer = cho.get10RecipeScore(after: 18)
XCTAssertEqual(test: "testGet10RecipeScore 18", withExpression: (answer == "9251071085"))
cho = Chocolate()
answer = cho.get10RecipeScore(after: 2018)
XCTAssertEqual(test: "testGet10RecipeScore 2018", withExpression: (answer == "5941429882"))
}
func testGetNumBefore() {
let cho = Chocolate()
_ = cho.get10RecipeScore(after: 2018)
var answer = cho.getNumBefore(pattern: "51589")
XCTAssertEqual(test: "testGetNumBefore 51589", withExpression: (answer == 9))
answer = cho.getNumBefore(pattern: "01245")
XCTAssertEqual(test: "testGetNumBefore 01245", withExpression: (answer == 5))
answer = cho.getNumBefore(pattern: "92510")
XCTAssertEqual(test: "testGetNumBefore 92510", withExpression: (answer == 18))
answer = cho.getNumBefore(pattern: "59414")
XCTAssertEqual(test: "testGetNumBefore 59414", withExpression: (answer == 2018))
}
func day14Tests() {
testNextRecipe()
testMoveForward()
testGet10RecipeScore()
testGetNumBefore()
}
func day14Final() {
let cho = Chocolate()
let answer = cho.get10RecipeScore(after: 580741)
print("Answer to part 1 is: \(answer)")
// let answer = cho.get10RecipeScore(after: 112580741)
// let dist = cho.getNumBefore(pattern: "580741")
// print("Answer to part 2 is: \(dist)")
print("Brute forced part 2 - takes too long")
}
}
+789
View File
@@ -0,0 +1,789 @@
//
// Advent of Code 2018 "Day 15: Beverage Bandits"
//
import Foundation
enum State: Int {
case Unknown = -4
case Wall = -3
case Open = 0
case Elf = 1
case Goblin = 2
}
struct Entity: Equatable, Comparable {
var kind: State
var loc: GridPoint
var power: Int
var hitPts: Int
init(kind: State, loc: GridPoint, power: Int = 3, hitPts: Int = 200) {
self.kind = kind
self.loc = loc
self.power = power
self.hitPts = hitPts
}
static func == (lhs: Entity, rhs: Entity) -> Bool {
return (lhs.loc == rhs.loc) && (lhs.power == rhs.power) && (lhs.hitPts == rhs.hitPts)
}
static func < (lhs: Entity, rhs: Entity) -> Bool {
return lhs.loc < rhs.loc
}
}
class Beverage {
var entities: [Entity] = []
var maze: [[Character]] = []
var nummaze: [[State]] = []
var entityDict: [GridPoint : Int] = [:]
var width = 0
var height = 0
var rounds = 0
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day15.txt'
init(withFile filename: String) {
let mazeFile = Tools.readFile(fromPath: filename)
var mazeStrings = mazeFile.components(separatedBy: "\n")
// This gurd statement is just an excuse to use guard
// I'm assuming the last string is an empty string, if not DON'T remove the last string
guard let lastStr = mazeStrings.last, lastStr.count == 0 else { return }
mazeStrings.removeLast() // empty string
parseData(intoGrid: mazeStrings)
}
// Supply test data in the form of a String
init(withString mazeFile: String) {
let mazeStrings = mazeFile.components(separatedBy: "\n")
parseData(intoGrid: mazeStrings)
}
func parseData(intoGrid mazeArray: [String]) {
guard mazeArray.count > 0 else { print("Error Parsing"); return }
width = mazeArray[0].count
height = mazeArray.count
for line in mazeArray {
maze.append(Array(line))
}
func newEntity(type kind: State, at loc: (Int, Int)) {
var power = 3
if kind == .Elf {
power = 12
}
entities.append(Entity(kind: kind, loc: GridPoint(X: loc.0, Y: loc.1), power: power))
}
for _ in 0..<height {
nummaze.append(Array(repeating: .Wall, count: width))
}
for j in 0..<height {
for i in 0..<width {
switch maze[j][i] {
case "#": break // we initialized this grid to all "walls"
case ".": nummaze[j][i] = .Open
case "G": nummaze[j][i] = .Goblin
newEntity(type: .Goblin,at: (i, j))
case "E": nummaze[j][i] = .Elf
newEntity(type: .Elf, at: (i, j))
default: nummaze[j][i] = .Unknown
}
}
}
updateEntityDict()
entities.sort()
}
func updateEntityDict() {
entityDict = [:]
for index in 0..<entities.count {
if entities[index].hitPts > 0 {
entityDict[entities[index].loc] = index
}
}
}
// Sort the entities (reading order) and repopulate the nummaze map
func updateMaze() {
for j in 0..<height {
for i in 0..<width {
if nummaze[j][i] == .Elf || nummaze[j][i] == .Goblin {
nummaze[j][i] = .Open
}
}
}
for entity in entities {
if entity.hitPts > 0 {
switch entity.kind {
case .Elf: nummaze[entity.loc.Y][entity.loc.X] = .Elf
case .Goblin: nummaze[entity.loc.Y][entity.loc.X] = .Goblin
default: break
}
}
}
}
func printMaze(with maze: [[Int]]) {
let width = maze[0].count
let height = maze.count
for j in 0..<height {
for i in 0..<width {
switch maze[j][i] {
case -4: print("?", terminator: "")
case -3: print("#", terminator: "")
case -2: print("G", terminator: "")
case -1: print("E", terminator: "")
case 0: print(".", terminator: "")
default: print("\(maze[j][i])", terminator: "")
}
}
print("")
}
print("")
}
// Return the distance and the preferred direction (direction only valid by reversing the request; i.e. swapping orig and dest)
func distance(from origin: GridPoint, to dest: GridPoint) -> (dist: Int, dir: GridPoint) {
var retVal = (dist: -1, dir: GridPoint(X:0, Y:0))
var distMaze: [[Int]] = []
for row in nummaze {
distMaze.append(row.map { if $0.rawValue > 0 { return -$0.rawValue } else { return $0.rawValue } })
}
func testAndQueue(for point: GridPoint, on wave: Int, in queue: inout [GridPoint]) {
if distMaze[point.Y][point.X] == 0 {
distMaze[point.Y][point.X] = wave
queue.append(point)
}
}
var wave = 1
var done = false
var queue: [GridPoint] = [origin]
distMaze[dest.Y][dest.X] = 0
while !done {
var newQueue: [GridPoint] = []
for point in queue {
testAndQueue(for: point.up, on: wave, in: &newQueue)
testAndQueue(for: point.down, on: wave, in: &newQueue)
testAndQueue(for: point.left, on: wave, in: &newQueue)
testAndQueue(for: point.right, on: wave, in: &newQueue)
}
queue = newQueue
if queue.contains(dest) {
done = true
retVal.dist = distMaze[dest.Y][dest.X]
if wave == 1 {
retVal.dir = origin - dest
}
}
done = done || (newQueue.count == 0)
wave += 1
}
// printMaze(with: distMaze)
// Determin direction by locating the lowest distance count via reading-order
if retVal.dir == GridDir.none {
if distMaze[dest.up.Y][dest.up.X] == retVal.dist-1 {
retVal.dir = GridDir.up
} else if distMaze[dest.left.Y][dest.left.X] == retVal.dist-1 {
retVal.dir = GridDir.left
} else if distMaze[dest.right.Y][dest.right.X] == retVal.dist-1 {
retVal.dir = GridDir.right
} else if distMaze[dest.down.Y][dest.down.X] == retVal.dist-1 {
retVal.dir = GridDir.down
}
}
return retVal
}
func findNearestTarget(for attacker: Entity) -> GridPoint {
var retVal = GridPoint(X: -1, Y: -1)
var list: [GridPoint : Bool] = [:]
func testAnAddToList(for point: GridPoint) {
if nummaze[point.Y][point.X] == .Open {
list[point] = true
}
}
// Create a list of reachables
for entity in entities {
if entity.hitPts > 0 && entity.kind == enemy(of: attacker) {
testAnAddToList(for: entity.loc.up)
testAnAddToList(for: entity.loc.down)
testAnAddToList(for: entity.loc.left)
testAnAddToList(for: entity.loc.right)
}
}
let inRange = Array(list.keys)
var reachable: [GridPoint : Int] = [:]
// Create a sorted list of Nearest targets from reachables
var minDist = width + height
for target in inRange {
let dist = distance(from: attacker.loc, to: target).dist
if dist > 0 {
minDist = min(dist, minDist)
reachable[target] = dist
}
}
var nearest = Array(reachable.filter { $0.value == minDist }.keys)
nearest.sort()
if nearest.count > 0 {
retVal = nearest[0]
}
return retVal
}
func moveDirection(from entity: Entity, to dest: GridPoint) -> GridPoint {
// use the reverse map in 'distance' to come up with a preferred direction
var retVal = GridPoint(X:0,Y:0)
if dest != GridPoint(X: -1, Y: -1) {
let dist = distance(from: dest, to: entity.loc)
if dist.dist > 0 {
retVal = dist.dir
}
}
return retVal
}
func round() -> Bool {
var done = false
// Only sort once per round
entities.sort()
for index in 0..<entities.count {
if entities[index].hitPts > 0 {
done = takeTurn(with: index)
if done {
break
}
}
}
if !done {
rounds += 1
}
return done
}
func tabulateScore() -> Int {
// sum remaining hitPts
var sum = 0
for entity in entities {
if entity.hitPts > 0 {
sum += entity.hitPts
}
}
return sum * rounds
}
let watchIndex = -1
func takeTurn(with entityIndex: Int) -> Bool {
//done test
let viableEnemy = entities.filter { $0.kind == enemy(of: entities[entityIndex]) && $0.hitPts > 0 }
guard viableEnemy.count > 0 else { return true }
// entityDict must be updated for every action (move or attack)
updateEntityDict()
// Adjacent to target?
var indexOfAdjeacentTarget = adjacent(to: entityIndex)
if indexOfAdjeacentTarget == -1 {
// find nearest enemy
let nearest = findNearestTarget(for: entities[entityIndex])
// determine direction to go
let direction = moveDirection(from: entities[entityIndex], to: nearest)
// print("nearest \(nearest), direction = \(direction)")
// move and update dict and map
entities[entityIndex].loc = entities[entityIndex].loc + direction
if entityIndex == watchIndex {
print("\(entities[entityIndex])")
print("nearest : \(nearest)")
print("direction : \(direction)")
}
updateEntityDict()
updateMaze()
}
// Check if we moved within range
indexOfAdjeacentTarget = adjacent(to: entityIndex)
if entityIndex == watchIndex && indexOfAdjeacentTarget > 0 {
print("adjacent Target : \(entities[indexOfAdjeacentTarget])")
}
if indexOfAdjeacentTarget != -1 {
attack(from: entities[entityIndex], to: indexOfAdjeacentTarget)
updateEntityDict()
updateMaze()
}
return false
}
func enemy(of entity: Entity) -> State {
var retVal = State.Goblin
if entity.kind == .Goblin {
retVal = .Elf
}
return retVal
}
// Return the index number of the target to attack (or -1 if no target)
func adjacent(to subjectIndex: Int) -> Int {
var retVal = -1
var enemyDict: [GridPoint:Int] = [:] // Loc : HitPts
func determineEnemyAndQueue(for loc: GridPoint) {
if nummaze[loc.Y][loc.X] == enemy(of: entities[subjectIndex]) {
updateEntityDict()
if let index = entityDict[loc] {
enemyDict[loc] = entities[index].hitPts
}
}
}
// create list of adjacent enemies
determineEnemyAndQueue(for: entities[subjectIndex].loc.up)
determineEnemyAndQueue(for: entities[subjectIndex].loc.left)
determineEnemyAndQueue(for: entities[subjectIndex].loc.right)
determineEnemyAndQueue(for: entities[subjectIndex].loc.down)
// sort list by HitPoints, fewest to most order
if enemyDict.count > 0 {
// find min hit point
let minHP = enemyDict.min { a, b in a.value < b.value }?.value ?? -1
// gather array of min-hitpoint enemies
let minDict = enemyDict.filter {$0.value == minHP}
// sort enemies by location in reading-order
let enemy = minDict.sorted(by: <)
// select the first one
retVal = entityDict[enemy[0].key]!
}
return retVal
}
func attack(from attacker: Entity, to victimIndex: Int) {
entities[victimIndex].hitPts = entities[victimIndex].hitPts - attacker.power
// print("attacker power = \(attacker.power)")
if entities[victimIndex].hitPts <= 0 && entities[victimIndex].kind == .Elf {
print("Fail")
while true {}
}
}
}
class Day15: AOCDay {
lazy var tests: (() -> ()) = day15Tests
lazy var final: (() -> ()) = day15Final
let testData1 = """
#######
#E..G.#
#...#.#
#.G.#G#
#######
"""
let testData2 = """
#######
#.E...#
#.....#
#...G.#
#######
"""
let testData3 = """
#########
#G.....G#
#...G...#
#...E...#
#G.....G#
#.......#
#.......#
#G..G..G#
#########
"""
let testData4 = """
#########
#G..G..G#
#.......#
#.......#
#G..E..G#
#.......#
#.......#
#G..G..G#
#########
"""
let testData5 = """
#######
#...G.#
#..G.G#
#.#.#G#
#...#E#
#.....#
#######
"""
let testData6 = """
#######
#G....#
#..G..#
#..EG.#
#..G..#
#...G.#
#######
"""
let testData7 = """
#######
#.G...#
#...EG#
#.#.#G#
#..G#E#
#.....#
#######
"""
// Combat ends after 37 full rounds
// Elves win with 982 total hit points left
// Outcome: 37 * 982 = 36334
let testData8 = """
#######
#G..#E#
#E#E.E#
#G.##.#
#...#E#
#...E.#
#######
"""
// Combat ends after 46 full rounds
// Elves win with 859 total hit points left
// Outcome: 46 * 859 = 39514
let testData9 = """
#######
#E..EG#
#.#G.E#
#E.##E#
#G..#.#
#..E#.#
#######
"""
// Combat ends after 35 full rounds
// Goblins win with 793 total hit points left
// Outcome: 35 * 793 = 27755
let testData10 = """
#######
#E.G#.#
#.#G..#
#G.#.G#
#G..#.#
#...E.#
#######
"""
// Combat ends after 54 full rounds
// Goblins win with 536 total hit points left
// Outcome: 54 * 536 = 28944
let testData11 = """
#######
#.E...#
#.#..G#
#.###.#
#E#G#G#
#...#G#
#######
"""
// Combat ends after 20 full rounds
// Goblins win with 937 total hit points left
// Outcome: 20 * 937 = 18740
let testData12 = """
#########
#G......#
#.E.#...#
#..##..G#
#...##..#
#...#...#
#.G...G.#
#.....G.#
#########
"""
func testInitFile() {
let bev = Beverage(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day15.txt")
printMaze(with: bev)
}
func testInitString() {
let bev = Beverage(withString: testData1)
printMaze(with: bev)
}
func testEntities() {
let bev = Beverage(withString: testData1)
var myentities = bev.entities
func show(entities: [Entity]) {
var id = 0
for entity in entities {
print("\(id) : \(entity)")
id += 1
}
}
// show(entities: myentities) // Demonstrated that sorting works when force-read in the entities in reversse order
myentities.sort()
// show(entities: myentities)
}
func testFindNearestTarget() {
var bev = Beverage(withString: testData1)
var nearest = bev.findNearestTarget(for: bev.entities[0])
XCTAssertEqual(test: "testFindNearestTarget (Elf)", withExpression: (nearest == GridPoint(X: 3, Y: 1)))
nearest = bev.findNearestTarget(for: bev.entities[1])
XCTAssertEqual(test: "testFindNearestTarget (Goblin 0)", withExpression: (nearest == GridPoint(X: 2, Y: 1)))
nearest = bev.findNearestTarget(for: bev.entities[2])
XCTAssertEqual(test: "testFindNearestTarget (Goblin 1)", withExpression: (nearest == GridPoint(X: 2, Y: 1)))
nearest = bev.findNearestTarget(for: bev.entities[3])
XCTAssertEqual(test: "testFindNearestTarget (Goblin 2)", withExpression: (nearest == GridPoint(X: -1, Y: -1)))
bev = Beverage(withString: testData5)
nearest = bev.findNearestTarget(for: bev.entities[3])
XCTAssertEqual(test: "testFindNearestTarget is Goblin", withExpression: (bev.entities[3].kind == .Goblin))
XCTAssertEqual(test: "testFindNearestTarget is Elf", withExpression: (bev.entities[4].kind == .Elf))
XCTAssertEqual(test: "testFindNearestTarget (Goblin)", withExpression: (nearest == GridPoint(X: 3, Y: 3)))
}
func testDistance() {
let bev = Beverage(withString: testData1)
var dist = bev.distance(from: bev.entities[0].loc, to: GridPoint(X: 2, Y: 2)).dist
XCTAssertEqual(test: "testDistance (2, 2) = 2", withExpression: (dist == 2))
dist = bev.distance(from: bev.entities[0].loc, to: GridPoint(X: 5, Y: 2)).dist
XCTAssertEqual(test: "testDistance (5, 2) = -1", withExpression: (dist == -1))
dist = bev.distance(from: bev.entities[0].loc, to: GridPoint(X: 2, Y: 1)).dist
XCTAssertEqual(test: "testDistance (2, 1) = 0", withExpression: (dist == 1))
dist = bev.distance(from: bev.entities[3].loc, to: GridPoint(X: 2, Y: 1)).dist
XCTAssertEqual(test: "testDistance last Goblin to` Elf", withExpression: (dist == -1))
}
func testMoveDirection() {
var bev = Beverage(withString: testData1)
var nearest = bev.findNearestTarget(for: bev.entities[0])
var direction = bev.moveDirection(from: bev.entities[0], to: nearest)
XCTAssertEqual(test: "testMoveDirection testData1", withExpression: (direction == GridDir.right))
bev = Beverage(withString: testData2)
nearest = bev.findNearestTarget(for: bev.entities[0])
direction = bev.moveDirection(from: bev.entities[0], to: nearest)
XCTAssertEqual(test: "testMoveDirection testData2", withExpression: (direction == GridDir.right))
bev = Beverage(withString: testData5)
nearest = bev.findNearestTarget(for: bev.entities[1])
direction = bev.moveDirection(from: bev.entities[1], to: nearest)
print("Nearest: \(nearest)")
print("Direction: \(direction)")
XCTAssertEqual(test: "testMoveDirection is Goblin", withExpression: (bev.entities[1].kind == .Goblin))
XCTAssertEqual(test: "testMoveDirection is Elf", withExpression: (bev.entities[4].kind == .Elf))
XCTAssertEqual(test: "testMoveDirection (nearest)", withExpression: (nearest == GridPoint(X: 5, Y: 5)))
XCTAssertEqual(test: "testMoveDirection (dir)", withExpression: (direction == GridDir.down))
}
func testAdjacent() {
var bev = Beverage(withString: testData3)
var adjacent = bev.adjacent(to: 3)
XCTAssertEqual(test: "testAdjacent is Elf", withExpression: (bev.entities[3].kind == .Elf))
XCTAssertEqual(test: "testAdjacent is adjacent", withExpression: (adjacent == 2))
bev = Beverage(withString: testData4)
adjacent = bev.adjacent(to: 4)
XCTAssertEqual(test: "testAdjacent is Elf", withExpression: (bev.entities[4].kind == .Elf))
XCTAssertEqual(test: "testAdjacent is not adjacent", withExpression: (adjacent == -1))
}
func testTakeTurn() {
var bev = Beverage(withString: testData3)
XCTAssertEqual(test: "testTakeTurn is Elf", withExpression: (bev.entities[3].kind == .Elf))
// printMaze(with: bev)
_ = bev.takeTurn(with: 3)
// printMaze(with: bev)
bev = Beverage(withString: testData4)
XCTAssertEqual(test: "testTakeTurn is Elf", withExpression: (bev.entities[4].kind == .Elf))
// printMaze(with: bev)
_ = bev.takeTurn(with: 4)
// printMaze(with: bev)
}
func testAttack() {
let bev = Beverage(withString: testData6)
// G.... 9 G.... 9
// ..G.. 4 ..G.. 4
// ..EG. 2 --> ..E..
// ..G.. 2 ..G.. 2
// ...G. 1 ...G. 1
bev.entities[0].hitPts = 9
bev.entities[1].hitPts = 4
bev.entities[3].hitPts = 2
bev.entities[4].hitPts = 2
bev.entities[5].hitPts = 1
printMaze(with: bev, withHP: true)
let indexOfAdjeacentTarget = bev.adjacent(to: 2)
if indexOfAdjeacentTarget != -1 {
bev.attack(from: bev.entities[2], to: indexOfAdjeacentTarget)
bev.updateEntityDict()
bev.updateMaze()
}
printMaze(with: bev, withHP: true)
}
func testRound() {
let bev = Beverage(withString: testData4)
// printMaze(with: bev)
_ = bev.round()
// printMaze(with: bev)
_ = bev.round()
// printMaze(with: bev)
_ = bev.round()
printMaze(with: bev)
let adjacent = bev.adjacent(to: 4)
// print("adjacent=\(adjacent)")
// print("entity = \(bev.entities[adjacent])")
XCTAssertEqual(test: "testRound is Elf", withExpression: (bev.entities[4].kind == .Elf))
XCTAssertEqual(test: "testRound attack entity 1", withExpression: (bev.entities[adjacent].loc == GridPoint(X: 4, Y: 2)))
}
func testSampleGame() {
var bev = Beverage(withString: testData7)
// printMaze(with: bev, withHP: true)
while !bev.round() {}
// printMaze(with: bev, withHP: true)
var final = bev.tabulateScore()
// print("Final score = \(final)")
XCTAssertEqual(test: "testSampleGame 7", withExpression: (final == 27730))
bev = Beverage(withString: testData8)
// printMaze(with: bev, withHP: true)
while !bev.round() {}
// printMaze(with: bev, withHP: true)
final = bev.tabulateScore()
// print("Final score = \(final)")
XCTAssertEqual(test: "testSampleGame 8", withExpression: (final == 36334))
bev = Beverage(withString: testData9)
// printMaze(with: bev, withHP: true)
while !bev.round() {}
// printMaze(with: bev, withHP: true)
final = bev.tabulateScore()
// print("Final score = \(final)")
XCTAssertEqual(test: "testSampleGame 9", withExpression: (final == 39514))
bev = Beverage(withString: testData10)
// printMaze(with: bev, withHP: true)
while !bev.round() {}
// printMaze(with: bev, withHP: true)
final = bev.tabulateScore()
// print("Final score = \(final)")
XCTAssertEqual(test: "testSampleGame 10", withExpression: (final == 27755))
bev = Beverage(withString: testData11)
// printMaze(with: bev, withHP: true)
while !bev.round() {}
// printMaze(with: bev, withHP: true)
final = bev.tabulateScore()
// print("Final score = \(final)")
XCTAssertEqual(test: "testSampleGame 11", withExpression: (final == 28944))
bev = Beverage(withString: testData12)
// printMaze(with: bev, withHP: true)
while !bev.round() {}
// printMaze(with: bev, withHP: true)
final = bev.tabulateScore()
// print("Final score = \(final)")
XCTAssertEqual(test: "testSampleGame 12", withExpression: (final == 18740))
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// for _ in 2..<23 {
// bev.round()
// }
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
// for _ in 28..<46 {
// bev.round()
// }
// printMaze(with: bev, withHP: true)
// bev.round()
// printMaze(with: bev, withHP: true)
}
func printMaze(with bev: Beverage, withHP: Bool = false) {
let width = bev.nummaze[0].count
let height = bev.nummaze.count
func toEntityHP(i: Int, j: Int) -> Int {
var retVal = 0
if let index = bev.entityDict[GridPoint(X: i, Y: j)] {
retVal = bev.entities[index].hitPts
}
return retVal
}
print(" ROUND \(bev.rounds)")
for j in 0..<height {
for i in 0..<width {
switch bev.nummaze[j][i] {
case .Wall: print(" # ", terminator: "")
case .Unknown: print(" ? ", terminator: "")
case .Open: print(" . ", terminator: "")
case .Goblin: withHP ? print("\u{001B}[0;31m\(String(format: "%03d", toEntityHP(i:i, j:j)))\u{001B}[0;37m", terminator: "") : print(" G ", terminator: "")
case .Elf: withHP ? print("\u{001B}[0;32m\(String(format: "%03d", toEntityHP(i:i, j:j)))\u{001B}[0;37m", terminator: "") : print(" E ", terminator: "")
}
}
print("")
}
print("")
}
func day15Tests() {
// testInitFile()
// testInitString()
// testEntities()
// testDistance()
// testMoveDirection()
// testFindNearestTarget()
// testAdjacent()
// testTakeTurn()
// testRound()
// testAttack()
// testSampleGame()
}
func day15Final() {
let retVal = "None"
let bev = Beverage(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day15.txt")
printMaze(with: bev, withHP: true)
while !bev.round() {
printMaze(with: bev, withHP: true)
}
// printMaze(with: bev, withHP: true)
let final = bev.tabulateScore()
print("Answer to part 1 is: \(final)")
print("Answer to part 2 is: \(retVal)")
}
}
+373
View File
@@ -0,0 +1,373 @@
//
// Advent of Code 2018 "Day 16: Chronal Classification"
//
import Foundation
typealias Opfn = () -> Void
// Create an array of functions for the op codes such that we can make a dictionary to map them
// 16 op-codes
// 4 regisers
class Z8 {
var reg: [Int]
var op: Int
var A: Int
var B: Int
var C: Int
lazy var fn = [addr, addi, mulr, muli, banr, bani, borr, bori, setr, seti, gtir, gtri, gtrr, eqir, eqri, eqrr]
init(reg: [Int], op: Int, A: Int, B: Int, C: Int) {
self.reg = reg
self.op = op
self.A = A
self.B = B
self.C = C
}
// addr (add register) stores into register C the result of adding register A and register B. C = 7
func addr() { reg[C] = reg[A] + reg[B] }
// addi (add immediate) stores into register C the result of adding register A and value B.reg[C] = 5
func addi() { reg[C] = reg[A] + B }
// mulr (multiply register) stores into register C the result of multiplying register A and register B. reg[C] = 12
func mulr() { reg[C] = reg[A] * reg[B] }
// muli (multiply immediate) stores into register C the result of multiplying register A and value B. reg[C] = 6
func muli() { reg[C] = reg[A] * B }
// banr (bitwise AND register) stores into register C the result of the bitwise AND of register A and register B. reg[C] = 0
func banr() { reg[C] = reg[A] & reg[B] }
// bani (bitwise AND immediate) stores into register C the result of the bitwise AND of register A and value B. reg[C] = 2
func bani() { reg[C] = reg[A] & B }
// borr (bitwise OR register) stores into register C the result of the bitwise OR of register A and register B. reg[C] = 7
func borr() { reg[C] = reg[A] | reg[B] }
// bori (bitwise OR immediate) stores into register C the result of the bitwise OR of register A and value B. reg[C] = 3
func bori() { reg[C] = reg[A] | B }
// setr (set register) copies the contents of register A into register C. (Input B is ignored.) reg[C] = 3
func setr() { reg[C] = reg[A] }
// seti (set immediate) stores value A into register C. (Input B is ignored.) reg[C] = 1
func seti() { reg[C] = A}
// gtir (greater-than immediate/register) sets register C to 1 if value A is greater than register B. Otherwise, register C is set to 0. reg[C] = 0
func gtir() { reg[C] = A > reg[B] ? 1 : 0 }
// gtri (greater-than register/immediate) sets register C to 1 if register A is greater than value B. Otherwise, register C is set to 0. reg[C] = 1
func gtri() { reg[C] = reg[A] > B ? 1 : 0 }
// gtrr (greater-than register/register) sets register C to 1 if register A is greater than register B. Otherwise, register C is set to 0. reg[C] = 0
func gtrr() { reg[C] = reg[A] > reg[B] ? 1 : 0 }
// eqir (equal immediate/register) sets register C to 1 if value A is equal to register B. Otherwise, register C is set to 0. reg[C] = 0
func eqir() { reg[C] = A == reg[B] ? 1 : 0 }
// eqri (equal register/immediate) sets register C to 1 if register A is equal to value B. Otherwise, register C is set to 0. reg[C] = 0
func eqri() { reg[C] = reg[A] == B ? 1 : 0 }
// eqrr (equal register/register) sets register C to 1 if register A is equal to register B. Otherwise, register C is set to 0.reg[C] =0
func eqrr() { reg[C] = reg[A] == reg[B] ? 1 : 0 }
}
struct TestCase {
var before: [Int]
var after: [Int]
var op: Int
var A: Int
var B: Int
var C: Int
init(before: [Int], after: [Int], op: Int, A: Int, B: Int, C: Int) {
self.before = before
self.after = after
self.op = op
self.A = A
self.B = B
self.C = C
}
func validate(withIndex fnIndex: Int) -> Bool {
let z8 = Z8(reg: before, op: op, A: A, B: B, C: C)
z8.fn[fnIndex]()
return z8.reg == after
}
func validate(withMapping map: [Int:Int]) -> Bool {
let z8 = Z8(reg: before, op: op, A: A, B: B, C: C)
z8.fn[map[op]!]()
return z8.reg == after
}
func countOpsValid() -> Int {
let tempz8 = Z8(reg: before, op: op, A: A, B: B, C: C)
var count = 0
for opIndex in 0..<tempz8.fn.count {
count += validate(withIndex: opIndex) ? 1 : 0
}
return count
}
}
struct Code {
var op: Int
var A: Int
var B: Int
var C: Int
init(op: Int, A: Int, B: Int, C: Int) {
self.op = op
self.A = A
self.B = B
self.C = C
}
}
class Classification {
var tests: [TestCase] = []
var program: [Code] = []
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day16.txt'
init(withFile filename: String) {
let testFile = Tools.readFile(fromPath: filename)
var testStrings = testFile.components(separatedBy: "\n")
// This gurd statement is just an excuse to use guard
// I'm assuming the last string is an empty string, if not DON'T remove the last string
guard let lastStr = testStrings.last, lastStr.count == 0 else { return }
testStrings.removeLast() // empty string
parse(data: testStrings)
}
// Supply test data in the form of a String
init(withString testFile: String) {
let testStrings = testFile.components(separatedBy: "\n")
parse(data: testStrings)
}
func parse(data testStrings: [String]) {
guard testStrings.count > 0 else { print("Error Parsing"); return }
func parseArray(with line: String) -> [Int] {
var retVal: [Int] = []
let split = line.components(separatedBy: "[")
guard split.count == 2 else { print("Error Array 1"); return retVal }
let split2 = split[1].components(separatedBy: "]")
guard split2.count == 2 else { print("Error Array 2"); return retVal }
let dataString = split2[0].replacingOccurrences(of: " ", with: "")
let data = dataString.components(separatedBy: ",")
retVal = data.map { Int($0)!}
return retVal
}
var testIntermediate = TestCase(before: [], after: [], op: 0, A: 0, B: 0, C: 0)
for line in testStrings {
if line.hasPrefix("Before") {
testIntermediate.before = parseArray(with: line)
} else if line.hasPrefix("After") {
testIntermediate.after = parseArray(with: line)
tests.append(testIntermediate)
} else if line.count > 4 {
let split = line.components(separatedBy: " ")
guard split.count == 4 else { print("Error code \(line)"); return }
testIntermediate.op = Int(split[0])!
testIntermediate.A = Int(split[1])!
testIntermediate.B = Int(split[2])!
testIntermediate.C = Int(split[3])!
} else {
testIntermediate = TestCase(before: [], after: [], op: 0, A: 0, B: 0, C: 0)
}
}
}
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day16Prog.txt'
func loadProgram(withFile filename: String) {
let progFile = Tools.readFile(fromPath: filename)
var progStrings = progFile.components(separatedBy: "\n")
// This gurd statement is just an excuse to use guard
// I'm assuming the last string is an empty string, if not DON'T remove the last string
guard let lastStr = progStrings.last, lastStr.count == 0 else { return }
progStrings.removeLast() // empty string
var progIntermediate = Code(op: 0, A: 0, B: 0, C: 0)
for line in progStrings {
if line.count > 4 {
let split = line.components(separatedBy: " ")
guard split.count == 4 else { print("Error code 2 \(line)"); return }
progIntermediate.op = Int(split[0])!
progIntermediate.A = Int(split[1])!
progIntermediate.B = Int(split[2])!
progIntermediate.C = Int(split[3])!
program.append(progIntermediate)
progIntermediate = Code(op: 0, A: 0, B: 0, C: 0)
}
}
}
func runTests() -> Int {
var validCount: [Int : Int] = [:]
for testNum in 0..<tests.count {
validCount[testNum] = tests[testNum].countOpsValid()
}
return validCount.filter {$0.value >= 3 }.count
}
func validateMap(with map: [Int:Int]) -> Bool {
for test in tests {
if !test.validate(withMapping: map) {
return false
}
}
return true
}
// returns the content of register zero
func runProgram(with map: [Int:Int]) -> Int {
let z8 = Z8(reg: [0, 0, 0, 0], op: 0, A: 0, B: 0, C: 0)
for lineIndex in 0..<program.count {
z8.A = program[lineIndex].A
z8.B = program[lineIndex].B
z8.C = program[lineIndex].C
z8.fn[map[program[lineIndex].op]!]()
}
return z8.reg[0]
}
// Return a map of [SysOp : myOp]
func determineOps() -> [Int:Int] {
var possibleOpCodes: [Int : [Int]] = [:]
for myOpCode in 0..<16 {
var sysOp: [Int: Bool] = [:]
for test in tests {
if test.validate(withIndex: myOpCode) {
sysOp[test.op] = true
}
}
possibleOpCodes[myOpCode] = Array(sysOp.keys)
}
// We have 16 sets off opcodes, now reduce them
func doneTest() -> Bool {
for possible in possibleOpCodes {
if possible.value.count > 1 {
return false
}
}
return true
}
while !doneTest() {
for index in 0..<possibleOpCodes.count {
if possibleOpCodes[index]!.count == 1 {
for inner in 0..<possibleOpCodes.count {
if inner != index {
var possibleArray = possibleOpCodes[inner]!
possibleArray.removeAll(where: { $0 == possibleOpCodes[index]![0] })
possibleOpCodes[inner] = possibleArray
}
}
}
}
}
var retVal: [Int:Int] = [:]
for myOpCode in 0..<16 {
let sysOp = possibleOpCodes[myOpCode]![0]
retVal[sysOp] = myOpCode
}
return retVal
}
}
class Day16: AOCDay {
lazy var tests: (() -> ()) = day16Tests
lazy var final: (() -> ()) = day16Final
let testData1 = """
Before: [3, 2, 1, 1]
9 2 1 2
After: [3, 2, 2, 1]
"""
func testZ8Instructions() {
let z8 = Z8(reg: [0, 0, 0, 0], op: 0, A: 0, B: 0, C: 0)
func initZ8() { z8.A = 1; z8.B = 2; z8.reg = [1, 3, 4, 2] }
initZ8(); z8.addr()
XCTAssertEqual(test: "testZ8Instructions addr", withExpression: (z8.reg[z8.C] == 7))
initZ8(); z8.addi()
XCTAssertEqual(test: "testZ8Instructions addi", withExpression: (z8.reg[z8.C] == 5))
initZ8(); z8.mulr()
XCTAssertEqual(test: "testZ8Instructions mulr", withExpression: (z8.reg[z8.C] == 12))
initZ8(); z8.muli()
XCTAssertEqual(test: "testZ8Instructions muli", withExpression: (z8.reg[z8.C] == 6))
initZ8(); z8.banr()
XCTAssertEqual(test: "testZ8Instructions banr", withExpression: (z8.reg[z8.C] == 0))
initZ8(); z8.bani()
XCTAssertEqual(test: "testZ8Instructions bani", withExpression: (z8.reg[z8.C] == 2))
initZ8(); z8.borr()
XCTAssertEqual(test: "testZ8Instructions borr", withExpression: (z8.reg[z8.C] == 7))
initZ8(); z8.bori()
XCTAssertEqual(test: "testZ8Instructions bori", withExpression: (z8.reg[z8.C] == 3))
initZ8(); z8.setr()
XCTAssertEqual(test: "testZ8Instructions setr", withExpression: (z8.reg[z8.C] == 3))
initZ8(); z8.seti()
XCTAssertEqual(test: "testZ8Instructions seti", withExpression: (z8.reg[z8.C] == 1))
initZ8(); z8.gtir()
XCTAssertEqual(test: "testZ8Instructions gtir", withExpression: (z8.reg[z8.C] == 0))
initZ8(); z8.gtri()
XCTAssertEqual(test: "testZ8Instructions gtri", withExpression: (z8.reg[z8.C] == 1))
initZ8(); z8.gtrr()
XCTAssertEqual(test: "testZ8Instructions gtrr", withExpression: (z8.reg[z8.C] == 0))
initZ8(); z8.eqir()
XCTAssertEqual(test: "testZ8Instructions eqir", withExpression: (z8.reg[z8.C] == 0))
initZ8(); z8.eqri()
XCTAssertEqual(test: "testZ8Instructions eqri", withExpression: (z8.reg[z8.C] == 0))
initZ8(); z8.eqrr()
XCTAssertEqual(test: "testZ8Instructions eqrr", withExpression: (z8.reg[z8.C] == 0))
}
func testInitFile() {
let cla = Classification(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day16.txt")
XCTAssertEqual(test: "testInitFile count", withExpression: (cla.tests.count > 0))
XCTAssertEqual(test: "testInitFile before", withExpression: (cla.tests.last!.before == [3, 1, 2, 2]))
XCTAssertEqual(test: "testInitFile after", withExpression: (cla.tests.last!.after == [3, 1, 2, 0]))
XCTAssertEqual(test: "testInitFile op", withExpression: (cla.tests.last!.op == 11))
XCTAssertEqual(test: "testInitFile A", withExpression: (cla.tests.last!.A == 1))
XCTAssertEqual(test: "testInitFile B", withExpression: (cla.tests.last!.B == 2))
XCTAssertEqual(test: "testInitFile C", withExpression: (cla.tests.last!.C == 3))
}
func testInitString() {
let cla = Classification(withString: testData1)
XCTAssertEqual(test: "testInitString count", withExpression: (cla.tests.count > 0))
XCTAssertEqual(test: "testInitString before", withExpression: (cla.tests[0].before == [3, 2, 1, 1]))
XCTAssertEqual(test: "testInitString after", withExpression: (cla.tests[0].after == [3, 2, 2, 1]))
XCTAssertEqual(test: "testInitString op", withExpression: (cla.tests[0].op == 9))
XCTAssertEqual(test: "testInitString A", withExpression: (cla.tests[0].A == 2))
XCTAssertEqual(test: "testInitString B", withExpression: (cla.tests[0].B == 1))
XCTAssertEqual(test: "testInitString C", withExpression: (cla.tests[0].C == 2))
}
func testCountValidOps3orMore() {
let cla = Classification(withString: testData1)
let testCount = cla.runTests()
XCTAssertEqual(test: "testCountValidOps3orMore count", withExpression: (testCount == 1))
}
func testValidateWithMapping() {
let cla = Classification(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day16.txt")
let mapping = cla.determineOps()
let works = cla.validateMap(with: mapping)
XCTAssertEqual(test: "testValidateWithMapping", withExpression: (works == true))
}
func day16Tests() {
testZ8Instructions()
testInitFile()
testInitString()
testCountValidOps3orMore()
testValidateWithMapping()
}
func day16Final() {
let cla = Classification(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day16.txt")
let testCount = cla.runTests()
print("Answer to part 1 is: \(testCount)")
let mapping = cla.determineOps()
cla.loadProgram(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day16Prog.txt")
let reg0 = cla.runProgram(with: mapping)
print("Answer to part 2 is: \(reg0)")
}
}
+19 -1
View File
@@ -5,7 +5,7 @@
import Foundation import Foundation
let showTests = true let showTests = true
let onlyOneDay = 7 let onlyOneDay = 16
var allTests: [(() -> ())] = [] var allTests: [(() -> ())] = []
var allFinal: [(() -> ())] = [] var allFinal: [(() -> ())] = []
@@ -19,6 +19,15 @@ allTests.append(Day04().tests)
allTests.append(Day05().tests) allTests.append(Day05().tests)
allTests.append(Day06().tests) allTests.append(Day06().tests)
allTests.append(Day07().tests) allTests.append(Day07().tests)
allTests.append(Day08().tests)
allTests.append(Day09().tests)
allTests.append(Day10().tests)
allTests.append(Day11().tests)
allTests.append(Day12().tests)
allTests.append(Day13().tests)
allTests.append(Day14().tests)
allTests.append(Day15().tests)
allTests.append(Day16().tests)
// Compile list of Answers // Compile list of Answers
allFinal.append(Day01().final) allFinal.append(Day01().final)
@@ -28,6 +37,15 @@ allFinal.append(Day04().final)
allFinal.append(Day05().final) allFinal.append(Day05().final)
allFinal.append(Day06().final) allFinal.append(Day06().final)
allFinal.append(Day07().final) allFinal.append(Day07().final)
allFinal.append(Day08().final)
allFinal.append(Day09().final)
allFinal.append(Day10().final)
allFinal.append(Day11().final)
allFinal.append(Day12().final)
allFinal.append(Day13().final)
allFinal.append(Day14().final)
allFinal.append(Day15().final)
allFinal.append(Day16().final)
if onlyOneDay > 0 { if onlyOneDay > 0 {
print("\nDay \(onlyOneDay)") print("\nDay \(onlyOneDay)")
+39 -4
View File
@@ -14,10 +14,45 @@ func XCTAssertEqual(test: String, withExpression isTrue: Bool) {
print(test) print(test)
} }
// func == <T:Equatable> (tuple1:(T,T),tuple2:(T,T)) -> Bool func == <T:Equatable> (tuple1:(T,T),tuple2:(T,T)) -> Bool
// { {
// return (tuple1.0 == tuple2.0) && (tuple1.1 == tuple2.1) return (tuple1.0 == tuple2.0) && (tuple1.1 == tuple2.1)
// } }
struct GridDir {
static let none = GridPoint(X: 0, Y: 0)
static let up = GridPoint(X: 0, Y: -1)
static let down = GridPoint(X: 0, Y: 1)
static let left = GridPoint(X: -1, Y: 0)
static let right = GridPoint(X: 1, Y: 0)
}
struct GridPoint: Equatable, Comparable, Hashable {
var X = 0
var Y = 0
var up: GridPoint { return GridPoint(X: self.X, Y: self.Y-1) }
var down: GridPoint { return GridPoint(X: self.X, Y: self.Y+1) }
var left: GridPoint { return GridPoint(X: self.X-1, Y: self.Y) }
var right: GridPoint {return GridPoint(X: self.X+1, Y: self.Y) }
var hashValue: Int { return X.hashValue ^ Y.hashValue }
static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
return (lhs.X == rhs.X) && (lhs.Y == rhs.Y)
}
static func < (lhs: GridPoint, rhs: GridPoint) -> Bool {
return lhs.Y == rhs.Y ? lhs.X < rhs.X : lhs.Y < rhs.Y
}
static func + (lhs: GridPoint, rhs: GridPoint) -> GridPoint {
return GridPoint(X: lhs.X + rhs.X, Y: lhs.Y + rhs.Y)
}
static func - (lhs: GridPoint, rhs: GridPoint) -> GridPoint {
return GridPoint(X: lhs.X - rhs.X, Y: lhs.Y - rhs.Y)
}
}
struct Tools { struct Tools {
static func readFile(fromPath path: String) -> String { static func readFile(fromPath path: String) -> String {