Compare commits

...
20 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
peterr 62f65846c7 Added code for Day 7 (Part 1)
Day 7: The Sum of Its Parts
2018-12-07 23:20:04 -06:00
peterr a57839a58a Enabled equatable for tuple 2018-12-07 23:19:00 -06:00
peterr 36f95e6f49 Add Day 6 code
Day 6: Chronal Coordinates
2018-12-07 01:16:58 -06:00
peterr f5c7fe9189 Add Equatable Tuple to tools 2018-12-07 01:16:01 -06:00
peterr c780f42f1d Changed the method for Day 5
Reduce as we're building the array vs. pulling elements out of an array bit by bit.
2018-12-05 22:11:53 -06:00
21 changed files with 8101 additions and 132 deletions
+101
View File
@@ -0,0 +1,101 @@
Step G must be finished before step X can begin.
Step X must be finished before step B can begin.
Step A must be finished before step I can begin.
Step D must be finished before step H can begin.
Step O must be finished before step T can begin.
Step H must be finished before step C can begin.
Step S must be finished before step E can begin.
Step U must be finished before step M can begin.
Step M must be finished before step Z can begin.
Step R must be finished before step N can begin.
Step C must be finished before step Q can begin.
Step T must be finished before step P can begin.
Step I must be finished before step W can begin.
Step W must be finished before step N can begin.
Step P must be finished before step J can begin.
Step N must be finished before step F can begin.
Step Y must be finished before step J can begin.
Step J must be finished before step L can begin.
Step L must be finished before step E can begin.
Step E must be finished before step B can begin.
Step Q must be finished before step B can begin.
Step F must be finished before step K can begin.
Step V must be finished before step K can begin.
Step Z must be finished before step B can begin.
Step B must be finished before step K can begin.
Step G must be finished before step U can begin.
Step E must be finished before step V can begin.
Step A must be finished before step Z can begin.
Step C must be finished before step V can begin.
Step R must be finished before step B can begin.
Step Q must be finished before step Z can begin.
Step R must be finished before step K can begin.
Step T must be finished before step B can begin.
Step L must be finished before step B can begin.
Step M must be finished before step K can begin.
Step T must be finished before step Z can begin.
Step W must be finished before step B can begin.
Step I must be finished before step E can begin.
Step A must be finished before step M can begin.
Step V must be finished before step Z can begin.
Step Y must be finished before step B can begin.
Step Q must be finished before step F can begin.
Step W must be finished before step Y can begin.
Step U must be finished before step K can begin.
Step D must be finished before step F can begin.
Step P must be finished before step F can begin.
Step N must be finished before step L can begin.
Step H must be finished before step T can begin.
Step H must be finished before step L can begin.
Step C must be finished before step T can begin.
Step H must be finished before step I can begin.
Step Z must be finished before step K can begin.
Step L must be finished before step Z can begin.
Step Y must be finished before step K can begin.
Step I must be finished before step V can begin.
Step P must be finished before step K can begin.
Step P must be finished before step N can begin.
Step G must be finished before step D can begin.
Step I must be finished before step J can begin.
Step H must be finished before step K can begin.
Step L must be finished before step Q can begin.
Step D must be finished before step M can begin.
Step O must be finished before step V can begin.
Step R must be finished before step L can begin.
Step D must be finished before step W can begin.
Step M must be finished before step J can begin.
Step O must be finished before step R can begin.
Step N must be finished before step Z can begin.
Step Y must be finished before step V can begin.
Step W must be finished before step L can begin.
Step U must be finished before step Y can begin.
Step S must be finished before step V can begin.
Step M must be finished before step P can begin.
Step X must be finished before step A can begin.
Step A must be finished before step E can begin.
Step A must be finished before step L can begin.
Step A must be finished before step R can begin.
Step V must be finished before step B can begin.
Step P must be finished before step B can begin.
Step E must be finished before step F can begin.
Step T must be finished before step V can begin.
Step S must be finished before step R can begin.
Step T must be finished before step F can begin.
Step P must be finished before step Y can begin.
Step A must be finished before step C can begin.
Step J must be finished before step F can begin.
Step H must be finished before step B can begin.
Step C must be finished before step E can begin.
Step P must be finished before step E can begin.
Step D must be finished before step I can begin.
Step X must be finished before step F can begin.
Step T must be finished before step Q can begin.
Step J must be finished before step B can begin.
Step C must be finished before step B can begin.
Step P must be finished before step Q can begin.
Step H must be finished before step R can begin.
Step F must be finished before step B can begin.
Step T must be finished before step J can begin.
Step A must be finished before step W can begin.
Step N must be finished before step K can begin.
Step T must be finished before step E can begin.
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
+39 -128
View File
@@ -4,13 +4,9 @@
import Foundation
// Traverse the string
// Find pairs of like letters, but opposite capitalization - < recursive? >
// -- reduce -- and repeat
class Reduction {
var polymer: [Character] = []
var acc: [Character] = []
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day05.txt'
init(withFile filename: String) {
@@ -20,84 +16,48 @@ class Reduction {
guard polymerString.count > 0 else { return }
polymerString.removeLast() // new-line
polymer = Array(polymerString)
acc = Array(repeating: " ", count: polymer.count)
}
// Supply test data in the form of a String
init(withString poly: String) {
polymer = Array(poly)
acc = Array(repeating: " ", count: polymer.count)
}
// return an array of indicies of the first in an opposing pair
func getOpposites()-> [Int] {
var retVal: [Int] = []
if polymer.count > 1 {
var hit = false
for index in 0..<polymer.count-1 {
if hit {
hit = false
} else {
if (polymer[index] != polymer[index+1]) && (String(polymer[index]).lowercased() == String(polymer[index+1]).lowercased()) {
hit = true
retVal.append(index)
}
}
func reducer() {
var aIdx = 0
acc[aIdx] = polymer[0]
for index in 1..<polymer.count {
if (aIdx > -1 && acc[aIdx] != polymer[index]) && (String(acc[aIdx]).lowercased() == String(polymer[index]).lowercased()) {
acc[aIdx] = " "
aIdx -= 1
} else {
aIdx += 1
acc[aIdx] = polymer[index]
}
}
return retVal
}
// blast the units and then "compact" the ploymer
func reduce(withRanges ranges: [Int]) {
for range in ranges {
polymer[range] = " "
polymer[range+1] = " "
}
polymer = polymer.filter {$0 != " "}
}
func reducePolymer() {
var opp = getOpposites()
while opp.count > 0 {
reduce(withRanges: opp)
opp = getOpposites()
}
}
func removeUnit(withType unit: Character) {
for index in 0..<polymer.count {
if polymer[index] == unit {
polymer[index] = " "
}
}
let upperUnit = Character(String(unit).uppercased())
for index in 0..<polymer.count {
if polymer[index] == upperUnit {
polymer[index] = " "
}
}
polymer = polymer.filter {$0 != " "}
polymer = acc.filter {$0 != " "}
}
func findSmallestFullyReactedAndRemovedPolymer() -> Int {
let start = Unicode.Scalar("a").value
let end = Unicode.Scalar("z").value
let myrange = start...end
let polyCopy = polymer
var minLen = polymer.count
for i in myrange {
for i in start...end {
polymer = polyCopy
acc = Array(repeating: " ", count: polymer.count)
if let type = Unicode.Scalar(i) {
let unit = Character(type)
removeUnit(withType: unit)
reducePolymer()
let upperUnit = Character(String(unit).uppercased())
polymer = polymer.filter { $0 != unit && $0 != upperUnit }
reducer()
minLen = min(minLen, polymer.count)
}
}
return minLen
}
}
class Day05: AOCDay {
@@ -119,99 +79,55 @@ class Day05: AOCDay {
XCTAssertEqual(test: "testReductionInit with File", withExpression: (reduc.polymer.last == "Y"))
}
func testGetOpposites() {
var reduc = Reduction(withString: "aA")
var opp = reduc.getOpposites()
XCTAssertEqual(test: "testGetOpposites count", withExpression: (opp.count == 1))
XCTAssertEqual(test: "testGetOpposites range", withExpression: (opp == [0]))
reduc = Reduction(withString: "abBA")
opp = reduc.getOpposites()
XCTAssertEqual(test: "testGetOpposites count", withExpression: (opp.count == 1))
XCTAssertEqual(test: "testGetOpposites range", withExpression: (opp == [1]))
reduc = Reduction(withString: "abAB")
opp = reduc.getOpposites()
XCTAssertEqual(test: "testGetOpposites count", withExpression: (opp.count == 0))
reduc = Reduction(withString: "aabAAB")
opp = reduc.getOpposites()
XCTAssertEqual(test: "testGetOpposites count", withExpression: (opp.count == 0))
reduc = Reduction(withString: testData)
opp = reduc.getOpposites()
XCTAssertEqual(test: "testGetOpposites count", withExpression: (opp.count == 2))
XCTAssertEqual(test: "testGetOpposites range", withExpression: (opp == [4, 10]))
}
func testReduce() {
var reduc = Reduction(withString: "aA")
var opp = reduc.getOpposites()
reduc.reduce(withRanges: opp)
XCTAssertEqual(test: "testReduce count after", withExpression: (reduc.polymer.count == 0))
reduc = Reduction(withString: "abBA")
opp = reduc.getOpposites()
reduc.reduce(withRanges: opp)
XCTAssertEqual(test: "testReduce count after", withExpression: (reduc.polymer.count == 2))
reduc = Reduction(withString: "abAB")
opp = reduc.getOpposites()
reduc.reduce(withRanges: opp)
XCTAssertEqual(test: "testReduce count after", withExpression: (reduc.polymer.count == 4))
reduc = Reduction(withString: "aabAAB")
opp = reduc.getOpposites()
reduc.reduce(withRanges: opp)
XCTAssertEqual(test: "testReduce count after", withExpression: (reduc.polymer.count == 6))
reduc = Reduction(withString: testData)
opp = reduc.getOpposites()
reduc.reduce(withRanges: opp)
XCTAssertEqual(test: "testReduce count after", withExpression: (reduc.polymer.count == 12))
}
func testReducePolymer() {
var reduc = Reduction(withString: "aA")
reduc.reducePolymer()
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == ""))
reduc = Reduction(withString: "abBA")
reduc.reducePolymer()
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == ""))
reduc = Reduction(withString: "abAB")
reduc.reducePolymer()
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == "abAB"))
reduc = Reduction(withString: "aabAAB")
reduc.reducePolymer()
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == "aabAAB"))
reduc = Reduction(withString: testData)
reduc.reducePolymer()
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == "dabCBAcaDA"))
}
func testRemoveUnit() {
var reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "a")
reduc.polymer = reduc.polymer.filter { $0 != "a" && $0 != "A" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "dbcCCBcCcD"))
reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "b")
reduc.polymer = reduc.polymer.filter { $0 != "b" && $0 != "B" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "daAcCaCAcCcaDA"))
reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "c")
reduc.polymer = reduc.polymer.filter { $0 != "c" && $0 != "C" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "dabAaBAaDA"))
reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "d")
reduc.polymer = reduc.polymer.filter { $0 != "d" && $0 != "D" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "abAcCaCBAcCcaA"))
}
func testRemoveAndReact() {
var reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "a")
reduc.reducePolymer()
reduc.polymer = reduc.polymer.filter { $0 != "a" && $0 != "A" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact a", withExpression: (String(reduc.polymer) == "dbCBcD"))
reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "b")
reduc.reducePolymer()
reduc.polymer = reduc.polymer.filter { $0 != "b" && $0 != "B" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact b", withExpression: (String(reduc.polymer) == "daCAcaDA"))
reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "c")
reduc.reducePolymer()
reduc.polymer = reduc.polymer.filter { $0 != "c" && $0 != "C" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact c", withExpression: (String(reduc.polymer) == "daDA"))
reduc = Reduction(withString: testData)
reduc.removeUnit(withType: "d")
reduc.reducePolymer()
reduc.polymer = reduc.polymer.filter { $0 != "d" && $0 != "D" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact d", withExpression: (String(reduc.polymer) == "abCBAc"))
}
@@ -223,8 +139,6 @@ class Day05: AOCDay {
func day05Tests() {
testReductionInit()
testGetOpposites()
testReduce()
testReducePolymer()
testRemoveUnit()
testRemoveAndReact()
@@ -232,13 +146,10 @@ class Day05: AOCDay {
}
func day05Final() {
// var reduc = Reduction(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day05.txt")
// Run test data as the real data takes too long
var reduc = Reduction(withString: testData)
reduc.reducePolymer()
var reduc = Reduction(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day05.txt")
reduc.reducer()
print("Answer to part 1 is: \(reduc.polymer.count)")
// reduc = Reduction(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day05.txt")
reduc = Reduction(withString: testData)
reduc = Reduction(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day05.txt")
let answer = reduc.findSmallestFullyReactedAndRemovedPolymer()
print("Answer to part 2 is: \(answer)")
}
+288
View File
@@ -0,0 +1,288 @@
//
// Advent of Code 2018 "Day 6: Chronal Coordinates"
//
import Foundation
class Coordinates {
var points: [GridPoint] = []
var dimensions: GridPoint
init(withString str: String) {
var maxX = 0
var maxY = 0
dimensions = GridPoint(X: 0, Y: 0)
let coordStrArray = str.components(separatedBy: "\n")
for elem in coordStrArray {
let coord = elem.components(separatedBy: ", ")
guard coord.count > 1 else { return }
guard let x = Int(coord[0]), let y = Int(coord[1]) else { return }
points.append(GridPoint(X: x, Y: y))
maxX = max(maxX, x)
maxY = max(maxY, y)
}
dimensions = GridPoint(X: maxX+1, Y: maxY)
}
func distance(from: GridPoint, to: GridPoint) -> Int {
let retVal = abs(from.X - to.X) + abs(from.Y - to.Y)
return retVal
}
// Given any gridpoint, find the LocPoint with the min distance to it (returned as Int (index))
func findLocWithMinDistance(toPoint measurePt: GridPoint) -> (dist: Int, index: Int) {
var minDist = dimensions.X + dimensions.Y // max distance
var minIndex = 0
var dist: [Int: Int] = [:]
for locIndex in 0..<points.count {
dist[locIndex] = distance(from: points[locIndex], to: measurePt)
if dist[locIndex] ?? -1 < minDist {
minDist = dist[locIndex] ?? -1
minIndex = locIndex
}
}
let duplicate = dist.filter { $0.value == minDist }.count > 1
return (dist: duplicate ? -1 : minDist, index: minIndex)
}
// Given any gridpoint, find the LocPoint with the min distance to it (returned as Int (index))
func findSumOfAllDistances(toPoint measurePt: GridPoint) -> Int {
var sum = 0
for locIndex in 0..<points.count {
sum += distance(from: points[locIndex], to: measurePt)
}
return sum
}
// Fill out the grid
func fillGridWithMinDistIndicies() -> [Int] {
var retVal: [Int] = []
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
let index = findLocWithMinDistance(toPoint: GridPoint(X: i, Y: j))
if index.dist < 0 {
retVal.append(-1) // indicate duplicate
} else {
retVal.append(index.index)
}
}
}
return retVal
}
// Fill out the grid
func fillGridWithSumLessThan(value nearestSum: Int) -> [Bool] {
var retVal: [Bool] = []
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
retVal.append(findSumOfAllDistances(toPoint: GridPoint(X: i, Y: j)) < nearestSum)
}
}
return retVal
}
func solveForPart1(print printMap: Bool) -> Int {
var map = fillGridWithMinDistIndicies()
var infinite: [Int : Int] = [:]
let maxX = dimensions.X
let maxY = dimensions.Y
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
let idx = j * (dimensions.X + 1) + i
if i == 0 || j == 0 || i == maxX || j == maxY && infinite[idx] == nil {
infinite[map[idx]] = 1
}
if printMap {
if map[idx] < 0 {
print("..", terminator: "")
} else {
print(NSString(format:"%2d", map[idx]), terminator: "")
}
}
}
if printMap { print("") }
}
if printMap { print("infinite = \(infinite)") }
var maxArea = 0
for locIdx in 0..<points.count {
if infinite[locIdx] == nil {
let area = map.filter { $0 == locIdx }.count
maxArea = max(maxArea, area)
}
}
return maxArea
}
func solveForPart2(print printMap: Bool, withValue nearestSum: Int) -> Int {
let map = fillGridWithSumLessThan(value: nearestSum)
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
let idx = j * (dimensions.X + 1) + i
if printMap {
if map[idx] {
print("#", terminator: "")
} else {
print(".", terminator: "")
}
}
}
if printMap { print("") }
}
return map.filter { $0 == true }.count
}
}
class Day06: AOCDay {
lazy var tests: (() -> ()) = day06Tests
lazy var final: (() -> ()) = day06Final
let testData = """
1, 1
1, 6
8, 3
3, 4
5, 5
8, 9
"""
func printGrid() {
let coor = Coordinates(withString: testData)
for j in 0...coor.dimensions.Y {
for i in 0...coor.dimensions.X {
if let index = coor.points.firstIndex(of: GridPoint(X: i, Y: j)) {
print(" \(index) ", terminator: "")
} else {
print(" . ", terminator: "")
}
}
print("")
}
print("")
}
func testCoordinatesInit() {
let coor = Coordinates(withString: testData)
guard coor.points.count == 6 else {
XCTAssertEqual(test: "testCoordinatesInit count", withExpression: (false))
return
}
XCTAssertEqual(test: "testCoordinatesInit A", withExpression: (coor.points[0] == GridPoint(X: 1, Y: 1)))
XCTAssertEqual(test: "testCoordinatesInit D", withExpression: (coor.points[3] == GridPoint(X: 3, Y: 4)))
XCTAssertEqual(test: "testCoordinatesInit F", withExpression: (coor.points[5] == GridPoint(X: 8, Y: 9)))
}
func testDistanceAtoAll() {
let coor = Coordinates(withString: testData)
guard coor.points.count == 6 else {
XCTAssertEqual(test: "testDistanceAtoAll count", withExpression: (false))
return
}
var dist = coor.distance(from: coor.points[0], to: coor.points[1])
XCTAssertEqual(test: "testDistanceAtoAll A to B", withExpression: (dist == 5))
dist = coor.distance(from: coor.points[0], to: coor.points[2])
XCTAssertEqual(test: "testDistanceAtoAll A to C", withExpression: (dist == 9))
dist = coor.distance(from: coor.points[0], to: coor.points[3])
XCTAssertEqual(test: "testDistanceAtoAll A to D", withExpression: (dist == 5))
dist = coor.distance(from: coor.points[0], to: coor.points[4])
XCTAssertEqual(test: "testDistanceAtoAll A to E", withExpression: (dist == 8))
dist = coor.distance(from: coor.points[0], to: coor.points[5])
XCTAssertEqual(test: "testDistanceAtoAll A to F", withExpression: (dist == 15))
}
func testFindLocWithMinDistance() {
let coor = Coordinates(withString: testData)
var nearest = coor.findLocWithMinDistance(toPoint: GridPoint(X: 0, Y: 0))
XCTAssertEqual(test: "testFindLocWithMinDistance (0, 0)", withExpression: (nearest.index == 0))
nearest = coor.findLocWithMinDistance(toPoint: GridPoint(X: 6, Y: 1))
XCTAssertEqual(test: "testFindLocWithMinDistance (6, 1)", withExpression: (nearest.index == 2))
}
func testSolveForPart1() {
let coor = Coordinates(withString: testData)
let answer = coor.solveForPart1(print: false)
XCTAssertEqual(test: "testSolveForPart1", withExpression: (answer == 17))
}
func testFindSumOfAllDistances() {
let coor = Coordinates(withString: testData)
let sum = coor.findSumOfAllDistances(toPoint: GridPoint(X: 4, Y: 3))
XCTAssertEqual(test: "testFindSumOfAllDistances (4, 3)", withExpression: (sum == 30))
}
func testSolveForPart2() {
let coor = Coordinates(withString: testData)
let answer = coor.solveForPart2(print: false , withValue: 32)
XCTAssertEqual(test: "testSolveForPart2", withExpression: (answer == 16))
}
func day06Tests() {
printGrid()
testCoordinatesInit()
testDistanceAtoAll()
testFindLocWithMinDistance()
testSolveForPart1()
testFindSumOfAllDistances()
testSolveForPart2()
}
func day06Final() {
let coor = Coordinates(withString: finalData)
var answer = coor.solveForPart1(print: false)
print("Answer to part 1 is: \(answer)")
answer = coor.solveForPart2(print: false, withValue: 10000)
print("Answer to part 2 is: \(answer)")
}
let finalData = """
342, 203
79, 64
268, 323
239, 131
246, 87
161, 93
306, 146
43, 146
57, 112
241, 277
304, 303
143, 235
253, 318
97, 103
200, 250
67, 207
345, 149
133, 222
232, 123
156, 359
80, 224
51, 145
138, 312
339, 294
297, 256
163, 311
241, 321
126, 66
145, 171
359, 184
241, 58
108, 312
117, 118
101, 180
58, 290
324, 42
141, 190
270, 149
209, 294
296, 345
68, 266
233, 281
305, 183
245, 230
161, 295
335, 352
93, 66
227, 59
264, 249
116, 173
"""
}
+305
View File
@@ -0,0 +1,305 @@
//
// Advent of Code 2018 "Day 7: The Sum of Its Parts"
//
import Foundation
struct Instruction: Equatable, Comparable {
var complete = Character(" ")
var before = Character(" ")
static func == (lhs: Instruction, rhs: Instruction) -> Bool {
return (lhs.complete == rhs.complete) && (lhs.before == rhs.before)
}
static func < (lhs: Instruction, rhs: Instruction) -> Bool {
return lhs.complete < rhs.complete
}
}
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 {
var instrList: [Instruction] = []
var workers: [Worker] = []
var masterClock = 0
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt'
init(withFile filename: String, numWorkers: Int) {
let instrString = Tools.readFile(fromPath: filename)
var instrArray = instrString.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 = instrArray.last, lastStr.count == 0 else { return }
instrArray.removeLast() // empty string
parseData(withInstructions: instrArray)
workers = Array(repeating: Worker(), count: numWorkers)
}
// Supply test data in the form of a String
init(withString instrString: String, numWorkers: Int) {
let instrArray = instrString.components(separatedBy: "\n")
parseData(withInstructions: instrArray)
workers = Array(repeating: Worker(), count: numWorkers)
}
func parseData(withInstructions instr: [String]) {
for ins in instr {
instrList.append(Instruction(complete: ins[5], before: ins[36]))
}
}
func getNextAvailable() -> Character? {
var retVal: Character?
var availDict: [Character : Bool] = [:]
for index in 0..<instrList.count {
if !instrList.contains(where: { $0.before == instrList[index].complete} ) {
availDict[instrList[index].complete] = true
}
}
var available = Array(availDict.keys)
available.sort()
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 completeAllInstructions() -> String {
var retVal = ""
var last: Character = "*"
while let instruction = getNextAvailable() {
retVal.append(instruction)
if let lastInstr = instrList.first(where: { $0.complete == instruction }) {
last = lastInstr.before
}
instrList.removeAll(where: { $0.complete == instruction })
}
retVal.append(last)
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 {
lazy var tests: (() -> ()) = day07Tests
lazy var final: (() -> ()) = day07Final
let testData = """
Step C must be finished before step A can begin.
Step C must be finished before step F can begin.
Step A must be finished before step B can begin.
Step A must be finished before step D can begin.
Step B must be finished before step E can begin.
Step D must be finished before step E can begin.
Step F must be finished before step E can begin.
"""
func testSumPartsInit() {
var instr = SumParts(withString: testData, numWorkers: 0)
XCTAssertEqual(test: "testSumPartsInit string 0", withExpression: (instr.instrList[0].before == "A"))
XCTAssertEqual(test: "testSumPartsInit string 4", withExpression: (instr.instrList[4].complete == "B"))
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 4", withExpression: (instr.instrList[4].complete == "O"))
}
func testGetNextAvailable() {
let instr = SumParts(withString: testData, numWorkers: 0)
if let avail = instr.getNextAvailable() {
XCTAssertEqual(test: "testGetNextAvailable", withExpression: (avail == "C"))
} else {
XCTAssertEqual(test: "testGetNextAvailable", withExpression: (false))
}
}
func testCompleteInstructions() {
let instr = SumParts(withString: testData, numWorkers: 0)
let answer = instr.completeAllInstructions()
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() {
testSumPartsInit()
testGetNextAvailable()
testCompleteInstructions()
testDuration()
testGetTimeUntilWorkerFree()
testAdvanceTime()
testAdvanceClockAndCompleteInstructions()
testScheduleWorkers()
testAnswerPart2()
}
func day07Final() {
var instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt", numWorkers: 0)
let answerPart1 = instr.completeAllInstructions()
instr = SumParts(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day07.txt", numWorkers: 5)
instr.scheduleWorkers()
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)")
}
}
+23 -1
View File
@@ -5,7 +5,7 @@
import Foundation
let showTests = true
let onlyOneDay = 0
let onlyOneDay = 16
var allTests: [(() -> ())] = []
var allFinal: [(() -> ())] = []
@@ -17,6 +17,17 @@ allTests.append(Day02().tests)
allTests.append(Day03().tests)
allTests.append(Day04().tests)
allTests.append(Day05().tests)
allTests.append(Day06().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
allFinal.append(Day01().final)
@@ -24,6 +35,17 @@ allFinal.append(Day02().final)
allFinal.append(Day03().final)
allFinal.append(Day04().final)
allFinal.append(Day05().final)
allFinal.append(Day06().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 {
print("\nDay \(onlyOneDay)")
+42 -3
View File
@@ -14,6 +14,45 @@ func XCTAssertEqual(test: String, withExpression isTrue: Bool) {
print(test)
}
func == <T:Equatable> (tuple1:(T,T),tuple2:(T,T)) -> Bool
{
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 {
static func readFile(fromPath path: String) -> String {
@@ -53,9 +92,9 @@ extension StringProtocol {
return compactMap { $0.ascii }
}
// subscript(offset: Int) -> Element {
// return self[index(startIndex, offsetBy: offset)]
// }
subscript(offset: Int) -> Element {
return self[index(startIndex, offsetBy: offset)]
}
}
extension String {