diff --git a/2018/benches/days.rs b/2018/benches/days.rs
index 93d96d2..e594a74 100644
--- a/2018/benches/days.rs
+++ b/2018/benches/days.rs
@@ -71,8 +71,9 @@ day_bench!(day16, 16);
day_bench!(day17, 17);
day_bench!(day18, 18);
day_bench!(day19, 19);
+day_bench!(day20, 20);
benchmark_main!(day01, day02, day03, day04, day05,
day06, day07, day08, day09, day10,
day11, day12, day13, day14, day15,
- day16, day17, day18, day19);
+ day16, day17, day18, day19, day20);
diff --git a/2018/inputs/20.txt b/2018/inputs/20.txt
new file mode 100644
index 0000000..0b8780f
--- /dev/null
+++ b/2018/inputs/20.txt
@@ -0,0 +1 @@
+^EENNNNNWWNENWWNEEEESS(WNSE|)EEESWWWSSESSENESENNEENESEESSSSWNWSSWSWWNENWWN(WSWW(SEEESWSWNWWSWNWWNEEENWWWWSWSSE(N|EESWSWNWWWNNE(S|NWNENE(S|NNEENN(NWWNNE(SEWN|)NNNWSWNWWWSEESWWWWNNNNWWWSEESSWNWWWSWSESWSESWWSWWNWWWWSWNWNEENNEEESS(WNWSNESE|)ENENNNNES(SSSSWS|ENENNNWNWNWSWSWSES(EEN(WNE|ES)|SSS(S|WWWNWWWWSWNWSSWWWWNNWWNENNWWNENNENNWWNENNWSWSWNNENNNWWNNNENEENENESEENESSSSSESSSSEENWNENNW(NENNWW(NNENNEESEESWWW(S(ESSSSSEENWNNESEEESEEENESEESWSSWWNENWWWWWSW(NNEWSS|)SEENEESSSEESSS(WNWSWNWWWSWSEEE(NWES|)E(SWSWNWSSWWNENWNNNNE(NWNE(NWN(E|WSSSWSESWWWNENWWWNNWNEE(SS|NWWNENNNWSWS(E|SSWW(NNN(WSWSEWNENE|)E(NEWS|)SS|SSEE(NWES|)SESS(WNSE|)EESWWSSESEEENEE(NWWWSWNW(ESENEEWWSWNW|)|SWSWWWSSENEESE(EES(ENEE(NWES|)S(W|E(SWEN|)N)|WWWW(WWSESWWNNWNENNW(NWSNES|)S|N))|NN))))))|EESS(WNSE|)EE(NN(WSNE|)N|EE))|S)|E)|EEEENNNESESWSEESWWSWNWS(WNWESE|)SS(SS|EEN(W|ESENEN(WW|ENWNNNW(S|NWNNNNNNWWSESSSWNNW(SWSES(WW(WW|SSES(ENNWESSW|)W)|EE)|NNNNESEEENNWSWNWWNWSSWNWNNE(S|ENWNNNNWWWSWNNNWSSWWWNNEE(SWEN|)NWWWWSSE(N|SWSWSS(EEN(NESEEE(NWWEES|)ESESSE(SSSES(EESWENWW|)WWW(SEWN|)NNWSWNNNW(SSWS(ESEE|WN)|NEN(WWSWENEE|)ESSSE(ESSNNW|)NN)|NNN(E(NWES|)SS|W))|W)|WWNNWNNNESSE(ENWNNE(S|NNNWSWWWSS(SWWWWWSWWWWWSEEEEESENNEESSW(N|SWWSSSWNNWSWWSESE(N|S(EEN(W|ENEENN(WWSEWNEE|)NESSENN(ESSS(WWS|EN)|NNNWSS))|SWSSSWNWSSWNWSSWWWWNENWWNWSSWWWSWSSENENESSSESENEENEEEESENNESSESSSESSWNWWWNNEN(ESSWENNW|)WWSSWSSE(N|SESSSWWWWWSWSESSWSSSWNNWWWSSSESEN(NNWSNESS|)EESENEEENNWNEENESSWSEENNESSENESENNESSSWWSWWWWW(NEEEEWWWWS|)WWSEESWWSEEEEENESSENNN(WWWWSE|ESEENWN(EEENNWNW(SSEWNN|)NENNWSWNWWS(SWNNWSWNWNWN(EEES(W|EEEENE(NN(E|WNNW(WWWSW(NN(E|W)|SES(W|ESEEN(E|WNWNEES(NWWSESNWNEES|))))|NENN(NW(SS|WNNNNW(S|N(EESNWW|)NWSWWSWWWWWSWNN(WSSNNE|)N))|E(E|SS))))|SEESSESENEESSW(N|SEENENWNEE(EENN(WSWWEENE|)E|SSSWSSWSESEEEENENN(WSWWW(SEEWWN|)NE(E|N)|EE(NWWEES|)EEESWSWNWWSESEESEESSSWSSWWNNNWWWSWWSWSESSSWWWSWNWWNNWWWNENNNWSSWWNENWNWN(WSSESWWNWSWWSSWWNWNNN(ESSE(NNESEN|S)|WSSSWNWSWSWNNNWWWNNW(SSSEEESSWNWSSEEEEEEN(W|ESSWWWWWWWSSSESENESSEESSSEEEESWSESENENNNNEEESENESESEEEENWWWNWNEEEEENESSESENENWNW(N(EENEEENENWNNNESEE(NNWSNESS|)SSEESSWSWSESSWNWWWWW(N(W|NESEEN(W|NE(N(NNWESS|)E(S|E)|SS)))|SSENESENESESEEN(EESWSESSWNWNWWWNWWSESEEESSSSEENESEEESESWWSESWWWWWNNWWWSSWNNNWNNENN(EESSW(N|S(W|ES(W|EEEESWSEENNE(WSSWWNSEENNE|))))|WNWWNENWW(SWSESESWWWWSWSSWSSESESSWNWWWSEESSWNWWWNENNNENWWNWWNWSWWNENWWSWNN(ENENESENNEN(WWW(NE|SE)|ESEEEESESS(ENENWN(EN(WN(NWWWEEES|)E|E(SSSEWNNN|)E)|W)|WWN(WSWNN(EE|WWSSE(S(WWNWWEESEE|)EEESW(SEE(NENWESWS|)SSS(W|E)|WW)|N))|E)))|WSSSESE(SWWSSSENNEENEN(W|ESESWSSWWSSWWWN(WNWNNWNNEE(E|S(W|SS)|NNWNWWSWSSWSEE(NNE(N|E)|SSESWSSWWWWSESSESSEEESESWSWNWWSSWNNN(WNN(ESNW|)WNN(ESNW|)NNNEEENNN(ESSSNNNW|)WNNWWSW(SSEE(S(ENSW|)WWSSSSSSSESSESWW(SSENESSSENEN(EEEESSWSSWWNN(WSSWSESWWNWW(SSE(EES(EEN(ENN(WSNE|)EENNESSESWSWNWSS(W|EEEEN(NEENNESSESENNWNENENWNENEENEENEEENESSESWWNWWSSE(N|SWWSSENESENESSSSES(WWWNNN(ESSNNW|)WSSWNNWSWSWS(EE(EE|N)|W(WWWNWSWN(SENESEWNWSWN|)|NNNE(ENENWW(SWEN|)NEEN(ENWESW|)WW|S)))|ENNENWNEENWWNN(WWS(WN|ESSSS)|NNNNW(S|NWNNESESENENWNEEENWWNNENNWNNE(NNWSWNWWSSW(NWN(ENN(WSNE|)NESENEE(SWS(WW|E)|N(N|E))|W)|SESEE(S(WSSS(ENNSSW|)S(WWWWSWWNENN(EES(W|ENNWWNEE(ESSSNNNW|)N)|WWNWWSWWSWSESENEN(W|E(SE(NEWS|)SSEESS(WNWSSWNNNW(NEWS|)SWSESSWNWSWNWWNENEN(E(SSWENN|)E|WN(E|NNN(NE(N(W|EE(SWEN|)NWNENE(NWNWESES|)S)|S)|WSWNWSWWN(NWNWSSWWWSEEEE(SS(WNWSWN|SENNEESSSE(SSWWSSSS(SSENE(SSWENN|)NNENE(NWWWS(SS|E)|SSWSEENNNE(WSSSWWEENNNE|))|WNNNN(NNE(SEWN|)NN|WSWWWN))|ENNW(NEWS|)S))|N)|E))))|ENNE(N|S))|N)))|S)|E)|NNW(S|N)))|SEEENNESSESWSSSSSENNENN(WSNE|)NESSSEEESESWSEESWSSSSWNWNNE(NWWSWWWSSWSWSWSESSESWSWWW(NNNNNWNEE(NE(ENENWWWW(WSS(ENEEWWSW|)W(SSSSEN|N)|NEEN(WW|NE(SEEENEEE(NWWWEEES|)SWWSWWWW(EEEENEWSWWWW|)|NNW(NW(SWEN|)NNESE(N|S)|S))))|S)|SSSESWSE(WNENWNSESWSE|))|WSESS(WNWSNESE|)EENEN(WWSNEE|)EEN(ENWNNESENNWWN(WSSNNE|)EEEE(NWNWN(WSS(W|E)|E)|SWSEENEEENENWW(SWWEEN|)NENENNNW(SSWSNENN|)NWNENWWNWNWW(SEWN|)NN(WW|EEEEESWW(WW|SEES(ENENNENNENESSENNNWNENWWWWNENWWWNNESENENENWNNENWNWWSWNWSWSESEEN(E(SSSWWN(E|WSSWNWNWSW(SEESSSES(WWWN(NNESSNNWSS|)WWW(N|S)|ES(W|SESENES(ENENWWWWNN(ES|WNNWS)|SWWS(WWNENSWSEE|)E(E|SS))))|NNENWNENE(SSSESNWNNN|)ENEENNWNENWWWNEENWNWSWSSSSSE(E(NWNEWSES|)E|SWWSWNNW(NN(WW|EE(NN(WSNE|)NNENEENENWWNEENWWWSSS(E|W(S|NNW(SWNSEN|)NENN(WSNE|)ENENWNNE(NWES|)SENESSWSESS(WNWSWENESE|)EEENESEE(SWWWWWSSSSESESSE(NNNWNNW(S|NEEE(SWSNEN|)E)|SSWSEENNESSEESENN(WWNSEE|)EESSSSWN(WSWNWWN(E|WWS(WWN(NNN(NNW(NWNSES|)S|E)|E)|ESEESWSESW(SESWSSW(N|SSENENESS(ESENENWWNEENNENNWSWNWNW(NEESENEES(SESWSESWSSENESEESWSSEESWSSWWWSWWSESSESSSWNWN(NWSWWNWNENW(NNNESES(W|E(NENNNW(NEN(NNN|ESSESWS(S|EEENWNNWNE(WSESSEWNNWNE|)))|WWS(EESW|WNN))|SWS(EE|S)))|WWSW(SW(N|SWSSENENESSWSWSW(NWNNSSES|)SESEENN(WSNE|)NESSSSESWWSWWNN(W(N|S(W|SSEEESWSESWWNWW(NEEWWS|)WSSWSSESS(WWN(NNNN(NESNWS|)WWWSSW(SEESS(ENNNWNE(WSESSSNNNWNE|)|WNWW(S(WW(NEWS|)W|E)|N))|N)|E)|ENEEES(ENEEENNEEENEESENESSENENNEEENWNEENNWSWWNNNNNENESENEEESENNENNWWWNWWSESS(ENE(E|S)|WWN(E|NNNENNNNWSSWWNW(NEE(S|NNW(SWEN|)NENEESWSES(ENESEENESSWSESENEESSESEENEESSSSWNN(WWSWSEE(N|SESSESSWWN(NWWWSEESWWWNWSSWNWSWWW(NN(WWWSES(WS|EN)|NESE(SWEN|)EENEENNNNE(SSES(E(N|E)|W)|N(WN(WN(ENSW|)WWSW(SEE(ESSSSW|N)|NWSWNNENN(WS|ESSE))|E)|E)))|SSEESWSW(N|WSEESSSESWS(WNNWSSWNWNW(WSS(WNWWS(E|WWNN(E(E|S)|WSSWNNWSSWWW(EEENNEWSSWWW|)|N))|E(E|N))|NEE(S|N(ESENSWNW|)WW))|EEEENESENNNWNNWWSESWW(NNW(SS|NENNEN(WWW|EEESWSES(ESESENENEESSSWN(N|WSSESENESS(WWWNWWW(SEEWWN|)NN(ESEN|NWN)|EEEENWWNENWW(SS|WNNNNESENNNWWNNNESENESS(SESSW(SEESWWWWSEEEESWSEESES(WWNSEE|)ENNWNEESEESENEEESEES(WWWNWSWWWWNE(WSEEEEWWWWNE|)|ENNWNW(S|WNEEEEE(NWNWSWWWWWNENEENES(SWWEEN|)EEE(NNNNNNWNENNWWNWWSSSSENN(E(SSSWSWSS(WSWWNENWNEE(N(WWWSSWSESWWWSWSESES(WWWN(NNNNNNESENE(SSWWSNEENN|)NNWWNNEES(ENESS(WSSNNE|)ENEE(SWEN|)NNNWNNNNEEEENNWNNNNWNWWSESSSE(SWWS(WNWWSSE(SE(N|SSSWWWNWSS(WWSSSS(EE|WWW(NNEE(SWEN|)NNNNESENNWNENWNWNWNNENESEESWW(SESEE(SWSEES(ESWENW|)WW|N(NNENNESSS(ENN(ESSNNW|)NNNEENEENWNNENEENWNEE(NWNWWNNWSSSWNNNNWSWNNEEEEEESE(NNWNWSWNNWWWNWNENNNENNWNEENNWWS(E|WWSSWSSSWSESSSSSE(SSSSEESSSWWNWN(EESNWW|)WWNWWSESESE(ESEEEENEE(NEWS|)SWSWWSWWN(E|WWWSWNN(WN(NWSSWWNWWWWWWNWNENWNNWSSWWSEESSSSWNWWWNWWWSSENESSWWWNNNWWWWSEEESWWSSWWSSSENEN(ESENEN(WNWSNESE|)EESWSESWSWN(N|WWWS(EESES(WWNSEE|)(EEN(NEEESWWSEEENEEESSESENNWNEESESWSSENESSENNNE(SSSSSSE(NN(ESSNNW|)N|SSWWN(NNWWSWSSSW(SS(WNSE|)ENESENN(WNEN(N|W)|ES(EENWESWW|)SSWWWWSSSSWSWNWWN(W(SSSESEN(NWES|)EEENEE|WW)|EEE))|NNNNNE(E(NWWNWWWWNWWN(EENESSE(WNNWSWENESSE|)|WSW(SEEESSE(NEES(ENSW|)W|S)|N))|EE)|S))|E))|NENWWSW(NNW(WWNEENWNNWWSESWSWS(E|WNNNNN(WSSSSW(SEWN|)NWNWSW(SEEWWN|)NNEEE(S|NNWSWN)|E(SSS|EEENWWWN(EEEEEESEEESWWSWWN(W(NEWS|)SSEEEESWWWSESENEES(W|ENENWWNN(W|E(NN|ES(W|ESSES(SWS(E|WN(NEWS|)WW)|ENE(NENWWN(EEEE(SWSNEN|)N|NWS(SSEWNN|)W)|S))))))|E)|N))))|S)|S))|W)|S)|WWWNW(NENWWW(SEWN|)NW(S|NNENWWNNEES(W|ESSS(W|ENNEE(NNENENENWNNWNNW(NENEENEENWWNEEESENENENNWWWWNWNWNENEEESENEENNEEENNWNEEENENWWNNNWSWSWSWSWNWWNNWWWSEESSWWN(WNNNNNWSSSWWSEESWSSWSWSWSSEESSENE(ENWNW(S|N(WSWENE|)EEES(W|SENNESEENWNEEEE(N(NEE(E|N(N|W))|WWWNWSWSWNWSWNNWSSW(ENNESSNNWSSW|))|S(WWSSWWW(EEENNEWSSWWW|)|E))))|SSSES(WWNWWWSW(NNEE(EE|NWN(WWNENNNNNNNESSE(SWSNEN|)ENWNNWWNNNNNENNNESSENENEESESSESSW(NWNNW(N|SW(N|WWSEE(E|SWWSW(NN|SEENES))))|SSEEN(NNEEESSWNWSSEEENES(SWSWNWS(NESENEWSWNWS|)|ENENESENEENWWNEENWNWNNESENEESSW(W|SSESWSESWWSSWW(NENSWS|)SEEESEESWSESSWSEENESESESWWWWN(EE|WWNNN(E|NNW(SSSSWSWW(WWSW(SWSS(WWN(ENSW|)WW(NWS|SE)|SEEEEENEENWWNWW(WSES(WWN|EN)|NEEEE(N|S(ESSENN(NWES|)ESESENN(EEENNEESSSW(SE(ENNENWNNWNNWWWW(SESEENW(ESWWNWESEENW|)|NNNESENNWNEESSSS(WW|ENENWNEEESWSESWWSSESES(ES(WSNE|)EEENNNESSESWSESSWNW(N|SSESSSWSSENEE(NNNW(SS|NENNNNNNNW(NWWWWW(W(W|SEES(E(SWEN|)N|W))|NENESEEENWWNNEEE(NNNNWNWNENNNNE(NNNNWSWSS(ENSW|)WNNWNWNNNNENNNENNNEESSE(NNNNNWNENNNWSSWWNENNEENNWSWWNWWWSESSWSSENE(NN(ESNW|)N|SSESWSS(EEN(ESNW|)(W|NN)|SWWSES(ENSW|)SWWWWSESENEESWSSWWN(WWWWNENE(SEWN|)NWWWNWSWNNEENNWNEESSSSENNENNNNEESESES(WWNW(N|SSSS(WNSE|)EE(NNWSNESS|)E)|ENNNW(WNNNN(E|NNWWWSESE(SWWNWSWSEEEESWWWSS(WWWWNNNESE(ESWWEENW|)NNWNENE(S|NWN(EE(EEEEEEEEE(EE|S)|SS)|WWSWWN(E|WWWWWWSSWWSEEENNEEESWSEESWWSSESEESE(SWSWWSWWWNEENN(ESENSWNW|)WN(NNN(WWWWSSESESE(S(E|WWNWWSSSWSEEESSESENNEN(ESSWSESSWWWN(EE|WSSSENEESSESWWN(WSWWWWSWWWWNNNNEEEENNNNN(ESE(N|S(SW(N|SSE(N|SWS(EE|WWN(E|WSW(SEEWWN|)N))))|E))|WSSSWS(E|WNWSWSWWNWWNNNEESENNWNEESEESS(ENNNWNW(WNNWNENWWSSWSWNWNEENNNNEEESS(WWNEWSEE|)EESWSSSENNEESWSSE(S|NENNNWWNEEE(SEWN|)NNNWSSWNWNENEENEENWWWWWS(EE|WS(E|SSS(WNNWWNEENN(E|WSWNWWSSWNWN(E|WWWSSSWSESSWWWSSWWSSESSESSSSSSSEEENENNNWWW(SES(SWN|EN)|NNESEENEE(NWNN(ESESSENNENES(NWSWSSNNENES|)|NWNWWW(NEEENNNESEE(SSWW(NEWS|)S|NWN(EEENNSSWWW|)WN(E|W(NEWS|)S))|SW(W|SSESENEE(SWSNEN|)NWW(NEWS|)W)))|SSW(SSE(N|SWSEESWWSEESWWWNWN(ENSW|)WWWSEESWWSWWSWNNNWWWNNNEENEESE(NNWNNWWWWWWSESEE(EENWWW|SWWWWSSSEE(NNWSNESS|)SSSWNWN(WWNENWNWWSSS(E(NN|SESSESSENESESEENEESWSWWWWWSSWWNWNNW(NEN(NN|W|ESSE(S(W|S)|EE))|SSSESEEEENEEEN(WWW|EENEESENNNEEE(NWWN(EEN(WW|N|EEESES(W(WWNEWSEE|)S|ENN(ESEESEESSSS(WNWNENWWNW(ESEESWENWWNW|)|EENWNNEENNN(ENEESES(SWSESS(E|SSWWSWNNW(NN(ENNE(N(W|E|N)|SSESSWNW(ESENNWESSWNW|))|W)|SS))|ENEEES(WW|EENWNNW(SWWWWEEEEN|)NENEESWSSEESWSEENEEESWWSWSEEEN(ESSENEENWWNWNNENWNNN(WSSWNNWNNN(WWWSWNWSW(SEEES(ESSEN(NNWNEWSESS|)ESSEESWWWNWW(EESEEEWWWNWW|)|WWWWSE)|NNNNESES(W|ENNWN(W|ENE(SEWN|)N)))|E)|ESES(EE(NWES|)SSWNWSS(W|SENESESE(NNWNSESS|)EESSSWSSWWNENWNEN(ESNW|)WW(N|SSSSSSENESSS(WW(N(WNNNWSSSWNNWWNEENWWWSWSSS(WSSWSW(SSSENN|NNENNWNW(SS(E|SW(WNE|SE))|NNN(ENWNEN(W|ESSSES(WWSESE(S|N)|ENEE(NWWWEEES|)EEESENNW(ESSWNWESENNW|)))|W)))|EEN(WNSE|)ESSEEE)|E)|SS(EENWESWW|)S)|ENESENNWNWS(NESESSNNWNWS|))))|W))|W)))|WSW(SEWN|)WN(W(WNNNWSS(WNNW(SS|N(NWES|)EEE)|S)|S)|E)))|W)))|WSW(N|W(SSENSWNN|)WWWW(N(ENWNEESS(NNWWSEWNEESS|)|W(WWNWNSESEE|)S)|S)))|SSWW(NEWS|)SESWSSWWSWWNENN(ESENSWNW|)(WWS(SWWSEESWSWNWNN(NEEWWS|)WSSSWNW(NW(NEESNWWS|)S|SSEEE(SSSS(ENENWNNESENESENNEEN(WWWSWENEEE|)NEE(NN|SWSSSWSESWSES(ENNNNNN|WWS(WWWWNEN(NEN(W|ESE(NNNE|SWSWN))|W)|ESSE(NN|EE))))|WWNNN(ESSNNW|)WSW(N|SW(N|S(EENSWW|)SS)))|N))|E)|N)))))|WWNW(S|WNNESEE(NWNEEENWNENESSE(NE(SEWN|)NNENNWWNWWSESE(E|S(S|WWNWWWNWNNNNWWSESWSWSWSWSEEEEE(NWW(NENSWS|)W|SSWW(SES(WSNE|)ENEENNW(NEESNWWS|)S|N(WWWWNNWNNEE(SWEN|)NWWWNWSWNWSSEEES(WWWWNNNNWS(WWNNE(ENNWNWSWS(SWSWSWNWSSWSSEE(SWWWNNWNWSWWNENWWSWSWSSWNWSSSSSENNE(N(ENEEN(EEESWSW(N|WW)|W(N|W))|W)|SSSSE(SSWSSENES(E|SWWWWWWSW(WWNENWWNEENESES(WSNE|)ENEE(SWEN|)NWNWNWWNENE(SEES(SEWN|)W|NWWWS(E|WWWNNWW(SESSSSSE(SSWSEESWSWNW(SS(EEENSWWW|)S|NNN(E|NNNNN))|EENNE(SEESEWNWWN|)NWWWSESW(ENWNEEWWSESW|))|NENENEEENNNNNEESSSSE(SSWW(WWWS(W|EES(WSWNSENE|)EEN(ESNW|)W)|N(NNNN|E))|ENE(S|ENWNENEENENENENEEENWN(WWWS(WWWWN(EEE|WWWSSENESESEE(SWSWWWW(WWNNNNN(WSSWWWNEN(ESNW|)WWWSSSSSENEN(WNNSSE|)EEESSWSWN(NEWS|)WSWWSSESS(ENNESE(NNWWW|SW)|W(N|S(E|S)))|ESSSEES(E(E|N)|WW))|SE(E|SSW(N|S)))|EN(WW|E)))|EE)|EEESSW(SWSWNWSWSESSW(SEE(S|ENWNNEES(ENE(S|NN(WSWENE|)E(ENWNN(WSSNNE|)ESEES(EENWN(WW|EESENEEESSENNEESSW(N|SWWSSWNWWWN(EN(ESENNW|W)|W(W|SSSESEEEN(EEESWS(WNSE|)EEE(SWSNEN|)NNNW(SS|N(WSWNSENE|)EN(W|NNNEESESWW(N|SESSEES(WWWNNSSEEE|)EENWNWN(WSNE|)EENENWN(EEEESWWSSWS(ESENESEESSESENESSWWSESSS(WWNENWNWNN(ESNW|)NWWN(WW(N|SSWNWSSS(WNNNSSSE|)E(SWEN|)NEEEN(WN|ESS))|EE)|EENWNNE(NNNEENWNNENWWSSSWNWSWNNWNNW(NNESESSENNN(ESENESS(WWSSWENNEE|)EEE(NWN(EESS|WS)|SWSES(E|WW))|W)|S(WNWSNESE|)S)|SESSESS(NNWNNWESSESS|)))|W)|WSSWNNW(ESSENNSSWNNW|)))))|WNW(W|S))))))|W)|SS))|W))|NW(N|SW(WWSNEE|)N))|N)))))))|SEEE(SSWNSENN|)EEN(WWW|EE)))|ENWNEES(ENESNWSW|)S))|N(NEEEN(W|N)|W))|EE)|S)|SSS)|S)|E)))))|S(S|W))|S)))|E))|SSSW(SEWN|)NNW(SWWNEWSEEN|)N))|N)))))|E))))|S)|WNWSSW(WWNSEE|)S)))|N))|WW(S|NNWSWNN(SSENESNWSWNN|))))|NNNW(S|W))|NN)|E)|NNNW(SWNWESEN|)NNN(WNSE|)EE(SWSE|EN)))))|SS)|N))|S))|E)))|SSWW(WSSSWSSESENN(W|EE(SWEN|)NWNN(ES|WSS))|N(E|NN)))|SSSSS)|S(WW|SSS)))|S))|SSW(N|W(SEESNWWN|)WWWNENN(WSNE|)NN(ESNW|)N)))|W)))|SSSWNNWWSWSEE(N|SESWSESE(N|SSSSSWS(WWWNENWWSWWWWWSW(NNENEENWWNWWWWSWNWWWNENENWN(WSWS(E|WSW(WWSWWSEEESSWW(N(W|E)|SESSEENWNENESSSSES(ENNE(SSSEENW(ESWWNNSSEENW|)|NNENE(SSWENN|)N(ESEE(SS|NN(ES|WS))|WWN(WWS(WNW(S|N(EENSWW|)W)|ES(WSS(ENSW|)S|E))|E)))|WWNWSWNWSW(ENESENSWNWSW|)))|N))|NNEESWSESSS(ENNNEENWN(WSNE|)EEEEN(ESEN(ESE(SWWWSWNWWSSWSES(WWNNSSEE|)ENEN(WNSE|)ESSS(WNSE|)EEENESSENN(NWNWSWSWNNNE(EEESNWWW|)S|ESESSSW(S|N(WWWNWSW(S(WW|E)|N)|N)))|NENEENWW(EESWWSNEENWW|))|N)|WW)|W))|SSENESS(EEEE(NN(ESNW|)NWWW(SEESWW|W)|S)|WW))|EE(SWEN|)NN))))|NN)|W)|W))))|N)|NENWNEE(N|S))|N)))|N))|W))|E))|WW(SEWN|)W)|ESWSEENESENE(WSWNWSNESENE|)))|E)|WSSSE(SWWSES(ENENNSSWSW|)SW(SEWN|)NW(S|NNWNNEE(SWEN|)NWN(WSWWW(WS(W(W|N)|SESWSSSENEN(W|NE(SESWENWN|)NWN(E|W)))|N)|E))|NN))|SS(ENSW|)W(SWWEEN|)N))))|SS(E|W))))|W)|E)|EE))|N)|NE(ES(EENWESWW|)W|NWNNNNNNE(E|NN|SSS))))|SS(WNW(NWWEES|)S|S))|SSSSWSW(SSESW(WNWESE|)SESWSSESE(SSW(N|SWWSEEE(N|SSWNWWWNW(NEWS|)S))|NN(NNNNN(W|N)|W))|N(NEWS|)W))|W)|W))|W)|SES(SSSE(NNNN|SSSS)|W)))|EEEESEN(SWNWWWEEESEN|)))|N)|EEE)|NN)|W)|E)|SEEEN(ESNW|)WWNENWWNEEE(WWWSEEWWNEEE|))|E)|S)|ENENE(SSSWNSENNN|)N)|E)|N)|S)|SSSSWNNNW(ESSSENSWNNNW|))))|N)|WW))))|WWWNEN)))|SSENEE))))|E))|N)|W))|WSSWNW(NEWS|)S(WNSE|)SSSEESEES(WS(E|SWWNENWW(NEWS|)WSESSSWNNWNWWWNNWW(SESSS(WNNSSE|)SENNEESSSW(SWW(NEWS|)SWW(NEWS|)SESWSSSE(SWWNNWSSWNNWW(NEWS|)S(ESWENW|)W|NNENEEEES(EENEE(NNWNN(WSWNW(NN|SWSWS(EENES(S|E(N|E))|W(N|W)))|ESE(SSESWENWNN|)NNNWWSE(WNEESSNNWWSE|))|S(S|W))|WWWS(W|E)))|NN)|N(EEESES(W|E)|NW(SS|N(W|N)))))|ENNNWNN(W(N|SWWSEESE(WNWWNEWSEESE|))|E(S|E))))))|WW))))|E(E|S)))|NN))|E)|W)|SSSE(ESWWWEEENW|)N)|W)|W)|W)))|NN))|N(ESENSWNW|)WNWNN(WSSWW(NNES|SE)|EE(NEWS|)S(W|S)))))|S(W|S)))|SSWSEESSWNWS(NESENNSSWNWS|)))))|N)|W)|W))))|W))|S))))))|W))|W)|WWW)|N)|NNE(SENE|NNWS))|NE(SS|E))|W)|NN)|N(N|W))|NNENENNWW(S(E|S)|NNNNNENWNN(ESEESSEE(NWES|)SSESWSWW(NNN(ESSNNW|)W(WSESWSE(WNENWNSESWSE|)|NN)|SES(ENENESEE(NWNWNE|S)|SSW(W|NN)))|NNNNNNN)))|EEE)))|EENNEEN(SWWSSWENNEEN|)))|N))|N))|W))|WWN(E|WWSS(ENSW|)WNNWSSWNNWSSSWNWSWWNENWWSSWSWNNENNEENNWN(WSS(WNNW(N|SSSWNWSWW(SES(W|ENESSWSSEE(EESSNNWW|)N(NNNENSWSSS|)W)|WN(WWSEWNEE|)EE))|E)|ENEEN(EESWSSWNWSSES(W|SENNEEEN(EEESWW|NNWSSWN(SENNESNWSSWN|)))|WW))))|S))|NEEN(ESSES(WWNSEE|)ENNWN(N|EEE(SSW(SS(WS|EN)|N)|N))|WNW(S|NNNNNNNESES(W|EEN(NW(S|WNNENWNEEES(WS(SWEN|)E|ENNWNENENWWSWSSWNWNENN(E(S|EENESE(NE(N(E|W)|S)|SSSSESS(ENSW|)WNW(NN|S)))|NWWW(NEENSWWS|)SSSSE(NNENWESWSS|)S(E|WSESWSSEN(SWNNENSWSSEN|)))))|E))))))|EESEEEEESSWW(NEWS|)SSEEESES(WWNSEE|)EENWNWNW(WW|NNNEN(WNWNWWSS(WNN(WWSESNWNEE|)NEN(WNN(WN|ES)|EE(SWEN|)E)|E(E|N))|EEEES(EEN(WNEWSE|)EES(ES(ENSW|)SS|W)|SWNWSSW(N(WSNE|)N|S))))))))))|WSS(WW(NENWESWS|)S(SWSES(E|W)|EE)|E))|E)|W))))))|ENE(S|E)))|SS))))))))))|W)|N)|S(E|S))|S))))|EESWSESWWSWN(SENEENSWWSWN|)))))|N(NN|E))|EEE(NN(WS|ESEN)|S))$
diff --git a/2018/loc.svg b/2018/loc.svg
index 97c11fc..067d45f 100644
--- a/2018/loc.svg
+++ b/2018/loc.svg
@@ -32,10 +32,10 @@ z
+" id="me1cf09a1d9" style="stroke:#000000;stroke-width:0.8;"/>
-
+
@@ -71,7 +71,7 @@ z
-
+
@@ -110,7 +110,7 @@ z
-
+
@@ -139,7 +139,7 @@ z
-
+
@@ -153,7 +153,7 @@ z
-
+
@@ -193,7 +193,7 @@ z
-
+
@@ -286,10 +286,10 @@ z
+" id="m480ecff4e3" style="stroke:#000000;stroke-width:0.8;"/>
-
+
@@ -302,7 +302,7 @@ L -3.5 0
-
+
@@ -316,7 +316,7 @@ L -3.5 0
-
+
@@ -331,7 +331,7 @@ L -3.5 0
-
+
@@ -346,7 +346,7 @@ L -3.5 0
-
+
@@ -361,7 +361,7 @@ L -3.5 0
-
+
@@ -577,7 +577,7 @@ z
-
-
-
+
diff --git a/2018/src/day20.rs b/2018/src/day20.rs
index 3fbf028..dda48b4 100644
--- a/2018/src/day20.rs
+++ b/2018/src/day20.rs
@@ -1,25 +1,187 @@
+use std::collections::HashMap;
+use std::collections::VecDeque;
use std::io::Read;
use common::Solution;
+type Coordinate = (i32, i32);
+
+#[derive(Copy, Clone)]
+enum Direction {
+ North,
+ South,
+ West,
+ East,
+}
+
+impl Direction {
+ pub fn walk(self, (x, y): Coordinate) -> Coordinate {
+ use self::Direction::*;
+ match self {
+ North => (x, y - 1),
+ West => (x - 1, y),
+ South => (x, y + 1),
+ East => (x + 1, y),
+ }
+ }
+}
+
+impl From for Direction {
+ fn from(idx: usize) -> Self {
+ use self::Direction::*;
+ match idx {
+ 0 => North,
+ 1 => South,
+ 2 => West,
+ 3 => East,
+ val => panic!("Invalid direction: {}", val),
+ }
+ }
+}
+
+impl From for Direction {
+ fn from(b: u8) -> Self {
+ use self::Direction::*;
+ match b {
+ b'N' => North,
+ b'S' => South,
+ b'W' => West,
+ b'E' => East,
+ val => panic!("Invalid direction: {}", val),
+ }
+ }
+}
+
#[derive(Default)]
-pub struct Day20 {}
+pub struct Day20 {
+ paths: HashMap,
+}
impl Day20 {
pub fn new() -> Self {
Default::default()
}
+
+ fn follow_directions(&mut self, initial: &[Coordinate], data: &[u8]) -> (Vec, usize) {
+ let mut pos = Vec::from(initial);
+ let mut positions = Vec::new();
+
+ let mut index = 0;
+
+ while index < data.len() {
+ let b = data[index];
+ match b {
+ b'|' => {
+ positions.extend_from_slice(&pos);
+ pos = Vec::from(initial);
+ }
+ b'$' | b')' => {
+ positions.extend_from_slice(&pos);
+ positions.sort_unstable();
+ positions.dedup();
+ return (positions, index);
+ }
+
+ b'(' => {
+ let (new_pos, read) = self.follow_directions(&pos, &data[index + 1..]);
+ pos = new_pos;
+ index += read + 1;
+ }
+
+ b'N' | b'S' | b'W' | b'E' => {
+ let dir = Direction::from(b);
+ for p in pos.iter_mut() {
+ let entry = self.paths.entry(*p).or_insert([false; 4]);
+ entry[dir as usize] = true;
+ *p = dir.walk(*p);
+ }
+ }
+ val => panic!("Invalid input character: {}", val)
+ }
+ index += 1;
+ }
+ unreachable!();
+ }
+
+ fn distances(&self) -> HashMap {
+ let mut todo = VecDeque::new();
+ let mut visited = HashMap::new();
+ todo.push_back((0, (0, 0)));
+ visited.insert((0, 0), 0);
+
+ while let Some((dist, pos)) = todo.pop_front() {
+ if let Some(dirs) = self.paths.get(&pos) {
+ let dirs = dirs.iter().enumerate()
+ .filter_map(|(idx, state)| if *state {
+ Some(Direction::from(idx))
+ } else {
+ None
+ });
+ for dir in dirs {
+ let new_pos = dir.walk(pos);
+ if !visited.contains_key(&new_pos) {
+ visited.insert(new_pos, dist + 1);
+ todo.push_back((dist + 1, new_pos));
+ }
+ }
+ }
+ }
+
+ visited
+ }
}
impl Solution for Day20 {
- fn part1(&mut self, _input: &mut Read) -> String {
- unimplemented!()
+ fn part1(&mut self, input: &mut Read) -> String {
+ let mut data = Vec::new();
+ input.read_to_end(&mut data).unwrap();
+ let pos = (0, 0);
+
+ self.follow_directions(&[pos], &data[1..]);
+ format!("{}", self.distances().values().max().unwrap())
}
- fn part2(&mut self, _input: &mut Read) -> String {
- unimplemented!()
+ fn part2(&mut self, input: &mut Read) -> String {
+ let mut data = Vec::new();
+ input.read_to_end(&mut data).unwrap();
+ let pos = (0, 0);
+
+ self.follow_directions(&[pos], &data[1..]);
+ format!("{}", self.distances().values().filter(|&&x| x >= 1000).count())
}
}
#[cfg(test)]
-mod tests {}
+mod tests {
+ use common::Solution;
+
+ use super::*;
+
+ #[test]
+ fn sane_enums() {
+ for idx in 0..4 {
+ let direction = Direction::from(idx);
+ let back = direction as usize;
+ assert_eq!(idx, back);
+ }
+ }
+
+ #[test]
+ fn sample_part1() {
+ let samples: [&[u8]; 5] = [
+ b"^WNE$",
+ b"^ENWWW(NEEE|SSE(EE|N))$",
+ b"^ENNWSWW(NEWS|)SSSEEN(WNSE|)EE(SWEN|)NNN$",
+ b"^ESSWWN(E|NNENN(EESS(WNSE|)SSS|WWWSSSSE(SW|NNNE)))$",
+ b"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$",
+ ];
+
+ let outputs = ["3", "10", "18", "23", "31"];
+
+ for (input, output) in samples.iter().zip(outputs.iter()) {
+ println!("{}", String::from_utf8_lossy(input));
+ let mut instance = Day20::new();
+ assert_eq!(*output, instance.part1(&mut input.as_ref()));
+ }
+ }
+}