Compare commits

...
28 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
peterr 904a46cc3c Add Day 5 code
Day 5: Alchemical Reduction
2018-12-05 18:26:08 -06:00
peterr 6bff35b952 Add String utils 2018-12-05 18:25:33 -06:00
peterr de4e101672 Finish Day 4 2018-12-05 09:31:00 -06:00
peterr 6ba10d386f Add Day 4 code (part 1)
Day 4: Repose Record
2018-12-04 23:47:45 -06:00
peterr 538c76c1eb Finish Day 3 2018-12-04 09:11:51 -06:00
peterr 72bafa3d08 Add Day 3 code (not finished)
Day 3: No Matter How You Slice It
2018-12-03 22:58:59 -06:00
peterr 9802ed1f35 Add Day 2 code with data file
Day 2: Inventory Management System
2018-12-03 12:37:50 -06:00
peterr 7da7595db4 Add String and Character extensions to Tools 2018-12-03 12:36:29 -06:00
28 changed files with 11627 additions and 2 deletions
+250
View File
@@ -0,0 +1,250 @@
fonbsmjyqugrapsczckghtvdxl
fonpsmjyquwrnpeczikghtvdxw
fonbsmdymuwrapexzikghtvdxl
fonwsmjyquwrapeczikghttdpl
fonbsmjkquwrapeczjkghtvdxx
yonbsmjyquwrapecgikghtvdxc
donbsmjyquqrapeczikghtadxl
monbsmjyquprgpeczikghtvdxl
fonbsmjyquwvapecqgkghtvdxl
fonbsmjyquwrkphczikghsvdxl
fonbomjyeuwvapeczikghtvdxl
fonwsmjyjuwrapoczikghtvdxl
foybsmjyquwcapeczikghsvdxl
fonbsmjyquwrtaeczikgptvdxl
ponbsmpyquwjapeczikghtvdxl
flnbcmjyquwrqpeczikghtvdxl
fonbsmjyquwrapegzikvbtvdxl
fonbjmjyqgwrazeczikghtvdxl
zoabsmjyquwkapeczikghtvdxl
fonbsmjyquwrapecziktxkvdxl
fonbsxjyrpwrapeczikghtvdxl
fonbsmjbquwqapeciikghtvdxl
lonbsmjyquwraphczikghtvdul
ftnbsmjyquwrapcczikghtxdxl
fonbsmjyqgwrapeczikghtldxc
fonbsmjsquwmapeyzikghtvdxl
fonbsmjyqfwrapecziqghtgdxl
yonbsmjyquwraveczikgftvdxl
fovbsmjyquwrapeczikggkvdxl
fonbsmjyquwrapezzikghbvdvl
fonzsmxyquwrapeczukghtvdxl
fonbemjyquwrapevzikghtvrxl
conbsxjxquwrapeczikghtvdxl
fonbsmjsmewrapeczikghtvdxl
folbsmjyqhwrapqczikghtvdxl
fonbsmjyquwrzneczikghtvdxn
fonbsmjyquirapeczikjhtvdll
fontsmgyquwrgpeczikghtvdxl
fonbsmjyauwrapeczbfghtvdxl
ftnbsmjyquwrapecpifghtvdxl
fonvsmjyqewrapeczikghlvdxl
fonbsljyquwrapecziklhtvdxw
fonbbmjyquwrapeczikghvadxl
ponbsmjyquwrspeczikghivdxl
fonbsmjcquwrapeccikghtvuxl
fonbsmjnquwrapetzikghtvlxl
fonbsmjymuwrapeczieghtvdxr
ffnbsxnyquwrapeczikghtvdxl
fonbsmjytuwrajeczzkghtvdxl
fonssmjyquwhapeczikghkvdxl
fonbsajyuuwrapeczikghlvdxl
fonbsmjyquwrapeczihghtcixl
fohbsmjyquwrapzczirghtvdxl
fonbsmjyquwrapecjqnghtvdxl
fonbsmjytuhrapeczihghtvdxl
foabumjyquwrapeczikghtvdxz
conbsmjyqtwrapeczikggtvdxl
fonbsmjyiqwrapeczokghtvdxl
fondsmjypuwrapeczikghtvjxl
fonbswjyquwrapeczikgvtydxl
fonbsmjyqqwrapeczikkhtvdbl
fonbsmjyquwrapemzitghtvdsl
fonbsmjyquwrspecziegxtvdxl
fonbsmpyquwrgpeczikghtwdxl
fodbsmjqquwrapeczmkghtvdxl
fonbsmjkquwrapeczikghpvdxr
fonbsmjyquwrapeczikshzvmxl
fznbsmjyqulrapeczikghkvdxl
fonbsmjyquwripeczikghtbdjl
fcnbsmjyquzrapecyikghtvdxl
ronbxmjyquwrapeczikghgvdxl
fonbsmuyvuwrgpeczikghtvdxl
fonbsmjyyuwraplczikghtudxl
poxbsmjyqewrapeczikghtvdxl
foabsmjyquwrapecziqghtvpxl
ponbsmjrquwrapeczikchtvdxl
fonzzmjyquwrapeczikghtvdxs
wonbsmjyquwghpeczikghtvdxl
fofbsejyquwrapeczikgctvdxl
ponbsmjyquwrayegzikghtvdxl
fonbumjyquwripeczikghtvdxf
fonbsmqyquwrapeczikgftvdxv
qonbsmjyquwraplczitghtvdxl
fmnbsajdquwrapeczikghtvdxl
fonbsrjyquwrapempikghtvdxl
fonbsmjyquwrapeczikgotudxw
fonbsmtyquwrapeflikghtvdxl
fzqbsmjyquwrapecjikghtvdxl
fdnbsmjyquwraqeclikghtvdxl
fvnbsijyquwrapechikghtvdxl
fovbsmjyquwsapeczikghqvdxl
ffjbsmjyqgwrapeczikghtvdxl
fonbsmjyquwrapeczvkhhivdxl
forbamjjquwrapeczikghtvdxl
fonbwmjyquwtapeyzikghtvdxl
fonvsmjyquwrapeczikglnvdxl
fonnsmjyguwrapeczikghtvxxl
fopbsmjyquwrapeczikghtvaxz
fonbsmjyquwiapeczikrhavdxl
fonbsujyquwrapeczikthtvdjl
fonpsmkyeuwrapeczikghtvdxl
fonbsmjyquwrapeczqkgttvdxk
fonbsmjyqzwrapeczikgrtddxl
fokbsmjiquwrapeczikgltvdxl
fonbsmjyqbwrapeczikghttdxo
fonbsejyquwrapeczikghbvdal
fonblmjyquwyaveczikghtvdxl
fonbsmjyquwlzpepzikghtvdxl
fonbsmjyqulrapbczigghtvdxl
fonbsmjyxuwrapecziyghtvsxl
fonbyjjyquwrapeczikghtvdxn
fonbhmjyquwrapeczikghtjhxl
fonbspjykuwraieczikghtvdxl
aonbsmjyquwwapeczikchtvdxl
fombsmjyquwyapeczikghtvdll
fonbsmjynuwrapeczivgbtvdxl
xonbsmjfquwrapeczikghqvdxl
fonbyzjyquwzapeczikghtvdxl
fbnbsmjyquwrapeczimgvtvdxl
qonbsmjyquwraoeczikgftvdxl
fonbsrjyquwrapeczikghtvjxm
fonbsmjyquwrapxjzykghtvdxl
fonbwgjyquwrapecziklhtvdxl
fonjcmjyouwrapeczikghtvdxl
fonbsmjyquwrapefzisuhtvdxl
fonbsmjyqywrspeczikghtvnxl
qonbsmjyquwrapeczlkuhtvdxl
fonbsmjyqlprapeczikghtvdbl
fonbsmjzquwrapedzikfhtvdxl
fonbsmjyquwrapeczizghtvjxq
fonbsmxyquwrrpeczikghtvcxl
fonpsmjyquwoapeczikghjvdxl
fonbshkyauwrapeczikghtvdxl
fonbsmjysuwrapeczilghpvdxl
fovwsxjyquwrapeczikghtvdxl
fonbsmjyquwrppecnikghmvdxl
fonbkmjyiuwrrpeczikghtvdxl
gonbsmjyquwrapeczikphtudxl
foncsmjyqlwrapeczimghtvdxl
fonbsmjhquwrtpeczikghtvdxg
fogbsmjyquarapeczikghtvdil
fonbsmjyquwraperzekghwvdxl
fonbstjyquwrapeczicghtedxl
fonbsmjoquhrapeczikgotvdxl
fonbsmjykuwrareczikgdtvdxl
fonbsmjyvuwrayeczivghtvdxl
fonbzmgyquwraptczikghtvdxl
fonbsmjyqubrapeczikgftvdxb
fonbgmjyjuwrapeczikghtvdul
fonbsmjzqurrapeczikghtvfxl
fonbsmjyiuwrapeczikgstvtxl
fpnbstjyquwrapeczikghtvdcl
fonbpmjyquwrapeczivghtndxl
fonbsmjyquwrapeczilgptvvxl
fonbsmjyqdwripecbikghtvdxl
fonbsmjytuwgapnczikghtvdxl
fonbsejyquwrapedzikghtvdml
fonbsojyqdwrapeczikghtgdxl
fonbsmjykuwrayeczicghtvdxl
foubsmtyquwrapeczikchtvdxl
fonbqmjyqukrapeyzikghtvdxl
fonbsmjyquwaapenzikghtvdwl
fonbsmeyquwrapeyzixghtvdxl
fonusmjyquhrapeczikgytvdxl
fonbsmjyquwrapwazikqhtvdxl
fonwsmeyquwrapeczikghhvdxl
fonmsmjyquxrspeczikghtvdxl
fonqsmjyqxwrapeczikghtvdml
fonfsmjyquwrapeuzikgatvdxl
fonvsmjyquwrapeczikgrtvdul
fonbsmayquwrapeczikihtvdxm
fonbsmnyquwrapecdifghtvdxl
fonbsmjyeuwraseczikghtvdxo
fonbvvjyquwrapeczikghtvdxi
fonbsmjyquwrapeczbkghtorxl
tonbsmjyqvwrapeczikghtvdcl
fonbsmjyquwrapeczhkgbtvdkl
fonqsmjyquwrapenzibghtvdxl
fontsmeyqudrapeczikghtvdxl
qonbsmjyauwrapeczikghtvdbl
fynbsmjyluwrapeczekghtvdxl
fonbsmjhquwrappczikghtvdxt
conbsmjyquwrapeczikahtvdxz
fonbsmjyquorapeczikvftvdxl
fonbsriyquwrapeczikchtvdxl
yonfsmjyquwrapeczikghtvdxq
fonaomjyquwrapecziwghtvdxl
fonbsxsyqdwrapeczikghtvdxl
fonbsqjyouwrapeczikgltvdxl
fonbstsyquwraleczikghtvdxl
fonbsmjyquwraoecztkghtvdsl
fonbsmjyquwrapezzjkghmvdxl
fonbwmjyqnwrapecpikghtvdxl
fonbsmvyqbwrapeczikghtvdsl
fonbsijyquwrazeczikghtvdwl
fonbsmjyouwrapewzikghtldxl
xonbsmjyqcwrapeczikghtvdul
fonbgmjxquwrajeczikghtvdxl
fokbsmjyquwrapechikghtrdxl
fonbqmjyqawrapeczikghtrdxl
fonbwmjzquwtapeyzikghtvdxl
fonbsmjyquwrapecdikgatvdnl
fonbsmjyqowrkpeczikghtvdxj
fonbsmjyquwkapejzikuhtvdxl
fonbsmjyquwrabeozikghtmdxl
fonbsijyeuwrapeczikghtvdxh
fonbsmjhquprapeczizghtvdxl
fonesmjyquwrapcczikghtvdxh
fonbamjyquwrapeczifrhtvdxl
foabsmjyquwpapeczikghtvdxs
fonbsmjyquwrapeczukghivdxh
fonbsejyoulrapeczikghtvdxl
fonbsmjyquwraceczikgdmvdxl
eonbsmjyquerppeczikghtvdxl
ffnzsmjyquwgapeczikghtvdxl
donbsmyyquwrapeczirghtvdxl
fjnbsmjyqufrapeczikghtwdxl
fonfsmjyquwrareczigghtvdxl
fonusmjyquwrapeczikgetvexl
tonbsmjyqpwrapeczikghtjdxl
fonbsmjhqukkapeczikghtvdxl
fonbsmjyqusraseczikghtvzxl
fonbsmjyquygapeczxkghtvdxl
folbsmjyquwraqeczikghjvdxl
fonbsmjyquwrppecjinghtvdxl
fonbsmjyquwraepczhkghtvdxl
fonbfmjyquwrapeczisghtrdxl
fsnbsmjwqubrapeczikghtvdxl
fonbspjyquwrapjczikghtedxl
fowbsmjyquwrapeczikghtbdbl
fonbymjyquwrapeczikghlvdrl
fonbsmjyruwrapecbikghtvixl
fonyqmjyqufrapeczikghtvdxl
focbscjyquwrapeczmkghtvdxl
fonbsmjyqtwnkpeczikghtvdxl
eonbsmjyquwrameczizghtvdxl
zonbsmjyqcwrapeczikghtvhxl
foubsmjyquwrapehzikghtvnxl
ffnbsmjyquwrapetzikghtjdxl
fonbjgjyquwrapkczikghtvdxl
fonbwmjyquwqapeczdkghtvdxl
forbsmjyquwrapeczikkhtvdml
fonbsmjyiuwrapeczivghevdxl
fonbsmjyquwrapeglikghwvdxl
fopgsmjyquwrapegzikghtvdxl
fonbsmjyqzwrajeczikghtldxl
fonbsmjyruwrapexzmkghtvdxl
fonbsmjyquwrdpeczikxstvdxl
fonbsmjyquwrapeezivghtvdql
fonbdmjyqujsapeczikghtvdxl
File diff suppressed because it is too large Load Diff
+976
View File
@@ -0,0 +1,976 @@
[1518-03-31 00:26] falls asleep
[1518-04-03 00:38] wakes up
[1518-11-21 00:14] falls asleep
[1518-07-21 00:34] wakes up
[1518-04-02 00:20] falls asleep
[1518-08-26 00:14] wakes up
[1518-05-22 00:45] wakes up
[1518-08-18 00:57] wakes up
[1518-05-20 00:02] falls asleep
[1518-07-06 00:57] falls asleep
[1518-07-04 00:49] falls asleep
[1518-10-23 23:49] Guard #659 begins shift
[1518-08-06 00:07] falls asleep
[1518-06-24 00:58] wakes up
[1518-04-27 00:13] falls asleep
[1518-06-08 00:01] Guard #179 begins shift
[1518-06-03 00:00] Guard #659 begins shift
[1518-10-03 00:35] wakes up
[1518-04-30 00:20] wakes up
[1518-10-15 23:59] Guard #1699 begins shift
[1518-06-07 00:39] wakes up
[1518-09-25 00:10] falls asleep
[1518-09-27 00:30] falls asleep
[1518-11-03 00:36] falls asleep
[1518-06-26 00:55] wakes up
[1518-04-14 00:57] wakes up
[1518-08-07 00:45] falls asleep
[1518-06-02 00:56] wakes up
[1518-05-13 00:02] Guard #223 begins shift
[1518-04-20 00:45] falls asleep
[1518-11-14 23:59] Guard #1069 begins shift
[1518-09-17 00:58] wakes up
[1518-04-07 00:34] wakes up
[1518-09-27 00:00] Guard #419 begins shift
[1518-03-21 00:59] wakes up
[1518-07-26 00:01] Guard #457 begins shift
[1518-08-18 00:04] Guard #659 begins shift
[1518-04-20 00:01] Guard #659 begins shift
[1518-04-17 23:57] Guard #3547 begins shift
[1518-07-10 23:59] Guard #2753 begins shift
[1518-06-28 00:59] wakes up
[1518-10-26 00:01] Guard #3547 begins shift
[1518-04-15 00:49] wakes up
[1518-09-14 00:04] Guard #179 begins shift
[1518-07-21 00:02] falls asleep
[1518-07-23 00:38] falls asleep
[1518-04-04 23:59] Guard #223 begins shift
[1518-09-15 00:12] falls asleep
[1518-06-01 00:32] wakes up
[1518-08-15 00:22] falls asleep
[1518-10-05 00:34] wakes up
[1518-10-01 00:58] wakes up
[1518-05-05 00:07] falls asleep
[1518-10-23 00:34] wakes up
[1518-10-08 00:39] falls asleep
[1518-08-27 00:14] falls asleep
[1518-05-17 00:53] wakes up
[1518-08-08 00:39] falls asleep
[1518-07-28 00:03] falls asleep
[1518-05-03 00:08] falls asleep
[1518-10-12 00:52] falls asleep
[1518-04-20 00:58] wakes up
[1518-04-27 00:20] wakes up
[1518-05-14 23:58] Guard #1933 begins shift
[1518-07-12 23:59] Guard #2953 begins shift
[1518-10-12 00:00] Guard #223 begins shift
[1518-10-21 00:38] falls asleep
[1518-04-12 00:40] falls asleep
[1518-04-05 00:58] wakes up
[1518-08-16 00:34] falls asleep
[1518-07-30 23:58] Guard #419 begins shift
[1518-10-17 00:55] wakes up
[1518-08-06 23:59] Guard #409 begins shift
[1518-06-17 00:47] falls asleep
[1518-06-29 00:46] falls asleep
[1518-09-30 00:58] wakes up
[1518-06-29 00:53] wakes up
[1518-03-30 00:03] Guard #457 begins shift
[1518-11-07 00:22] falls asleep
[1518-05-04 23:56] Guard #2953 begins shift
[1518-09-23 00:19] wakes up
[1518-10-12 00:16] falls asleep
[1518-08-08 00:00] Guard #659 begins shift
[1518-11-15 00:31] wakes up
[1518-08-16 00:58] wakes up
[1518-08-18 23:59] Guard #3347 begins shift
[1518-07-06 23:58] Guard #2039 begins shift
[1518-10-15 00:52] falls asleep
[1518-09-18 00:36] wakes up
[1518-06-17 23:57] Guard #409 begins shift
[1518-09-19 23:56] Guard #647 begins shift
[1518-10-10 00:30] wakes up
[1518-11-18 23:58] Guard #2953 begins shift
[1518-10-27 00:19] falls asleep
[1518-08-05 00:51] wakes up
[1518-07-15 23:58] Guard #1699 begins shift
[1518-10-14 00:02] Guard #647 begins shift
[1518-06-04 00:00] Guard #1153 begins shift
[1518-04-16 00:00] Guard #1933 begins shift
[1518-06-25 00:28] falls asleep
[1518-05-13 23:57] Guard #419 begins shift
[1518-07-09 23:58] Guard #503 begins shift
[1518-05-08 00:16] falls asleep
[1518-08-12 00:10] falls asleep
[1518-09-16 00:47] falls asleep
[1518-07-06 00:04] Guard #3547 begins shift
[1518-06-08 00:22] falls asleep
[1518-07-09 00:02] Guard #2953 begins shift
[1518-08-22 23:58] Guard #179 begins shift
[1518-05-11 00:51] wakes up
[1518-06-05 00:59] wakes up
[1518-10-03 00:25] wakes up
[1518-05-05 00:17] wakes up
[1518-11-10 23:58] Guard #457 begins shift
[1518-09-17 00:04] Guard #409 begins shift
[1518-08-17 00:02] falls asleep
[1518-08-13 00:32] falls asleep
[1518-09-02 00:00] Guard #419 begins shift
[1518-07-24 00:48] falls asleep
[1518-04-10 00:32] wakes up
[1518-04-20 00:42] wakes up
[1518-03-24 00:03] Guard #223 begins shift
[1518-11-21 23:50] Guard #2953 begins shift
[1518-09-20 00:57] wakes up
[1518-08-11 00:42] wakes up
[1518-08-08 00:49] wakes up
[1518-06-12 23:47] Guard #647 begins shift
[1518-03-26 00:58] wakes up
[1518-11-02 00:55] wakes up
[1518-10-22 00:03] Guard #1069 begins shift
[1518-07-14 23:59] Guard #401 begins shift
[1518-04-30 00:15] falls asleep
[1518-06-21 00:37] wakes up
[1518-07-15 00:54] wakes up
[1518-05-14 00:50] wakes up
[1518-09-16 00:53] wakes up
[1518-09-05 00:01] Guard #2039 begins shift
[1518-05-25 23:59] Guard #2753 begins shift
[1518-10-28 00:30] falls asleep
[1518-10-06 23:56] Guard #2953 begins shift
[1518-08-21 00:01] Guard #419 begins shift
[1518-04-25 23:59] Guard #2693 begins shift
[1518-11-16 00:55] wakes up
[1518-05-12 00:47] wakes up
[1518-07-03 00:39] falls asleep
[1518-05-10 00:54] falls asleep
[1518-03-30 00:57] wakes up
[1518-11-20 00:56] falls asleep
[1518-07-23 00:11] wakes up
[1518-10-12 00:59] wakes up
[1518-04-25 00:03] Guard #1153 begins shift
[1518-11-05 23:57] Guard #179 begins shift
[1518-03-30 23:53] Guard #691 begins shift
[1518-05-15 23:57] Guard #223 begins shift
[1518-08-23 00:31] falls asleep
[1518-08-22 00:54] wakes up
[1518-09-07 00:53] falls asleep
[1518-11-20 00:00] Guard #1699 begins shift
[1518-08-13 00:35] wakes up
[1518-09-15 00:59] wakes up
[1518-10-27 00:42] wakes up
[1518-05-27 00:22] wakes up
[1518-08-18 00:25] wakes up
[1518-08-04 00:28] falls asleep
[1518-09-24 00:57] wakes up
[1518-07-24 00:57] wakes up
[1518-07-16 00:51] wakes up
[1518-05-25 00:37] falls asleep
[1518-06-01 00:14] falls asleep
[1518-10-05 00:20] falls asleep
[1518-04-15 00:11] wakes up
[1518-05-23 23:56] Guard #2953 begins shift
[1518-11-22 00:04] falls asleep
[1518-09-11 00:59] wakes up
[1518-10-23 00:44] wakes up
[1518-11-13 00:41] falls asleep
[1518-10-06 00:04] Guard #2753 begins shift
[1518-04-25 00:48] wakes up
[1518-05-01 00:13] falls asleep
[1518-06-27 00:49] wakes up
[1518-09-29 00:18] falls asleep
[1518-10-02 23:56] Guard #691 begins shift
[1518-03-28 00:42] wakes up
[1518-05-30 00:23] falls asleep
[1518-10-21 00:24] falls asleep
[1518-11-03 00:28] wakes up
[1518-10-18 00:20] falls asleep
[1518-10-11 00:45] falls asleep
[1518-10-02 00:23] falls asleep
[1518-11-02 00:42] wakes up
[1518-11-03 00:01] Guard #457 begins shift
[1518-08-05 00:47] falls asleep
[1518-09-05 00:23] wakes up
[1518-08-28 00:00] Guard #1069 begins shift
[1518-09-17 00:44] wakes up
[1518-06-16 23:59] Guard #691 begins shift
[1518-08-05 00:02] Guard #1069 begins shift
[1518-04-12 00:01] Guard #691 begins shift
[1518-11-06 00:43] wakes up
[1518-06-09 00:28] falls asleep
[1518-05-14 00:26] falls asleep
[1518-09-11 00:04] Guard #2693 begins shift
[1518-09-06 00:33] falls asleep
[1518-09-29 00:44] wakes up
[1518-06-04 23:49] Guard #1933 begins shift
[1518-03-25 00:02] Guard #1153 begins shift
[1518-10-25 00:59] wakes up
[1518-08-29 00:37] falls asleep
[1518-09-30 00:40] wakes up
[1518-05-17 23:50] Guard #223 begins shift
[1518-05-19 23:46] Guard #1933 begins shift
[1518-07-18 00:40] falls asleep
[1518-09-23 00:33] falls asleep
[1518-09-08 00:17] falls asleep
[1518-11-19 00:12] falls asleep
[1518-03-31 00:05] falls asleep
[1518-08-24 00:31] wakes up
[1518-05-11 00:10] falls asleep
[1518-07-29 00:14] wakes up
[1518-07-10 00:43] wakes up
[1518-08-18 00:15] falls asleep
[1518-04-10 00:50] wakes up
[1518-05-26 00:23] wakes up
[1518-09-03 00:04] Guard #223 begins shift
[1518-04-11 00:06] falls asleep
[1518-07-29 00:12] falls asleep
[1518-10-04 00:28] wakes up
[1518-08-21 00:49] falls asleep
[1518-10-15 00:43] wakes up
[1518-03-26 00:47] wakes up
[1518-04-08 00:58] wakes up
[1518-07-27 00:52] wakes up
[1518-05-30 23:56] Guard #179 begins shift
[1518-09-22 00:02] Guard #2693 begins shift
[1518-10-14 00:46] falls asleep
[1518-11-05 00:21] falls asleep
[1518-05-16 23:59] Guard #1069 begins shift
[1518-05-17 00:27] falls asleep
[1518-09-28 00:52] falls asleep
[1518-07-22 00:20] falls asleep
[1518-06-13 00:02] falls asleep
[1518-05-28 00:27] falls asleep
[1518-05-07 00:43] wakes up
[1518-05-20 00:44] falls asleep
[1518-05-20 23:57] Guard #691 begins shift
[1518-05-02 00:51] wakes up
[1518-10-01 00:53] falls asleep
[1518-11-04 00:26] falls asleep
[1518-04-01 00:55] wakes up
[1518-04-07 00:25] falls asleep
[1518-03-26 00:03] Guard #1933 begins shift
[1518-07-16 00:28] falls asleep
[1518-07-05 00:03] Guard #163 begins shift
[1518-04-24 00:49] wakes up
[1518-03-30 00:23] falls asleep
[1518-04-27 00:04] Guard #647 begins shift
[1518-07-31 00:36] falls asleep
[1518-10-06 00:42] wakes up
[1518-06-10 00:51] wakes up
[1518-08-10 00:22] falls asleep
[1518-04-22 00:00] Guard #647 begins shift
[1518-04-16 00:43] wakes up
[1518-05-27 00:13] falls asleep
[1518-07-18 23:58] Guard #2039 begins shift
[1518-05-11 00:37] falls asleep
[1518-09-28 00:34] wakes up
[1518-08-26 00:49] wakes up
[1518-04-26 00:24] falls asleep
[1518-07-04 00:50] wakes up
[1518-05-15 00:57] wakes up
[1518-11-01 00:39] wakes up
[1518-09-28 00:55] wakes up
[1518-06-25 00:17] wakes up
[1518-06-25 00:00] Guard #163 begins shift
[1518-07-20 00:59] wakes up
[1518-10-06 00:36] falls asleep
[1518-10-02 00:02] Guard #659 begins shift
[1518-09-23 23:50] Guard #503 begins shift
[1518-03-20 00:00] Guard #457 begins shift
[1518-04-24 00:19] falls asleep
[1518-05-08 00:51] wakes up
[1518-07-16 23:58] Guard #2753 begins shift
[1518-11-01 00:49] wakes up
[1518-11-08 00:00] Guard #1699 begins shift
[1518-06-12 00:15] falls asleep
[1518-10-18 23:59] Guard #647 begins shift
[1518-08-02 00:53] wakes up
[1518-05-23 00:29] wakes up
[1518-03-25 00:09] falls asleep
[1518-10-21 00:25] wakes up
[1518-03-22 00:00] Guard #503 begins shift
[1518-05-19 00:05] falls asleep
[1518-06-09 00:50] wakes up
[1518-09-26 00:32] wakes up
[1518-03-24 00:34] falls asleep
[1518-08-25 00:01] Guard #1069 begins shift
[1518-04-26 00:44] wakes up
[1518-05-22 00:00] Guard #419 begins shift
[1518-11-20 00:57] wakes up
[1518-05-02 00:50] falls asleep
[1518-11-17 00:41] wakes up
[1518-06-07 00:21] falls asleep
[1518-06-19 00:24] falls asleep
[1518-08-08 23:57] Guard #1069 begins shift
[1518-11-16 00:36] falls asleep
[1518-09-03 00:45] wakes up
[1518-07-15 00:44] wakes up
[1518-07-11 00:25] wakes up
[1518-09-18 23:51] Guard #2953 begins shift
[1518-10-03 23:49] Guard #1933 begins shift
[1518-10-30 00:31] falls asleep
[1518-09-18 00:33] falls asleep
[1518-08-10 00:39] wakes up
[1518-07-30 00:56] wakes up
[1518-09-25 23:51] Guard #659 begins shift
[1518-11-19 00:59] wakes up
[1518-05-21 00:55] wakes up
[1518-10-15 00:53] wakes up
[1518-09-22 00:20] falls asleep
[1518-04-21 00:44] falls asleep
[1518-11-12 00:45] wakes up
[1518-05-23 00:28] falls asleep
[1518-05-05 23:59] Guard #2753 begins shift
[1518-10-15 00:39] falls asleep
[1518-09-09 00:51] wakes up
[1518-06-11 23:57] Guard #1069 begins shift
[1518-06-01 00:47] wakes up
[1518-09-28 00:43] falls asleep
[1518-04-27 00:33] falls asleep
[1518-08-08 00:31] wakes up
[1518-09-09 23:59] Guard #691 begins shift
[1518-10-17 00:43] wakes up
[1518-10-23 00:43] falls asleep
[1518-07-03 00:50] wakes up
[1518-07-06 00:33] wakes up
[1518-06-25 00:41] wakes up
[1518-06-13 00:44] wakes up
[1518-10-28 00:35] wakes up
[1518-08-16 00:01] falls asleep
[1518-03-22 00:17] falls asleep
[1518-07-06 00:47] wakes up
[1518-09-13 00:01] Guard #659 begins shift
[1518-06-14 00:01] Guard #2953 begins shift
[1518-07-19 00:57] wakes up
[1518-09-15 23:58] Guard #223 begins shift
[1518-10-19 00:06] falls asleep
[1518-09-21 00:49] wakes up
[1518-08-26 00:03] falls asleep
[1518-07-08 00:13] falls asleep
[1518-06-08 23:56] Guard #1069 begins shift
[1518-07-27 00:37] falls asleep
[1518-07-06 00:17] falls asleep
[1518-04-23 00:25] wakes up
[1518-06-30 00:33] wakes up
[1518-04-08 00:46] falls asleep
[1518-04-02 00:57] wakes up
[1518-11-22 00:51] falls asleep
[1518-06-10 23:58] Guard #1933 begins shift
[1518-09-15 00:49] falls asleep
[1518-10-10 00:42] falls asleep
[1518-04-14 00:49] falls asleep
[1518-09-03 23:59] Guard #2039 begins shift
[1518-06-17 00:34] falls asleep
[1518-07-20 00:00] Guard #2953 begins shift
[1518-07-31 00:41] wakes up
[1518-10-25 00:45] falls asleep
[1518-03-24 00:30] wakes up
[1518-04-10 00:15] falls asleep
[1518-06-30 00:36] falls asleep
[1518-07-03 00:01] Guard #2953 begins shift
[1518-05-21 00:08] falls asleep
[1518-09-04 00:29] wakes up
[1518-10-03 00:10] falls asleep
[1518-06-04 00:56] wakes up
[1518-09-04 00:23] falls asleep
[1518-05-09 23:59] Guard #179 begins shift
[1518-10-20 00:42] wakes up
[1518-07-22 00:04] Guard #1699 begins shift
[1518-06-23 00:49] wakes up
[1518-04-29 00:58] wakes up
[1518-05-02 00:03] Guard #647 begins shift
[1518-08-03 00:07] falls asleep
[1518-09-24 00:22] falls asleep
[1518-04-13 00:05] falls asleep
[1518-09-03 00:41] falls asleep
[1518-09-26 00:00] falls asleep
[1518-05-10 00:45] wakes up
[1518-04-18 00:39] wakes up
[1518-11-15 00:41] falls asleep
[1518-05-25 00:04] Guard #409 begins shift
[1518-07-07 00:35] falls asleep
[1518-04-28 00:53] wakes up
[1518-11-21 00:54] wakes up
[1518-10-10 00:24] falls asleep
[1518-07-17 00:40] falls asleep
[1518-10-26 00:18] falls asleep
[1518-07-14 00:58] wakes up
[1518-06-27 00:11] falls asleep
[1518-09-17 00:51] falls asleep
[1518-07-25 00:51] wakes up
[1518-07-02 00:06] falls asleep
[1518-03-29 00:01] falls asleep
[1518-11-09 00:57] wakes up
[1518-08-06 00:32] wakes up
[1518-10-02 00:25] wakes up
[1518-08-17 00:39] wakes up
[1518-06-21 00:21] falls asleep
[1518-11-17 23:53] Guard #3547 begins shift
[1518-04-17 00:38] wakes up
[1518-04-12 00:50] wakes up
[1518-11-23 00:49] wakes up
[1518-10-05 00:07] falls asleep
[1518-03-20 00:14] falls asleep
[1518-05-28 00:00] Guard #1933 begins shift
[1518-05-29 00:04] falls asleep
[1518-10-28 00:43] falls asleep
[1518-03-26 00:21] falls asleep
[1518-11-21 00:50] falls asleep
[1518-10-04 00:05] falls asleep
[1518-05-07 00:19] falls asleep
[1518-10-10 00:50] falls asleep
[1518-03-31 00:45] wakes up
[1518-10-06 00:30] falls asleep
[1518-11-04 00:00] Guard #179 begins shift
[1518-05-28 00:56] falls asleep
[1518-05-18 00:31] falls asleep
[1518-09-08 00:34] falls asleep
[1518-09-13 00:17] falls asleep
[1518-03-19 00:37] falls asleep
[1518-06-30 00:58] wakes up
[1518-03-23 00:23] falls asleep
[1518-07-30 00:26] falls asleep
[1518-04-09 00:47] wakes up
[1518-07-26 00:11] falls asleep
[1518-07-02 00:04] Guard #1699 begins shift
[1518-09-14 00:51] wakes up
[1518-04-29 00:46] falls asleep
[1518-04-19 00:58] wakes up
[1518-04-18 00:57] wakes up
[1518-07-14 00:10] falls asleep
[1518-05-28 00:33] wakes up
[1518-05-10 00:27] falls asleep
[1518-09-28 00:18] falls asleep
[1518-08-13 00:01] Guard #647 begins shift
[1518-09-06 00:51] wakes up
[1518-11-17 00:02] Guard #2953 begins shift
[1518-04-09 00:31] falls asleep
[1518-07-08 00:02] Guard #659 begins shift
[1518-09-22 00:58] wakes up
[1518-07-28 00:34] wakes up
[1518-11-17 00:22] falls asleep
[1518-04-03 00:00] Guard #659 begins shift
[1518-08-14 00:51] wakes up
[1518-05-12 00:04] Guard #2039 begins shift
[1518-09-16 00:39] wakes up
[1518-06-02 00:19] falls asleep
[1518-08-19 23:58] Guard #3547 begins shift
[1518-04-21 00:03] Guard #179 begins shift
[1518-04-17 00:13] falls asleep
[1518-06-26 23:56] Guard #1933 begins shift
[1518-03-27 23:58] Guard #2693 begins shift
[1518-04-01 00:11] falls asleep
[1518-08-30 00:04] Guard #2753 begins shift
[1518-11-02 00:16] wakes up
[1518-10-08 00:01] Guard #2039 begins shift
[1518-04-02 00:00] Guard #457 begins shift
[1518-10-04 00:55] wakes up
[1518-05-28 00:58] wakes up
[1518-09-13 00:55] wakes up
[1518-08-23 00:38] wakes up
[1518-04-18 00:25] wakes up
[1518-08-15 23:51] Guard #401 begins shift
[1518-07-28 00:48] wakes up
[1518-08-27 00:02] Guard #691 begins shift
[1518-03-28 00:59] wakes up
[1518-08-29 00:04] Guard #1153 begins shift
[1518-07-31 23:58] Guard #3347 begins shift
[1518-11-01 23:56] Guard #409 begins shift
[1518-08-12 00:32] falls asleep
[1518-06-05 00:05] falls asleep
[1518-09-16 00:21] falls asleep
[1518-04-04 00:03] Guard #1637 begins shift
[1518-04-12 00:26] wakes up
[1518-06-15 00:23] wakes up
[1518-05-07 00:01] Guard #1699 begins shift
[1518-05-06 00:43] falls asleep
[1518-09-27 00:46] wakes up
[1518-07-22 00:58] wakes up
[1518-09-03 00:36] falls asleep
[1518-04-16 23:58] Guard #419 begins shift
[1518-11-11 00:20] falls asleep
[1518-04-20 00:11] falls asleep
[1518-06-29 00:27] falls asleep
[1518-10-09 00:59] wakes up
[1518-07-15 00:31] falls asleep
[1518-11-10 00:00] Guard #419 begins shift
[1518-09-11 00:40] falls asleep
[1518-03-24 00:59] wakes up
[1518-06-01 00:36] falls asleep
[1518-05-31 00:33] falls asleep
[1518-05-16 00:47] falls asleep
[1518-10-12 00:40] falls asleep
[1518-10-23 00:29] falls asleep
[1518-11-22 00:37] wakes up
[1518-07-09 00:54] wakes up
[1518-07-05 00:42] falls asleep
[1518-07-29 00:00] Guard #2953 begins shift
[1518-09-30 00:46] falls asleep
[1518-08-10 00:03] Guard #2039 begins shift
[1518-03-27 00:08] falls asleep
[1518-03-24 00:24] falls asleep
[1518-05-09 00:25] falls asleep
[1518-06-14 00:57] wakes up
[1518-10-29 23:56] Guard #1699 begins shift
[1518-05-02 23:56] Guard #401 begins shift
[1518-11-20 00:27] falls asleep
[1518-07-20 23:51] Guard #419 begins shift
[1518-04-06 00:59] wakes up
[1518-10-01 00:04] Guard #2753 begins shift
[1518-10-01 00:46] wakes up
[1518-07-14 00:02] Guard #1069 begins shift
[1518-04-16 00:25] falls asleep
[1518-10-10 23:56] Guard #691 begins shift
[1518-08-20 00:58] wakes up
[1518-09-21 00:11] falls asleep
[1518-04-03 00:26] falls asleep
[1518-06-20 00:54] wakes up
[1518-11-01 00:04] Guard #1069 begins shift
[1518-05-28 23:54] Guard #2039 begins shift
[1518-03-22 00:36] wakes up
[1518-10-26 00:40] wakes up
[1518-10-11 00:51] wakes up
[1518-04-27 00:58] wakes up
[1518-04-10 00:18] wakes up
[1518-04-22 00:54] wakes up
[1518-09-12 00:48] wakes up
[1518-04-28 00:23] falls asleep
[1518-11-21 00:38] wakes up
[1518-05-20 00:40] wakes up
[1518-10-14 00:51] wakes up
[1518-06-27 00:46] falls asleep
[1518-09-18 00:44] falls asleep
[1518-10-09 23:56] Guard #419 begins shift
[1518-04-27 00:18] falls asleep
[1518-10-20 00:59] wakes up
[1518-05-17 00:47] falls asleep
[1518-04-18 00:08] falls asleep
[1518-07-29 00:58] wakes up
[1518-06-10 00:03] Guard #1699 begins shift
[1518-09-06 00:15] falls asleep
[1518-10-23 00:49] wakes up
[1518-11-12 00:33] falls asleep
[1518-10-12 23:51] Guard #163 begins shift
[1518-06-04 00:33] falls asleep
[1518-08-24 00:43] falls asleep
[1518-07-17 23:56] Guard #1699 begins shift
[1518-10-02 00:44] wakes up
[1518-09-12 00:01] Guard #401 begins shift
[1518-08-12 00:28] wakes up
[1518-07-18 00:27] wakes up
[1518-03-27 00:01] Guard #647 begins shift
[1518-05-27 00:57] wakes up
[1518-03-20 00:26] wakes up
[1518-04-23 00:01] Guard #691 begins shift
[1518-09-24 23:59] Guard #1153 begins shift
[1518-06-02 00:34] wakes up
[1518-09-09 00:02] Guard #503 begins shift
[1518-04-11 00:03] Guard #457 begins shift
[1518-05-30 00:38] wakes up
[1518-04-05 00:43] falls asleep
[1518-06-17 00:59] wakes up
[1518-05-01 00:04] Guard #659 begins shift
[1518-06-11 00:46] wakes up
[1518-09-12 00:08] falls asleep
[1518-08-18 00:41] falls asleep
[1518-07-19 00:36] wakes up
[1518-09-02 00:39] wakes up
[1518-05-27 00:50] falls asleep
[1518-10-13 00:54] wakes up
[1518-07-09 00:17] falls asleep
[1518-07-05 00:26] falls asleep
[1518-08-10 23:50] Guard #659 begins shift
[1518-04-27 00:14] wakes up
[1518-04-29 00:42] wakes up
[1518-11-09 00:50] falls asleep
[1518-05-24 00:39] falls asleep
[1518-09-15 00:45] wakes up
[1518-07-06 00:58] wakes up
[1518-09-09 00:56] falls asleep
[1518-09-20 23:59] Guard #2039 begins shift
[1518-06-24 00:47] falls asleep
[1518-07-03 00:56] falls asleep
[1518-06-01 23:59] Guard #223 begins shift
[1518-04-13 00:35] wakes up
[1518-05-07 23:57] Guard #457 begins shift
[1518-11-08 00:43] wakes up
[1518-07-27 00:03] Guard #1153 begins shift
[1518-08-07 00:53] wakes up
[1518-09-20 00:33] wakes up
[1518-11-14 00:44] wakes up
[1518-05-31 00:44] wakes up
[1518-06-22 00:44] wakes up
[1518-05-15 00:15] falls asleep
[1518-09-30 00:00] Guard #2693 begins shift
[1518-11-22 00:53] wakes up
[1518-10-20 23:58] Guard #163 begins shift
[1518-06-15 23:56] Guard #1699 begins shift
[1518-07-08 00:34] wakes up
[1518-11-02 00:30] falls asleep
[1518-06-03 00:57] wakes up
[1518-06-30 00:15] falls asleep
[1518-04-12 00:54] falls asleep
[1518-06-19 00:00] Guard #1933 begins shift
[1518-11-11 23:57] Guard #179 begins shift
[1518-04-08 00:02] Guard #503 begins shift
[1518-04-09 23:57] Guard #163 begins shift
[1518-07-21 00:50] falls asleep
[1518-11-12 00:10] falls asleep
[1518-10-10 00:54] wakes up
[1518-10-27 23:59] Guard #1069 begins shift
[1518-08-03 00:59] wakes up
[1518-07-23 23:58] Guard #223 begins shift
[1518-08-21 00:59] wakes up
[1518-05-09 00:43] wakes up
[1518-06-26 00:16] falls asleep
[1518-08-21 00:50] wakes up
[1518-10-16 00:35] falls asleep
[1518-09-28 00:49] wakes up
[1518-05-30 00:00] Guard #419 begins shift
[1518-11-12 00:13] wakes up
[1518-06-07 00:53] falls asleep
[1518-07-18 00:58] wakes up
[1518-07-10 00:54] falls asleep
[1518-09-07 00:55] wakes up
[1518-04-19 00:57] falls asleep
[1518-05-05 00:52] wakes up
[1518-06-18 00:55] wakes up
[1518-10-18 00:00] Guard #1933 begins shift
[1518-09-11 00:23] wakes up
[1518-06-22 23:58] Guard #2953 begins shift
[1518-06-29 00:42] wakes up
[1518-04-10 00:25] falls asleep
[1518-11-13 00:00] Guard #2753 begins shift
[1518-03-28 23:50] Guard #419 begins shift
[1518-08-25 00:39] wakes up
[1518-08-21 00:57] falls asleep
[1518-08-29 00:49] wakes up
[1518-10-12 00:48] wakes up
[1518-05-11 00:23] wakes up
[1518-06-23 23:56] Guard #1153 begins shift
[1518-05-19 00:50] wakes up
[1518-11-13 00:55] wakes up
[1518-07-05 00:28] wakes up
[1518-10-18 00:53] wakes up
[1518-07-19 00:54] falls asleep
[1518-06-07 00:42] falls asleep
[1518-10-22 00:47] wakes up
[1518-05-03 00:54] falls asleep
[1518-09-05 00:17] falls asleep
[1518-10-21 00:42] wakes up
[1518-11-01 00:13] falls asleep
[1518-05-10 23:58] Guard #223 begins shift
[1518-07-01 00:48] wakes up
[1518-03-23 00:55] wakes up
[1518-08-16 23:54] Guard #2039 begins shift
[1518-04-29 00:16] falls asleep
[1518-07-01 00:20] falls asleep
[1518-05-03 00:57] wakes up
[1518-06-28 00:03] Guard #179 begins shift
[1518-04-25 00:21] falls asleep
[1518-05-13 00:38] wakes up
[1518-05-18 23:52] Guard #1699 begins shift
[1518-04-14 23:59] Guard #2039 begins shift
[1518-06-28 00:51] falls asleep
[1518-07-20 00:20] falls asleep
[1518-06-02 00:42] falls asleep
[1518-09-08 00:04] Guard #1699 begins shift
[1518-05-18 00:01] falls asleep
[1518-11-10 00:48] wakes up
[1518-10-08 23:56] Guard #409 begins shift
[1518-10-19 00:53] wakes up
[1518-04-12 00:55] wakes up
[1518-06-23 00:14] falls asleep
[1518-09-02 00:17] falls asleep
[1518-09-20 00:20] falls asleep
[1518-11-18 00:03] falls asleep
[1518-09-23 00:12] falls asleep
[1518-06-20 00:08] falls asleep
[1518-09-29 00:05] falls asleep
[1518-08-20 00:16] falls asleep
[1518-10-05 00:16] wakes up
[1518-09-04 00:55] wakes up
[1518-10-05 00:00] Guard #3547 begins shift
[1518-10-29 00:11] falls asleep
[1518-09-03 00:37] wakes up
[1518-06-07 00:01] Guard #457 begins shift
[1518-10-16 00:54] wakes up
[1518-05-20 00:34] falls asleep
[1518-06-01 00:01] Guard #1069 begins shift
[1518-08-11 00:04] falls asleep
[1518-03-27 00:12] wakes up
[1518-11-07 00:55] wakes up
[1518-08-22 00:00] falls asleep
[1518-08-30 00:51] wakes up
[1518-07-11 00:21] falls asleep
[1518-07-21 00:53] wakes up
[1518-10-02 00:30] falls asleep
[1518-10-06 00:31] wakes up
[1518-07-26 00:45] wakes up
[1518-11-21 00:00] Guard #2693 begins shift
[1518-03-21 00:03] Guard #691 begins shift
[1518-06-21 00:00] Guard #503 begins shift
[1518-07-10 00:08] falls asleep
[1518-07-23 00:09] falls asleep
[1518-09-05 00:29] falls asleep
[1518-09-10 00:23] falls asleep
[1518-06-20 00:04] Guard #1933 begins shift
[1518-06-30 23:59] Guard #691 begins shift
[1518-10-09 00:35] falls asleep
[1518-10-19 23:58] Guard #179 begins shift
[1518-09-06 00:18] wakes up
[1518-04-10 00:47] falls asleep
[1518-08-28 00:18] falls asleep
[1518-05-18 00:06] wakes up
[1518-11-06 00:31] wakes up
[1518-08-08 00:26] falls asleep
[1518-11-08 00:30] falls asleep
[1518-09-20 00:56] falls asleep
[1518-08-15 00:42] wakes up
[1518-09-18 00:50] wakes up
[1518-06-03 00:22] falls asleep
[1518-05-25 00:56] wakes up
[1518-06-11 00:33] falls asleep
[1518-05-16 00:59] wakes up
[1518-09-18 00:03] Guard #659 begins shift
[1518-10-30 00:48] wakes up
[1518-08-26 00:25] falls asleep
[1518-11-15 00:26] falls asleep
[1518-06-19 00:26] wakes up
[1518-10-29 00:42] wakes up
[1518-09-01 00:47] wakes up
[1518-08-25 23:48] Guard #1069 begins shift
[1518-06-22 00:32] falls asleep
[1518-08-21 23:51] Guard #1069 begins shift
[1518-10-12 00:22] wakes up
[1518-10-27 00:26] wakes up
[1518-04-28 23:58] Guard #179 begins shift
[1518-06-10 00:58] wakes up
[1518-11-06 00:18] falls asleep
[1518-07-20 00:57] falls asleep
[1518-04-01 00:35] falls asleep
[1518-08-14 00:10] falls asleep
[1518-06-06 00:52] wakes up
[1518-08-27 00:33] wakes up
[1518-07-04 00:00] Guard #691 begins shift
[1518-07-25 00:33] falls asleep
[1518-11-10 00:21] falls asleep
[1518-08-16 00:17] wakes up
[1518-11-05 00:51] wakes up
[1518-10-01 00:41] falls asleep
[1518-04-08 00:20] wakes up
[1518-08-12 00:00] Guard #223 begins shift
[1518-09-01 00:03] Guard #223 begins shift
[1518-10-28 00:54] wakes up
[1518-09-12 00:45] falls asleep
[1518-11-01 00:44] falls asleep
[1518-03-19 00:02] Guard #2953 begins shift
[1518-04-06 00:41] falls asleep
[1518-07-15 00:49] falls asleep
[1518-10-25 00:16] falls asleep
[1518-05-28 00:46] falls asleep
[1518-03-27 00:22] falls asleep
[1518-10-17 00:50] falls asleep
[1518-04-13 23:57] Guard #1153 begins shift
[1518-09-04 00:37] falls asleep
[1518-05-01 00:57] wakes up
[1518-11-13 23:57] Guard #691 begins shift
[1518-03-21 00:31] falls asleep
[1518-10-10 00:45] wakes up
[1518-04-28 00:09] falls asleep
[1518-06-07 00:57] wakes up
[1518-07-28 00:47] falls asleep
[1518-09-06 23:58] Guard #409 begins shift
[1518-06-13 00:53] wakes up
[1518-10-03 00:33] falls asleep
[1518-06-16 00:34] wakes up
[1518-03-28 00:18] falls asleep
[1518-10-07 00:26] falls asleep
[1518-10-23 00:00] Guard #1069 begins shift
[1518-06-18 00:20] falls asleep
[1518-11-09 00:04] Guard #457 begins shift
[1518-11-03 00:59] wakes up
[1518-11-09 00:25] falls asleep
[1518-04-15 00:08] falls asleep
[1518-05-03 00:35] wakes up
[1518-04-28 00:12] wakes up
[1518-04-06 00:03] Guard #179 begins shift
[1518-07-20 00:44] wakes up
[1518-09-05 00:48] wakes up
[1518-06-17 00:35] wakes up
[1518-07-24 23:57] Guard #223 begins shift
[1518-10-29 00:00] Guard #419 begins shift
[1518-03-19 00:41] wakes up
[1518-07-30 00:00] Guard #2953 begins shift
[1518-06-14 00:50] falls asleep
[1518-07-12 00:32] wakes up
[1518-06-25 23:57] Guard #1069 begins shift
[1518-06-10 00:44] falls asleep
[1518-05-17 00:32] wakes up
[1518-10-08 00:48] wakes up
[1518-11-03 00:22] falls asleep
[1518-10-24 00:02] falls asleep
[1518-10-27 00:29] falls asleep
[1518-04-01 00:23] wakes up
[1518-08-05 00:33] wakes up
[1518-08-09 00:41] wakes up
[1518-11-06 00:42] falls asleep
[1518-08-24 00:49] wakes up
[1518-09-14 23:56] Guard #1699 begins shift
[1518-07-19 00:11] falls asleep
[1518-04-15 00:37] falls asleep
[1518-09-01 00:34] falls asleep
[1518-07-29 00:22] falls asleep
[1518-11-02 00:51] falls asleep
[1518-05-02 00:22] wakes up
[1518-05-26 00:10] falls asleep
[1518-10-24 23:59] Guard #1153 begins shift
[1518-07-12 00:01] Guard #691 begins shift
[1518-08-04 00:04] Guard #691 begins shift
[1518-05-02 00:58] wakes up
[1518-11-11 00:52] wakes up
[1518-10-31 00:00] Guard #683 begins shift
[1518-06-13 00:50] falls asleep
[1518-07-05 00:53] wakes up
[1518-07-05 00:22] wakes up
[1518-10-23 00:48] falls asleep
[1518-04-22 00:52] falls asleep
[1518-09-28 00:04] Guard #647 begins shift
[1518-05-04 00:24] falls asleep
[1518-05-20 00:21] wakes up
[1518-10-15 00:01] Guard #409 begins shift
[1518-09-10 00:33] wakes up
[1518-04-28 00:01] Guard #1699 begins shift
[1518-04-11 00:50] wakes up
[1518-05-05 00:23] falls asleep
[1518-10-16 23:59] Guard #409 begins shift
[1518-11-15 00:51] wakes up
[1518-09-09 00:33] falls asleep
[1518-07-12 00:21] falls asleep
[1518-04-12 23:51] Guard #1699 begins shift
[1518-06-10 00:54] falls asleep
[1518-07-13 00:39] wakes up
[1518-09-12 00:38] wakes up
[1518-06-06 00:02] Guard #1153 begins shift
[1518-06-25 00:10] falls asleep
[1518-09-24 00:14] wakes up
[1518-10-24 00:33] wakes up
[1518-07-17 00:43] wakes up
[1518-07-23 00:03] Guard #419 begins shift
[1518-10-07 00:55] wakes up
[1518-05-04 00:04] Guard #2753 begins shift
[1518-05-22 00:06] falls asleep
[1518-10-13 00:04] falls asleep
[1518-11-23 00:02] Guard #457 begins shift
[1518-08-04 00:57] wakes up
[1518-09-30 00:33] falls asleep
[1518-11-02 00:15] falls asleep
[1518-03-28 00:56] falls asleep
[1518-10-04 00:47] falls asleep
[1518-04-30 00:03] Guard #401 begins shift
[1518-06-27 00:33] wakes up
[1518-07-10 00:56] wakes up
[1518-03-25 00:51] wakes up
[1518-10-20 00:33] falls asleep
[1518-11-20 00:51] wakes up
[1518-05-06 00:46] wakes up
[1518-07-27 23:47] Guard #3547 begins shift
[1518-08-02 00:02] Guard #419 begins shift
[1518-08-12 00:55] wakes up
[1518-09-22 23:58] Guard #419 begins shift
[1518-05-27 00:03] Guard #457 begins shift
[1518-04-08 00:19] falls asleep
[1518-07-27 00:20] falls asleep
[1518-03-31 00:22] wakes up
[1518-09-29 00:14] wakes up
[1518-06-07 00:50] wakes up
[1518-07-05 00:06] falls asleep
[1518-09-14 00:06] falls asleep
[1518-05-20 00:54] wakes up
[1518-08-15 00:51] falls asleep
[1518-04-18 00:44] falls asleep
[1518-07-27 00:24] wakes up
[1518-10-20 00:52] falls asleep
[1518-08-28 00:45] wakes up
[1518-08-02 00:15] falls asleep
[1518-04-21 00:52] wakes up
[1518-07-23 00:51] wakes up
[1518-09-19 00:02] falls asleep
[1518-10-26 23:59] Guard #179 begins shift
[1518-04-23 00:15] falls asleep
[1518-04-06 23:57] Guard #2693 begins shift
[1518-09-23 00:38] wakes up
[1518-08-05 00:28] falls asleep
[1518-09-08 00:51] wakes up
[1518-11-09 00:44] wakes up
[1518-07-03 00:59] wakes up
[1518-08-06 00:00] Guard #419 begins shift
[1518-06-16 00:29] falls asleep
[1518-09-28 23:53] Guard #401 begins shift
[1518-11-04 23:57] Guard #163 begins shift
[1518-07-31 00:19] wakes up
[1518-06-06 00:43] falls asleep
[1518-11-04 00:42] wakes up
[1518-08-02 23:59] Guard #1699 begins shift
[1518-05-10 00:56] wakes up
[1518-05-28 00:48] wakes up
[1518-08-09 00:13] falls asleep
[1518-06-22 00:04] Guard #2953 begins shift
[1518-05-08 23:59] Guard #2953 begins shift
[1518-04-01 00:03] Guard #419 begins shift
[1518-10-25 00:38] wakes up
[1518-05-02 00:13] falls asleep
[1518-05-04 00:51] wakes up
[1518-10-17 00:41] falls asleep
[1518-09-24 00:03] falls asleep
[1518-09-09 00:58] wakes up
[1518-04-12 00:12] falls asleep
[1518-06-14 23:48] Guard #2693 begins shift
[1518-03-27 00:35] wakes up
[1518-03-23 00:02] Guard #223 begins shift
[1518-06-12 00:50] wakes up
[1518-07-18 00:23] falls asleep
[1518-08-25 00:30] falls asleep
[1518-05-12 00:11] falls asleep
[1518-09-19 00:40] wakes up
[1518-08-15 00:57] wakes up
[1518-09-25 00:46] wakes up
[1518-07-07 00:41] wakes up
[1518-05-02 00:54] falls asleep
[1518-05-24 00:57] wakes up
[1518-11-16 00:00] Guard #2039 begins shift
[1518-08-24 00:23] falls asleep
[1518-07-13 00:36] falls asleep
[1518-07-02 00:42] falls asleep
[1518-04-08 23:57] Guard #2953 begins shift
[1518-06-29 23:56] Guard #3547 begins shift
[1518-03-26 00:56] falls asleep
[1518-08-15 00:01] Guard #659 begins shift
[1518-06-29 00:00] Guard #1153 begins shift
[1518-05-29 00:56] wakes up
[1518-05-13 00:07] falls asleep
[1518-04-24 00:01] Guard #419 begins shift
[1518-09-17 00:40] falls asleep
[1518-08-23 23:59] Guard #179 begins shift
[1518-08-31 00:04] Guard #1637 begins shift
[1518-10-22 00:14] falls asleep
[1518-04-19 00:04] Guard #3547 begins shift
[1518-06-15 00:01] falls asleep
[1518-06-08 00:46] wakes up
[1518-08-14 00:03] Guard #2693 begins shift
[1518-07-06 00:44] falls asleep
[1518-11-14 00:27] falls asleep
[1518-09-08 00:18] wakes up
[1518-07-02 00:45] wakes up
[1518-05-22 23:59] Guard #1699 begins shift
[1518-07-02 00:37] wakes up
[1518-07-31 00:16] falls asleep
[1518-08-30 00:12] falls asleep
[1518-09-06 00:01] Guard #409 begins shift
[1518-11-06 23:57] Guard #223 begins shift
[1518-11-23 00:24] falls asleep
[1518-04-18 00:36] falls asleep
[1518-11-18 00:16] wakes up
[1518-05-18 00:51] wakes up
[1518-03-29 00:48] wakes up
[1518-09-11 00:16] falls asleep
File diff suppressed because one or more lines are too long
+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
+206
View File
@@ -0,0 +1,206 @@
//
// Advent of Code 2018 "Day 2: Inventory Management System"
//
import Foundation
class Inventory {
var IDarray: [String] = []
var IDarrayOfdict: [[Character : Int]] = []
var validIDs: [String] = []
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day02.txt'
init(withFile filename: String) {
let IDs = Tools.readFile(fromPath: filename)
IDarray = IDs.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 = IDarray.last, lastStr.count == 0 else { return }
IDarray.removeLast() // empty string
}
// Supply test data in the form of a String
init(withString IDs: String) {
IDarray = IDs.components(separatedBy: "\n")
}
func createDictionaryCount(withID ID: String) -> [Character : Int] {
var retVal: [Character : Int] = [:]
for idChar in ID {
if let count = retVal[idChar] {
retVal[idChar] = count + 1
} else {
retVal[idChar] = 1
}
}
return retVal
}
func createArrayOfDicts() {
for idStr in IDarray {
IDarrayOfdict.append( createDictionaryCount(withID: idStr))
}
}
func countExactlyNLetters(number: Int) -> Int {
var retVal = 0
if IDarrayOfdict.count < 1 {
createArrayOfDicts()
}
// Set up new dictionary of combination of all
for index in 0..<IDarrayOfdict.count {
for (_, count) in IDarrayOfdict[index] {
if count == number {
retVal += 1
validIDs.append(IDarray[index])
break
}
}
}
return retVal
}
func computeChecksum() -> Int {
let twos = countExactlyNLetters(number: 2)
let threes = countExactlyNLetters(number: 3)
return twos * threes
}
// Find IDs that differ by only one character at the identical location
// Use a diff filter on the output of 'zip' (zip : Creates a sequence of pairs built out of two underlying sequences)
// Only add the indicies of the IDs if there is only one diff
func determineListOfCandidates() -> (box1: Int, box2: Int) {
var retVal: (box1: Int, box2: Int) = (0,0)
var difference: [(Character, Character)] = []
for index in 0..<IDarray.count-1 {
for inner in index+1..<IDarray.count {
difference = zip(IDarray[index], IDarray[inner]).filter{ $0 != $1 }
if difference.count == 1 {
retVal = (index, inner)
}
}
}
return retVal
}
}
class Day02: AOCDay {
lazy var tests: (() -> ()) = day02Tests
lazy var final: (() -> ()) = day02Final
let testString = """
abcdef
bababc
abbcde
abcccd
aabcdd
abcdee
ababab
"""
let testStringPart2 = """
abcde
fghij
klmno
pqrst
fguij
axcye
wvxyz
"""
func testInventoryInitWithFile() {
let inv = Inventory(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day02.txt")
XCTAssertEqual(test: "testInventoryInitWithFile count", withExpression: (inv.IDarray.count == 250))
XCTAssertEqual(test: "testInventoryInitWithFile [3]", withExpression: (inv.IDarray[3] == "fonwsmjyquwrapeczikghttdpl"))
if let lastString = inv.IDarray.last {
XCTAssertEqual(test: "testInventoryInitWithFile [last]", withExpression: (lastString == "fonbdmjyqujsapeczikghtvdxl"))
}
}
// abcdef contains no letters that appear exactly two or three times.
// bababc contains two a and three b, so it counts for both.
// abbcde contains two b, but no letter appears exactly three times.
// abcccd contains three c, but no letter appears exactly two times.
// aabcdd contains two a and two d, but it only counts once.
// abcdee contains two e.
// ababab contains three a and three b, but it only counts once.
func testInventoryInitWithString() {
let inv = Inventory(withString: testString)
XCTAssertEqual(test: "testInventoryInitWithString count", withExpression: (inv.IDarray.count == 7))
XCTAssertEqual(test: "testInventoryInitWithString [3]", withExpression: (inv.IDarray[3] == "abcccd"))
if let lastString = inv.IDarray.last {
XCTAssertEqual(test: "testInventoryInitWithString [last]", withExpression: (lastString == "ababab"))
}
}
func testCreateDictionaryCount() {
let inv = Inventory(withString: testString)
var dict = inv.createDictionaryCount(withID: inv.IDarray[0])
XCTAssertEqual(test: "testCreateDictionaryCount [0][a]", withExpression: (dict["a"] == 1))
dict = inv.createDictionaryCount(withID: inv.IDarray[1])
XCTAssertEqual(test: "testCreateDictionaryCount [1][a]", withExpression: (dict["a"] == 2))
XCTAssertEqual(test: "testCreateDictionaryCount [1][b]", withExpression: (dict["b"] == 3))
dict = inv.createDictionaryCount(withID: inv.IDarray[6])
XCTAssertEqual(test: "testCreateDictionaryCount [6][a]", withExpression: (dict["a"] == 3))
XCTAssertEqual(test: "testCreateDictionaryCount [6][b]", withExpression: (dict["b"] == 3))
}
func testCreateArrayOfDicts() {
let inv = Inventory(withString: testString)
inv.createArrayOfDicts() //inv.IDarrayOfdict[][]
XCTAssertEqual(test: "testCreateArrayOfDicts count", withExpression: (inv.IDarrayOfdict.count == 7))
if inv.IDarrayOfdict.count > 6 {
XCTAssertEqual(test: "testCreateArrayOfDicts [0][a]", withExpression: (inv.IDarrayOfdict[0]["a"] == 1))
XCTAssertEqual(test: "testCreateArrayOfDicts [1][a]", withExpression: (inv.IDarrayOfdict[1]["a"] == 2))
XCTAssertEqual(test: "testCreateArrayOfDicts [1][b]", withExpression: (inv.IDarrayOfdict[1]["b"] == 3))
XCTAssertEqual(test: "testCreateArrayOfDicts [6][a]", withExpression: (inv.IDarrayOfdict[6]["a"] == 3))
XCTAssertEqual(test: "testCreateArrayOfDicts [6][b]", withExpression: (inv.IDarrayOfdict[6]["b"] == 3))
}
}
func testCountExactlyNLetters() {
let inv = Inventory(withString: testString)
let twos = inv.countExactlyNLetters(number: 2)
XCTAssertEqual(test: "testCountExactlyNLetters 2", withExpression: (twos == 4))
let threes = inv.countExactlyNLetters(number: 3)
XCTAssertEqual(test: "testCountExactlyNLetters 3", withExpression: (threes == 3))
}
func testComputeChecksum() {
let inv = Inventory(withString: testString)
let checksum = inv.computeChecksum()
XCTAssertEqual(test: "testComputeChecksum", withExpression: (checksum == 12))
}
func testDetermineListOfCandidates() {
let inv = Inventory(withString: testStringPart2)
let candidate = inv.determineListOfCandidates()
XCTAssertEqual(test: "testDetermineListOfCandidates", withExpression: (candidate == (1, 4)))
}
func day02Tests() {
testInventoryInitWithFile()
testInventoryInitWithString()
testCreateDictionaryCount()
testCreateArrayOfDicts()
testCountExactlyNLetters()
testComputeChecksum()
testDetermineListOfCandidates()
}
func day02Final() {
// let retVal = "None"
let inv = Inventory(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day02.txt")
let checksum = inv.computeChecksum()
let ID = inv.determineListOfCandidates()
print("Answer to part 1 is: \(checksum)")
var answer = ""
let answerChars = zip(inv.IDarray[ID.box1], inv.IDarray[ID.box2]).filter{ $0 == $1 }
for tuple in answerChars {
answer.append(tuple.0)
}
print("Answer to part 2 is: \(answer)")
}
}
+226
View File
@@ -0,0 +1,226 @@
//
// Advent of Code 2018 "Day 3: No Matter How You Slice It"
//
import Foundation
struct ElfSquare {
var ID = 0
var loc = (fromLeft: 0, fromTop: 0)
var size = (width: 0, height: 0)
}
// We know:
// - the number of claims
// - the size and position of each claim
// - the claim size and positions are all integers => using array cells to solve
// Read in data
// parse data
// find out the size of the sheet
// lay down all the claims
// count the overlapping cells
class Slice {
var fabric: [[Int]] = []
var claims: [ElfSquare] = []
var corruptedClaims: [Int : Bool] = [:] // build list of claims that overlap
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day03.txt'
init(withFile filename: String) {
let slices = Tools.readFile(fromPath: filename)
var sliceArray = slices.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 = sliceArray.last, lastStr.count == 0 else { return }
sliceArray.removeLast() // empty string
parseData(withSlices: sliceArray)
}
// Supply test data in the form of a String
init(withString slices: String) {
let sliceArray = slices.components(separatedBy: "\n")
parseData(withSlices: sliceArray)
}
func parseData(withSlices sliceArray: [String]) {
func getTuple(from tupleString: String, withSeparator sep: String) -> (Int, Int) {
var retVal = (-1, -1)
let elements = tupleString.components(separatedBy: sep)
if (elements.count > 1) {
let first = Int(elements[0]) ?? -1
let second = Int(elements[1]) ?? -1
retVal = (first, second)
}
return retVal
}
// #1 @ 1,3: 4x4
for line in sliceArray {
var claim = line
var square = ElfSquare()
// remove all spaces and convert delimeters to ':'
claim.removeFirst()
claim = claim.replacingOccurrences(of: " ", with: "")
claim = claim.replacingOccurrences(of: "@", with: ":")
var parts = claim.components(separatedBy: ":")
square.ID = Int(parts[0]) ?? -1
square.loc = getTuple(from: parts[1], withSeparator: ",")
square.size = getTuple(from: parts[2], withSeparator: "x")
claims.append(square)
corruptedClaims[square.ID] = false
}
}
// find out the size of the sheet
func getFabricSize() -> (width: Int, height: Int) {
var retVal = (-1, -1)
var maxHeight = 0
var maxWidth = 0
for claim in claims {
let height = claim.loc.fromTop + claim.size.height
let width = claim.loc.fromLeft + claim.size.width
maxHeight = max(maxHeight, height)
maxWidth = max(maxWidth, width)
}
maxHeight += 1
maxWidth += 1
retVal = (maxWidth, maxHeight)
fabric = Array(repeating: Array(repeating: 0, count: maxWidth), count: maxHeight)
return retVal
}
// lay down all the claims
func apply(claim: ElfSquare) {
for j in claim.loc.fromTop..<(claim.loc.fromTop+claim.size.height) {
for i in claim.loc.fromLeft..<(claim.loc.fromLeft+claim.size.width) {
if fabric[j][i] != 0 {
if fabric[j][i] > 0 {
corruptedClaims[fabric[j][i]] = true
}
corruptedClaims[claim.ID] = true
fabric[j][i] = -1
} else {
fabric[j][i] = claim.ID
}
}
}
}
// count the overlapping cells
func countOverlappingClaims() -> Int {
var retVal = 0
if fabric.count == 0 {
_ = getFabricSize()
}
for claim in claims {
apply(claim: claim)
}
for row in fabric {
retVal += row.filter { $0 == -1 }.count
}
return retVal
}
// Find the one cell that does not overlap
func findUncorruptedClaim() -> Int {
return corruptedClaims.filter{ $0.value == false }.keys.first ?? -1
}
}
class Day03: AOCDay {
lazy var tests: (() -> ()) = day03Tests
lazy var final: (() -> ()) = day03Final
let testSample = """
#1 @ 1,3: 4x4
#2 @ 3,1: 4x4
#3 @ 5,5: 2x2
"""
func testDisplaySample(fabric: [[Int]]) {
for j in 0..<fabric.count {
for i in 0..<fabric[j].count {
if fabric[j][i] == 0 {
print(".", terminator: " ")
} else if fabric[j][i] == -1 {
print("X", terminator: " ")
} else {
print("\(fabric[j][i])", terminator: " ")
}
}
print("")
}
}
// Read in data
func testSliceInitWithString() {
let slice = Slice(withString: testSample)
XCTAssertEqual(test: "testSliceInitWithString [1].ID", withExpression: (slice.claims[1].ID == 2))
XCTAssertEqual(test: "testSliceInitWithString [1].loc", withExpression: (slice.claims[1].loc == (3,1)))
XCTAssertEqual(test: "testSliceInitWithString [1].size", withExpression: (slice.claims[1].size == (4, 4)))
}
// Read in data
func testSliceInitWithFile() {
let slice = Slice(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day03.txt")
XCTAssertEqual(test: "testSliceInitWithFile [699].ID", withExpression: (slice.claims[699].ID == 700))
XCTAssertEqual(test: "testSliceInitWithFile [700].loc", withExpression: (slice.claims[700].loc == (821, 673)))
XCTAssertEqual(test: "testSliceInitWithFile [701].size", withExpression: (slice.claims[701].size == (13, 20)))
}
// find out the size of the sheet
func testGetFabricSize() {
let slice = Slice(withString: testSample)
let dims = slice.getFabricSize()
XCTAssertEqual(test: "testGetFabricSize", withExpression: (dims == (8, 8)))
}
// lay down all the claims
func testApplyClaim() {
let slice = Slice(withString: testSample)
_ = slice.getFabricSize()
testDisplaySample(fabric: slice.fabric)
slice.apply(claim: slice.claims[0])
print("")
testDisplaySample(fabric: slice.fabric)
slice.apply(claim: slice.claims[1])
print("")
testDisplaySample(fabric: slice.fabric)
slice.apply(claim: slice.claims[2])
print("")
testDisplaySample(fabric: slice.fabric)
}
// count the overlapping cells
func testCountOverlappingFrames() {
let slice = Slice(withString: testSample)
let overlapArea = slice.countOverlappingClaims()
XCTAssertEqual(test: "testCountOverlappingFrames", withExpression: (overlapArea == 4))
}
func testFindUncorruptedClaim() {
let slice = Slice(withString: testSample)
_ = slice.countOverlappingClaims()
let uncorruptedClaimID = slice.findUncorruptedClaim()
XCTAssertEqual(test: "testFindUncorruptedClaim", withExpression: (uncorruptedClaimID == 3))
}
func day03Tests() {
testSliceInitWithString()
testSliceInitWithFile()
testGetFabricSize()
testApplyClaim()
testCountOverlappingFrames()
testFindUncorruptedClaim()
}
func day03Final() {
let slice = Slice(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day03.txt")
let overlapArea = slice.countOverlappingClaims()
print("Answer to part 1 is: \(overlapArea)")
print("Answer to part 2 is: \(slice.findUncorruptedClaim())")
}
}
+400
View File
@@ -0,0 +1,400 @@
//
// Advent of Code 2018 "Day 4: Repose Record"
//
import Foundation
enum Action {
case startShift
case sleep
case wake
case none
}
struct Activity: Equatable, Comparable {
var day = -1
var minute = -1
var sortKey = -1.0 // Cobination of day + minute/60
var action = Action.none
var id = -1
static func == (lhs: Activity, rhs: Activity) -> Bool {
return (lhs.day == rhs.day) && (lhs.minute == rhs.minute) && (lhs.sortKey == rhs.sortKey) && (lhs.action == rhs.action) && (lhs.id == rhs.id)
}
static func < (lhs: Activity, rhs: Activity) -> Bool {
return lhs.sortKey < rhs.sortKey
}
}
// Make some assumptions based on the fact that there is only on guard on duty per night
// read in data
// parse data to extract sleep times for each guard on each day
// create guard sleep map
// determine best guard with best minute
// - find guard with most minutes asleep
// - create histogram and determine which minute he has slept through the most
class Repose {
var scheduleArray: [String] = []
var sleepMapForGuardID: [Int : [Int]] = [:] // dictionary of [id : Array of ints, one for each hour; increment if asleep]
var activitiesForDay: [Int : [Activity]] = [:]
// Supply filename for input ex: '/home/peterr/AOC2018/Sources/AOC2018/data/day04.txt'
init(withFile filename: String) {
let schedule = Tools.readFile(fromPath: filename)
scheduleArray = schedule.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 = scheduleArray.last, lastStr.count == 0 else { return }
scheduleArray.removeLast() // empty string
}
// Supply test data in the form of a String
init(withString schedule: String) {
scheduleArray = schedule.components(separatedBy: "\n")
}
// Needed this due to Guard starting day before midnight of the previous month (broke my simple day = month * 31 rule)
static func increment(day: Int) -> Int {
// there is a leap year every year divisible by four except for years which are both divisible by 100 and not divisible by 400.
// Therefore, the year 2000 will be a leap year, but the years 1700, 1800, and 1900 were not.
var retVal = 0
let nDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
// let leapnDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
var myMonth = day / 31
var myDay = day % 31
if myDay == 0 {
myDay = 31
myMonth -= 1
}
if myDay == nDays[myMonth - 1] {
retVal = (myMonth + 1) * 31 + 1
} else {
retVal = day + 1
}
return retVal
}
static func parse(line: String) -> Activity {
var retVal = Activity()
parseScope:
if line.count > 0 {
// Split line into time and action
var parseString = line
parseString.removeFirst()
let splitStr = parseString.components(separatedBy: "]")
guard splitStr.count > 1 else { break parseScope }
let timedateSplit = splitStr[0].components(separatedBy: " ")
guard timedateSplit.count > 1 else { break parseScope }
let dateSplit = timedateSplit[0].components(separatedBy: "-")
guard dateSplit.count > 2 else { break parseScope }
let month = (Int(dateSplit[1]) ?? 0) * 31
let date = Int(dateSplit[2]) ?? 0
let day = month + date
// Parse time into day and minutes
let timeSplit = timedateSplit[1].components(separatedBy: ":")
guard timeSplit.count > 1 else { break parseScope }
guard let hour = Int(timeSplit[0]) else { break parseScope }
guard let min = Int(timeSplit[1]) else { break parseScope }
retVal.day = day
retVal.minute = min
if hour == 23 {
retVal.day = Repose.increment(day: retVal.day) // Need to accomodate last day of the month
retVal.minute = 0
}
retVal.sortKey = Double(retVal.day) + Double(retVal.minute) / 60.0
// parse Action
let actionStr = splitStr[1].suffix(splitStr[1].count - 7)
switch actionStr {
case "asleep" :
retVal.action = Action.sleep
case "up" :
retVal.action = Action.wake
default:
retVal.action = Action.startShift
var startShiftStr = actionStr
startShiftStr.removeFirst()
retVal.id = Int(startShiftStr.components(separatedBy: " ")[0]) ?? -1
}
}
return retVal
}
func add(activity: Activity) {
if activitiesForDay[activity.day] == nil {
activitiesForDay[activity.day] = [activity]
} else {
activitiesForDay[activity.day]!.append(activity)
}
}
func addActivitiesIfNecessary() {
if activitiesForDay.keys.count == 0 {
for act in scheduleArray {
add(activity: Repose.parse(line: act))
}
for day in activitiesForDay.keys {
activitiesForDay[day]!.sort()
sleepMapForGuardID[findID(forDay: day)] = Array(repeating: 0, count: 60)
}
}
}
func findID(forDay day: Int) -> Int {
var retVal = -1
addActivitiesIfNecessary()
if let array = activitiesForDay[day] {
retVal = array.filter { $0.id != -1 }[0].id
}
return retVal
}
func buildHistogram(forDay day: Int) -> [Int] {
var retVal = Array(repeating: 0, count: 60)
addActivitiesIfNecessary()
if let array = activitiesForDay[day] {
var startSleep = 0
var endSleep = 0
for activity in array {
if activity.action == Action.sleep {
startSleep = activity.minute
} else if activity.action == Action.wake {
endSleep = activity.minute
for min in startSleep..<endSleep {
retVal[min] = 1
}
}
}
}
return retVal
}
func add(histogram: [Int], toID id: Int) {
guard var array = sleepMapForGuardID[id] else { return }
guard array.count == 60 else { return }
guard histogram.count == 60 else { return }
for i in 0..<60 {
array[i] = array[i] + histogram[i]
}
sleepMapForGuardID[id] = array
}
// Sum all the minutes slept, retrun the total and the minute of most sleeps
func sumMinutes(forID id: Int) -> (total: Int, maxMinute: Int, maxMinuteVal: Int) {
var retVal = (total: 0, maxMinute: -1, maxMinuteVal: -1)
guard var array = sleepMapForGuardID[id] else { return retVal }
guard array.count == 60 else { return retVal }
for i in 0..<60 {
retVal.total += array[i]
}
retVal.maxMinuteVal = array.max() ?? 1
retVal.maxMinute = array.firstIndex(of: retVal.maxMinuteVal) ?? 0
return retVal
}
func findGuard(forPart1 part1: Bool) -> (id: Int, minute: Int) {
var retVal = (id: 0, minute: -1)
addActivitiesIfNecessary()
for day in activitiesForDay.keys {
let hist = buildHistogram(forDay: day)
add(histogram: hist, toID: findID(forDay: day))
}
var maxTime = 0
for id in sleepMapForGuardID.keys {
let stats = sumMinutes(forID: id)
let maxForPart = part1 ? stats.total : stats.maxMinuteVal
if maxForPart > maxTime {
maxTime = maxForPart
retVal.minute = stats.maxMinute
retVal.id = id
}
}
return retVal
}
}
// Need a state-machine
// - start shift
// - sleep
// - wake
// Date ID Minute
// 000000000011111111112222222222333333333344444444445555555555
// 012345678901234567890123456789012345678901234567890123456789
// 11-01 #10 .....####################.....#########################.....
// 11-03 #10 ........................#####...............................
// #10 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
// 11-02 #99 ........................................##########..........
// 11-04 #99 ....................................##########..............
// 11-05 #99 .............................................##########.....
// #99 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,2,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0
class Day04: AOCDay {
lazy var tests: (() -> ()) = day04Tests
lazy var final: (() -> ()) = day04Final
let testData = """
[1518-11-01 00:00] Guard #10 begins shift
[1518-11-01 00:05] falls asleep
[1518-11-01 00:25] wakes up
[1518-11-01 00:30] falls asleep
[1518-11-01 00:55] wakes up
[1518-11-01 23:58] Guard #99 begins shift
[1518-11-02 00:40] falls asleep
[1518-11-02 00:50] wakes up
[1518-11-03 00:05] Guard #10 begins shift
[1518-11-03 00:24] falls asleep
[1518-11-03 00:29] wakes up
[1518-11-04 00:02] Guard #99 begins shift
[1518-11-04 00:36] falls asleep
[1518-11-04 00:46] wakes up
[1518-11-05 00:03] Guard #99 begins shift
[1518-11-05 00:45] falls asleep
[1518-11-05 00:55] wakes up
"""
let mapNum10 = [0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0]
let mapNum99 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,2,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0]
let day342 = [0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0]
let day344 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
func testIncrementDay() {
var testDay = Repose.increment(day: 62)
XCTAssertEqual(test: "testIncrementDay end-of-month 1", withExpression: (testDay == 2*31 + 1))
testDay = Repose.increment(day:90)
XCTAssertEqual(test: "testIncrementDay end-of-month 2", withExpression: (testDay == 3*31 + 1))
testDay = Repose.increment(day: 124)
XCTAssertEqual(test: "testIncrementDay end-of-month 3", withExpression: (testDay == 4*31 + 1))
testDay = Repose.increment(day: 154)
XCTAssertEqual(test: "testIncrementDay end-of-month 4", withExpression: (testDay == 5*31 + 1))
testDay = Repose.increment(day: 186)
XCTAssertEqual(test: "testIncrementDay end-of-month 5", withExpression: (testDay == 6*31 + 1))
testDay = Repose.increment(day: 216)
XCTAssertEqual(test: "testIncrementDay end-of-month 6", withExpression: (testDay == 7*31 + 1))
testDay = Repose.increment(day: 248)
XCTAssertEqual(test: "testIncrementDay end-of-month 7", withExpression: (testDay == 8*31 + 1))
testDay = Repose.increment(day: 279)
XCTAssertEqual(test: "testIncrementDay end-of-month 8", withExpression: (testDay == 9*31 + 1))
testDay = Repose.increment(day: 309)
XCTAssertEqual(test: "testIncrementDay end-of-month 9", withExpression: (testDay == 10*31 + 1))
testDay = Repose.increment(day: 341)
XCTAssertEqual(test: "testIncrementDay end-of-month 10", withExpression: (testDay == 11*31 + 1))
testDay = Repose.increment(day: 371)
XCTAssertEqual(test: "testIncrementDay end-of-month 11", withExpression: (testDay == 12*31 + 1))
testDay = Repose.increment(day: 403)
XCTAssertEqual(test: "testIncrementDay end-of-month 12", withExpression: (testDay == 13*31 + 1))
}
func testPasrseLine() {
var response = Repose.parse(line: "")
XCTAssertEqual(test: "testPasrseLine empty", withExpression: (response.minute == -1))
let repo = Repose(withString: testData)
response = Repose.parse(line: repo.scheduleArray[0])
XCTAssertEqual(test: "testPasrseLine begin", withExpression: (response == Activity(day: 341+1, minute: 0, sortKey: 342.0, action: Action.startShift, id: 10)))
response = Repose.parse(line: repo.scheduleArray[1])
XCTAssertEqual(test: "testPasrseLine first asleep", withExpression: (response == Activity(day: 341+1, minute: 5, sortKey: 342.0 + 5.0/60.0, action: Action.sleep, id: -1)))
response = Repose.parse(line: repo.scheduleArray[2])
XCTAssertEqual(test: "testPasrseLine first wake up", withExpression: (response == Activity(day: 341+1, minute: 25, sortKey: 342.0 + 25.0/60.0, action: Action.wake, id: -1)))
response = Repose.parse(line: repo.scheduleArray[3])
XCTAssertEqual(test: "testPasrseLine second alseep", withExpression: (response == Activity(day: 341+1, minute: 30, sortKey: 342.0 + 0.5, action: Action.sleep, id: -1)))
response = Repose.parse(line: repo.scheduleArray[4])
XCTAssertEqual(test: "testPasrseLine second wake up", withExpression: (response == Activity(day: 341+1, minute: 55, sortKey: 342.0 + 55.0/60.0, action: Action.wake, id: -1)))
response = Repose.parse(line: repo.scheduleArray[5])
XCTAssertEqual(test: "testPasrseLine new guard", withExpression: (response == Activity(day: 341+2, minute: 0, sortKey: 343.0, action: Action.startShift, id: 99)))
response = Repose.parse(line: repo.scheduleArray[6])
XCTAssertEqual(test: "testPasrseLine alseep", withExpression: (response == Activity(day: 341+2, minute: 40, sortKey: 343.0 + 2.0/3.0, action: Action.sleep, id: -1)))
response = Repose.parse(line: repo.scheduleArray[7])
XCTAssertEqual(test: "testPasrseLine wake up", withExpression: (response == Activity(day: 341+2, minute: 50, sortKey: 343.0 + 50.0/60.0, action: Action.wake, id: -1)))
}
func testAddActivity() {
let repo = Repose(withString: testData)
for act in repo.scheduleArray {
repo.add(activity: Repose.parse(line: act))
}
XCTAssertEqual(test: "testAddActivity number of days", withExpression: (repo.activitiesForDay.keys.count == 5))
var count = repo.activitiesForDay[342]?.count ?? 0
XCTAssertEqual(test: "testAddActivity activies day 1", withExpression: (count == 5))
count = repo.activitiesForDay[343]?.count ?? 0
XCTAssertEqual(test: "testAddActivity activies day 2", withExpression: (count == 3))
count = repo.activitiesForDay[344]?.count ?? 0
XCTAssertEqual(test: "testAddActivity activies day 3", withExpression: (count == 3))
}
func testFindIDForDay() {
let repo = Repose(withString: testData)
var id = repo.findID(forDay: 342)
XCTAssertEqual(test: "testFindIDForDay activies day 342", withExpression: (id == 10))
id = repo.findID(forDay: 343)
XCTAssertEqual(test: "testFindIDForDay activies day 343", withExpression: (id == 99))
id = repo.findID(forDay: 344)
XCTAssertEqual(test: "testFindIDForDay activies day 344", withExpression: (id == 10))
id = repo.findID(forDay: 345)
XCTAssertEqual(test: "testFindIDForDay activies day 345", withExpression: (id == 99))
id = repo.findID(forDay: 346)
XCTAssertEqual(test: "testFindIDForDay activies day 346", withExpression: (id == 99))
}
func testBuildHistogram() {
let repo = Repose(withString: testData)
var hist = repo.buildHistogram(forDay: 342)
XCTAssertEqual(test: "testBuildHistogram activies day 342", withExpression: (hist == day342))
hist = repo.buildHistogram(forDay: 344)
XCTAssertEqual(test: "testBuildHistogram activies day 344", withExpression: (hist == day344))
}
func testAddHistogram() {
let repo = Repose(withString: testData)
repo.addActivitiesIfNecessary()
for day in repo.activitiesForDay.keys {
let hist = repo.buildHistogram(forDay: day)
repo.add(histogram: hist, toID: repo.findID(forDay: day))
}
guard let histID10 = repo.sleepMapForGuardID[10] else { return }
guard let histID99 = repo.sleepMapForGuardID[99] else { return }
XCTAssertEqual(test: "testAddHistogram id 10", withExpression: (histID10 == mapNum10))
XCTAssertEqual(test: "testAddHistogram id 99", withExpression: (histID99 == mapNum99))
}
func testSumMinutes() {
let repo = Repose(withString: testData)
repo.addActivitiesIfNecessary()
for day in repo.activitiesForDay.keys {
let hist = repo.buildHistogram(forDay: day)
repo.add(histogram: hist, toID: repo.findID(forDay: day))
}
var tuple = repo.sumMinutes(forID: 10)
let passTest = (tuple.total == 50) && (tuple.maxMinute == 24)
XCTAssertEqual(test: "testSumMinutes id 10", withExpression: passTest)
tuple = repo.sumMinutes(forID: 99)
XCTAssertEqual(test: "testSumMinutes id 99", withExpression: (tuple == (30, 45, 3)))
}
func testFindGuard() {
let repo = Repose(withString: testData)
var answer = repo.findGuard(forPart1: true)
XCTAssertEqual(test: "testFindGuard Part 1", withExpression: (answer == (10, 24)))
answer = repo.findGuard(forPart1: false)
XCTAssertEqual(test: "testFindGuard Part 2", withExpression: (answer == (99, 45)))
}
func day04Tests() {
testIncrementDay()
testPasrseLine()
testAddActivity()
testFindIDForDay()
testBuildHistogram()
testAddHistogram()
testSumMinutes()
testFindGuard()
}
func day04Final() {
let repo = Repose(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day04.txt")
var answer = repo.findGuard(forPart1: true)
print("Answer to part 1 is: \(answer.id * answer.minute)")
answer = repo.findGuard(forPart1: false)
print("Answer to part 2 is: \(answer.id * answer.minute)")
}
}
+156
View File
@@ -0,0 +1,156 @@
//
// Advent of Code 2018 "Day 5: Alchemical Reduction"
//
import Foundation
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) {
var polymerString = Tools.readFile(fromPath: filename)
// 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 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)
}
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]
}
}
polymer = acc.filter {$0 != " "}
}
func findSmallestFullyReactedAndRemovedPolymer() -> Int {
let start = Unicode.Scalar("a").value
let end = Unicode.Scalar("z").value
let polyCopy = polymer
var minLen = polymer.count
for i in start...end {
polymer = polyCopy
acc = Array(repeating: " ", count: polymer.count)
if let type = Unicode.Scalar(i) {
let unit = Character(type)
let upperUnit = Character(String(unit).uppercased())
polymer = polymer.filter { $0 != unit && $0 != upperUnit }
reducer()
minLen = min(minLen, polymer.count)
}
}
return minLen
}
}
class Day05: AOCDay {
lazy var tests: (() -> ()) = day05Tests
lazy var final: (() -> ()) = day05Final
// In aA, a and A react, leaving nothing behind.
// In abBA, bB destroys itself, leaving aA. As above, this then destroys itself, leaving nothing.
// In abAB, no two adjacent units are of the same type, and so nothing happens.
// In aabAAB, even though aa and AA are of the same type, their polarities match, and so nothing happens.
let testData = "dabAcCaCBAcCcaDA"
func testReductionInit() {
let testArray = Array(testData)
var reduc = Reduction(withString: testData)
XCTAssertEqual(test: "testReductionInit with String", withExpression: (reduc.polymer == testArray))
reduc = Reduction(withFile: "/home/peterr/AOC2018/Sources/AOC2018/data/day05.txt")
XCTAssertEqual(test: "testReductionInit with File", withExpression: (reduc.polymer.last == "Y"))
}
func testReducePolymer() {
var reduc = Reduction(withString: "aA")
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == ""))
reduc = Reduction(withString: "abBA")
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == ""))
reduc = Reduction(withString: "abAB")
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == "abAB"))
reduc = Reduction(withString: "aabAAB")
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == "aabAAB"))
reduc = Reduction(withString: testData)
reduc.reducer()
XCTAssertEqual(test: "testReducePolymer", withExpression: (String(reduc.polymer) == "dabCBAcaDA"))
}
func testRemoveUnit() {
var reduc = Reduction(withString: testData)
reduc.polymer = reduc.polymer.filter { $0 != "a" && $0 != "A" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "dbcCCBcCcD"))
reduc = Reduction(withString: testData)
reduc.polymer = reduc.polymer.filter { $0 != "b" && $0 != "B" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "daAcCaCAcCcaDA"))
reduc = Reduction(withString: testData)
reduc.polymer = reduc.polymer.filter { $0 != "c" && $0 != "C" }
XCTAssertEqual(test: "testRemoveOneType", withExpression: (String(reduc.polymer) == "dabAaBAaDA"))
reduc = Reduction(withString: testData)
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.polymer = reduc.polymer.filter { $0 != "a" && $0 != "A" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact a", withExpression: (String(reduc.polymer) == "dbCBcD"))
reduc = Reduction(withString: testData)
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.polymer = reduc.polymer.filter { $0 != "c" && $0 != "C" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact c", withExpression: (String(reduc.polymer) == "daDA"))
reduc = Reduction(withString: testData)
reduc.polymer = reduc.polymer.filter { $0 != "d" && $0 != "D" }
reduc.reducer()
XCTAssertEqual(test: "testRemoveAndReact d", withExpression: (String(reduc.polymer) == "abCBAc"))
}
func testFindSmallestFullyReactedAndRemovedPolymer() {
let reduc = Reduction(withString: testData)
let answer = reduc.findSmallestFullyReactedAndRemovedPolymer()
XCTAssertEqual(test: "testFindSmallestFullyReactedAndRemovedPolymer", withExpression: (answer == 4))
}
func day05Tests() {
testReductionInit()
testReducePolymer()
testRemoveUnit()
testRemoveAndReact()
testFindSmallestFullyReactedAndRemovedPolymer()
}
func day05Final() {
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")
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)")
}
}
+31 -1
View File
@@ -5,7 +5,7 @@
import Foundation
let showTests = true
let onlyOneDay = 0
let onlyOneDay = 16
var allTests: [(() -> ())] = []
var allFinal: [(() -> ())] = []
@@ -13,9 +13,39 @@ print("Advent of Code 2018")
// Compile list of Tests
allTests.append(Day01().tests)
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)
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)")
+96
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 {
@@ -27,4 +66,61 @@ struct Tools {
}
return retVal
}
// Assumes THE string is 'polymer'
static func stringIndexRange(withString str: String, fromRange range: Range<Int>) -> Range<String.Index> {
let myrange = Range(uncheckedBounds: (lower: max(0, min(str.length, range.lowerBound)), upper: min(str.length, max(0, range.upperBound))))
let start = str.index(str.startIndex, offsetBy: myrange.lowerBound)
let end = str.index(start, offsetBy: myrange.upperBound - myrange.lowerBound)
return start ..< end
}
}
extension Character {
var isAscii: Bool {
return unicodeScalars.first?.isASCII == true
}
var ascii: UInt32? {
return isAscii ? unicodeScalars.first?.value : nil
}
}
extension StringProtocol {
// var string: String { return String(self) }
var ascii: [UInt32] {
return compactMap { $0.ascii }
}
subscript(offset: Int) -> Element {
return self[index(startIndex, offsetBy: offset)]
}
}
extension String {
var length: Int {
return count
}
subscript (i: Int) -> String {
return self[i ..< i + 1]
}
func substring(fromIndex: Int) -> String {
return self[min(fromIndex, length) ..< length]
}
func substring(toIndex: Int) -> String {
return self[0 ..< max(0, toIndex)]
}
subscript (r: Range<Int>) -> String {
let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
upper: min(length, max(0, r.upperBound))))
let start = index(startIndex, offsetBy: range.lowerBound)
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return String(self[start ..< end])
}
}