From 77064a9563fce57cd8bd4feedebbb2627fab11af Mon Sep 17 00:00:00 2001 From: Pim Kunis Date: Mon, 17 Apr 2023 20:18:20 +0200 Subject: [PATCH] init --- 2018/1/2/Makefile | 16 + 2018/1/2/input | 998 ++++++++++++++++ 2018/1/2/main.cpp | 44 + 2018/1/input | 998 ++++++++++++++++ 2018/1/main.c | 36 + 2018/2/2/Makefile | 16 + 2018/2/2/main.cpp | 37 + 2018/2/Makefile | 16 + 2018/2/input | 250 +++++ 2018/2/main.cpp | 48 + 2018/3/input | 1347 ++++++++++++++++++++++ 2018/3/main.rb | 31 + 2018/4/input | 1110 ++++++++++++++++++ 2018/4/main.rb | 88 ++ 2018/5/input | 1 + 2018/5/main.rb | 49 + 2018/6/input | 50 + 2018/6/main.rb | 75 ++ 2018/6/sample | 5 + 2018/7/input | 101 ++ 2018/7/main.rb | 101 ++ 2018/7/sample | 7 + 2020/.formatter.exs | 4 + 2020/lib/days/day1.ex | 19 + 2020/lib/days/day10.ex | 48 + 2020/lib/days/day11.ex | 91 ++ 2020/lib/days/day12.ex | 93 ++ 2020/lib/days/day13.ex | 45 + 2020/lib/days/day2.ex | 36 + 2020/lib/days/day3.ex | 33 + 2020/lib/days/day4.ex | 82 ++ 2020/lib/days/day5.ex | 42 + 2020/lib/days/day6.ex | 29 + 2020/lib/days/day7.ex | 61 + 2020/lib/days/day8.ex | 60 + 2020/lib/days/day9.ex | 46 + 2020/lib/util.ex | 21 + 2020/mix.exs | 27 + 2020/mix.lock | 3 + 2020/test/test_helper.exs | 1 + 2021/.formatter.exs | 4 + 2021/lib/days/day1.ex | 17 + 2021/lib/days/day2.ex | 27 + 2021/lib/util.ex | 21 + 2021/mix.exs | 28 + 2022/.formatter.exs | 4 + 2022/Makefile | 2 + 2022/README.md | 21 + 2022/day10.py | 41 + 2022/day10.txt | 139 +++ 2022/day10test.txt | 146 +++ 2022/day12.py | 104 ++ 2022/day12.txt | 41 + 2022/day12test.txt | 5 + 2022/day14.py | 89 ++ 2022/day15.py | 101 ++ 2022/day16.py | 103 ++ 2022/day17.py | 311 +++++ 2022/day18.py | 113 ++ 2022/day8.py | 54 + 2022/day8.txt | 99 ++ 2022/day9.py | 106 ++ 2022/day9.txt | 2000 +++++++++++++++++++++++++++++++++ 2022/day9test.txt | 8 + 2022/lib/day.ex | 46 + 2022/lib/days/day1.ex | 24 + 2022/lib/days/day11.ex | 93 ++ 2022/lib/days/day11/monkey.ex | 63 ++ 2022/lib/days/day13.ex | 67 ++ 2022/lib/days/day16.ex | 81 ++ 2022/lib/days/day2.ex | 68 ++ 2022/lib/days/day3.ex | 39 + 2022/lib/days/day4.ex | 38 + 2022/lib/days/day5.ex | 70 ++ 2022/lib/days/day6.ex | 29 + 2022/lib/days/day7.ex | 82 ++ 2022/lib/days/day8.ex | 53 + 2022/mix.exs | 28 + README.md | 3 + 79 files changed, 10533 insertions(+) create mode 100644 2018/1/2/Makefile create mode 100644 2018/1/2/input create mode 100644 2018/1/2/main.cpp create mode 100644 2018/1/input create mode 100644 2018/1/main.c create mode 100644 2018/2/2/Makefile create mode 100644 2018/2/2/main.cpp create mode 100644 2018/2/Makefile create mode 100644 2018/2/input create mode 100644 2018/2/main.cpp create mode 100644 2018/3/input create mode 100644 2018/3/main.rb create mode 100644 2018/4/input create mode 100644 2018/4/main.rb create mode 100644 2018/5/input create mode 100644 2018/5/main.rb create mode 100644 2018/6/input create mode 100644 2018/6/main.rb create mode 100644 2018/6/sample create mode 100644 2018/7/input create mode 100644 2018/7/main.rb create mode 100644 2018/7/sample create mode 100644 2020/.formatter.exs create mode 100644 2020/lib/days/day1.ex create mode 100644 2020/lib/days/day10.ex create mode 100644 2020/lib/days/day11.ex create mode 100644 2020/lib/days/day12.ex create mode 100644 2020/lib/days/day13.ex create mode 100644 2020/lib/days/day2.ex create mode 100644 2020/lib/days/day3.ex create mode 100644 2020/lib/days/day4.ex create mode 100644 2020/lib/days/day5.ex create mode 100644 2020/lib/days/day6.ex create mode 100644 2020/lib/days/day7.ex create mode 100644 2020/lib/days/day8.ex create mode 100644 2020/lib/days/day9.ex create mode 100644 2020/lib/util.ex create mode 100644 2020/mix.exs create mode 100644 2020/mix.lock create mode 100644 2020/test/test_helper.exs create mode 100644 2021/.formatter.exs create mode 100644 2021/lib/days/day1.ex create mode 100644 2021/lib/days/day2.ex create mode 100644 2021/lib/util.ex create mode 100644 2021/mix.exs create mode 100644 2022/.formatter.exs create mode 100644 2022/Makefile create mode 100644 2022/README.md create mode 100755 2022/day10.py create mode 100644 2022/day10.txt create mode 100644 2022/day10test.txt create mode 100755 2022/day12.py create mode 100644 2022/day12.txt create mode 100644 2022/day12test.txt create mode 100755 2022/day14.py create mode 100755 2022/day15.py create mode 100755 2022/day16.py create mode 100755 2022/day17.py create mode 100755 2022/day18.py create mode 100755 2022/day8.py create mode 100644 2022/day8.txt create mode 100755 2022/day9.py create mode 100644 2022/day9.txt create mode 100644 2022/day9test.txt create mode 100644 2022/lib/day.ex create mode 100644 2022/lib/days/day1.ex create mode 100644 2022/lib/days/day11.ex create mode 100644 2022/lib/days/day11/monkey.ex create mode 100644 2022/lib/days/day13.ex create mode 100644 2022/lib/days/day16.ex create mode 100644 2022/lib/days/day2.ex create mode 100644 2022/lib/days/day3.ex create mode 100644 2022/lib/days/day4.ex create mode 100644 2022/lib/days/day5.ex create mode 100644 2022/lib/days/day6.ex create mode 100644 2022/lib/days/day7.ex create mode 100644 2022/lib/days/day8.ex create mode 100644 2022/mix.exs create mode 100644 README.md diff --git a/2018/1/2/Makefile b/2018/1/2/Makefile new file mode 100644 index 0000000..5a613a6 --- /dev/null +++ b/2018/1/2/Makefile @@ -0,0 +1,16 @@ +CXX = g++-7 +CC = g++-7 +CXXFLAGS = -Wall -Wextra + +all: main + +main.o: main.cpp + $(CXX) $(CXXFLAGS) -c main.cpp + +main: main.o + +clean: + rm -f *.o *.h.gch *.exe main + +run: all + ./main \ No newline at end of file diff --git a/2018/1/2/input b/2018/1/2/input new file mode 100644 index 0000000..a0470c1 --- /dev/null +++ b/2018/1/2/input @@ -0,0 +1,998 @@ +-14 +-9 +-14 +-12 ++13 ++2 ++7 +-18 ++10 +-8 ++13 ++12 ++11 +-1 ++9 ++3 ++6 +-1 ++11 +-9 +-6 ++11 +-3 ++18 +-7 ++13 +-11 ++18 ++10 ++9 ++16 ++11 ++14 +-19 ++14 +-3 +-8 +-5 +-10 +-18 +-9 +-10 ++6 ++8 ++10 ++10 +-19 ++18 ++17 +-14 ++4 ++2 ++4 +-17 ++3 +-9 +-16 +-16 ++7 ++7 ++21 ++13 +-11 ++17 ++11 ++1 ++19 +-4 ++6 +-7 +-13 +-10 ++11 +-4 +-2 +-22 +-9 ++8 +-19 +-12 +-13 +-8 +-16 +-4 +-14 +-8 +-1 ++7 ++11 +-4 +-4 +-6 +-13 +-12 +-11 +-19 +-3 ++10 ++1 ++19 ++12 ++9 +-12 ++4 ++16 ++14 ++1 +-8 +-9 ++5 ++17 ++12 +-20 ++7 +-11 ++15 ++18 +-10 +-4 +-6 ++9 ++19 ++8 ++24 +-18 +-10 +-11 +-3 ++17 ++17 +-4 +-7 +-10 ++20 ++8 ++5 ++19 ++31 +-9 ++18 +-7 +-13 +-2 +-1 ++12 ++1 ++11 +-4 ++13 ++3 ++2 ++5 ++8 +-1 ++7 ++2 ++6 ++9 +-10 ++15 ++8 +-6 ++12 ++16 ++10 +-19 +-18 +-6 ++9 ++1 +-19 ++6 +-1 ++5 ++18 ++9 ++12 +-6 ++18 +-17 ++15 ++5 ++13 +-19 ++10 ++14 +-7 ++16 +-18 ++8 +-5 +-13 ++17 ++17 ++15 +-7 +-3 ++18 ++5 ++12 ++17 ++11 +-18 ++13 ++16 +-14 +-10 ++14 ++18 ++2 ++14 ++16 ++18 ++9 ++14 +-19 ++16 +-12 ++7 +-12 +-1 ++4 ++10 ++17 +-2 +-3 ++6 ++3 ++18 ++10 +-6 ++17 +-5 +-13 +-20 ++7 ++7 ++9 +-19 ++2 ++12 ++8 +-11 ++7 +-3 +-8 +-2 +-1 +-5 +-15 +-16 +-5 +-12 ++2 +-10 +-7 +-14 +-2 +-14 +-13 +-19 +-17 +-5 ++14 +-4 ++5 +-3 +-8 ++2 ++2 +-14 +-7 ++4 ++16 +-19 +-17 +-16 +-18 ++2 +-10 ++14 +-16 +-8 ++1 +-12 ++4 ++6 +-14 +-19 ++11 +-16 ++17 ++20 ++8 ++7 ++19 ++8 +-18 +-15 ++8 +-11 +-24 ++11 +-7 +-14 +-18 +-19 +-15 +-13 ++22 ++15 +-12 +-2 ++19 +-9 +-13 +-4 ++10 +-14 +-6 ++12 +-11 ++8 +-6 +-1 +-5 +-16 ++3 +-1 ++21 ++1 +-12 ++22 ++30 +-16 ++15 +-16 +-7 +-25 ++28 ++29 ++10 +-5 ++23 ++2 +-12 ++6 ++15 ++24 +-4 ++8 ++14 +-7 +-13 ++23 +-2 ++17 ++4 +-5 +-5 +-4 ++6 ++15 +-10 ++16 +-1 +-9 +-16 +-5 +-10 ++2 +-22 ++18 ++10 ++9 ++15 +-10 +-19 ++9 ++41 ++6 +-4 +-10 ++13 ++7 ++6 ++14 ++4 ++5 ++19 ++7 +-17 +-8 ++7 +-5 ++21 +-2 ++12 +-13 +-16 ++9 ++11 ++16 +-1 ++12 +-15 ++1 ++10 +-15 +-20 +-19 +-11 ++16 +-9 ++8 +-22 ++17 ++18 +-1 ++13 ++5 ++23 +-16 ++11 +-3 ++18 ++10 ++10 +-8 +-6 ++12 ++11 ++15 +-19 +-3 ++6 +-14 +-10 ++1 ++18 +-16 ++8 ++17 +-21 +-22 +-5 +-18 +-15 +-15 +-5 +-8 +-3 +-13 ++5 ++14 ++1 ++29 ++12 ++2 ++22 ++25 +-34 +-2 +-27 ++15 +-23 +-28 +-13 ++9 +-26 +-16 ++17 +-7 ++35 ++77 ++47 +-8 ++34 +-12 ++1 +-20 ++24 ++19 +-16 ++19 +-14 ++12 ++7 ++14 ++13 +-21 +-5 +-2 +-5 ++13 ++3 ++3 ++2 +-17 +-15 ++7 ++12 ++7 ++2 +-8 +-12 +-7 ++3 +-15 +-16 ++22 ++10 +-3 +-10 ++30 ++17 +-10 ++11 +-5 +-1 ++4 ++15 ++2 ++54 +-36 ++53 +-19 +-9 +-10 ++50 ++1 ++21 ++13 ++14 +-24 +-6 +-52 ++11 +-95 +-25 +-5 +-14 ++70 ++199 +-3 ++2 +-7 +-7 ++49 +-7 ++11 +-33 +-10 ++13 ++86 +-34 +-34 ++127 +-25 +-1700 +-76565 +-15 ++43 +-9 +-9 ++41 ++24 ++24 +-27 ++13 +-16 +-19 +-29 +-4 +-52 +-25 +-9 +-7 ++6 +-19 ++2 ++3 ++7 ++19 +-7 +-3 ++6 +-16 +-3 +-20 ++18 ++16 ++8 ++6 +-13 ++18 ++7 ++8 +-23 +-1 +-14 +-8 +-1 +-8 +-10 +-11 +-2 +-5 +-16 ++5 ++3 +-17 +-5 +-16 +-8 ++7 +-18 +-7 +-3 ++13 ++9 ++4 ++15 ++19 ++17 +-1 +-4 ++14 ++14 ++5 +-21 ++11 +-22 ++18 ++3 +-13 +-20 +-6 +-12 ++4 +-1 ++5 ++7 +-19 ++17 +-14 ++6 ++6 ++8 ++16 ++1 ++8 ++5 ++4 ++1 ++22 +-21 +-10 +-20 ++15 ++6 ++12 ++17 ++9 ++14 ++1 +-5 ++10 +-62 +-19 +-13 +-1 +-19 +-2 +-16 ++4 ++5 +-17 +-16 +-3 +-14 +-7 ++15 ++5 +-12 +-2 ++19 +-13 ++1 +-15 +-16 ++12 +-16 +-17 ++13 ++12 +-16 ++19 ++7 ++1 +-10 ++16 +-2 +-8 +-16 ++11 +-9 +-12 ++13 +-12 ++1 +-11 +-12 +-4 ++12 +-9 +-16 +-7 ++16 ++12 ++2 +-17 +-17 ++9 +-7 +-10 +-8 ++1 +-2 ++7 ++9 ++8 ++8 +-17 +-5 +-7 +-11 +-8 +-10 +-6 ++11 +-17 +-8 +-13 ++18 +-19 ++10 +-19 +-12 +-5 +-12 +-15 ++3 +-15 ++14 ++9 ++19 +-1 +-12 +-10 ++12 +-18 +-15 ++4 +-15 ++17 +-20 ++10 ++1 ++15 ++10 ++10 +-9 ++12 +-16 ++15 ++14 ++5 +-6 ++3 ++14 +-3 ++8 ++2 +-1 ++3 +-10 +-7 ++23 +-3 +-22 ++5 ++21 ++18 +-15 +-9 ++11 ++3 ++14 ++11 ++19 +-14 +-18 ++14 +-4 ++13 ++12 ++12 ++18 ++9 +-4 +-18 ++4 ++17 +-10 ++20 +-2 ++9 +-2 ++4 +-10 ++19 +-16 ++4 +-22 +-1 ++13 ++7 ++11 ++2 ++11 +-19 ++11 ++9 ++14 +-9 ++5 ++7 ++2 ++13 ++10 ++1 ++16 +-5 +-17 +-8 ++5 ++4 ++6 ++1 ++12 ++14 +-19 ++1 ++11 +-8 +-25 +-6 +-18 ++26 ++17 ++12 +-15 ++19 ++7 +-5 ++20 +-5 ++2 ++12 +-11 +-6 +-2 ++6 +-19 +-24 +-15 ++20 ++3 ++26 ++17 ++13 +-23 ++31 ++5 ++29 +-30 ++5 ++56 +-59 +-59 +-40 +-14 ++18 +-66 +-7 +-23 +-1 +-12 +-6 +-16 ++4 ++8 ++17 ++21 +-14 +-18 +-7 +-18 +-5 ++1 ++12 ++2 ++2 ++15 ++21 +-20 +-4 +-4 +-14 +-9 +-22 ++15 +-9 ++13 +-16 ++7 +-17 +-10 +-3 +-14 ++2 +-10 +-19 +-8 +-19 ++6 +-15 +-18 ++3 +-19 ++10 +-6 ++7 ++20 +-4 +-6 +-13 +-14 +-11 ++5 ++7 +-9 ++11 +-1 ++9 ++13 +-15 +-10 +-13 +-5 +-13 +-6 ++5 ++20 +-7 +-10 ++13 +-5 ++13 +-6 ++5 +-18 +-12 +-12 +-17 ++6 +-9 +-21 ++1 ++6 +-12 ++15 +-14 ++24 ++6 ++18 +-16 ++15 +-18 +-6 ++20 ++11 ++4 +-17 ++8 +-9 ++78549 diff --git a/2018/1/2/main.cpp b/2018/1/2/main.cpp new file mode 100644 index 0000000..b90c7d7 --- /dev/null +++ b/2018/1/2/main.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +using namespace std; + +int main() { + map freqs; + + ifstream input; + input.open("input"); + string line; + + int total = 0; + int number; + + if (input.is_open()) { + while (true) { + input.clear(); + input.seekg(0, ios::beg); + + while (getline(input, line)) { + auto found = freqs.find(total); + if (found == freqs.end()) { + // Insert new value + freqs.insert(pair(total, true)); + } else { + // Value was found. Exit. + cout << found->first << endl; + input.close(); + return 0; + } + + number = stoi(line); + total += number; + } + } + } else { + cout << "Could not open file." << endl; + } + + return 1; +} \ No newline at end of file diff --git a/2018/1/input b/2018/1/input new file mode 100644 index 0000000..9a8e98b --- /dev/null +++ b/2018/1/input @@ -0,0 +1,998 @@ +-14 +-9 +-14 +-12 ++13 ++2 ++7 +-18 ++10 +-8 ++13 ++12 ++11 +-1 ++9 ++3 ++6 +-1 ++11 +-9 +-6 ++11 +-3 ++18 +-7 ++13 +-11 ++18 ++10 ++9 ++16 ++11 ++14 +-19 ++14 +-3 +-8 +-5 +-10 +-18 +-9 +-10 ++6 ++8 ++10 ++10 +-19 ++18 ++17 +-14 ++4 ++2 ++4 +-17 ++3 +-9 +-16 +-16 ++7 ++7 ++21 ++13 +-11 ++17 ++11 ++1 ++19 +-4 ++6 +-7 +-13 +-10 ++11 +-4 +-2 +-22 +-9 ++8 +-19 +-12 +-13 +-8 +-16 +-4 +-14 +-8 +-1 ++7 ++11 +-4 +-4 +-6 +-13 +-12 +-11 +-19 +-3 ++10 ++1 ++19 ++12 ++9 +-12 ++4 ++16 ++14 ++1 +-8 +-9 ++5 ++17 ++12 +-20 ++7 +-11 ++15 ++18 +-10 +-4 +-6 ++9 ++19 ++8 ++24 +-18 +-10 +-11 +-3 ++17 ++17 +-4 +-7 +-10 ++20 ++8 ++5 ++19 ++31 +-9 ++18 +-7 +-13 +-2 +-1 ++12 ++1 ++11 +-4 ++13 ++3 ++2 ++5 ++8 +-1 ++7 ++2 ++6 ++9 +-10 ++15 ++8 +-6 ++12 ++16 ++10 +-19 +-18 +-6 ++9 ++1 +-19 ++6 +-1 ++5 ++18 ++9 ++12 +-6 ++18 +-17 ++15 ++5 ++13 +-19 ++10 ++14 +-7 ++16 +-18 ++8 +-5 +-13 ++17 ++17 ++15 +-7 +-3 ++18 ++5 ++12 ++17 ++11 +-18 ++13 ++16 +-14 +-10 ++14 ++18 ++2 ++14 ++16 ++18 ++9 ++14 +-19 ++16 +-12 ++7 +-12 +-1 ++4 ++10 ++17 +-2 +-3 ++6 ++3 ++18 ++10 +-6 ++17 +-5 +-13 +-20 ++7 ++7 ++9 +-19 ++2 ++12 ++8 +-11 ++7 +-3 +-8 +-2 +-1 +-5 +-15 +-16 +-5 +-12 ++2 +-10 +-7 +-14 +-2 +-14 +-13 +-19 +-17 +-5 ++14 +-4 ++5 +-3 +-8 ++2 ++2 +-14 +-7 ++4 ++16 +-19 +-17 +-16 +-18 ++2 +-10 ++14 +-16 +-8 ++1 +-12 ++4 ++6 +-14 +-19 ++11 +-16 ++17 ++20 ++8 ++7 ++19 ++8 +-18 +-15 ++8 +-11 +-24 ++11 +-7 +-14 +-18 +-19 +-15 +-13 ++22 ++15 +-12 +-2 ++19 +-9 +-13 +-4 ++10 +-14 +-6 ++12 +-11 ++8 +-6 +-1 +-5 +-16 ++3 +-1 ++21 ++1 +-12 ++22 ++30 +-16 ++15 +-16 +-7 +-25 ++28 ++29 ++10 +-5 ++23 ++2 +-12 ++6 ++15 ++24 +-4 ++8 ++14 +-7 +-13 ++23 +-2 ++17 ++4 +-5 +-5 +-4 ++6 ++15 +-10 ++16 +-1 +-9 +-16 +-5 +-10 ++2 +-22 ++18 ++10 ++9 ++15 +-10 +-19 ++9 ++41 ++6 +-4 +-10 ++13 ++7 ++6 ++14 ++4 ++5 ++19 ++7 +-17 +-8 ++7 +-5 ++21 +-2 ++12 +-13 +-16 ++9 ++11 ++16 +-1 ++12 +-15 ++1 ++10 +-15 +-20 +-19 +-11 ++16 +-9 ++8 +-22 ++17 ++18 +-1 ++13 ++5 ++23 +-16 ++11 +-3 ++18 ++10 ++10 +-8 +-6 ++12 ++11 ++15 +-19 +-3 ++6 +-14 +-10 ++1 ++18 +-16 ++8 ++17 +-21 +-22 +-5 +-18 +-15 +-15 +-5 +-8 +-3 +-13 ++5 ++14 ++1 ++29 ++12 ++2 ++22 ++25 +-34 +-2 +-27 ++15 +-23 +-28 +-13 ++9 +-26 +-16 ++17 +-7 ++35 ++77 ++47 +-8 ++34 +-12 ++1 +-20 ++24 ++19 +-16 ++19 +-14 ++12 ++7 ++14 ++13 +-21 +-5 +-2 +-5 ++13 ++3 ++3 ++2 +-17 +-15 ++7 ++12 ++7 ++2 +-8 +-12 +-7 ++3 +-15 +-16 ++22 ++10 +-3 +-10 ++30 ++17 +-10 ++11 +-5 +-1 ++4 ++15 ++2 ++54 +-36 ++53 +-19 +-9 +-10 ++50 ++1 ++21 ++13 ++14 +-24 +-6 +-52 ++11 +-95 +-25 +-5 +-14 ++70 ++199 +-3 ++2 +-7 +-7 ++49 +-7 ++11 +-33 +-10 ++13 ++86 +-34 +-34 ++127 +-25 +-1700 +-76565 +-15 ++43 +-9 +-9 ++41 ++24 ++24 +-27 ++13 +-16 +-19 +-29 +-4 +-52 +-25 +-9 +-7 ++6 +-19 ++2 ++3 ++7 ++19 +-7 +-3 ++6 +-16 +-3 +-20 ++18 ++16 ++8 ++6 +-13 ++18 ++7 ++8 +-23 +-1 +-14 +-8 +-1 +-8 +-10 +-11 +-2 +-5 +-16 ++5 ++3 +-17 +-5 +-16 +-8 ++7 +-18 +-7 +-3 ++13 ++9 ++4 ++15 ++19 ++17 +-1 +-4 ++14 ++14 ++5 +-21 ++11 +-22 ++18 ++3 +-13 +-20 +-6 +-12 ++4 +-1 ++5 ++7 +-19 ++17 +-14 ++6 ++6 ++8 ++16 ++1 ++8 ++5 ++4 ++1 ++22 +-21 +-10 +-20 ++15 ++6 ++12 ++17 ++9 ++14 ++1 +-5 ++10 +-62 +-19 +-13 +-1 +-19 +-2 +-16 ++4 ++5 +-17 +-16 +-3 +-14 +-7 ++15 ++5 +-12 +-2 ++19 +-13 ++1 +-15 +-16 ++12 +-16 +-17 ++13 ++12 +-16 ++19 ++7 ++1 +-10 ++16 +-2 +-8 +-16 ++11 +-9 +-12 ++13 +-12 ++1 +-11 +-12 +-4 ++12 +-9 +-16 +-7 ++16 ++12 ++2 +-17 +-17 ++9 +-7 +-10 +-8 ++1 +-2 ++7 ++9 ++8 ++8 +-17 +-5 +-7 +-11 +-8 +-10 +-6 ++11 +-17 +-8 +-13 ++18 +-19 ++10 +-19 +-12 +-5 +-12 +-15 ++3 +-15 ++14 ++9 ++19 +-1 +-12 +-10 ++12 +-18 +-15 ++4 +-15 ++17 +-20 ++10 ++1 ++15 ++10 ++10 +-9 ++12 +-16 ++15 ++14 ++5 +-6 ++3 ++14 +-3 ++8 ++2 +-1 ++3 +-10 +-7 ++23 +-3 +-22 ++5 ++21 ++18 +-15 +-9 ++11 ++3 ++14 ++11 ++19 +-14 +-18 ++14 +-4 ++13 ++12 ++12 ++18 ++9 +-4 +-18 ++4 ++17 +-10 ++20 +-2 ++9 +-2 ++4 +-10 ++19 +-16 ++4 +-22 +-1 ++13 ++7 ++11 ++2 ++11 +-19 ++11 ++9 ++14 +-9 ++5 ++7 ++2 ++13 ++10 ++1 ++16 +-5 +-17 +-8 ++5 ++4 ++6 ++1 ++12 ++14 +-19 ++1 ++11 +-8 +-25 +-6 +-18 ++26 ++17 ++12 +-15 ++19 ++7 +-5 ++20 +-5 ++2 ++12 +-11 +-6 +-2 ++6 +-19 +-24 +-15 ++20 ++3 ++26 ++17 ++13 +-23 ++31 ++5 ++29 +-30 ++5 ++56 +-59 +-59 +-40 +-14 ++18 +-66 +-7 +-23 +-1 +-12 +-6 +-16 ++4 ++8 ++17 ++21 +-14 +-18 +-7 +-18 +-5 ++1 ++12 ++2 ++2 ++15 ++21 +-20 +-4 +-4 +-14 +-9 +-22 ++15 +-9 ++13 +-16 ++7 +-17 +-10 +-3 +-14 ++2 +-10 +-19 +-8 +-19 ++6 +-15 +-18 ++3 +-19 ++10 +-6 ++7 ++20 +-4 +-6 +-13 +-14 +-11 ++5 ++7 +-9 ++11 +-1 ++9 ++13 +-15 +-10 +-13 +-5 +-13 +-6 ++5 ++20 +-7 +-10 ++13 +-5 ++13 +-6 ++5 +-18 +-12 +-12 +-17 ++6 +-9 +-21 ++1 ++6 +-12 ++15 +-14 ++24 ++6 ++18 +-16 ++15 +-18 +-6 ++20 ++11 ++4 +-17 ++8 +-9 ++78549 \ No newline at end of file diff --git a/2018/1/main.c b/2018/1/main.c new file mode 100644 index 0000000..b8b51bf --- /dev/null +++ b/2018/1/main.c @@ -0,0 +1,36 @@ +#include +#include + +int +main(int argc, char *argv[]) +{ + FILE *stream; + char *line = NULL; + size_t len = 0; + int nread; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + stream = fopen(argv[1], "r"); + if (stream == NULL) { + perror("fopen"); + exit(EXIT_FAILURE); + } + + int number; + int total = 0; + + while ((nread = getline(&line, &len, stream)) != -1) { + number = atoi(line); + total += number; + } + + printf("%d\n", total); + + free(line); + fclose(stream); + exit(EXIT_SUCCESS); +} \ No newline at end of file diff --git a/2018/2/2/Makefile b/2018/2/2/Makefile new file mode 100644 index 0000000..5a613a6 --- /dev/null +++ b/2018/2/2/Makefile @@ -0,0 +1,16 @@ +CXX = g++-7 +CC = g++-7 +CXXFLAGS = -Wall -Wextra + +all: main + +main.o: main.cpp + $(CXX) $(CXXFLAGS) -c main.cpp + +main: main.o + +clean: + rm -f *.o *.h.gch *.exe main + +run: all + ./main \ No newline at end of file diff --git a/2018/2/2/main.cpp b/2018/2/2/main.cpp new file mode 100644 index 0000000..b97ad90 --- /dev/null +++ b/2018/2/2/main.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +using namespace std; + +int main () { + ifstream input; + input.open("../input"); + string line; + + vector strings = {}; + + while (getline(input, line)) { + strings.push_back(line); + } + + // Compare every string with ones that come after it. + for (vector::const_iterator it = strings.begin(); it != strings.end(); ++it) { + for (vector::const_iterator it2 = ++it; it2 != strings.end(); ++it2) { + int differences = 0; + string::const_iterator str_it = it->begin(); + + for (string::const_iterator str_it2 = it2->begin(); str_it2 != it2->end(); ++str_it2) { + if (*str_it != *str_it2) { + ++differences; + } + ++str_it; + } + //cout << differences << endl; + if (differences == 1) { + cout << "Found a difference of 1 in strings: " << *it << " and " << *it2 << endl; + } + } + } +} \ No newline at end of file diff --git a/2018/2/Makefile b/2018/2/Makefile new file mode 100644 index 0000000..5a613a6 --- /dev/null +++ b/2018/2/Makefile @@ -0,0 +1,16 @@ +CXX = g++-7 +CC = g++-7 +CXXFLAGS = -Wall -Wextra + +all: main + +main.o: main.cpp + $(CXX) $(CXXFLAGS) -c main.cpp + +main: main.o + +clean: + rm -f *.o *.h.gch *.exe main + +run: all + ./main \ No newline at end of file diff --git a/2018/2/input b/2018/2/input new file mode 100644 index 0000000..efe58ee --- /dev/null +++ b/2018/2/input @@ -0,0 +1,250 @@ +bazvmqthjtrnlosiecxyghkwud +pazvmqbijirzlosiecxyghkwud +pazvtqbmjtrnlosiecxyghkwzd +pazvmqbfjtrjlosnlcxyghkwud +pazvkqbfjtrtlosiecjyghkwud +paztmqbfjtrnbosiecxyglkwud +pazvmqbfjtunlosievxmghkwud +pazvmqbfjtmngosiecyyghkwud +jazvmqbfjtrnlosiecxygikpud +pazvqqbfctrnlosimcxyghkwud +pazvmqbfjtrnwogiecxyihkwud +pazvmqbfjtrqlojiecxeghkwud +payvmqbfjtrzlosiecxyghkwuk +pkzvmqnfjtrnlosieciyghkwud +pazvmqqfjtrnldsiecxyghkwui +pazvmqbfttrqlosiecxywhkwud +gazvmybfjthnlosiecxyghkwud +pazvmqbfjtrnlasiecxygptwud +pktvmqbfjtrnwosiecxyghkwud +pazvmqwfjtrnlosiecxgghkkud +pazvmzkbjtrnlosiecxyghkwud +pazvmqbfjtrnloslecxyghuwui +pezvmqbfjtrnlesieyxyghkwud +cazvmqbfjrrnlosiecxyghkmud +pazvmqrfjjrnlosiecxyghkwnd +pazvmqbgjtrnlosiecxyphtwud +pazvmqbvmtrnlosiecxyghkpud +pazdmqbfjtrnlosiecxyuhkpud +pazvmqbflnrnloshecxyghkwud +pazvvqbfjprilosiecxyghkwud +pazvwqbfjtrllosiecxyghknud +pazvmqbfjtrnloniecxdghkaud +pazvmqbfjtrnlvsuecxynhkwud +ptzvmqwfjtrnlosieccyghkwud +pkzvmqbjjtrnlosiecryghkwud +pazvmqqfjtrexosiecxyghkwud +pazgmqbfjtrneoyiecxyghkwud +paznmqbfjtrnlosiecxydhkwzd +pazvmqbfjtrnaosiwcxsghkwud +pazomqbfjxrnlosiewxyghkwud +pazsmqbfjprnlosiecxrghkwud +pazvmqbfqtrnoosiecxygmkwud +aazvmqbfjtrnlosiacxyghjwud +pazviqbfjtrnlobiecxygrkwud +qazwmqbfjhrnlosiecxyghkwud +pazvmqbfftrnlosiqcxygfkwud +patvmqbfjtonlosircxyghkwud +pazvmqbfjtrnlomaecxyghkpud +paztmqbfjtrulossecxyghkwud +pazvmqbijtrnlobiecxyghkwkd +pazvsqbfjtrnlospecxyghkqud +pbzmmqbfjtrnlosiecxyghkwhd +pezvkqbfjtenlosiecxyghkwud +razvmqbfjkrnlosiecxeghkwud +pazcmqbfjtrnloriecxyghkgud +pazvmqbfftfnlosiecvyghkwud +pazvmqpujtrnlosiepxyghkwud +patvgqbfjtrnloslecxyghkwud +pazvmqbfltrnlosibcxyghswud +pazvmebfjtrnlosaecxyehkwud +pazdmqbejtrnlosiecxyghrwud +pazvmcbfntrplosiecxyghkwud +pszvmqbfjtrnlosivcfyghkwud +puzvmqbfjtrnloeiecxyxhkwud +pazvmqbfjtrivooiecxyghkwud +pazvyqbfjtrngosiwcxyghkwud +pauvmqbfjtrnlosimexyghkwud +pazvmqbfjtrnwoshecxeghkwud +dazvmqbfjtrnloshecxygxkwud +pazvmqbfjtrtdosiecxyghvwud +pazxmqbfjtrnlosieceyghjwud +pazvmqbfjtrnlosihexjghkwud +pazvmqbfjsrnlosiecxughiwud +phzvcqbfjtrqlosiecxyghkwud +pazvmibfjtrnlosjecxxghkwud +pazvmqbfjtrbeosiecxlghkwud +pazvmqyfjttolosiecxyghkwud +fawvmqbfjtrnlosiecxyghkwhd +pazvmqbfjprnxosiecxyghkbud +macvmqbfjtrnlosiesxyghkwud +pazsmqbfjtrflouiecxyghkwud +pacvmqbfjtrnltsiecxyghcwud +pazvmqbfjtymlosiecxygykwud +pazvmqbfjtrclosiecxygukwmd +pazvmqbfjtrnlobiecxphhkwud +mazvmqbhitrnlosiecxyghkwud +pazvmqdtjtrnlrsiecxyghkwud +pazvmqbfjgrnllsieczyghkwud +pazvmqbfjtrilosiecxxgikwud +pazvmqbjjtrnlosreceyghkwud +paxvmmbfjtrilosiecxyghkwud +pazqmwbfjtrnlowiecxyghkwud +pazvmqbfjfrnqosiecxyghkwui +pazvmqbfjtrrgosiecxyghswud +pazvmqnfjtrnlosiecsyghkwmd +paiemqbmjtrnlosiecxyghkwud +pazvmqbfdtqnlosiecxyjhkwud +pazvmxbfjthndosiecxyghkwud +pqzvmqbfjtrnlosiecxbghkzud +pagrmqbfjtrnlosiecxygskwud +pazamqtfjtrnsosiecxyghkwud +pazvmqbfjtrnldshecxyzhkwud +pazvmnbfjtrllosieclyghkwud +snzvmqbfjnrnlosiecxyghkwud +pazvsqbfjdrnlosiecxyghswud +pazvmqnfjfrnlosiecsyghkwud +pazvmqbfjtrnlosiecxjghowum +pazvmqbfjtjnlosieczygfkwud +pazvmqbsjtrnloziecxyghkeud +pazvxqbgjtrnlooiecxyghkwud +pazvmqbfjtrnlooiecxmyhkwud +pazvmqbyftrnlosgecxyghkwud +pazvmqbfjtrnlosiwcxyqhksud +pazvmqkyjtrnlokiecxyghkwud +pazfmqbfjtrnlosijcxyohkwud +pazvmqbfjtrnlociecxygikcud +fazvmqbfjtrnlosiecxyjhkuud +pazvmqbojtknlohiecxyghkwud +pazvmqbfjtgnlosbecxyghkwux +pazvmqbfjtrnlocieckoghkwud +pazvdqbfjtrlltsiecxyghkwud +pazvmqbfjtsnlfsiecxyglkwud +przvpqbfjtrnyosiecxyghkwud +pazvmbrfjtrnlosiecxmghkwud +dazvmqbfttrnlostecxyghkwud +pazvmqbfttdnlosiecxygwkwud +pazvmqbvitrnlosieexyghkwud +pazvmqbfjhrnlosjecxyvhkwud +pazvmqbfstrnlosiecxyggkwpd +bazvmqbfjtrnlmsiecxyohkwud +patmmqbfjtrnlosizcxyghkwud +pazvmqbfwtrglosieqxyghkwud +pazvmqbfjtrnlosiecxdhhkwmd +pazvmqbfjdrnlosnexxyghkwud +oazrrqbfjtrnlosiecxyghkwud +pazvmqbfjcrnlosiecxygakwjd +pazvmqbfjtrnlosifcxfghkwyd +pazvmnbfjtrnlosiecxyahzwud +pazvmqbfgtrnlojiecxyghkgud +pazvmqbfjtrnlaliecxyghkwuy +pazvmqbfjtrnlfsiecrtghkwud +pazvmqbkjtrnloswecxdghkwud +pazvtqbfjtdnlosiecxyghkwuu +pozvmqbfrtrnlosiesxyghkwud +payvmqbfjornlossecxyghkwud +pazvuqbfjtrnlosiscxyghkpud +pgzcmqbfjtrnlotiecxyghkwud +pazvvqbfjtrnlobieyxyghkwud +pazycqbfjtrnlosiecxyzhkwud +pizvdqbfjtrnlosiecxbghkwud +pazvmqbfjtrnloqiecxmgtkwud +gazvmqbfjtrnlusiecxpghkwud +pazvmqdfjtralosiecxyghkwmd +pazvmqbfjtmnlosiecxywhawud +pazvlqbfjtrnlosqecxyghqwud +pazvmqbfjtrnlhsneixyghkwud +kazvmqbfjtrqlosimcxyghkwud +pazvmwbfjtrclosiecxyghkuud +pazvmqjfjtrnlosieckyghpwud +pezvmqbgjtrnloseecxyghkwud +pazvqqbfjtfnlosvecxyghkwud +oazvmqbfjtunlosiecxyghkwad +pazvmqbfjtrncoswecxyghfwud +pazvyqbfjtrnlosqecxygtkwud +pazvmqbfjtrvlzsiecxygwkwud +pazvmqbfjjrnlosiekxylhkwud +madvmqbfjtrnlosircxyghkwud +pazvmybfjtrnlisiecxyghkwbd +pazvmqbjjixnlosiecxyghkwud +pazvmqefjtrnloqiecxyghhwud +pazveqbfjtrnlosiecgygzkwud +pazvmqbfjtrxlosiecxmgwkwud +uazvmqufjtrnlosiecxyghkwuo +pasymqbfjtrnlosiecxyghowud +pazvmqbfjtlnlpsiecxyghswud +pnzvmqbfjprnloszecxyghkwud +pafjmqcfjtrnlosiecxyghkwud +pazvmqxfbtrnloqiecxyghkwud +pazvmzbfjtrnposiccxyghkwud +pazvmqbfjotulosiecxyghkwud +pazvmqbfotrnlosgecxykhkwud +przvmqbfjtrnlosiecxyqhkwcd +pazvmqbfjtsnlogiecxyyhkwud +pazvmqbfrtrnlzsiecxyghkwug +pazvmqbfjtrnlosiecxzgukwuo +pqzvmqbqjtrnlosdecxyghkwud +pazvmqbfjtqqlosiecxughkwud +pazvmqbfjtrnlosiedhyphkwud +pazsmqbcutrnlosiecxyghkwud +pazvmqbgrtrnlosiecxyghpwud +pazemqbfjtznlosiecxyghkvud +pazvkqbfjtrilosiecxyghkwod +pfzvmqbfjtrnlopiecxygjkwud +pazvmqvfjtreloniecxyghkwud +pazvmqbfjernljsiecxgghkwud +pazvmqikjtrnlosiecxyghqwud +pazvmqbfjtrnpesoecxyghkwud +fazvmqbfjtrnlosihchyghkwud +pazvmqbfjtgnloanecxyghkwud +pazvmqsfjqrnlosiecxychkwud +parvmqbfjtrnlosiecxygfuwud +przvmqbfjtrhlosihcxyghkwud +pazvmqbcjtrnlosimcxgghkwud +pazvmqbfjtrnlosceciyjhkwud +pazvkqbfjtrylosivcxyghkwud +pazvmqbfjtrnlgsieoxyghdwud +pazvmqnfstrnlowiecxyghkwud +pazvmqbfdtrnlosieumyghkwud +pazvmqbfjtrnlosyecxfghkwul +pazvmqbfjtrclosivcxyghkcud +pazjmqbfjtrnlosiecxygokwkd +hazvmqbfjtrflosiecxzghkwud +wazvmqbfjtrnlomiecxyphkwud +yazvmqbfjirnkosiecxyghkwud +pczvmqbfjtrnlohiecxyghkwpd +pazvmqbfotrbeosiecxlghkwud +pazvmqbfjtrplosiecxynhzwud +paxvbqbwjtrnlosiecxyghkwud +pazvmqvfjtrnlosiecbyghqwud +pazjmqbfjtrnlosiecxoghkwed +pazvmqbfjtreljsitcxyghkwud +mazamqbfjtrnlosiecxoghkwud +pazvmqbfjjrnposiscxyghkwud +pbrvmqbfjtrnloliecxyghkwud +pazvmqbfjtrnlosiecxgghkyyd +pmzvmqbfntrnlosiecxyghkwuw +pazvzqbfjtrnlosienxyghzwud +pazvmqifjtvnlosrecxyghkwud +tazvmqbhjtjnlosiecxyghkwud +pazvmqbfjtlnxosiecxyghkwuo +pazvmqbfjennlosiecxyghkwxd +pahvmqbfjhrnlosiecxythkwud +pazvmlkfjtrnlxsiecxyghkwud +pfzvmqbojtrnlosieciyghkwud +pazvbqbfjtrollsiecxyghkwud +eazvmqbfjtrnlosiecayghkoud +pazvmqbfjtjnlvsiecxyghkwsd +pazvoqbojtrnlosiecfyghkwud +pazvmqbfjtuslosiecxyghksud +pazvmqbfjnrnlosiedxyghkwup +pazvmqbjjtrnlosieaxyghdwud +pazccqbfjtrhlosiecxyghkwud +pbzvmqkfjtrnlosievxyghkwud +pazvmqrljtrnlosiscxyghkwud +pazvmqbfjfoqlosiecxyghkwud +pazcmqbfjtrnlosiecxyihkwuf +pszvmqbfjtrnnosiacxyghkwud +aazvmqbfjtrnlosieyxyghkwld +pazvrqbfntrnlosiycxyghkwud +pkzvoqbfjtrnlosiecxyghxwud \ No newline at end of file diff --git a/2018/2/main.cpp b/2018/2/main.cpp new file mode 100644 index 0000000..14ed397 --- /dev/null +++ b/2018/2/main.cpp @@ -0,0 +1,48 @@ +#include +#include +#include + +using namespace std; + +int main () { + int twice = 0; + int thrice = 0; + + ifstream input; + input.open("input"); + string line; + + while (getline(input, line)) { + map freqs; + + for (string::const_iterator it = line.begin(); it != line.end(); ++it) { + auto found = freqs.find(*it); + if (found == freqs.end()) { + freqs.insert(pair(*it, 1)); + } else { + found->second++; + } + } + + int twice_found = false; + int thrice_found = false; + + for (map::const_iterator it = freqs.begin(); it != freqs.end(); ++it) { + if (it->second == 2) { + twice_found = true; + } else if (it->second == 3) { + thrice_found = true; + } + } + + if (twice_found) { + ++twice; + } + + if (thrice_found) { + ++thrice; + } + } + + cout << (twice * thrice) << endl; +} \ No newline at end of file diff --git a/2018/3/input b/2018/3/input new file mode 100644 index 0000000..aa65d46 --- /dev/null +++ b/2018/3/input @@ -0,0 +1,1347 @@ +#1 @ 249,597: 20x15 +#2 @ 192,174: 10x21 +#3 @ 734,527: 23x10 +#4 @ 165,232: 27x27 +#5 @ 834,22: 17x12 +#6 @ 558,963: 18x26 +#7 @ 88,870: 13x10 +#8 @ 877,380: 20x13 +#9 @ 431,810: 12x22 +#10 @ 359,82: 26x23 +#11 @ 466,394: 24x26 +#12 @ 90,393: 24x17 +#13 @ 166,192: 14x17 +#14 @ 939,687: 11x27 +#15 @ 491,18: 11x18 +#16 @ 124,106: 16x22 +#17 @ 595,627: 17x20 +#18 @ 596,781: 27x28 +#19 @ 458,527: 24x10 +#20 @ 615,401: 11x8 +#21 @ 724,287: 15x24 +#22 @ 274,692: 18x14 +#23 @ 557,102: 28x13 +#24 @ 797,403: 29x10 +#25 @ 473,655: 12x29 +#26 @ 300,959: 19x24 +#27 @ 416,724: 26x29 +#28 @ 684,176: 28x19 +#29 @ 296,109: 10x14 +#30 @ 148,191: 19x24 +#31 @ 878,716: 10x29 +#32 @ 951,234: 25x29 +#33 @ 111,385: 13x22 +#34 @ 224,716: 11x16 +#35 @ 919,236: 20x15 +#36 @ 202,499: 15x11 +#37 @ 790,13: 11x24 +#38 @ 229,891: 12x19 +#39 @ 717,434: 17x26 +#40 @ 294,642: 10x15 +#41 @ 427,693: 18x21 +#42 @ 125,763: 13x18 +#43 @ 122,217: 14x14 +#44 @ 274,253: 27x25 +#45 @ 613,19: 21x23 +#46 @ 57,45: 14x12 +#47 @ 324,512: 28x19 +#48 @ 966,949: 24x18 +#49 @ 214,149: 17x15 +#50 @ 261,636: 22x10 +#51 @ 882,809: 28x27 +#52 @ 610,801: 16x11 +#53 @ 830,568: 12x3 +#54 @ 228,904: 16x11 +#55 @ 798,573: 17x22 +#56 @ 338,652: 27x13 +#57 @ 71,514: 28x20 +#58 @ 302,337: 16x11 +#59 @ 619,348: 11x10 +#60 @ 198,655: 13x18 +#61 @ 565,857: 29x27 +#62 @ 758,353: 15x16 +#63 @ 923,531: 19x15 +#64 @ 475,180: 17x20 +#65 @ 418,943: 25x16 +#66 @ 304,194: 10x21 +#67 @ 213,505: 24x13 +#68 @ 240,345: 19x29 +#69 @ 261,356: 18x21 +#70 @ 304,572: 12x18 +#71 @ 234,57: 12x19 +#72 @ 896,417: 14x23 +#73 @ 218,940: 19x26 +#74 @ 610,129: 13x22 +#75 @ 836,802: 23x15 +#76 @ 781,268: 26x28 +#77 @ 183,230: 23x27 +#78 @ 213,223: 18x3 +#79 @ 591,931: 16x21 +#80 @ 940,333: 12x25 +#81 @ 205,618: 26x13 +#82 @ 173,277: 15x19 +#83 @ 259,601: 22x13 +#84 @ 10,581: 26x12 +#85 @ 229,161: 13x11 +#86 @ 321,581: 11x17 +#87 @ 111,508: 18x23 +#88 @ 191,572: 17x12 +#89 @ 134,796: 22x12 +#90 @ 977,643: 3x5 +#91 @ 387,574: 27x24 +#92 @ 634,152: 21x18 +#93 @ 69,265: 15x25 +#94 @ 111,386: 10x29 +#95 @ 239,943: 29x13 +#96 @ 604,606: 24x24 +#97 @ 33,419: 23x29 +#98 @ 752,736: 26x12 +#99 @ 646,46: 11x21 +#100 @ 140,61: 20x18 +#101 @ 960,105: 21x28 +#102 @ 933,885: 13x21 +#103 @ 53,51: 13x21 +#104 @ 776,5: 15x17 +#105 @ 440,907: 28x19 +#106 @ 268,315: 17x17 +#107 @ 150,176: 18x22 +#108 @ 555,336: 13x29 +#109 @ 552,307: 29x22 +#110 @ 193,190: 18x27 +#111 @ 531,33: 22x28 +#112 @ 786,516: 26x19 +#113 @ 61,480: 22x24 +#114 @ 117,675: 28x16 +#115 @ 5,151: 10x18 +#116 @ 700,74: 10x25 +#117 @ 315,641: 24x16 +#118 @ 273,805: 12x25 +#119 @ 924,526: 24x12 +#120 @ 58,79: 29x21 +#121 @ 624,191: 20x23 +#122 @ 180,432: 26x27 +#123 @ 275,205: 16x21 +#124 @ 726,980: 11x16 +#125 @ 154,198: 14x23 +#126 @ 152,192: 15x15 +#127 @ 820,541: 17x26 +#128 @ 896,173: 28x29 +#129 @ 769,608: 25x13 +#130 @ 736,263: 22x13 +#131 @ 521,597: 16x12 +#132 @ 121,477: 15x18 +#133 @ 143,34: 15x12 +#134 @ 208,715: 16x18 +#135 @ 557,521: 23x14 +#136 @ 274,814: 27x11 +#137 @ 154,542: 14x19 +#138 @ 588,902: 28x15 +#139 @ 322,351: 28x25 +#140 @ 156,799: 27x28 +#141 @ 635,324: 21x22 +#142 @ 488,564: 13x25 +#143 @ 763,882: 27x16 +#144 @ 9,718: 16x22 +#145 @ 145,772: 14x22 +#146 @ 108,396: 15x24 +#147 @ 417,826: 15x16 +#148 @ 366,36: 15x13 +#149 @ 106,961: 19x22 +#150 @ 810,224: 18x28 +#151 @ 30,456: 12x22 +#152 @ 974,636: 12x21 +#153 @ 114,104: 14x12 +#154 @ 114,183: 29x23 +#155 @ 514,13: 18x14 +#156 @ 64,571: 11x25 +#157 @ 774,276: 15x19 +#158 @ 950,229: 28x29 +#159 @ 722,154: 20x20 +#160 @ 30,575: 16x24 +#161 @ 802,607: 28x23 +#162 @ 425,944: 23x11 +#163 @ 226,945: 25x20 +#164 @ 218,194: 12x12 +#165 @ 880,386: 5x9 +#166 @ 46,593: 14x10 +#167 @ 550,746: 13x20 +#168 @ 592,328: 22x22 +#169 @ 131,608: 29x21 +#170 @ 371,248: 22x24 +#171 @ 159,177: 23x23 +#172 @ 274,409: 16x23 +#173 @ 301,577: 11x15 +#174 @ 130,167: 16x20 +#175 @ 301,814: 18x11 +#176 @ 893,413: 24x15 +#177 @ 266,316: 23x17 +#178 @ 860,491: 24x29 +#179 @ 708,737: 24x20 +#180 @ 625,250: 16x25 +#181 @ 902,420: 27x25 +#182 @ 152,76: 14x19 +#183 @ 492,166: 8x14 +#184 @ 182,367: 17x21 +#185 @ 226,605: 28x16 +#186 @ 544,365: 20x27 +#187 @ 69,672: 24x26 +#188 @ 354,775: 29x15 +#189 @ 821,715: 10x27 +#190 @ 763,436: 27x18 +#191 @ 259,273: 9x11 +#192 @ 562,554: 19x27 +#193 @ 571,770: 14x23 +#194 @ 593,81: 11x5 +#195 @ 59,187: 16x15 +#196 @ 235,69: 18x23 +#197 @ 381,34: 11x23 +#198 @ 58,621: 25x15 +#199 @ 812,985: 25x10 +#200 @ 146,657: 18x24 +#201 @ 144,132: 25x22 +#202 @ 570,791: 12x15 +#203 @ 663,490: 24x12 +#204 @ 642,180: 16x22 +#205 @ 124,293: 12x27 +#206 @ 815,137: 28x18 +#207 @ 16,880: 27x28 +#208 @ 230,365: 28x22 +#209 @ 230,782: 14x13 +#210 @ 969,108: 5x15 +#211 @ 862,726: 23x27 +#212 @ 858,135: 23x10 +#213 @ 853,588: 12x24 +#214 @ 430,311: 26x16 +#215 @ 814,207: 29x29 +#216 @ 618,653: 14x25 +#217 @ 664,101: 16x23 +#218 @ 703,285: 27x23 +#219 @ 825,438: 23x16 +#220 @ 265,725: 27x20 +#221 @ 18,561: 28x24 +#222 @ 469,252: 17x11 +#223 @ 388,520: 29x16 +#224 @ 382,492: 15x29 +#225 @ 452,449: 26x13 +#226 @ 72,803: 23x17 +#227 @ 652,84: 7x15 +#228 @ 27,205: 20x25 +#229 @ 330,74: 19x17 +#230 @ 805,24: 25x14 +#231 @ 405,578: 18x21 +#232 @ 242,393: 27x26 +#233 @ 216,606: 22x11 +#234 @ 734,870: 18x14 +#235 @ 780,737: 14x27 +#236 @ 154,502: 4x10 +#237 @ 912,536: 22x13 +#238 @ 365,413: 19x10 +#239 @ 85,859: 11x12 +#240 @ 973,708: 27x14 +#241 @ 193,149: 29x26 +#242 @ 958,418: 14x28 +#243 @ 818,875: 19x14 +#244 @ 345,0: 10x21 +#245 @ 641,182: 26x17 +#246 @ 694,276: 26x14 +#247 @ 563,413: 12x16 +#248 @ 303,702: 24x27 +#249 @ 131,145: 17x24 +#250 @ 298,135: 19x27 +#251 @ 87,306: 10x14 +#252 @ 178,180: 11x15 +#253 @ 39,587: 25x15 +#254 @ 391,61: 27x28 +#255 @ 840,758: 13x14 +#256 @ 406,714: 12x25 +#257 @ 385,184: 16x23 +#258 @ 448,913: 26x26 +#259 @ 847,117: 26x22 +#260 @ 956,371: 12x24 +#261 @ 600,964: 29x11 +#262 @ 217,519: 20x24 +#263 @ 75,805: 4x12 +#264 @ 137,452: 10x15 +#265 @ 406,299: 24x14 +#266 @ 48,871: 23x14 +#267 @ 571,234: 23x24 +#268 @ 134,745: 28x27 +#269 @ 739,155: 28x25 +#270 @ 349,784: 12x25 +#271 @ 653,953: 14x21 +#272 @ 122,561: 19x11 +#273 @ 195,373: 18x29 +#274 @ 290,90: 22x23 +#275 @ 829,493: 27x18 +#276 @ 929,536: 13x13 +#277 @ 82,23: 23x27 +#278 @ 53,846: 21x10 +#279 @ 365,656: 13x16 +#280 @ 274,79: 21x17 +#281 @ 535,193: 16x27 +#282 @ 969,552: 16x27 +#283 @ 278,116: 29x12 +#284 @ 111,173: 21x23 +#285 @ 3,568: 17x10 +#286 @ 425,567: 17x21 +#287 @ 447,436: 27x20 +#288 @ 8,129: 20x15 +#289 @ 477,133: 14x10 +#290 @ 261,948: 6x4 +#291 @ 339,833: 19x15 +#292 @ 596,665: 20x12 +#293 @ 638,255: 16x13 +#294 @ 488,164: 19x20 +#295 @ 761,106: 17x23 +#296 @ 799,25: 27x13 +#297 @ 277,172: 23x28 +#298 @ 1,555: 23x28 +#299 @ 262,141: 10x25 +#300 @ 530,231: 11x17 +#301 @ 311,587: 13x11 +#302 @ 95,343: 13x14 +#303 @ 27,755: 27x26 +#304 @ 63,605: 20x24 +#305 @ 502,678: 22x25 +#306 @ 963,451: 13x11 +#307 @ 391,346: 13x24 +#308 @ 299,192: 15x19 +#309 @ 330,9: 23x22 +#310 @ 111,351: 10x10 +#311 @ 204,7: 16x12 +#312 @ 646,296: 11x14 +#313 @ 273,744: 14x15 +#314 @ 229,296: 17x21 +#315 @ 644,214: 29x11 +#316 @ 799,403: 29x14 +#317 @ 565,794: 24x19 +#318 @ 91,348: 23x24 +#319 @ 557,164: 24x29 +#320 @ 146,533: 16x25 +#321 @ 629,963: 13x15 +#322 @ 710,385: 20x10 +#323 @ 420,832: 18x17 +#324 @ 24,400: 24x26 +#325 @ 662,52: 17x18 +#326 @ 826,550: 21x11 +#327 @ 172,790: 14x24 +#328 @ 41,534: 19x26 +#329 @ 450,277: 26x26 +#330 @ 770,624: 19x11 +#331 @ 871,936: 10x20 +#332 @ 824,265: 21x10 +#333 @ 297,88: 13x19 +#334 @ 18,538: 13x16 +#335 @ 289,182: 20x25 +#336 @ 722,234: 14x18 +#337 @ 673,405: 29x27 +#338 @ 816,348: 27x29 +#339 @ 398,52: 17x14 +#340 @ 146,893: 18x20 +#341 @ 241,552: 24x21 +#342 @ 728,388: 14x23 +#343 @ 81,250: 18x16 +#344 @ 654,501: 19x19 +#345 @ 349,422: 19x24 +#346 @ 66,39: 19x15 +#347 @ 560,238: 21x14 +#348 @ 753,434: 17x10 +#349 @ 191,199: 18x16 +#350 @ 131,188: 28x16 +#351 @ 582,356: 18x19 +#352 @ 324,92: 15x10 +#353 @ 955,256: 11x29 +#354 @ 920,449: 17x16 +#355 @ 308,357: 11x19 +#356 @ 827,903: 19x27 +#357 @ 447,158: 16x11 +#358 @ 361,749: 25x25 +#359 @ 159,649: 22x26 +#360 @ 197,732: 22x13 +#361 @ 858,889: 13x19 +#362 @ 869,800: 25x11 +#363 @ 967,687: 29x29 +#364 @ 219,404: 14x22 +#365 @ 878,735: 28x16 +#366 @ 848,374: 12x19 +#367 @ 521,523: 24x24 +#368 @ 147,893: 17x12 +#369 @ 84,157: 21x20 +#370 @ 369,135: 21x17 +#371 @ 262,138: 16x20 +#372 @ 402,930: 21x29 +#373 @ 306,90: 27x24 +#374 @ 256,622: 3x5 +#375 @ 250,875: 23x23 +#376 @ 925,694: 12x16 +#377 @ 169,167: 23x16 +#378 @ 876,448: 28x17 +#379 @ 924,284: 25x29 +#380 @ 598,253: 13x18 +#381 @ 198,248: 21x27 +#382 @ 638,842: 22x24 +#383 @ 398,733: 19x27 +#384 @ 542,56: 14x12 +#385 @ 257,424: 14x10 +#386 @ 308,337: 22x27 +#387 @ 504,448: 14x16 +#388 @ 456,922: 29x21 +#389 @ 155,88: 20x24 +#390 @ 9,706: 25x24 +#391 @ 645,357: 28x15 +#392 @ 34,699: 12x22 +#393 @ 851,621: 10x17 +#394 @ 653,854: 21x11 +#395 @ 294,736: 13x23 +#396 @ 407,573: 26x17 +#397 @ 823,418: 19x24 +#398 @ 315,365: 15x16 +#399 @ 282,185: 26x14 +#400 @ 602,907: 22x20 +#401 @ 336,783: 26x17 +#402 @ 546,328: 15x11 +#403 @ 848,488: 29x20 +#404 @ 6,499: 12x23 +#405 @ 861,629: 22x24 +#406 @ 28,209: 25x28 +#407 @ 221,738: 23x20 +#408 @ 306,758: 19x28 +#409 @ 154,521: 21x24 +#410 @ 830,269: 18x18 +#411 @ 594,905: 28x13 +#412 @ 261,810: 24x26 +#413 @ 633,40: 16x12 +#414 @ 326,351: 10x22 +#415 @ 261,912: 23x21 +#416 @ 882,470: 20x18 +#417 @ 774,31: 29x10 +#418 @ 809,921: 25x21 +#419 @ 840,537: 10x21 +#420 @ 737,802: 21x29 +#421 @ 539,976: 29x19 +#422 @ 611,124: 23x13 +#423 @ 70,592: 26x29 +#424 @ 617,965: 11x11 +#425 @ 799,32: 18x23 +#426 @ 281,725: 13x20 +#427 @ 959,678: 29x15 +#428 @ 862,874: 22x29 +#429 @ 759,667: 22x24 +#430 @ 66,400: 10x10 +#431 @ 126,242: 21x18 +#432 @ 835,385: 27x21 +#433 @ 343,737: 10x20 +#434 @ 970,280: 29x28 +#435 @ 386,889: 17x16 +#436 @ 302,356: 14x25 +#437 @ 8,513: 27x13 +#438 @ 75,364: 20x20 +#439 @ 970,336: 16x20 +#440 @ 440,63: 29x22 +#441 @ 795,752: 14x25 +#442 @ 331,787: 26x19 +#443 @ 378,53: 23x11 +#444 @ 444,840: 16x7 +#445 @ 806,89: 21x29 +#446 @ 236,496: 29x10 +#447 @ 879,556: 17x15 +#448 @ 631,800: 14x23 +#449 @ 540,388: 14x12 +#450 @ 859,629: 22x28 +#451 @ 103,348: 15x27 +#452 @ 310,22: 22x12 +#453 @ 542,99: 23x22 +#454 @ 63,505: 29x15 +#455 @ 333,479: 23x23 +#456 @ 60,132: 22x24 +#457 @ 297,220: 27x22 +#458 @ 331,560: 10x25 +#459 @ 583,665: 17x29 +#460 @ 512,786: 14x20 +#461 @ 962,432: 11x10 +#462 @ 951,374: 14x22 +#463 @ 169,275: 29x20 +#464 @ 428,624: 19x26 +#465 @ 145,203: 29x29 +#466 @ 96,211: 29x21 +#467 @ 211,921: 15x12 +#468 @ 520,787: 11x10 +#469 @ 710,330: 17x17 +#470 @ 248,403: 10x29 +#471 @ 393,900: 16x26 +#472 @ 949,206: 22x27 +#473 @ 170,348: 13x12 +#474 @ 878,703: 20x10 +#475 @ 488,481: 20x28 +#476 @ 929,447: 13x23 +#477 @ 246,389: 14x28 +#478 @ 611,956: 28x11 +#479 @ 397,934: 20x15 +#480 @ 948,476: 25x25 +#481 @ 184,760: 15x25 +#482 @ 260,100: 22x23 +#483 @ 577,336: 25x21 +#484 @ 359,261: 19x10 +#485 @ 876,803: 28x18 +#486 @ 941,128: 19x20 +#487 @ 248,378: 10x26 +#488 @ 36,431: 19x29 +#489 @ 742,561: 11x17 +#490 @ 862,65: 19x19 +#491 @ 252,102: 19x21 +#492 @ 957,321: 28x21 +#493 @ 331,444: 27x21 +#494 @ 576,784: 20x21 +#495 @ 597,487: 22x27 +#496 @ 302,651: 20x15 +#497 @ 392,749: 25x24 +#498 @ 266,419: 14x26 +#499 @ 201,959: 25x11 +#500 @ 854,445: 29x15 +#501 @ 514,580: 19x29 +#502 @ 37,722: 13x29 +#503 @ 206,567: 18x13 +#504 @ 822,346: 18x29 +#505 @ 738,329: 17x21 +#506 @ 834,365: 14x14 +#507 @ 826,877: 15x18 +#508 @ 23,271: 23x16 +#509 @ 12,534: 27x20 +#510 @ 568,232: 14x22 +#511 @ 939,816: 25x16 +#512 @ 464,603: 11x17 +#513 @ 28,274: 14x11 +#514 @ 801,204: 29x23 +#515 @ 837,542: 18x22 +#516 @ 469,909: 20x10 +#517 @ 666,396: 21x10 +#518 @ 615,698: 25x11 +#519 @ 606,351: 16x11 +#520 @ 937,408: 26x21 +#521 @ 207,244: 14x24 +#522 @ 772,697: 10x15 +#523 @ 350,762: 29x19 +#524 @ 344,417: 15x15 +#525 @ 286,192: 23x20 +#526 @ 359,764: 15x16 +#527 @ 456,857: 25x28 +#528 @ 828,654: 20x23 +#529 @ 768,802: 27x24 +#530 @ 523,917: 26x13 +#531 @ 371,30: 18x11 +#532 @ 11,281: 20x15 +#533 @ 805,924: 29x11 +#534 @ 25,196: 29x20 +#535 @ 562,588: 13x18 +#536 @ 385,738: 22x24 +#537 @ 139,38: 10x12 +#538 @ 436,546: 24x15 +#539 @ 300,335: 22x28 +#540 @ 361,676: 24x20 +#541 @ 742,427: 16x29 +#542 @ 814,217: 25x26 +#543 @ 859,36: 15x14 +#544 @ 323,238: 19x12 +#545 @ 661,60: 21x28 +#546 @ 236,394: 22x12 +#547 @ 337,14: 14x17 +#548 @ 917,686: 12x14 +#549 @ 927,130: 26x19 +#550 @ 125,672: 18x22 +#551 @ 516,687: 19x16 +#552 @ 664,519: 18x13 +#553 @ 255,99: 16x12 +#554 @ 461,281: 23x21 +#555 @ 684,676: 20x15 +#556 @ 258,731: 28x12 +#557 @ 847,983: 21x13 +#558 @ 984,318: 11x14 +#559 @ 439,923: 5x5 +#560 @ 178,330: 20x20 +#561 @ 962,946: 18x24 +#562 @ 649,813: 12x26 +#563 @ 16,252: 27x24 +#564 @ 13,942: 12x25 +#565 @ 189,484: 13x11 +#566 @ 959,104: 20x23 +#567 @ 300,246: 19x25 +#568 @ 840,258: 14x16 +#569 @ 754,738: 10x7 +#570 @ 878,921: 23x18 +#571 @ 417,540: 14x12 +#572 @ 232,661: 27x12 +#573 @ 554,758: 12x17 +#574 @ 955,173: 16x18 +#575 @ 438,579: 21x11 +#576 @ 571,740: 24x29 +#577 @ 218,912: 16x25 +#578 @ 667,63: 25x18 +#579 @ 683,642: 16x24 +#580 @ 308,115: 14x28 +#581 @ 419,4: 27x26 +#582 @ 812,249: 29x29 +#583 @ 818,442: 16x19 +#584 @ 453,136: 27x27 +#585 @ 17,202: 15x23 +#586 @ 65,834: 24x19 +#587 @ 810,752: 28x22 +#588 @ 54,892: 14x20 +#589 @ 372,134: 11x17 +#590 @ 203,845: 19x15 +#591 @ 109,491: 26x13 +#592 @ 118,7: 19x22 +#593 @ 871,113: 21x25 +#594 @ 52,311: 24x23 +#595 @ 254,222: 25x24 +#596 @ 787,893: 24x11 +#597 @ 442,435: 20x19 +#598 @ 586,439: 14x17 +#599 @ 37,114: 20x17 +#600 @ 108,168: 19x25 +#601 @ 146,187: 14x16 +#602 @ 201,576: 17x23 +#603 @ 387,759: 21x11 +#604 @ 861,520: 10x20 +#605 @ 834,801: 16x14 +#606 @ 909,568: 13x21 +#607 @ 111,947: 27x21 +#608 @ 326,584: 13x26 +#609 @ 312,235: 25x17 +#610 @ 734,267: 17x21 +#611 @ 168,259: 14x21 +#612 @ 753,541: 20x17 +#613 @ 83,879: 20x13 +#614 @ 778,695: 20x20 +#615 @ 601,859: 29x14 +#616 @ 48,115: 12x18 +#617 @ 472,455: 11x25 +#618 @ 436,918: 12x15 +#619 @ 118,655: 17x29 +#620 @ 375,418: 13x14 +#621 @ 32,503: 14x24 +#622 @ 562,463: 13x20 +#623 @ 883,444: 10x28 +#624 @ 948,256: 26x15 +#625 @ 710,715: 14x19 +#626 @ 86,858: 26x22 +#627 @ 211,220: 24x16 +#628 @ 159,626: 17x29 +#629 @ 747,9: 22x10 +#630 @ 203,254: 22x27 +#631 @ 52,677: 12x29 +#632 @ 233,163: 3x5 +#633 @ 880,694: 16x28 +#634 @ 778,65: 3x7 +#635 @ 608,625: 21x12 +#636 @ 198,350: 29x25 +#637 @ 428,836: 29x21 +#638 @ 39,778: 16x26 +#639 @ 234,106: 17x16 +#640 @ 130,453: 17x12 +#641 @ 51,602: 29x26 +#642 @ 425,545: 16x26 +#643 @ 553,554: 29x12 +#644 @ 822,108: 19x20 +#645 @ 472,260: 27x18 +#646 @ 731,173: 17x21 +#647 @ 532,360: 12x22 +#648 @ 583,801: 13x19 +#649 @ 558,595: 20x16 +#650 @ 226,895: 11x28 +#651 @ 956,243: 12x20 +#652 @ 156,596: 14x14 +#653 @ 426,189: 21x10 +#654 @ 425,45: 25x17 +#655 @ 461,715: 19x21 +#656 @ 659,925: 13x17 +#657 @ 312,762: 21x24 +#658 @ 868,50: 15x24 +#659 @ 388,168: 15x17 +#660 @ 945,704: 20x29 +#661 @ 587,761: 12x22 +#662 @ 182,816: 27x22 +#663 @ 251,226: 22x14 +#664 @ 609,160: 24x26 +#665 @ 437,877: 11x11 +#666 @ 41,261: 23x14 +#667 @ 977,31: 10x29 +#668 @ 22,180: 13x11 +#669 @ 830,797: 12x15 +#670 @ 785,441: 15x26 +#671 @ 647,247: 12x27 +#672 @ 447,594: 23x10 +#673 @ 817,607: 26x19 +#674 @ 627,862: 20x10 +#675 @ 391,43: 16x29 +#676 @ 601,955: 12x26 +#677 @ 748,870: 16x11 +#678 @ 857,484: 16x22 +#679 @ 953,719: 19x23 +#680 @ 525,922: 19x4 +#681 @ 689,525: 18x23 +#682 @ 462,97: 26x13 +#683 @ 138,670: 13x19 +#684 @ 750,114: 20x27 +#685 @ 492,311: 11x21 +#686 @ 624,497: 24x13 +#687 @ 754,432: 15x19 +#688 @ 201,563: 10x17 +#689 @ 581,106: 10x26 +#690 @ 300,936: 21x19 +#691 @ 558,409: 27x10 +#692 @ 105,467: 13x14 +#693 @ 57,178: 12x10 +#694 @ 585,440: 23x14 +#695 @ 204,664: 24x18 +#696 @ 350,922: 26x20 +#697 @ 40,909: 26x17 +#698 @ 253,619: 10x13 +#699 @ 811,485: 16x22 +#700 @ 373,26: 16x22 +#701 @ 461,667: 25x10 +#702 @ 313,408: 27x16 +#703 @ 787,464: 28x27 +#704 @ 970,481: 25x10 +#705 @ 383,758: 17x20 +#706 @ 848,310: 19x26 +#707 @ 384,23: 21x10 +#708 @ 797,288: 11x23 +#709 @ 35,794: 11x14 +#710 @ 264,207: 18x22 +#711 @ 214,606: 20x15 +#712 @ 347,339: 28x15 +#713 @ 421,766: 13x25 +#714 @ 837,583: 13x15 +#715 @ 89,28: 13x15 +#716 @ 150,793: 21x17 +#717 @ 455,451: 19x22 +#718 @ 461,371: 26x28 +#719 @ 99,261: 15x13 +#720 @ 815,402: 10x17 +#721 @ 298,936: 14x22 +#722 @ 938,748: 26x27 +#723 @ 557,263: 29x10 +#724 @ 611,746: 11x22 +#725 @ 0,437: 28x25 +#726 @ 466,697: 10x29 +#727 @ 656,115: 21x23 +#728 @ 865,971: 23x26 +#729 @ 943,740: 11x27 +#730 @ 581,751: 22x25 +#731 @ 810,205: 12x10 +#732 @ 178,76: 14x14 +#733 @ 335,593: 12x24 +#734 @ 194,559: 10x19 +#735 @ 186,63: 14x22 +#736 @ 227,591: 15x17 +#737 @ 730,751: 12x18 +#738 @ 679,497: 18x29 +#739 @ 792,15: 6x19 +#740 @ 229,313: 7x10 +#741 @ 802,209: 17x27 +#742 @ 890,971: 14x13 +#743 @ 551,256: 18x17 +#744 @ 206,745: 19x16 +#745 @ 299,954: 14x17 +#746 @ 217,573: 13x11 +#747 @ 919,305: 27x22 +#748 @ 530,33: 28x27 +#749 @ 703,373: 29x29 +#750 @ 149,142: 27x21 +#751 @ 721,285: 12x15 +#752 @ 389,7: 25x26 +#753 @ 812,241: 24x21 +#754 @ 450,144: 14x16 +#755 @ 647,895: 15x25 +#756 @ 556,173: 24x27 +#757 @ 159,261: 23x22 +#758 @ 33,455: 12x13 +#759 @ 338,325: 14x15 +#760 @ 567,77: 13x22 +#761 @ 339,821: 29x11 +#762 @ 328,488: 4x3 +#763 @ 14,180: 11x27 +#764 @ 274,254: 27x21 +#765 @ 796,747: 17x23 +#766 @ 528,451: 25x17 +#767 @ 196,796: 10x21 +#768 @ 48,391: 12x19 +#769 @ 644,484: 11x14 +#770 @ 293,777: 19x22 +#771 @ 657,82: 28x20 +#772 @ 734,962: 22x25 +#773 @ 455,95: 13x14 +#774 @ 440,198: 27x28 +#775 @ 581,742: 28x25 +#776 @ 450,48: 13x17 +#777 @ 956,246: 26x28 +#778 @ 110,500: 14x19 +#779 @ 666,908: 19x13 +#780 @ 709,234: 21x13 +#781 @ 98,814: 18x27 +#782 @ 32,182: 27x28 +#783 @ 519,457: 28x13 +#784 @ 477,840: 29x18 +#785 @ 826,564: 26x24 +#786 @ 351,425: 13x17 +#787 @ 311,927: 21x17 +#788 @ 524,477: 22x15 +#789 @ 257,267: 22x25 +#790 @ 85,525: 19x18 +#791 @ 364,586: 16x15 +#792 @ 14,72: 15x25 +#793 @ 877,378: 13x21 +#794 @ 519,232: 18x17 +#795 @ 15,570: 17x21 +#796 @ 793,563: 25x20 +#797 @ 823,758: 15x20 +#798 @ 617,269: 11x16 +#799 @ 430,930: 27x26 +#800 @ 325,14: 18x26 +#801 @ 28,883: 17x16 +#802 @ 843,585: 15x16 +#803 @ 572,673: 26x21 +#804 @ 668,135: 28x19 +#805 @ 309,31: 21x18 +#806 @ 731,740: 24x22 +#807 @ 776,59: 27x20 +#808 @ 716,701: 22x28 +#809 @ 685,811: 15x18 +#810 @ 625,662: 12x25 +#811 @ 447,684: 26x26 +#812 @ 591,73: 17x25 +#813 @ 853,307: 25x13 +#814 @ 648,372: 14x23 +#815 @ 282,967: 22x20 +#816 @ 654,22: 25x21 +#817 @ 151,498: 11x19 +#818 @ 349,650: 12x28 +#819 @ 841,129: 16x28 +#820 @ 886,967: 14x10 +#821 @ 127,54: 27x26 +#822 @ 86,586: 20x11 +#823 @ 553,304: 18x20 +#824 @ 185,543: 16x26 +#825 @ 251,363: 3x4 +#826 @ 286,716: 23x25 +#827 @ 617,344: 24x22 +#828 @ 620,163: 9x5 +#829 @ 535,476: 24x13 +#830 @ 636,285: 26x19 +#831 @ 929,321: 11x25 +#832 @ 8,8: 14x28 +#833 @ 243,614: 12x11 +#834 @ 972,249: 11x16 +#835 @ 296,268: 13x15 +#836 @ 208,644: 29x23 +#837 @ 859,385: 28x16 +#838 @ 603,350: 29x20 +#839 @ 442,827: 22x25 +#840 @ 339,588: 20x19 +#841 @ 310,81: 23x16 +#842 @ 403,718: 16x16 +#843 @ 315,771: 18x12 +#844 @ 644,80: 29x15 +#845 @ 573,80: 25x13 +#846 @ 740,550: 16x20 +#847 @ 127,437: 19x14 +#848 @ 121,483: 11x26 +#849 @ 471,603: 14x13 +#850 @ 341,504: 18x21 +#851 @ 983,308: 16x23 +#852 @ 455,45: 24x29 +#853 @ 13,12: 10x20 +#854 @ 610,33: 26x23 +#855 @ 427,6: 12x22 +#856 @ 951,182: 12x14 +#857 @ 564,245: 15x12 +#858 @ 640,50: 27x18 +#859 @ 46,915: 10x26 +#860 @ 133,753: 21x28 +#861 @ 590,251: 13x14 +#862 @ 866,531: 26x13 +#863 @ 560,408: 15x18 +#864 @ 133,764: 15x28 +#865 @ 395,455: 28x27 +#866 @ 170,805: 14x18 +#867 @ 216,253: 11x28 +#868 @ 741,862: 21x17 +#869 @ 342,832: 25x13 +#870 @ 691,529: 13x3 +#871 @ 93,372: 21x24 +#872 @ 431,458: 29x12 +#873 @ 242,650: 10x14 +#874 @ 35,920: 12x10 +#875 @ 804,300: 17x22 +#876 @ 890,720: 16x23 +#877 @ 219,136: 14x24 +#878 @ 276,507: 21x13 +#879 @ 670,847: 28x28 +#880 @ 597,19: 18x27 +#881 @ 326,483: 29x12 +#882 @ 430,202: 15x18 +#883 @ 124,204: 28x21 +#884 @ 747,605: 28x19 +#885 @ 379,926: 10x13 +#886 @ 314,33: 27x11 +#887 @ 622,964: 19x22 +#888 @ 761,894: 13x19 +#889 @ 241,772: 10x23 +#890 @ 662,655: 28x26 +#891 @ 805,290: 22x12 +#892 @ 444,638: 22x29 +#893 @ 865,769: 19x18 +#894 @ 67,661: 27x22 +#895 @ 179,758: 23x20 +#896 @ 227,188: 17x27 +#897 @ 307,400: 14x23 +#898 @ 375,768: 13x16 +#899 @ 806,924: 21x11 +#900 @ 192,412: 18x10 +#901 @ 965,338: 13x15 +#902 @ 528,793: 26x17 +#903 @ 822,225: 25x26 +#904 @ 488,902: 19x17 +#905 @ 835,347: 20x20 +#906 @ 799,393: 25x20 +#907 @ 652,290: 15x23 +#908 @ 313,30: 18x21 +#909 @ 389,445: 29x22 +#910 @ 470,52: 21x11 +#911 @ 554,401: 15x20 +#912 @ 612,887: 21x22 +#913 @ 833,990: 27x10 +#914 @ 127,125: 25x24 +#915 @ 78,867: 23x26 +#916 @ 13,144: 20x19 +#917 @ 945,314: 20x13 +#918 @ 525,33: 29x26 +#919 @ 110,830: 21x15 +#920 @ 703,65: 24x20 +#921 @ 936,443: 19x25 +#922 @ 383,526: 19x19 +#923 @ 869,135: 17x15 +#924 @ 950,454: 10x24 +#925 @ 84,724: 13x8 +#926 @ 754,258: 17x13 +#927 @ 941,351: 27x20 +#928 @ 971,344: 25x16 +#929 @ 452,811: 19x16 +#930 @ 656,29: 9x5 +#931 @ 520,16: 3x3 +#932 @ 65,143: 12x9 +#933 @ 804,121: 21x19 +#934 @ 134,150: 10x16 +#935 @ 11,234: 23x17 +#936 @ 786,95: 21x10 +#937 @ 466,190: 23x22 +#938 @ 624,952: 12x26 +#939 @ 406,27: 29x26 +#940 @ 39,251: 25x27 +#941 @ 198,389: 13x25 +#942 @ 846,2: 22x29 +#943 @ 840,349: 13x21 +#944 @ 495,183: 18x29 +#945 @ 661,305: 14x19 +#946 @ 575,197: 10x21 +#947 @ 557,521: 18x17 +#948 @ 401,755: 24x13 +#949 @ 519,48: 15x27 +#950 @ 590,727: 10x26 +#951 @ 262,968: 16x14 +#952 @ 177,795: 12x13 +#953 @ 211,893: 25x22 +#954 @ 85,514: 14x19 +#955 @ 524,430: 25x21 +#956 @ 836,805: 9x6 +#957 @ 300,14: 17x28 +#958 @ 219,699: 20x11 +#959 @ 310,43: 19x16 +#960 @ 117,379: 10x29 +#961 @ 530,774: 22x25 +#962 @ 843,584: 19x13 +#963 @ 425,711: 10x10 +#964 @ 271,975: 15x11 +#965 @ 879,445: 10x11 +#966 @ 433,341: 19x16 +#967 @ 29,425: 20x24 +#968 @ 247,361: 11x19 +#969 @ 251,478: 21x22 +#970 @ 730,781: 17x24 +#971 @ 38,803: 25x29 +#972 @ 654,257: 16x29 +#973 @ 283,215: 25x14 +#974 @ 198,692: 14x28 +#975 @ 384,394: 19x13 +#976 @ 639,148: 14x28 +#977 @ 597,299: 29x16 +#978 @ 748,803: 27x12 +#979 @ 59,573: 19x23 +#980 @ 313,133: 26x12 +#981 @ 342,481: 12x18 +#982 @ 207,794: 26x15 +#983 @ 47,286: 27x27 +#984 @ 88,663: 11x17 +#985 @ 723,747: 13x17 +#986 @ 299,716: 18x22 +#987 @ 827,893: 21x21 +#988 @ 482,396: 28x28 +#989 @ 170,364: 29x12 +#990 @ 973,342: 25x10 +#991 @ 879,356: 23x28 +#992 @ 435,352: 21x16 +#993 @ 432,290: 17x29 +#994 @ 770,16: 25x26 +#995 @ 39,687: 21x23 +#996 @ 148,600: 10x13 +#997 @ 279,787: 28x22 +#998 @ 137,310: 29x14 +#999 @ 867,554: 25x26 +#1000 @ 949,341: 29x13 +#1001 @ 931,220: 23x18 +#1002 @ 394,527: 15x13 +#1003 @ 914,429: 19x12 +#1004 @ 116,315: 23x18 +#1005 @ 27,698: 13x22 +#1006 @ 872,814: 21x18 +#1007 @ 618,470: 13x22 +#1008 @ 274,708: 13x23 +#1009 @ 869,684: 23x27 +#1010 @ 455,560: 23x26 +#1011 @ 668,923: 10x16 +#1012 @ 863,65: 17x27 +#1013 @ 143,179: 12x28 +#1014 @ 793,136: 25x23 +#1015 @ 14,850: 27x12 +#1016 @ 715,326: 19x14 +#1017 @ 58,834: 13x28 +#1018 @ 657,895: 25x16 +#1019 @ 870,752: 26x23 +#1020 @ 846,137: 26x23 +#1021 @ 877,761: 22x23 +#1022 @ 527,234: 29x13 +#1023 @ 396,522: 20x26 +#1024 @ 919,416: 13x29 +#1025 @ 63,549: 29x23 +#1026 @ 906,305: 26x16 +#1027 @ 91,849: 14x16 +#1028 @ 625,658: 15x18 +#1029 @ 77,721: 29x15 +#1030 @ 958,815: 13x14 +#1031 @ 527,104: 11x12 +#1032 @ 447,515: 26x17 +#1033 @ 610,976: 19x21 +#1034 @ 711,174: 21x11 +#1035 @ 235,595: 13x19 +#1036 @ 750,871: 26x17 +#1037 @ 253,593: 13x19 +#1038 @ 375,660: 20x25 +#1039 @ 10,131: 7x8 +#1040 @ 939,344: 23x11 +#1041 @ 339,897: 12x26 +#1042 @ 602,293: 10x26 +#1043 @ 263,352: 15x25 +#1044 @ 655,131: 22x13 +#1045 @ 95,257: 21x28 +#1046 @ 527,107: 26x14 +#1047 @ 124,284: 17x16 +#1048 @ 589,788: 29x22 +#1049 @ 754,342: 10x21 +#1050 @ 823,84: 19x21 +#1051 @ 506,657: 21x23 +#1052 @ 917,933: 17x28 +#1053 @ 307,596: 27x13 +#1054 @ 239,570: 18x22 +#1055 @ 251,652: 14x28 +#1056 @ 47,556: 13x20 +#1057 @ 106,335: 29x21 +#1058 @ 286,262: 19x29 +#1059 @ 658,641: 26x10 +#1060 @ 888,498: 13x16 +#1061 @ 294,574: 14x25 +#1062 @ 15,889: 28x12 +#1063 @ 56,390: 11x20 +#1064 @ 497,322: 12x16 +#1065 @ 35,165: 15x3 +#1066 @ 353,435: 12x10 +#1067 @ 857,55: 16x15 +#1068 @ 234,609: 27x20 +#1069 @ 269,204: 10x27 +#1070 @ 659,655: 22x15 +#1071 @ 499,662: 22x28 +#1072 @ 649,902: 9x11 +#1073 @ 817,482: 16x20 +#1074 @ 418,795: 25x20 +#1075 @ 813,904: 10x25 +#1076 @ 773,609: 21x22 +#1077 @ 450,735: 21x16 +#1078 @ 739,170: 24x10 +#1079 @ 249,103: 14x11 +#1080 @ 241,909: 24x14 +#1081 @ 122,231: 27x26 +#1082 @ 48,734: 11x19 +#1083 @ 823,743: 19x18 +#1084 @ 142,679: 18x10 +#1085 @ 565,850: 16x11 +#1086 @ 263,603: 4x7 +#1087 @ 970,709: 15x15 +#1088 @ 42,840: 15x24 +#1089 @ 949,723: 13x21 +#1090 @ 781,483: 23x28 +#1091 @ 329,241: 26x10 +#1092 @ 531,220: 29x26 +#1093 @ 880,740: 29x11 +#1094 @ 277,313: 10x14 +#1095 @ 540,57: 26x24 +#1096 @ 830,659: 18x28 +#1097 @ 374,606: 12x26 +#1098 @ 636,63: 28x11 +#1099 @ 933,905: 19x13 +#1100 @ 429,586: 17x20 +#1101 @ 131,113: 14x22 +#1102 @ 340,819: 13x24 +#1103 @ 761,58: 16x21 +#1104 @ 760,355: 9x10 +#1105 @ 231,84: 14x29 +#1106 @ 638,367: 28x25 +#1107 @ 770,261: 12x19 +#1108 @ 367,797: 18x23 +#1109 @ 530,348: 18x19 +#1110 @ 568,717: 19x24 +#1111 @ 467,725: 14x16 +#1112 @ 14,175: 27x20 +#1113 @ 439,539: 22x28 +#1114 @ 202,565: 20x23 +#1115 @ 974,280: 25x23 +#1116 @ 528,527: 18x17 +#1117 @ 547,332: 10x23 +#1118 @ 91,584: 13x10 +#1119 @ 828,366: 10x28 +#1120 @ 86,842: 29x28 +#1121 @ 437,1: 25x17 +#1122 @ 358,401: 22x23 +#1123 @ 468,822: 26x16 +#1124 @ 58,844: 13x26 +#1125 @ 288,705: 17x11 +#1126 @ 322,540: 27x27 +#1127 @ 628,838: 24x23 +#1128 @ 469,502: 26x10 +#1129 @ 937,336: 29x22 +#1130 @ 615,676: 15x13 +#1131 @ 502,687: 23x14 +#1132 @ 235,706: 15x25 +#1133 @ 369,36: 11x28 +#1134 @ 98,720: 22x13 +#1135 @ 465,464: 27x14 +#1136 @ 828,202: 21x20 +#1137 @ 721,441: 16x28 +#1138 @ 69,482: 16x10 +#1139 @ 105,755: 23x21 +#1140 @ 105,438: 26x13 +#1141 @ 846,630: 20x13 +#1142 @ 612,19: 25x14 +#1143 @ 618,613: 16x13 +#1144 @ 491,174: 29x20 +#1145 @ 388,399: 11x16 +#1146 @ 232,53: 19x13 +#1147 @ 493,580: 11x14 +#1148 @ 820,76: 13x28 +#1149 @ 283,103: 28x11 +#1150 @ 332,749: 29x19 +#1151 @ 288,269: 20x18 +#1152 @ 225,305: 26x25 +#1153 @ 640,801: 16x17 +#1154 @ 301,161: 25x23 +#1155 @ 505,103: 29x25 +#1156 @ 179,526: 15x23 +#1157 @ 937,318: 26x19 +#1158 @ 452,605: 20x11 +#1159 @ 895,672: 21x29 +#1160 @ 192,740: 20x15 +#1161 @ 347,537: 13x11 +#1162 @ 633,181: 13x23 +#1163 @ 575,914: 17x21 +#1164 @ 793,401: 23x20 +#1165 @ 296,801: 15x29 +#1166 @ 949,398: 22x12 +#1167 @ 49,225: 16x10 +#1168 @ 283,513: 8x3 +#1169 @ 456,497: 16x15 +#1170 @ 105,452: 15x17 +#1171 @ 170,966: 11x24 +#1172 @ 574,795: 12x19 +#1173 @ 745,14: 22x23 +#1174 @ 255,310: 18x14 +#1175 @ 17,326: 24x26 +#1176 @ 735,687: 25x20 +#1177 @ 764,883: 29x15 +#1178 @ 602,572: 18x26 +#1179 @ 666,916: 15x12 +#1180 @ 246,762: 18x28 +#1181 @ 202,451: 14x20 +#1182 @ 560,801: 25x10 +#1183 @ 817,767: 22x11 +#1184 @ 814,313: 17x13 +#1185 @ 44,613: 10x24 +#1186 @ 503,441: 27x10 +#1187 @ 484,374: 18x16 +#1188 @ 815,724: 29x19 +#1189 @ 923,702: 25x21 +#1190 @ 408,25: 14x15 +#1191 @ 590,710: 17x16 +#1192 @ 4,321: 20x15 +#1193 @ 723,759: 24x25 +#1194 @ 248,761: 28x28 +#1195 @ 246,572: 26x21 +#1196 @ 434,463: 25x10 +#1197 @ 342,661: 18x16 +#1198 @ 699,817: 23x15 +#1199 @ 646,371: 10x27 +#1200 @ 30,388: 24x13 +#1201 @ 50,876: 11x19 +#1202 @ 11,849: 11x20 +#1203 @ 360,922: 23x27 +#1204 @ 532,218: 18x27 +#1205 @ 588,718: 19x18 +#1206 @ 197,491: 20x14 +#1207 @ 0,547: 15x19 +#1208 @ 233,556: 17x22 +#1209 @ 560,172: 20x16 +#1210 @ 806,284: 15x12 +#1211 @ 632,674: 27x13 +#1212 @ 53,846: 29x22 +#1213 @ 126,770: 13x18 +#1214 @ 859,429: 19x28 +#1215 @ 221,719: 13x10 +#1216 @ 209,400: 26x21 +#1217 @ 348,934: 12x26 +#1218 @ 949,447: 24x24 +#1219 @ 521,367: 28x10 +#1220 @ 369,659: 24x22 +#1221 @ 473,6: 27x21 +#1222 @ 532,686: 15x21 +#1223 @ 609,960: 17x24 +#1224 @ 475,548: 12x24 +#1225 @ 712,278: 27x16 +#1226 @ 33,162: 21x11 +#1227 @ 3,866: 20x20 +#1228 @ 785,73: 14x26 +#1229 @ 130,179: 25x29 +#1230 @ 209,540: 25x28 +#1231 @ 220,27: 13x17 +#1232 @ 948,474: 18x28 +#1233 @ 647,228: 21x21 +#1234 @ 362,797: 25x11 +#1235 @ 966,265: 16x13 +#1236 @ 412,50: 22x17 +#1237 @ 779,552: 21x24 +#1238 @ 760,63: 26x21 +#1239 @ 52,70: 29x23 +#1240 @ 47,15: 29x10 +#1241 @ 956,575: 20x19 +#1242 @ 760,536: 19x24 +#1243 @ 635,702: 16x19 +#1244 @ 892,166: 28x16 +#1245 @ 0,430: 27x19 +#1246 @ 883,387: 10x10 +#1247 @ 88,666: 11x19 +#1248 @ 640,250: 16x20 +#1249 @ 21,220: 26x15 +#1250 @ 976,55: 14x15 +#1251 @ 728,372: 19x12 +#1252 @ 14,937: 13x11 +#1253 @ 655,125: 25x11 +#1254 @ 617,346: 15x27 +#1255 @ 943,383: 28x10 +#1256 @ 951,221: 29x23 +#1257 @ 482,662: 16x28 +#1258 @ 806,546: 15x26 +#1259 @ 370,604: 23x13 +#1260 @ 120,643: 10x22 +#1261 @ 98,447: 20x23 +#1262 @ 764,800: 24x20 +#1263 @ 427,192: 16x23 +#1264 @ 115,720: 16x13 +#1265 @ 257,945: 14x14 +#1266 @ 511,445: 18x26 +#1267 @ 633,221: 29x16 +#1268 @ 615,819: 28x28 +#1269 @ 89,311: 19x14 +#1270 @ 231,825: 28x17 +#1271 @ 133,0: 29x22 +#1272 @ 220,822: 13x18 +#1273 @ 699,690: 23x10 +#1274 @ 91,441: 22x20 +#1275 @ 213,788: 22x19 +#1276 @ 873,458: 19x28 +#1277 @ 459,490: 23x17 +#1278 @ 215,963: 28x23 +#1279 @ 56,12: 22x28 +#1280 @ 644,937: 17x26 +#1281 @ 613,397: 17x20 +#1282 @ 559,468: 15x14 +#1283 @ 642,244: 17x10 +#1284 @ 140,779: 14x22 +#1285 @ 232,313: 25x18 +#1286 @ 614,737: 22x29 +#1287 @ 790,187: 23x20 +#1288 @ 166,537: 24x23 +#1289 @ 954,368: 15x17 +#1290 @ 294,957: 11x16 +#1291 @ 95,170: 25x12 +#1292 @ 208,831: 20x20 +#1293 @ 915,752: 24x21 +#1294 @ 790,497: 28x10 +#1295 @ 214,12: 18x29 +#1296 @ 872,20: 22x24 +#1297 @ 84,24: 20x22 +#1298 @ 72,859: 10x23 +#1299 @ 414,871: 29x11 +#1300 @ 148,534: 12x13 +#1301 @ 883,17: 25x23 +#1302 @ 95,854: 28x17 +#1303 @ 264,878: 14x10 +#1304 @ 257,942: 23x15 +#1305 @ 400,523: 25x10 +#1306 @ 125,555: 17x20 +#1307 @ 913,427: 19x17 +#1308 @ 890,502: 7x3 +#1309 @ 868,445: 24x28 +#1310 @ 820,759: 25x10 +#1311 @ 643,82: 21x21 +#1312 @ 249,117: 22x27 +#1313 @ 320,935: 29x19 +#1314 @ 376,492: 27x25 +#1315 @ 467,666: 11x27 +#1316 @ 608,583: 20x25 +#1317 @ 445,672: 12x19 +#1318 @ 428,284: 25x21 +#1319 @ 286,411: 18x17 +#1320 @ 81,539: 18x27 +#1321 @ 600,969: 20x23 +#1322 @ 358,571: 11x19 +#1323 @ 594,348: 13x16 +#1324 @ 401,337: 13x18 +#1325 @ 45,843: 16x22 +#1326 @ 18,80: 16x26 +#1327 @ 946,465: 12x21 +#1328 @ 10,206: 18x26 +#1329 @ 178,967: 24x17 +#1330 @ 722,531: 17x28 +#1331 @ 415,525: 29x24 +#1332 @ 376,90: 14x14 +#1333 @ 103,530: 10x21 +#1334 @ 958,103: 28x18 +#1335 @ 893,579: 22x15 +#1336 @ 913,924: 10x20 +#1337 @ 272,436: 20x29 +#1338 @ 823,63: 17x29 +#1339 @ 2,495: 13x16 +#1340 @ 202,2: 22x26 +#1341 @ 268,735: 14x14 +#1342 @ 261,628: 19x26 +#1343 @ 672,888: 16x15 +#1344 @ 884,17: 27x11 +#1345 @ 318,911: 22x25 +#1346 @ 433,843: 20x20 +#1347 @ 796,526: 28x18 diff --git a/2018/3/main.rb b/2018/3/main.rb new file mode 100644 index 0000000..c792d3c --- /dev/null +++ b/2018/3/main.rb @@ -0,0 +1,31 @@ +require 'pry' + +arr = Array.new(1000){Array.new(1000){{count: 0, id: nil}}} + +ids = Array.new +dups = Array.new + +File.open("input", "r") do |f| + f.each_line do |line| + id = line[/\d+/].to_i + offset_left, offset_top = line[/\d+,\d+/].split(",").map(&:to_i) + width, height = line[/\d+x\d+/].split("x").map(&:to_i) + + ids.push id + + height.times do |y| + width.times do |x| + arr[offset_top + y][offset_left + x][:count] += 1 + if arr[offset_top + y][offset_left + x][:id] != nil + dups.push arr[offset_top + y][offset_left + x][:id] + dups.push id + end + arr[offset_top + y][offset_left + x][:id] = id + end + end + end +end + +puts arr.flatten.select{|a| a[:count] > 1}.count + +puts (ids - dups.uniq) \ No newline at end of file diff --git a/2018/4/input b/2018/4/input new file mode 100644 index 0000000..c77935d --- /dev/null +++ b/2018/4/input @@ -0,0 +1,1110 @@ +[1518-05-27 00:42] falls asleep +[1518-07-14 00:53] falls asleep +[1518-09-22 00:10] falls asleep +[1518-10-27 00:55] wakes up +[1518-10-25 00:53] falls asleep +[1518-06-02 00:56] wakes up +[1518-07-02 00:05] falls asleep +[1518-08-04 00:16] falls asleep +[1518-03-19 00:21] falls asleep +[1518-05-15 00:53] wakes up +[1518-06-10 00:46] falls asleep +[1518-09-01 23:52] Guard #3187 begins shift +[1518-03-14 00:43] wakes up +[1518-04-11 00:00] Guard #2207 begins shift +[1518-08-08 00:48] wakes up +[1518-03-29 00:29] falls asleep +[1518-10-03 00:55] wakes up +[1518-04-23 00:54] wakes up +[1518-04-18 00:14] falls asleep +[1518-08-19 00:44] wakes up +[1518-03-31 00:02] Guard #1901 begins shift +[1518-10-14 00:59] wakes up +[1518-05-12 00:30] falls asleep +[1518-07-08 00:23] falls asleep +[1518-06-22 00:03] Guard #1499 begins shift +[1518-04-29 00:03] Guard #191 begins shift +[1518-06-05 00:35] falls asleep +[1518-11-08 00:05] wakes up +[1518-08-29 00:24] falls asleep +[1518-07-23 00:41] wakes up +[1518-03-03 00:58] wakes up +[1518-07-03 00:44] falls asleep +[1518-09-03 00:04] wakes up +[1518-06-14 00:18] falls asleep +[1518-09-15 23:56] Guard #1103 begins shift +[1518-04-24 23:56] Guard #601 begins shift +[1518-08-17 00:23] falls asleep +[1518-02-13 00:40] falls asleep +[1518-07-20 00:00] Guard #1069 begins shift +[1518-07-12 00:26] falls asleep +[1518-02-22 00:58] wakes up +[1518-11-03 00:24] falls asleep +[1518-11-20 00:00] Guard #599 begins shift +[1518-08-12 00:28] falls asleep +[1518-10-11 00:36] wakes up +[1518-06-11 00:58] wakes up +[1518-04-01 00:44] falls asleep +[1518-07-17 00:41] wakes up +[1518-10-14 00:53] wakes up +[1518-07-16 00:02] Guard #1031 begins shift +[1518-11-09 00:50] wakes up +[1518-04-19 00:35] falls asleep +[1518-09-06 00:24] wakes up +[1518-04-15 00:00] Guard #599 begins shift +[1518-07-21 00:44] wakes up +[1518-08-09 00:02] Guard #2477 begins shift +[1518-11-06 00:32] falls asleep +[1518-07-31 00:49] wakes up +[1518-05-06 00:52] wakes up +[1518-11-21 00:00] Guard #1607 begins shift +[1518-03-15 00:43] wakes up +[1518-07-20 00:08] falls asleep +[1518-10-12 00:55] falls asleep +[1518-08-30 00:04] falls asleep +[1518-03-16 00:17] wakes up +[1518-05-31 00:19] wakes up +[1518-05-14 23:52] Guard #1789 begins shift +[1518-10-07 00:13] falls asleep +[1518-04-24 00:45] wakes up +[1518-08-14 23:59] Guard #2617 begins shift +[1518-11-04 00:41] falls asleep +[1518-04-21 00:57] wakes up +[1518-08-11 00:00] Guard #2213 begins shift +[1518-10-28 23:56] Guard #1103 begins shift +[1518-06-29 00:50] wakes up +[1518-07-27 00:19] falls asleep +[1518-06-16 00:39] wakes up +[1518-05-23 00:42] falls asleep +[1518-09-08 00:57] falls asleep +[1518-08-01 00:18] falls asleep +[1518-09-07 00:16] wakes up +[1518-04-18 00:41] wakes up +[1518-08-31 00:50] wakes up +[1518-09-03 00:58] wakes up +[1518-04-12 00:48] wakes up +[1518-04-23 00:19] wakes up +[1518-03-19 00:26] wakes up +[1518-04-05 00:05] falls asleep +[1518-08-19 00:31] falls asleep +[1518-09-26 00:37] wakes up +[1518-03-17 00:34] falls asleep +[1518-10-31 00:46] wakes up +[1518-06-29 00:57] wakes up +[1518-02-14 23:49] Guard #1997 begins shift +[1518-11-13 00:51] wakes up +[1518-03-10 00:42] wakes up +[1518-03-15 00:48] falls asleep +[1518-06-19 00:09] falls asleep +[1518-05-03 00:03] Guard #2221 begins shift +[1518-03-10 00:26] falls asleep +[1518-03-16 00:58] wakes up +[1518-06-27 00:24] wakes up +[1518-07-08 23:46] Guard #1069 begins shift +[1518-10-08 00:48] wakes up +[1518-07-30 00:00] falls asleep +[1518-02-28 00:00] Guard #1103 begins shift +[1518-10-29 23:58] Guard #1873 begins shift +[1518-04-11 00:26] falls asleep +[1518-11-10 00:24] wakes up +[1518-09-12 00:39] wakes up +[1518-11-07 00:19] falls asleep +[1518-08-16 00:00] Guard #3187 begins shift +[1518-05-06 00:41] falls asleep +[1518-03-10 23:54] Guard #1789 begins shift +[1518-10-01 00:11] falls asleep +[1518-08-25 00:52] falls asleep +[1518-03-17 00:57] falls asleep +[1518-08-23 23:58] Guard #1069 begins shift +[1518-07-20 00:56] wakes up +[1518-08-22 00:48] wakes up +[1518-05-31 00:40] falls asleep +[1518-08-25 00:36] wakes up +[1518-08-03 00:58] wakes up +[1518-03-24 00:43] falls asleep +[1518-06-17 00:11] falls asleep +[1518-02-19 00:00] Guard #1873 begins shift +[1518-04-17 00:01] falls asleep +[1518-06-30 00:59] wakes up +[1518-08-26 00:59] wakes up +[1518-10-17 00:29] falls asleep +[1518-07-11 00:00] Guard #2477 begins shift +[1518-06-25 00:58] wakes up +[1518-10-01 00:58] wakes up +[1518-04-20 00:42] wakes up +[1518-05-10 00:03] Guard #1901 begins shift +[1518-03-10 00:51] falls asleep +[1518-04-04 00:27] falls asleep +[1518-02-26 00:45] wakes up +[1518-08-03 00:00] Guard #2213 begins shift +[1518-07-01 00:27] falls asleep +[1518-04-04 00:14] wakes up +[1518-08-25 00:25] falls asleep +[1518-06-20 00:46] falls asleep +[1518-07-23 23:59] Guard #1997 begins shift +[1518-03-09 00:25] falls asleep +[1518-09-19 00:48] falls asleep +[1518-07-04 23:51] Guard #1607 begins shift +[1518-08-04 00:21] wakes up +[1518-07-18 00:51] wakes up +[1518-09-23 23:57] Guard #3041 begins shift +[1518-05-17 00:26] falls asleep +[1518-06-26 00:01] Guard #1789 begins shift +[1518-04-27 00:52] wakes up +[1518-11-21 00:13] falls asleep +[1518-07-23 00:12] falls asleep +[1518-11-13 00:03] falls asleep +[1518-07-10 00:15] falls asleep +[1518-04-04 00:12] falls asleep +[1518-03-24 23:54] Guard #3041 begins shift +[1518-10-09 00:27] falls asleep +[1518-08-09 00:36] wakes up +[1518-10-04 00:45] falls asleep +[1518-02-22 00:14] falls asleep +[1518-08-03 00:57] falls asleep +[1518-05-05 00:11] falls asleep +[1518-07-08 00:00] Guard #1229 begins shift +[1518-06-20 00:39] wakes up +[1518-04-23 00:45] falls asleep +[1518-02-25 00:53] wakes up +[1518-08-20 00:09] wakes up +[1518-04-24 00:42] falls asleep +[1518-09-12 00:22] wakes up +[1518-09-20 00:14] wakes up +[1518-08-16 00:36] wakes up +[1518-08-23 00:56] wakes up +[1518-06-28 23:58] Guard #599 begins shift +[1518-03-10 00:55] wakes up +[1518-07-29 00:16] falls asleep +[1518-09-04 00:55] falls asleep +[1518-11-08 00:02] falls asleep +[1518-03-22 00:04] Guard #1499 begins shift +[1518-04-17 00:46] falls asleep +[1518-07-05 00:00] falls asleep +[1518-05-25 00:32] falls asleep +[1518-07-02 23:56] Guard #1873 begins shift +[1518-05-12 00:51] wakes up +[1518-11-06 23:57] Guard #601 begins shift +[1518-07-15 00:59] wakes up +[1518-03-14 00:50] falls asleep +[1518-02-14 00:01] Guard #2617 begins shift +[1518-04-22 00:55] wakes up +[1518-03-07 00:05] falls asleep +[1518-10-28 00:22] falls asleep +[1518-04-30 00:18] wakes up +[1518-03-04 00:42] wakes up +[1518-11-19 00:52] wakes up +[1518-08-23 00:35] falls asleep +[1518-10-13 00:59] wakes up +[1518-11-22 00:18] falls asleep +[1518-08-04 00:54] wakes up +[1518-09-20 00:04] falls asleep +[1518-11-12 00:37] falls asleep +[1518-07-01 00:58] wakes up +[1518-06-06 00:41] wakes up +[1518-05-01 00:00] Guard #191 begins shift +[1518-06-16 23:58] Guard #3187 begins shift +[1518-06-17 23:54] Guard #1873 begins shift +[1518-04-03 00:04] Guard #1069 begins shift +[1518-04-19 00:32] wakes up +[1518-05-30 00:25] falls asleep +[1518-05-19 00:00] falls asleep +[1518-09-13 00:32] wakes up +[1518-07-20 00:47] wakes up +[1518-05-18 00:15] falls asleep +[1518-10-20 23:58] Guard #191 begins shift +[1518-05-26 00:54] wakes up +[1518-04-09 00:30] falls asleep +[1518-06-22 23:58] Guard #1901 begins shift +[1518-05-07 00:21] wakes up +[1518-10-11 00:22] falls asleep +[1518-05-23 00:08] falls asleep +[1518-03-01 00:43] falls asleep +[1518-06-03 00:59] wakes up +[1518-09-07 00:04] Guard #2441 begins shift +[1518-11-07 23:46] Guard #599 begins shift +[1518-06-28 00:51] wakes up +[1518-09-17 23:48] Guard #2207 begins shift +[1518-08-21 00:29] wakes up +[1518-05-02 00:41] falls asleep +[1518-08-20 00:04] falls asleep +[1518-06-25 00:31] falls asleep +[1518-07-13 23:57] Guard #2617 begins shift +[1518-03-16 00:13] falls asleep +[1518-10-21 00:46] wakes up +[1518-07-17 00:03] falls asleep +[1518-09-11 23:58] Guard #1229 begins shift +[1518-09-18 00:54] wakes up +[1518-03-01 00:31] wakes up +[1518-11-13 00:32] wakes up +[1518-06-08 00:42] falls asleep +[1518-06-18 00:13] wakes up +[1518-09-10 00:16] falls asleep +[1518-11-15 00:01] Guard #2221 begins shift +[1518-07-13 00:18] falls asleep +[1518-08-15 00:23] wakes up +[1518-10-03 00:47] wakes up +[1518-03-19 23:58] Guard #601 begins shift +[1518-07-29 23:46] Guard #1789 begins shift +[1518-08-16 00:41] falls asleep +[1518-07-15 00:43] falls asleep +[1518-10-19 23:59] Guard #2617 begins shift +[1518-03-16 00:34] wakes up +[1518-08-24 00:45] wakes up +[1518-10-09 00:54] falls asleep +[1518-02-23 00:37] falls asleep +[1518-04-29 00:20] wakes up +[1518-02-21 00:00] Guard #3167 begins shift +[1518-08-25 00:57] wakes up +[1518-06-20 00:34] falls asleep +[1518-04-30 00:00] Guard #3041 begins shift +[1518-05-16 00:52] wakes up +[1518-02-24 00:35] wakes up +[1518-11-05 23:59] Guard #601 begins shift +[1518-11-22 00:43] wakes up +[1518-10-18 00:44] wakes up +[1518-07-17 00:38] falls asleep +[1518-09-02 00:02] falls asleep +[1518-07-01 00:55] falls asleep +[1518-11-13 00:44] falls asleep +[1518-08-28 23:56] Guard #1229 begins shift +[1518-10-03 00:46] falls asleep +[1518-07-30 23:59] Guard #2281 begins shift +[1518-06-02 23:47] Guard #2477 begins shift +[1518-07-27 00:52] wakes up +[1518-09-13 23:57] Guard #2477 begins shift +[1518-03-17 00:58] wakes up +[1518-10-07 00:52] wakes up +[1518-11-08 23:53] Guard #2617 begins shift +[1518-03-29 00:51] wakes up +[1518-04-02 00:39] wakes up +[1518-03-29 23:59] Guard #2281 begins shift +[1518-10-16 00:44] wakes up +[1518-07-26 00:53] wakes up +[1518-11-04 00:18] wakes up +[1518-10-10 00:56] wakes up +[1518-10-08 00:58] wakes up +[1518-09-15 00:00] Guard #1069 begins shift +[1518-11-17 00:26] falls asleep +[1518-06-16 00:54] wakes up +[1518-10-04 00:03] Guard #2617 begins shift +[1518-03-28 00:15] falls asleep +[1518-09-27 00:16] wakes up +[1518-11-02 00:00] Guard #1901 begins shift +[1518-08-01 23:53] Guard #1069 begins shift +[1518-10-11 00:52] falls asleep +[1518-04-09 00:03] Guard #3041 begins shift +[1518-06-07 00:50] wakes up +[1518-08-01 00:23] wakes up +[1518-02-14 00:53] falls asleep +[1518-05-20 00:44] wakes up +[1518-05-06 23:57] Guard #3187 begins shift +[1518-08-17 00:54] falls asleep +[1518-10-09 00:55] wakes up +[1518-03-27 00:25] wakes up +[1518-03-11 23:53] Guard #601 begins shift +[1518-05-05 00:40] wakes up +[1518-11-18 23:58] Guard #3041 begins shift +[1518-04-04 00:56] wakes up +[1518-08-18 00:34] wakes up +[1518-04-26 00:45] wakes up +[1518-03-18 23:57] Guard #3187 begins shift +[1518-10-13 00:00] Guard #2617 begins shift +[1518-03-18 00:15] falls asleep +[1518-03-13 00:44] falls asleep +[1518-04-28 00:06] falls asleep +[1518-04-12 00:01] Guard #191 begins shift +[1518-09-19 00:27] wakes up +[1518-10-24 23:59] Guard #1997 begins shift +[1518-08-27 00:31] wakes up +[1518-02-19 00:12] falls asleep +[1518-06-09 00:37] falls asleep +[1518-08-16 23:57] Guard #1789 begins shift +[1518-04-01 00:38] wakes up +[1518-05-07 23:51] Guard #1499 begins shift +[1518-08-03 00:52] wakes up +[1518-11-12 00:48] wakes up +[1518-04-21 23:54] Guard #2441 begins shift +[1518-05-18 23:49] Guard #1789 begins shift +[1518-03-11 00:44] wakes up +[1518-06-18 00:51] wakes up +[1518-04-23 23:57] Guard #191 begins shift +[1518-07-04 00:23] falls asleep +[1518-04-04 00:03] Guard #2213 begins shift +[1518-10-18 00:19] falls asleep +[1518-07-29 00:44] wakes up +[1518-02-16 00:21] falls asleep +[1518-05-12 00:08] falls asleep +[1518-08-19 00:00] Guard #2281 begins shift +[1518-06-08 00:03] Guard #1873 begins shift +[1518-05-23 00:57] falls asleep +[1518-09-03 00:26] wakes up +[1518-06-09 00:44] wakes up +[1518-03-22 00:28] falls asleep +[1518-11-23 00:45] wakes up +[1518-11-16 00:45] falls asleep +[1518-04-28 00:43] wakes up +[1518-06-18 00:29] falls asleep +[1518-07-22 00:04] Guard #2441 begins shift +[1518-06-13 00:05] falls asleep +[1518-08-01 00:03] Guard #2617 begins shift +[1518-03-11 00:52] falls asleep +[1518-03-11 00:27] wakes up +[1518-02-24 00:13] falls asleep +[1518-10-27 23:58] Guard #2477 begins shift +[1518-02-18 00:54] wakes up +[1518-10-02 00:48] wakes up +[1518-06-15 00:45] falls asleep +[1518-07-20 00:54] falls asleep +[1518-09-22 00:02] Guard #3041 begins shift +[1518-02-24 00:47] falls asleep +[1518-06-25 00:21] wakes up +[1518-11-22 00:04] Guard #2441 begins shift +[1518-06-16 00:52] falls asleep +[1518-05-23 00:09] wakes up +[1518-11-04 00:04] falls asleep +[1518-09-03 00:34] falls asleep +[1518-11-14 00:12] falls asleep +[1518-05-02 00:38] wakes up +[1518-09-05 00:26] falls asleep +[1518-11-09 00:46] falls asleep +[1518-03-21 00:25] falls asleep +[1518-06-18 00:42] wakes up +[1518-07-05 00:41] wakes up +[1518-07-05 23:58] Guard #2213 begins shift +[1518-03-25 00:58] wakes up +[1518-06-06 00:03] Guard #2207 begins shift +[1518-04-17 00:30] falls asleep +[1518-11-23 00:21] falls asleep +[1518-08-20 00:57] wakes up +[1518-03-08 00:46] falls asleep +[1518-06-29 00:55] falls asleep +[1518-02-17 00:54] falls asleep +[1518-07-28 00:29] falls asleep +[1518-07-13 00:37] wakes up +[1518-05-01 00:10] falls asleep +[1518-02-15 23:59] Guard #3041 begins shift +[1518-10-05 00:34] falls asleep +[1518-03-18 00:41] wakes up +[1518-03-02 00:55] wakes up +[1518-08-06 23:59] Guard #3167 begins shift +[1518-04-22 00:53] falls asleep +[1518-05-06 00:36] wakes up +[1518-06-18 00:46] falls asleep +[1518-05-23 00:49] wakes up +[1518-10-19 00:13] falls asleep +[1518-05-13 00:39] wakes up +[1518-04-29 00:56] wakes up +[1518-05-18 00:03] falls asleep +[1518-02-23 00:31] wakes up +[1518-08-30 23:56] Guard #2207 begins shift +[1518-08-18 00:04] Guard #1789 begins shift +[1518-10-21 00:17] falls asleep +[1518-05-25 00:52] wakes up +[1518-10-12 00:18] wakes up +[1518-04-03 00:41] falls asleep +[1518-02-26 00:24] wakes up +[1518-05-16 00:02] Guard #1789 begins shift +[1518-11-15 23:57] Guard #2213 begins shift +[1518-03-23 00:57] falls asleep +[1518-04-13 00:58] wakes up +[1518-02-17 00:58] wakes up +[1518-08-13 23:59] Guard #1031 begins shift +[1518-07-26 00:02] Guard #191 begins shift +[1518-03-11 00:42] falls asleep +[1518-10-15 00:50] wakes up +[1518-06-26 00:52] wakes up +[1518-04-22 00:47] wakes up +[1518-11-05 00:49] wakes up +[1518-07-03 00:51] wakes up +[1518-07-22 00:39] falls asleep +[1518-03-24 00:47] wakes up +[1518-10-28 00:31] wakes up +[1518-11-09 00:54] falls asleep +[1518-09-19 23:52] Guard #1607 begins shift +[1518-03-17 00:51] wakes up +[1518-09-10 00:56] wakes up +[1518-04-17 00:19] wakes up +[1518-11-23 00:00] Guard #1499 begins shift +[1518-04-22 00:03] falls asleep +[1518-05-21 00:34] wakes up +[1518-05-07 00:18] falls asleep +[1518-03-13 00:37] wakes up +[1518-06-04 00:54] falls asleep +[1518-02-22 00:35] wakes up +[1518-04-30 00:07] falls asleep +[1518-08-09 00:30] falls asleep +[1518-09-21 00:44] wakes up +[1518-04-29 00:24] falls asleep +[1518-08-24 00:08] falls asleep +[1518-09-21 00:06] wakes up +[1518-04-16 23:50] Guard #2281 begins shift +[1518-07-12 00:59] wakes up +[1518-10-03 00:03] Guard #1229 begins shift +[1518-06-12 23:49] Guard #1069 begins shift +[1518-07-26 00:44] falls asleep +[1518-07-25 00:58] wakes up +[1518-05-20 00:10] falls asleep +[1518-05-02 00:44] wakes up +[1518-09-29 00:58] wakes up +[1518-04-28 00:02] Guard #1901 begins shift +[1518-06-25 00:09] falls asleep +[1518-05-13 23:47] Guard #601 begins shift +[1518-02-15 00:25] wakes up +[1518-09-05 00:00] Guard #1607 begins shift +[1518-09-15 00:32] wakes up +[1518-05-10 23:56] Guard #1873 begins shift +[1518-08-28 00:39] falls asleep +[1518-10-27 00:07] falls asleep +[1518-09-22 00:50] wakes up +[1518-11-20 00:54] wakes up +[1518-07-10 00:59] wakes up +[1518-02-15 00:35] falls asleep +[1518-06-16 00:00] falls asleep +[1518-03-13 00:07] falls asleep +[1518-05-08 00:50] wakes up +[1518-09-08 00:58] wakes up +[1518-07-14 00:59] wakes up +[1518-04-10 00:39] falls asleep +[1518-04-21 00:34] falls asleep +[1518-04-15 00:25] falls asleep +[1518-05-19 00:59] wakes up +[1518-02-19 00:27] wakes up +[1518-10-02 00:04] Guard #599 begins shift +[1518-03-01 00:02] falls asleep +[1518-04-28 00:47] falls asleep +[1518-08-21 00:05] falls asleep +[1518-07-28 00:05] falls asleep +[1518-10-31 23:57] Guard #1031 begins shift +[1518-10-14 00:37] falls asleep +[1518-09-25 00:02] falls asleep +[1518-05-17 00:00] Guard #1229 begins shift +[1518-03-14 00:53] wakes up +[1518-07-15 00:55] falls asleep +[1518-03-30 00:37] wakes up +[1518-03-22 23:58] Guard #191 begins shift +[1518-03-16 00:42] falls asleep +[1518-11-02 00:49] wakes up +[1518-11-09 00:55] wakes up +[1518-08-16 00:30] falls asleep +[1518-10-24 00:37] falls asleep +[1518-11-12 00:26] falls asleep +[1518-09-13 00:58] wakes up +[1518-06-12 00:04] Guard #3041 begins shift +[1518-07-24 00:17] falls asleep +[1518-11-05 00:35] falls asleep +[1518-07-30 00:36] wakes up +[1518-09-30 00:58] wakes up +[1518-04-14 00:01] Guard #2213 begins shift +[1518-02-26 00:32] falls asleep +[1518-07-21 00:00] Guard #1997 begins shift +[1518-11-17 00:00] Guard #1499 begins shift +[1518-10-29 00:16] falls asleep +[1518-10-08 00:00] Guard #1873 begins shift +[1518-06-03 00:46] wakes up +[1518-06-14 23:56] Guard #1103 begins shift +[1518-06-06 00:49] falls asleep +[1518-08-03 00:31] falls asleep +[1518-10-13 00:36] falls asleep +[1518-02-13 00:25] wakes up +[1518-06-11 00:31] falls asleep +[1518-11-04 00:54] wakes up +[1518-05-09 00:47] falls asleep +[1518-08-27 00:52] falls asleep +[1518-09-16 00:47] wakes up +[1518-10-10 00:29] wakes up +[1518-02-26 00:16] falls asleep +[1518-11-10 00:38] falls asleep +[1518-05-27 00:00] Guard #1997 begins shift +[1518-06-07 00:21] wakes up +[1518-08-16 00:56] wakes up +[1518-06-04 00:57] wakes up +[1518-09-12 00:32] falls asleep +[1518-08-31 00:15] falls asleep +[1518-10-22 00:00] Guard #3187 begins shift +[1518-04-12 00:40] falls asleep +[1518-04-20 00:07] falls asleep +[1518-07-11 00:55] wakes up +[1518-07-09 00:01] falls asleep +[1518-03-31 00:40] falls asleep +[1518-05-12 00:55] falls asleep +[1518-11-14 00:56] wakes up +[1518-11-14 00:32] falls asleep +[1518-06-24 00:41] falls asleep +[1518-08-25 23:58] Guard #3041 begins shift +[1518-07-06 00:59] wakes up +[1518-03-05 00:02] Guard #1789 begins shift +[1518-04-08 00:24] falls asleep +[1518-05-23 00:00] Guard #2213 begins shift +[1518-07-25 00:10] falls asleep +[1518-11-02 00:12] falls asleep +[1518-09-07 00:09] falls asleep +[1518-04-16 00:50] wakes up +[1518-07-18 00:06] falls asleep +[1518-08-26 23:56] Guard #2617 begins shift +[1518-08-13 00:00] Guard #2477 begins shift +[1518-10-19 00:21] wakes up +[1518-09-27 00:41] falls asleep +[1518-04-09 00:55] wakes up +[1518-03-05 00:33] wakes up +[1518-10-08 00:51] falls asleep +[1518-09-04 00:30] falls asleep +[1518-09-23 00:15] wakes up +[1518-03-04 00:55] wakes up +[1518-07-10 00:04] Guard #1229 begins shift +[1518-05-30 23:50] Guard #1873 begins shift +[1518-10-08 00:24] falls asleep +[1518-11-12 00:34] wakes up +[1518-02-14 00:22] falls asleep +[1518-04-14 00:58] wakes up +[1518-05-14 00:49] falls asleep +[1518-08-28 00:53] wakes up +[1518-11-11 00:17] falls asleep +[1518-09-19 00:00] Guard #2213 begins shift +[1518-09-20 23:47] Guard #1873 begins shift +[1518-09-24 23:53] Guard #2477 begins shift +[1518-03-14 23:57] Guard #1103 begins shift +[1518-02-24 00:00] Guard #1069 begins shift +[1518-09-05 00:58] wakes up +[1518-03-02 00:03] Guard #1997 begins shift +[1518-04-17 00:41] wakes up +[1518-02-13 00:05] falls asleep +[1518-05-26 00:02] Guard #2441 begins shift +[1518-05-20 00:56] wakes up +[1518-09-07 23:56] Guard #1069 begins shift +[1518-08-11 00:14] falls asleep +[1518-09-19 00:23] falls asleep +[1518-11-09 00:03] falls asleep +[1518-11-10 00:58] wakes up +[1518-04-06 00:13] falls asleep +[1518-08-09 23:53] Guard #1229 begins shift +[1518-10-26 00:52] wakes up +[1518-11-17 00:51] wakes up +[1518-06-27 23:47] Guard #1997 begins shift +[1518-05-22 00:31] falls asleep +[1518-06-15 00:22] falls asleep +[1518-02-25 00:33] falls asleep +[1518-05-31 00:03] falls asleep +[1518-03-25 23:59] Guard #1789 begins shift +[1518-09-28 00:25] falls asleep +[1518-03-08 00:55] wakes up +[1518-05-12 00:26] wakes up +[1518-06-02 00:02] falls asleep +[1518-08-10 00:39] falls asleep +[1518-02-15 00:45] wakes up +[1518-08-26 00:46] wakes up +[1518-06-12 00:41] wakes up +[1518-08-21 00:43] wakes up +[1518-11-09 23:49] Guard #601 begins shift +[1518-06-28 00:01] falls asleep +[1518-09-02 00:45] wakes up +[1518-03-09 00:44] falls asleep +[1518-03-03 00:16] wakes up +[1518-04-29 00:41] wakes up +[1518-04-01 00:00] Guard #2477 begins shift +[1518-03-08 00:01] Guard #1901 begins shift +[1518-02-15 00:01] falls asleep +[1518-03-12 00:00] falls asleep +[1518-06-08 00:49] wakes up +[1518-02-25 23:58] Guard #2441 begins shift +[1518-06-27 00:00] Guard #1499 begins shift +[1518-04-13 00:45] wakes up +[1518-07-31 00:52] falls asleep +[1518-05-07 00:54] wakes up +[1518-07-28 00:26] wakes up +[1518-03-18 00:55] wakes up +[1518-07-11 00:19] falls asleep +[1518-10-10 00:32] falls asleep +[1518-07-01 00:47] wakes up +[1518-04-26 00:54] falls asleep +[1518-06-02 00:08] wakes up +[1518-10-17 00:39] wakes up +[1518-02-13 00:52] wakes up +[1518-07-14 00:47] wakes up +[1518-06-01 00:43] wakes up +[1518-09-21 00:11] falls asleep +[1518-05-28 00:19] falls asleep +[1518-05-04 00:57] wakes up +[1518-05-06 00:43] wakes up +[1518-08-05 23:59] Guard #2281 begins shift +[1518-09-27 23:59] Guard #1103 begins shift +[1518-10-10 00:03] falls asleep +[1518-09-23 00:00] Guard #1873 begins shift +[1518-09-09 00:53] wakes up +[1518-04-26 23:57] Guard #191 begins shift +[1518-08-05 00:04] falls asleep +[1518-04-17 00:55] wakes up +[1518-05-17 23:48] Guard #1901 begins shift +[1518-05-11 00:45] wakes up +[1518-09-28 23:50] Guard #3041 begins shift +[1518-03-09 00:01] Guard #1069 begins shift +[1518-07-02 00:35] falls asleep +[1518-10-14 00:02] Guard #2617 begins shift +[1518-05-22 00:02] Guard #601 begins shift +[1518-10-15 23:53] Guard #1607 begins shift +[1518-04-08 00:00] Guard #601 begins shift +[1518-05-09 00:04] Guard #191 begins shift +[1518-04-25 00:19] falls asleep +[1518-08-05 00:46] wakes up +[1518-03-25 00:29] falls asleep +[1518-02-17 00:45] wakes up +[1518-03-23 23:57] Guard #1499 begins shift +[1518-08-10 00:53] wakes up +[1518-05-20 00:52] falls asleep +[1518-06-14 00:25] wakes up +[1518-11-10 00:50] wakes up +[1518-09-03 00:02] falls asleep +[1518-04-06 00:00] Guard #2207 begins shift +[1518-04-18 23:59] Guard #1901 begins shift +[1518-06-25 00:44] wakes up +[1518-06-10 23:58] Guard #2477 begins shift +[1518-06-08 00:55] wakes up +[1518-03-31 00:49] wakes up +[1518-04-14 00:19] falls asleep +[1518-06-26 00:24] wakes up +[1518-10-23 23:56] Guard #1789 begins shift +[1518-03-17 00:00] Guard #3187 begins shift +[1518-03-27 00:13] falls asleep +[1518-10-03 00:51] falls asleep +[1518-09-28 00:55] wakes up +[1518-07-22 00:55] falls asleep +[1518-03-09 00:41] wakes up +[1518-03-06 00:21] falls asleep +[1518-05-29 00:37] wakes up +[1518-05-08 00:04] falls asleep +[1518-05-24 00:58] wakes up +[1518-10-02 00:30] falls asleep +[1518-07-15 00:52] wakes up +[1518-06-08 00:52] falls asleep +[1518-09-29 23:58] Guard #2617 begins shift +[1518-09-16 00:46] falls asleep +[1518-07-08 00:50] wakes up +[1518-03-05 23:59] Guard #1069 begins shift +[1518-07-14 23:58] Guard #2213 begins shift +[1518-05-01 00:51] wakes up +[1518-09-02 23:54] Guard #1901 begins shift +[1518-08-12 00:55] wakes up +[1518-06-06 00:52] wakes up +[1518-08-17 00:46] wakes up +[1518-06-05 00:00] Guard #2617 begins shift +[1518-02-28 00:12] falls asleep +[1518-10-09 00:04] Guard #1901 begins shift +[1518-05-17 00:59] wakes up +[1518-08-23 00:01] Guard #3041 begins shift +[1518-06-04 00:09] falls asleep +[1518-10-29 00:52] wakes up +[1518-07-13 00:00] Guard #1789 begins shift +[1518-08-10 00:25] wakes up +[1518-03-03 00:13] falls asleep +[1518-04-21 00:02] Guard #2441 begins shift +[1518-06-05 00:56] wakes up +[1518-02-26 00:38] falls asleep +[1518-06-01 23:53] Guard #1873 begins shift +[1518-11-08 00:45] wakes up +[1518-03-03 23:57] Guard #2281 begins shift +[1518-09-21 00:04] falls asleep +[1518-11-12 23:54] Guard #191 begins shift +[1518-03-12 00:39] wakes up +[1518-09-26 00:01] Guard #2477 begins shift +[1518-10-04 00:58] wakes up +[1518-08-02 00:38] wakes up +[1518-04-29 00:13] falls asleep +[1518-03-11 00:04] falls asleep +[1518-07-01 23:54] Guard #1069 begins shift +[1518-10-12 00:13] falls asleep +[1518-03-07 00:55] wakes up +[1518-10-14 23:58] Guard #2213 begins shift +[1518-06-25 00:51] falls asleep +[1518-04-10 00:40] wakes up +[1518-03-29 00:42] falls asleep +[1518-10-23 00:48] wakes up +[1518-02-14 00:29] wakes up +[1518-02-17 00:04] Guard #1873 begins shift +[1518-04-15 00:34] wakes up +[1518-05-12 00:03] Guard #3041 begins shift +[1518-09-15 00:17] falls asleep +[1518-10-17 00:50] wakes up +[1518-10-16 00:40] falls asleep +[1518-06-10 00:54] falls asleep +[1518-04-07 00:55] falls asleep +[1518-10-13 00:49] wakes up +[1518-05-06 00:46] falls asleep +[1518-09-14 00:51] wakes up +[1518-11-18 00:52] wakes up +[1518-08-19 23:47] Guard #1607 begins shift +[1518-05-07 00:53] falls asleep +[1518-03-15 00:33] falls asleep +[1518-09-24 00:39] falls asleep +[1518-07-19 00:53] wakes up +[1518-11-05 00:11] falls asleep +[1518-08-11 00:19] wakes up +[1518-08-29 00:53] wakes up +[1518-10-20 00:30] falls asleep +[1518-02-24 23:59] Guard #2213 begins shift +[1518-03-03 00:04] Guard #2281 begins shift +[1518-11-05 00:20] wakes up +[1518-02-14 00:50] wakes up +[1518-08-15 00:20] falls asleep +[1518-09-29 00:01] falls asleep +[1518-05-10 00:48] wakes up +[1518-07-07 00:04] Guard #3167 begins shift +[1518-02-26 23:57] Guard #2441 begins shift +[1518-11-08 00:14] falls asleep +[1518-06-15 23:51] Guard #1499 begins shift +[1518-05-20 00:04] Guard #3041 begins shift +[1518-09-30 00:46] falls asleep +[1518-11-07 00:54] wakes up +[1518-05-15 00:04] falls asleep +[1518-06-26 00:28] falls asleep +[1518-09-23 00:53] wakes up +[1518-03-12 23:56] Guard #1607 begins shift +[1518-06-23 00:09] falls asleep +[1518-10-16 00:16] falls asleep +[1518-08-08 00:44] falls asleep +[1518-11-20 00:08] falls asleep +[1518-09-13 00:25] falls asleep +[1518-09-09 00:58] wakes up +[1518-09-14 00:49] falls asleep +[1518-05-14 00:41] wakes up +[1518-09-29 00:41] wakes up +[1518-04-25 23:46] Guard #1997 begins shift +[1518-05-31 00:53] wakes up +[1518-02-18 00:31] falls asleep +[1518-03-22 00:43] wakes up +[1518-11-03 23:50] Guard #1901 begins shift +[1518-03-24 00:55] wakes up +[1518-10-14 00:56] falls asleep +[1518-05-27 00:12] falls asleep +[1518-06-30 00:02] Guard #2441 begins shift +[1518-06-21 00:07] falls asleep +[1518-10-09 23:54] Guard #1873 begins shift +[1518-08-17 00:58] wakes up +[1518-07-18 00:04] Guard #1997 begins shift +[1518-08-27 00:21] falls asleep +[1518-05-05 23:59] Guard #1789 begins shift +[1518-06-18 00:00] falls asleep +[1518-03-21 00:47] wakes up +[1518-11-10 00:01] falls asleep +[1518-06-23 00:47] wakes up +[1518-10-13 00:29] wakes up +[1518-07-11 23:57] Guard #1069 begins shift +[1518-10-25 00:20] wakes up +[1518-10-23 00:10] falls asleep +[1518-10-12 00:01] Guard #1997 begins shift +[1518-07-31 00:19] falls asleep +[1518-05-02 00:54] falls asleep +[1518-10-31 00:00] Guard #2441 begins shift +[1518-09-24 00:56] wakes up +[1518-10-07 00:01] Guard #3041 begins shift +[1518-10-24 00:59] wakes up +[1518-06-20 00:02] Guard #599 begins shift +[1518-03-23 00:58] wakes up +[1518-06-10 00:49] wakes up +[1518-04-01 00:25] wakes up +[1518-07-02 00:50] wakes up +[1518-04-24 00:50] falls asleep +[1518-10-17 00:04] Guard #1499 begins shift +[1518-08-20 00:42] falls asleep +[1518-07-28 00:50] wakes up +[1518-02-14 00:47] falls asleep +[1518-02-16 00:47] wakes up +[1518-10-19 00:03] Guard #1607 begins shift +[1518-08-27 23:59] Guard #1229 begins shift +[1518-03-18 00:54] falls asleep +[1518-02-28 00:51] wakes up +[1518-09-23 00:30] wakes up +[1518-04-06 00:47] wakes up +[1518-06-03 23:56] Guard #601 begins shift +[1518-06-21 00:00] Guard #3041 begins shift +[1518-07-24 00:54] falls asleep +[1518-10-26 00:31] falls asleep +[1518-09-16 23:52] Guard #601 begins shift +[1518-06-01 00:14] falls asleep +[1518-10-30 00:47] wakes up +[1518-07-06 00:21] falls asleep +[1518-03-14 00:07] falls asleep +[1518-10-22 00:42] wakes up +[1518-05-30 00:57] wakes up +[1518-08-26 00:50] falls asleep +[1518-03-01 00:56] wakes up +[1518-05-16 00:49] falls asleep +[1518-06-18 23:58] Guard #1103 begins shift +[1518-06-19 00:38] wakes up +[1518-05-13 00:30] falls asleep +[1518-07-25 00:48] falls asleep +[1518-10-11 00:59] wakes up +[1518-03-23 00:45] wakes up +[1518-07-21 00:11] falls asleep +[1518-08-11 23:58] Guard #2207 begins shift +[1518-08-04 00:42] falls asleep +[1518-07-16 23:48] Guard #1499 begins shift +[1518-08-18 00:24] falls asleep +[1518-07-26 23:56] Guard #1499 begins shift +[1518-06-30 00:55] falls asleep +[1518-05-12 00:59] wakes up +[1518-02-27 00:20] falls asleep +[1518-07-21 00:26] wakes up +[1518-04-28 00:59] wakes up +[1518-06-22 00:10] falls asleep +[1518-10-13 00:54] falls asleep +[1518-10-17 00:43] falls asleep +[1518-06-30 00:22] falls asleep +[1518-05-14 00:01] falls asleep +[1518-03-25 00:04] falls asleep +[1518-03-04 00:32] falls asleep +[1518-10-30 00:19] falls asleep +[1518-07-31 00:57] wakes up +[1518-07-28 23:58] Guard #1997 begins shift +[1518-07-19 00:00] Guard #3041 begins shift +[1518-08-26 00:34] falls asleep +[1518-04-01 00:37] falls asleep +[1518-09-17 00:02] falls asleep +[1518-03-11 00:56] wakes up +[1518-03-10 00:04] Guard #1069 begins shift +[1518-06-10 00:00] Guard #1229 begins shift +[1518-04-16 00:23] falls asleep +[1518-03-09 00:59] wakes up +[1518-03-26 00:45] wakes up +[1518-09-04 00:45] wakes up +[1518-09-27 00:01] Guard #1069 begins shift +[1518-04-13 00:16] falls asleep +[1518-09-03 23:58] Guard #2617 begins shift +[1518-09-23 00:38] falls asleep +[1518-09-09 00:56] falls asleep +[1518-04-05 00:28] wakes up +[1518-11-10 00:57] falls asleep +[1518-07-25 00:34] wakes up +[1518-05-27 00:34] wakes up +[1518-06-29 00:40] falls asleep +[1518-09-09 00:03] Guard #1901 begins shift +[1518-03-04 00:53] falls asleep +[1518-06-24 00:55] wakes up +[1518-02-23 00:53] wakes up +[1518-07-29 00:58] wakes up +[1518-10-12 00:59] wakes up +[1518-06-07 00:00] Guard #2213 begins shift +[1518-10-26 00:01] Guard #1901 begins shift +[1518-05-24 23:57] Guard #2281 begins shift +[1518-09-17 00:47] wakes up +[1518-06-26 00:21] falls asleep +[1518-09-01 00:48] wakes up +[1518-03-02 00:12] falls asleep +[1518-05-04 23:56] Guard #1789 begins shift +[1518-05-22 00:41] wakes up +[1518-04-19 00:51] wakes up +[1518-08-21 00:35] falls asleep +[1518-03-13 00:13] wakes up +[1518-04-13 00:04] Guard #2441 begins shift +[1518-04-01 00:55] wakes up +[1518-09-19 00:57] wakes up +[1518-03-06 23:46] Guard #1997 begins shift +[1518-05-09 00:55] wakes up +[1518-03-17 23:57] Guard #2207 begins shift +[1518-06-07 00:06] falls asleep +[1518-11-16 00:57] wakes up +[1518-05-24 00:04] Guard #2477 begins shift +[1518-05-26 00:23] falls asleep +[1518-10-06 00:38] falls asleep +[1518-09-04 00:57] wakes up +[1518-05-10 00:46] falls asleep +[1518-06-07 00:45] falls asleep +[1518-06-21 00:58] wakes up +[1518-08-22 00:35] falls asleep +[1518-04-13 00:54] falls asleep +[1518-04-24 00:57] wakes up +[1518-07-22 00:57] wakes up +[1518-10-16 00:02] falls asleep +[1518-03-13 23:57] Guard #1069 begins shift +[1518-07-04 00:56] wakes up +[1518-02-22 00:39] falls asleep +[1518-11-09 00:35] wakes up +[1518-03-21 00:00] Guard #1873 begins shift +[1518-02-22 23:59] Guard #1901 begins shift +[1518-10-09 00:48] wakes up +[1518-05-24 00:20] falls asleep +[1518-10-20 00:58] wakes up +[1518-03-20 00:30] wakes up +[1518-07-22 00:52] wakes up +[1518-09-23 00:11] falls asleep +[1518-06-10 00:57] wakes up +[1518-04-27 00:46] falls asleep +[1518-07-10 00:57] falls asleep +[1518-05-04 00:01] falls asleep +[1518-03-29 00:38] wakes up +[1518-03-06 00:39] wakes up +[1518-07-03 00:38] wakes up +[1518-04-16 00:01] Guard #1789 begins shift +[1518-07-01 00:01] Guard #1607 begins shift +[1518-05-14 00:53] wakes up +[1518-07-02 00:25] wakes up +[1518-07-22 23:56] Guard #1499 begins shift +[1518-08-10 00:04] falls asleep +[1518-02-17 00:21] falls asleep +[1518-06-30 00:47] wakes up +[1518-10-11 00:03] Guard #2213 begins shift +[1518-05-06 00:27] falls asleep +[1518-05-21 00:32] falls asleep +[1518-05-18 00:06] wakes up +[1518-09-23 00:28] falls asleep +[1518-04-19 23:59] Guard #1997 begins shift +[1518-10-05 00:58] wakes up +[1518-10-22 00:18] falls asleep +[1518-02-22 00:00] Guard #191 begins shift +[1518-04-10 00:04] Guard #2281 begins shift +[1518-08-25 00:00] Guard #2207 begins shift +[1518-09-29 00:50] falls asleep +[1518-06-08 23:58] Guard #191 begins shift +[1518-06-02 00:40] falls asleep +[1518-05-01 23:58] Guard #2441 begins shift +[1518-02-14 00:56] wakes up +[1518-04-19 00:11] falls asleep +[1518-05-28 00:40] wakes up +[1518-03-28 00:45] wakes up +[1518-05-03 23:48] Guard #1103 begins shift +[1518-04-04 23:47] Guard #1873 begins shift +[1518-09-09 00:52] falls asleep +[1518-11-11 00:42] wakes up +[1518-10-31 00:25] falls asleep +[1518-08-06 00:16] falls asleep +[1518-04-29 00:47] falls asleep +[1518-06-15 00:35] wakes up +[1518-08-27 00:56] wakes up +[1518-03-26 23:59] Guard #3041 begins shift +[1518-05-30 00:01] Guard #1607 begins shift +[1518-06-01 00:00] Guard #2617 begins shift +[1518-04-17 23:58] Guard #1873 begins shift +[1518-11-17 23:59] Guard #599 begins shift +[1518-11-11 23:59] Guard #1069 begins shift +[1518-07-24 00:22] wakes up +[1518-08-30 00:34] wakes up +[1518-05-27 23:59] Guard #3041 begins shift +[1518-08-11 00:59] wakes up +[1518-11-02 23:57] Guard #2213 begins shift +[1518-03-16 00:03] Guard #3041 begins shift +[1518-07-21 00:40] falls asleep +[1518-06-06 00:30] falls asleep +[1518-11-13 23:57] Guard #2207 begins shift +[1518-10-25 00:15] falls asleep +[1518-02-17 23:56] Guard #2281 begins shift +[1518-03-27 23:57] Guard #1901 begins shift +[1518-11-21 00:33] wakes up +[1518-04-01 00:21] falls asleep +[1518-10-06 00:58] wakes up +[1518-03-16 00:32] falls asleep +[1518-08-09 00:58] wakes up +[1518-05-18 00:53] wakes up +[1518-08-06 00:37] wakes up +[1518-11-06 00:40] wakes up +[1518-07-29 00:52] falls asleep +[1518-05-11 00:30] falls asleep +[1518-05-21 00:03] Guard #1229 begins shift +[1518-08-04 23:53] Guard #1901 begins shift +[1518-02-19 23:56] Guard #3167 begins shift +[1518-09-27 00:44] wakes up +[1518-08-08 00:04] Guard #191 begins shift +[1518-08-20 23:52] Guard #1997 begins shift +[1518-02-27 00:58] wakes up +[1518-07-04 00:02] Guard #1069 begins shift +[1518-05-02 00:55] wakes up +[1518-02-12 23:50] Guard #1789 begins shift +[1518-09-12 23:58] Guard #2213 begins shift +[1518-06-12 00:32] falls asleep +[1518-04-08 00:46] wakes up +[1518-07-05 00:05] wakes up +[1518-03-25 00:21] wakes up +[1518-11-19 00:38] falls asleep +[1518-11-10 23:57] Guard #1997 begins shift +[1518-06-03 00:50] falls asleep +[1518-05-29 00:01] Guard #2441 begins shift +[1518-07-24 00:57] wakes up +[1518-09-13 00:46] falls asleep +[1518-09-06 00:10] falls asleep +[1518-07-19 00:33] falls asleep +[1518-06-13 00:42] wakes up +[1518-07-04 00:32] falls asleep +[1518-03-15 00:58] wakes up +[1518-04-26 00:56] wakes up +[1518-04-02 00:25] falls asleep +[1518-06-17 00:44] wakes up +[1518-09-10 23:59] Guard #3167 begins shift +[1518-03-13 00:54] wakes up +[1518-07-05 00:25] falls asleep +[1518-10-04 23:57] Guard #1901 begins shift +[1518-11-04 23:57] Guard #2281 begins shift +[1518-08-03 23:59] Guard #1997 begins shift +[1518-08-13 00:47] falls asleep +[1518-09-12 00:06] falls asleep +[1518-03-30 00:35] falls asleep +[1518-07-04 00:26] wakes up +[1518-10-01 00:02] Guard #2281 begins shift +[1518-03-24 00:51] falls asleep +[1518-08-11 00:48] falls asleep +[1518-03-20 00:11] falls asleep +[1518-07-10 00:48] wakes up +[1518-09-25 00:33] wakes up +[1518-10-25 00:54] wakes up +[1518-08-09 00:51] falls asleep +[1518-02-28 23:50] Guard #1607 begins shift +[1518-06-22 00:17] wakes up +[1518-08-29 23:47] Guard #2477 begins shift +[1518-04-22 23:56] Guard #1997 begins shift +[1518-09-27 00:07] falls asleep +[1518-07-09 00:28] wakes up +[1518-09-05 23:57] Guard #1873 begins shift +[1518-06-03 00:04] falls asleep +[1518-06-04 00:29] wakes up +[1518-11-18 00:07] falls asleep +[1518-10-16 00:17] wakes up +[1518-08-28 00:23] falls asleep +[1518-05-02 00:35] falls asleep +[1518-05-27 00:51] wakes up +[1518-05-12 23:59] Guard #2441 begins shift +[1518-09-26 00:24] falls asleep +[1518-07-14 00:23] falls asleep +[1518-10-05 23:56] Guard #2207 begins shift +[1518-09-18 00:05] falls asleep +[1518-03-05 00:19] falls asleep +[1518-02-24 00:56] wakes up +[1518-10-17 23:56] Guard #1789 begins shift +[1518-09-01 00:00] Guard #1103 begins shift +[1518-10-13 00:10] falls asleep +[1518-03-26 00:41] falls asleep +[1518-07-03 00:20] falls asleep +[1518-02-26 00:34] wakes up +[1518-06-20 00:55] wakes up +[1518-09-10 00:02] Guard #191 begins shift +[1518-07-25 00:01] Guard #1229 begins shift +[1518-06-15 00:59] wakes up +[1518-08-21 23:58] Guard #2477 begins shift +[1518-04-07 00:02] Guard #1229 begins shift +[1518-04-03 00:55] wakes up +[1518-06-13 23:59] Guard #1069 begins shift +[1518-03-13 00:26] falls asleep +[1518-10-22 23:59] Guard #2617 begins shift +[1518-08-28 00:33] wakes up +[1518-07-17 00:34] wakes up +[1518-03-03 00:41] falls asleep +[1518-09-03 00:14] falls asleep +[1518-08-13 00:57] wakes up +[1518-10-15 00:48] falls asleep +[1518-04-01 23:58] Guard #1789 begins shift +[1518-11-14 00:28] wakes up +[1518-06-24 00:02] Guard #1499 begins shift +[1518-08-02 00:04] falls asleep +[1518-10-16 00:12] wakes up +[1518-05-23 00:58] wakes up +[1518-06-27 00:21] falls asleep +[1518-10-27 00:00] Guard #1901 begins shift +[1518-09-01 00:35] falls asleep +[1518-06-24 23:58] Guard #2213 begins shift +[1518-11-03 00:53] wakes up +[1518-05-29 00:07] falls asleep +[1518-04-25 00:54] wakes up +[1518-04-11 00:50] wakes up +[1518-03-28 23:59] Guard #3041 begins shift +[1518-03-23 00:15] falls asleep +[1518-04-23 00:14] falls asleep +[1518-07-27 23:47] Guard #2617 begins shift +[1518-02-23 00:22] falls asleep +[1518-04-26 00:01] falls asleep +[1518-04-07 00:59] wakes up \ No newline at end of file diff --git a/2018/4/main.rb b/2018/4/main.rb new file mode 100644 index 0000000..ec30d1a --- /dev/null +++ b/2018/4/main.rb @@ -0,0 +1,88 @@ +require 'pry' + +events = [] + +guards = {} + +File.open("input", "r") do |f| + f.each_line do |line| + events.push ({ + date: line[/\d{4}-\d{2}-\d{2} \d{2}:\d{2}/], + type: (line.end_with?("shift\n") ? :begins_shift : (line.end_with?("asleep\n") ? :falls_asleep : :wakes_up)), + id: line[/#\d+/].to_s[1..-1].to_i + }) + end +end + +events.sort_by! do |event| + event[:date] +end + +current_guard = 0 +begin_minute = 0 + +events.each do |event| + if event[:type] == :begins_shift + if guards[event[:id]].nil? + guards[event[:id]] = Array.new(60){0} + end + + current_guard = event[:id] + elsif event[:type] == :falls_asleep + begin_minute = event[:date][-2..-1].to_i + else + (event[:date][-2..-1].to_i - begin_minute).times do |minute| + guards[current_guard][begin_minute + minute] += 1 + end + end +end + +# Strategy 1 + +sleepiest_guard = 0 +longest_time = 0 + +guards.each do |id, counts| + time = counts.inject(:+) + if time > longest_time + longest_time = time + sleepiest_guard = id + end +end + +sleepiest_minute = 0 +max_count = 0 + +guards[sleepiest_guard].each_with_index do |count, index| + if count > max_count + max_count = count + sleepiest_minute = index + end +end + +puts sleepiest_minute * sleepiest_guard + +# Strategy 2 + +guard = 0 +minute = 0 +count = 0 + +guards.each do |id, counts| + max_count = 0 + max_index = 0 + counts.each_with_index do |count_, index| + if count_ > max_count + max_count = count_ + max_index = index + end + end + + if max_count > count + guard = id + minute = max_index + count = max_count + end +end + +puts guard * minute \ No newline at end of file diff --git a/2018/5/input b/2018/5/input new file mode 100644 index 0000000..c1bd474 --- /dev/null +++ b/2018/5/input @@ -0,0 +1 @@ +JjDdoODgGdNnIiTtJjFfnsSNsVUaAugGpPLAalvVHRrhvhoOZzQqHLhjJSsOoJjSaAsrqkBbKQRtTHlSqQeEioOICcUuHmMhPVvJjpJjDdhHUuSLllswWSLsJjFxXbBVvaAfuUoaFPpPpWwZzfAOrKkRxXnNqIJjKkiJCcjVvrRTIHhNnipPWwvVtLlBbMmrReEAaQwWlLSLldjgAattTTGZzJqUnNVvuQlLDsEDdLlzuWwUZDdCceFRrNpPnRrfFGLlgXWwxiAaILkKDYydlYqQytdDTtNnMFCcBbTQqtfsSmTaAyCcYhSsGgkDgBbfFGdKPpmMjuUJHfkuYyUXnNxDdyYlLOoQqmMuUuUPpYrRSrRnEeNOosyYSosSNMmnOOojJsFfYyEuUhMmTtzZQLhHFflmMkKJBMmbDdjoPpxXLwWlBbOQhHIiLlXxqqxXHjoOmMJdlLYyAariqQITtRHhoODiIzZqZzxXFfQlQOoqLtpPpeEPNLlncldDLCTIieEdZzoaAOWwIihHBbhHyIiIiYVvRrxXqQiIQDzZdqtTLlPccCCpPpHhWwiYyoOIBbVfFfhHFvWoYyfpPaAFbwWPTDdtrRpDGfXDdxFQqtTxXfFgxEZzZzeQqBbZzXWBbwdzZByYAuUgGaTKkcCtnNOlkKxXLFrRMmUiIFEefcUiIuCgGOoIioUujeEIiJjxXiIyYGrRyYoOJjgeRrEEeEelLKkbBzBbZJFTtfbBAkKqQASsGgaFOoIipqtTQPfxFfTrRaABYOYZzyoymMMmbAfzLKkEeCcxXlXxjpPeEJVvzZZmMIihHoOFsSamRrMhHBqQHhBPpbbBtTFAantTNnNfoObsqQTtSsyRXxrYSsSBrRHhRrAabPILlilPmBbZFfkHhuUTRrXxtKxXhHzMdDHLkeEfFKlPwFeEfWpDdOohoQqnNOpWwTNnPpoOtLyYPpTeEuUtzTrRtZBbeEBbIoeFfLYuUylOoEfFySsdDYOViIvisSmDdiINtdDWwTLUutTlPnNhyYHXxkKbBvVpJjqdDQnpPwWqQAaFgFfGDdecVvXIiGgzZxCGgZgGzWwqQqQwWyYnNmnNMtTUEeuEIVUoOooOzsHhCcSPpZHhOjNnYyOPpoGgUuJujaAGgXxJifRrFInNUuisSxXIKNxXnkPpTQqoBbOtuUdDgGrRbBgGUuIDdhHiHcHLlhCCcWhHeNrRiIHHhhngGEGgNnnFfNKkAacCUuPpMLlmcCwdRrerjJVvREDPpaEeuUAnNhNnQGJrRjgjJBwWbqfFGgWwaqQAPpPdDpPMaAmGaAyYcCgkKxnNkKPpsvNnVNnyfRrFYzZEehHSmEeXDdxCpEeHhPcoOFiIqQOorLlPqQYypRGgptTVvmAaMCcyYYyrRkVvTtOvMmVoaWwAKZzhHqQEpPslLqQSsSFfGgpwWXoOxGgPCYiIVvybNnyYxXqkKQBYPpyqQcTigGIsSisuUwWoOSIXxWwiIdlLWfFZwWznNwiGSsgKkVvkRrvGgVIieEbBwoOWxXKImMDgGtjJGwWgChHclmsSMLMJjmSXxsAafFtTLiIeEGgPfFmMpYynNAaNnoOPphHpPjJyqQwWPrRpgGYZzyNnCMmeESsXxbBciOoqQLlfTtFgGNnqQtTPXIHhixpEeRryFDdfCcyFfYYkKWqQwhHMrRmJjiZzKkIbLlmIugGzZUiMyyYPuLsoOsSzZXxzZSfmMPpeENQqnlHhLscbBCGBfFbgJjSQqYyqQklLKpPneEpPNUuPptxBbXTjJFvhHfFpcyYPPpVEevFAaTwPBbwWZzpGgaWwwWHXxhAWtfiILlxXJKkjvVpCJjPpvVjkpPJjiIgGNnYysSKJGgJjXxYrJjfFRyxfKkFqQwtJjwWTQhirRIHoOqveEVRvVrvFuUfgcCGZzIikKAaDdDbPpPpBDdolLYyMyYmeuUdsSDEbBRrhHOEUucCfuvVDdiIUFeMmSIisrZzeEgGRdYyVORrowJjdDjJknRrNpzZnNyYPKVQqvdDJcCGKkWwIrRigvVTtcwuUWzZyoOieyYEIYpPFKkfiIuUEeZiINGgZzEEeVvTYypPQAapPqIiaAJjDUudlQqLwWtHqQZzWwFfqJjRoOFfrQLbBlDIidnNiIhyYoyGgYJKkjJjOeyIgGilVoOlLCgGEecvLvQqVgsAapuEedDUlLOorRsSEexXyYHGgoOhFoPpOpPnBFfbeENcECcdDeUxxTtXXuNnuUWwTJSsBbIdDijnNrRnPpJrRHhlLTnsSDdNLbBqQoOlsNTtNndBbDXxVvmMnSGNzaAZuDdUEeBbsxXNnSjJZuUzkKvViIcCWdbBDZYyzdDIrRhHLEedDlFjJuURrfOoNniCcIdDiPpXxFfwkFfSfFsKnRrwWNbPHhpBkuSsUKbBRcCQFfiIqsSjJGgkKHhDdDddsScCIiXxawWAYAaylhHLDUwNnBbWNqQvVvCcVneEubBTtePpIicCEhGgRrfFgGsVVUuvPLEeNnlpPpoOvnNNnSHChHcdDDQqUubgGBdxXzZwWRhDWwKkdyYXdDxVvHxXZzxXwLlsSsSZzpnNPqWwQgGQqsSELlezzZCuhQjrRJqEEeekxKkXKHtnrsPpxXeAaqQvVVvEShzZKkZzHSsRHhYvVyigxXFlLftTKTtYyONnVvokWuUwLlhHYnNgGPoyYvVVvqQhHOpxLgGlsSXKjJkZwWqjJfMmzZyYmMFzcCyuUYTEetEGgrRZCcRrzKJjTtZzqlSsLQJjDdTtCaAMmCccqQEeoOrsgGSRQqlLdFfYNnyDFrvVNnVvrRRDTtqQdFfORrfFoXsSsSxPpVItTicCnNVvgDkKdGDLlbrwWRBLlShEeHWwtTxXRrXxCyYnGgNcsVvBbhGSsgDNJjnEkKeuUnLlNcKTLlrHhRtiIGgNyYCcbBnGzZEegqQmJjuhsSHUMsSsCKkcSjJaFfEeAaAEesSJqQVvjMuABbYTthHWwhHyaUwWDdTtGgnNRrDqQdNwVKkvwWOogHhGWntwztTLlbmTHhtMBZgGWdqgGQGgCcoKkOsSvVraEeDgGeEMmdGEAaegAJjRCrhHeEZxXLlzvdDVRZziIciITtPHQPpqRrhZzpPpLlFfDoMmNeEyaAYnsSOjJjJyYyYWwlIiPZzZzXxpfRrFzZmjNnnNuUbBgGJMLqQeEPvVTtJrRrnNYzZyocCTtORjrsSRyXxYtTuUPtTtTohFfyYHOYLAalfWTwWtDsSvVdRrAawWdmwWaAPPpbOoBmNnMpIvVxuUXvVNnDiIdXxAaKRrJjhHgGkHnOoFfNhuUVvyYtTazgsJhHjATtbBafFZzIifFfjgGuUJnNfmMFXxcFfCFpmWUuwMzZiIhwyYQqWBbBbwWBbBRyYrmHhuUrRhHxGCdDcgoOlLsSXMNOonsdMmDuUDeEdeESsWcCnNwQGCcIHhAQGHwNWwnwWYcJVvjCyqQWhxbBhgpFfPGHXXxEemMeEnpPNZzVvAagZzqmMWwoOyYBbwKkpPWNnuMmeEUuaAoOUHhHoOTtfaAUbBTtgjJqQxXGLlgOLloBbEeXxXxaAinNzEeDZzdZwzZWYyLlZzhHFfRrPpVuUvpPWwyYJjIiNnGHhZzNoOFMfFmfjJnKkVEOhHHJjhHFfhYyXMmGFfBbgbBxRIiRTtrrFLlfoBbbBVvvyYSYyEeEFfXxdDHhEvVgGmMeetTKknNWwQNnqjJkKTfFOOooZztSsBbpEeDdsnGgNhGgHZdDzSRCsSHhcOoFfEsSuUjcjyYGgWsSwKksdDbBSAaDKkMVvgGmdssSoOtTLfZzRrvVtTcMmCLlfFDMmdiIwWFYMmLuJjUhHTtPpGgyIxXinYyClLcGgGgxTmMDLldtdDxXXqQRKWwkoOCXzLlZxRriIxXrRjJHTQqtheExXcCkJjKPFfpyezjJCcZEhHCAacGgzZqMxacnNCaIVvitTtcCTGSsSstzZTpPDdCiqQcCIcBbdDanGgNAMmApPOoPFOlLoiIfFuUhmMyBbaAZzxXPpLPplbHhdLlyYIifrgGJFzZiIfyWsSGgwYaDdAdDEezJjvVHSXxzXxJNnjZHDdhKkvtTiIYPpyQqQqVvlLvVkHXxhtTjJWCcwXxwIUuBbVOikKIoOojJXpZzPoOxvSsiyYXwWTtqhHQTYyTmBbBfFYQmjJsSzZTtTLlMmPptuUuGdDNnRcCoOLcRgpkKkKDdhHbBjsjJSdDAaVvuUJPGqQlLVvPLlnNSpPszZrRpTZzZzvVbBqQtUumMJuPpKgPlLpGkJjiIwWaABDdYyueEaAhHSeWYywStqQTsIFEefEXxcCeiENnyDdUugGVvdDtGjJcCgCcGQqzIOoLhHliAaBbZHhpHhPCCpPcOfFLlqQoPRrpBbwWtTkuUAKkoOaeaAkKEXxGgsiIJlLhHaAYcCyUuNniILlzmtPpFfByyYInNiLlQqYUueGgMmEDMxXmdDdyBbuUAalLaAlLyBnNvVbSKfyFUufYFktxXVmhHMeEjWtVvwfeEFWNnNnsSTHhviIQqcCamaAMIiDdAVXLGgdDyYlUudmMeIiEOorRSslkrRpvzZkKKkVPIioRrGgOKLSiIIiPpGUugcCsUucCqjJQtuomMOdDvVwNiITYySstnOoHTIinCcmMXxZzZzNOotSswAaWaAyYhWKktoZzbBLljkrQqVBHhyYbZzaRrzZAwWvQEeuUqRgGfFKFOsSobBfkrlRrPpmjJYyMOSIiGgsoKjJylHhLYnvVBbNaAkBbQwWRrRCcNnsUnHhLleENgGuUuXuUktTKCTttTslLScaAfFxBmMbWwHdDiIHhqQOohtktTKTXyYbBrjJRaZlLmhCcuRrTtlMGghHjJcvnNVkKvaRrKkAsSHhYBrRnNiyYOoIbgGnNyjRrtTJopPkKfFlLXAjJJUumMacxXmMCqQAfFIixpPwWeuUiIERrQqcLlPpgQqlLIeEivVaALXfFRrtTxDdFsSfNeEnaAEHhPpqQrRKXxkeXxnNBVItTixXYyoHhOrRvNnliHhLlJjImMxXEeFlLPNfFnpTtDddDrIiRascCSADdzZPPpoOIRrNCcnifFUddoOBbDDJyYCcwWjZfFzdDGgdQmMcCAGyYgdDjJaQqQqNnwWKJjHlLhkhHvRSdDoOxEemTtIiRoOrbpPFfBTIitMWwxXEUuXOoCcxwhdDHrRGgXxWvVyVvYLlELlCOjJkedDmMEmsSKkeELqQlPanNvvVVAfSsGRrgFoGgGscCSowQNnEeqWlLZzpfdDRrFeSSssESLlRAaroODdtuFpPfUxXudDUhHrWjJwRhMmLlHpzZlpPnNLIiYyBzvoOVvVeryYRECcZHCcrRhgGQqzZAALlKkOiIRCUufiRXqQIiTvVtMmxLlSWvVwUusiISJRejJEeEOeEHrXxLlrEFbBNnfPTKQCcyYjJVvlCcLJjqbQXxBblwWiIzZLWVvwpKcuUpPCuvVRUuxXrOopnNoxXpPiIiIhHBUuIiXxPpYaTtAyjGgwBbeEyYiEeItPVvPdDGgpDbINnhwWzZdLICcizZbBaAjRvVPpriIZztTAuBiCcaAIEeboDdOKkMmUyYSilkKLJYyjVvJjoOIExsrtlLhHTRDnLlodDeEfrRrRPkKCcpbBHSshFZPpzIBXxKkbKkcCglmMLcCnKkQqqQPkKpXxxWwXSslLaeEuUBbUurDXxdZqnfFNoOiIvVAKuUCczXxsSUGgdFixXIIiRrfzDdZDvaAqEeQxxuHhFfUXNnZRroOqkzZKcxyYyYpPRLlrXCljNnJLTtlVMmvVuUvbvVBqaAJjQcCPdDpUuRfZZzOiIoznpPNFQiTtHhTtIqODzZdVvaUYyCcqSsfFqYyQSsQEeqQKkqLlLlYCcyhHNnNnBbuNBbnUNnjzjJudPpDCDdgqQGcPpfFIbBijtTJOhwxXkKnYyHhqQUujSsUtTWwnpPvVNyYuymMiIYxXsSbgKkMmMmQSAasEVvelLjJkKRrYtCcTyfYyKkjWLlDduflZzLnNRrmMLRrUuwhHWfhHBbFIilUuAaFSzFfeEZdDLlQqsFfIiSJjsPpeESswGgrmbBMjiILWNnwlRrMqhnNHvVQYylLICcimqVNnvZYyzTtnsSNnCsSBboOiIolLiIKlLdGWkWwYyKaAquUEBeEjJKkqQIiuyYUJjkKDdndzZDZzNWwdIiNvViIjJeEnEfFTxXtkKiIeBzJjpPtfFaHhlLtTuUDdTGgPptAruUwWqqQlIiQqEeiIPgGpiEBbtTleiIEUujJaALlZOozdsSiIlmMzZXpPhHxQWkSeEsKeyPRrLlpwWXsKAaAabBNnNBRjJrbDdnCOockxXsLlSASIisGgwZLIixeEEehHXPpEVvQqeAoOlLkKewWzhHApPsSZYyocCBoOnNulLEcCEeeZzBOobupPUlLQqmMQKkqXxHhhHfFxXZwWXwWZbBzSVnAarRIXRFGgfrZzxiXaAxSZzSsXWbBEvVSsewxsfFOUukKobBIYSkKhHsyqqQrNZzTaZLxXZzVUAazcCZGgTtgoORuUrmMaAGpPSqQDdsrRBPpCcjJdZzDmMSsRrYmZzMMTaAJjPpchVvHCPXZZzznNlmoOncCGgkDdkKKGgeeuUaAqYCciIyVUuBbeElPqQpXxLNnxnSsNiJuOoUbBGgidoOWwUzZoOMmPCcpOoLlqQEeuBbUBTlfFLKCcNlLniIIiTunTQubBPpUeQqWwEjzmMsnEFfHrRZaAFBwWNnwCVvTtEkXSsXWwxjJxKDFYyoVvOIivVyYrlLRoOfOSshHbPpZzlOoNngGnbBNKkClZxXxIiekKnGxXlLeEnRrNiIdDHnNmMPpONVWeEwHsZVpPvhHUuWwuUoOsSWwtMlLWHhhHwbBCJjbcCBQiIGgaAPZhGgSsyYHbBpxFfWBbwhCcHDdSszGfuUFRiIrdDieEeVYyvBXxHoOhwWVjJvVmxXpKuUkFfMmKMdDNnmXcCxkPkKjLluxFfXISsiJgGjicDdhWwjzZCcJsqQBbSHrKknNdZzRbBOoZxXzxlLoiIJHhjOoPcChHdOoWwlLDgGXTtxwyYTtinNsSYyFftTjZzJfFAOWsSwolLPNnMmuULLlWwaAVvYybBUtTspPMmHhdDsSSQMmZjJAIyyYhHYJjLlReEeEhHoOdwWZzDFfhXxTHHhhEKGNpPnguFfUjsSuUuUcOfFwozZOeEWWwqcCQZzeEEepPRBbBbaACpDdVvPifFNyYAOoanFfFiIQqfIaqSsQloOLfFOoFfIqVNnvQiTtuLlJjZzCcWwtVvzZpPVvXWwdMmjEeJDKiXxtpPOvVBXxbvcSsjIiJCiIxFKksSoIiOLrQqRxozaAZOjJIdxOlLwziIcCiaPixXjJjkKHhaAxXRrGgLlsQxXKkSsqeaAEkKyYBbxHnNhXbBKsSoOiBDdNnKkbIEZzqQeKXqQxUEeWwHhUPpAahHuOozbBZHqeaAESslLQbMmBzCaAjJRrkKduUcCQkMMmGvhcMmKkSsOBbrRocCfZzrREWwmMoOeogGKkZFjQqmTtMwWEkKSdDEeDvlLVfnNHTtMujoOmMfARrasTtSFKkZzJRrUHJxzZXjJOfFkKwKGMmgkXxGgWlTvVWwhQqHhbHhOWworRdONiImLlVBbzZvlLNRDdriOovVIndWwoKZfNnFzSslLggGGxXDbkAGgaKlWzfFZwphHOrxSEeMmQdYyDttQqoOMsOSyYcOokWwKjAlLaRhHicCvwWVIrzTtcCpPezZjJMmEYXxCxXcKkxXDxXdmMKkFiRreEfFeEIOoDoOdjJMzwWggkKQlLnoOeCcEDFfdSsfrRFrRzyYmtTMPUHdviIxXYyjJVQqDHdDAaArPhHDdlLehHHhDEedFoOujJUfOopPjJGRrgPRvVyyYWfFZlOoLJjzwYsSuLeEjVFfGgvbXxuUjPpjBlLbQqJKQqXxvEeLlVnNtTQTFfxXZRIiBWwuUNcCfQZzqpeAeEacCEYyPlLdaAovIYyZfXNnvVqQOTtmUuFfDdDzZdZIilLYyzpPkmMPpPprRrRiGgIEAzOoZqEWwvVJjememMEmMFfUuiIukKUCcyQSsqHhdNnLVDdvxgGYEpfFtTPNneJjMBboOSsZzcCMKgZoOzGoZHiIHhuUMmXKmMTtxXkIiOAizZRiIPYyTICcIiifFfzZFtNIPpqQinpdxAaYfFeEHhoCcpkTCaXxAMJyAaYtTnNnNjvFmMfVaAKkvVZjJzmMAaJjmltTwWfRmCaVvAaUuASsIisAwWfFaDdGjzwWiIZvVvVMQvSsfxXugGvVUxXOqQoVvhHNGPzZnNpgEeMIifFmaHXgZkrRZzKZzKkzRxXYydDrGfgAdDeEQabCJjLgohKVvkHhCwWUCcuyYiICcIwMdWxnNZzuUXzJjBaAYRryZiatThLlNoFOofOnPpPphHHbBPRrSpPvVYaJjEeWQqiVvIUuwWfFQqUHBTteEtTcFfGDdQqkKgEDdeNnoOCbMmtTjwWMmJOoCPpnMmNcnNeawWAQqURruESlLmTtDZzBbdzZLllOoZzLHhqQaAjYPpxAuQbBvOZzjkrRKJoYyiIfFjSsJfFVqBbRLlRtufHqQhWYhHfFSsQqyYgGiWwIdDdDyqQymbYVvyCcBpuGWRrwgswWyYxlBbmaAPIvHhVipPcgYyiIGJjCkKpfFgGfIipPslsDSMmrRsoBLzXxMmZlGZzLlXaiIjZoOIXKOoWUuMmvVwiIkWNnwijJXvnMvvVaAWwxXBGgGWwGEegvwGnIiyPpYNxHhQqXgwVnNvwllLLvVJZzCcjiWwICcXcuBsSbvKZXxUuzYGQxXqoOUqSsDLlMNnGfNnQqFijdpPTRrpPWpHYyhPaACchHbWwBLqsbxXBeEJnUuNEBbejYyBQqoObbrRMmBVOdBbDUIiSsuqQUbBFrRFSZnmMNjHuKiIkUhFrpjJPpMmsEuuhHvQqftmMsUaAGEpPeEguUlLsSVNnvAZzaAaCfVxXvEeUuFxadDnNurbRrBwWbWMMHhZzNnTGgMmDlLdpYBbyoOCmMcikCcKaABbYcCzZBbyIsSvVEaAOojKaAEeBbQqkoEeOAawUudDTWwSsoLWTtJjwltTicCMmIZzqQZmMYygRrGTtngeaAhCcGgHEGniIvtTVhoOxXuJqQoOoKWseWdDgMFfdsSIiTtHhETtlLjQqrTtLlfFoOgGRkKOyYDmMJjPzZUuHhYCcyLRqgYyGQXLvvzvtTldPiItTvJjKqQqEdLMmyYlDyoOxXYubBVvUwWtTzZRTXxQqdIiZzDDdwJLleMmTtbBISwWoZzWwOoOHhzQqZHhvtThJjXxCzZcXRxXrnNuULlpPcJjnNNbBTtnSsTYyHDPAacCArNcbBCaAiNvVdDpHhdhHKkLlIixCyLsEZIizdkKDvVbcKkNUojJOpPPpofFEeIOeFfTtEOooicHgGVvhoOeEZxXzoOQcqBbQpPCZzYTtvnjIizZUzZvVxPpyYTuUtmhHnzZvlAdDxPpduUXxXxDdDJYlvVLlsiIKkLljFfJrRvkKceECgJejFfJPRrrRpHBbBbxOsWSscWwKkAaQeUeELpPCaAzZclrmMqQxXBbFfVGgVvpPyYvIizlLZXIiZzzZeBbWKkwneENFrROjJoRmPpMXxrCcqQiltTNUunLjvlLVnhHNaATtVZyIzZiBbpjKkHhJjCSscRYnNFfUiqQIHsSafFAhvErRXRgGpusSUULlyHhaAYnwWNCERrjJEeecaAQFYylLfbBOkHhddDYAapPiIaAyiFfIyYWqTKDlLiIcPaAsSBoObhNNnntZNOorRnTaWFfcpPSYyUGYygaAlkKLiIKkkKGgXxNnqjJqpPpcCrkYyKnNbBVvViibYWwiIvVxSAamMsmMSoOsNnyYkKGgxsPpZzstTSTHZWwzdNnAaDhrmMRmqQLsMmWQqwJjjNnpPpnJOojLlaDdNqxdDXiZzIVeNnNnAmMaAtHhTMmaApPaEvQHhTtZIiTtzmyRexXEdzLcChJrzEemdwaATtVbmMBYyrgIMulUcCIiuqMOoJjiIwWxXnNsSqQMgfFGNCwwWWcbGgtPpEeaoOALlTBUuhHISsCcZYyBJjjGguIiqQkKXpKNnkcqQCPcBQAsIqQNnLXBdDbjGgxzZzZXQyYhXHbcCOVeRrEEexXEAaeTtThEWvVWsIcfFCiTzZtJNnjymtTMAmKhHypPMmqQYkEGgkUuKZmhMmubBUaAAaqQprSsRPPuUpxDdXiPGgbEwWMmdDeEKkDdbRuNnUaZzlLZzTUutIiGgMmDKkAhiIhHaiIARrHyYlMmLYyadMmMbRdDKGGMmcAGgbmKkMUudgGbBjFfJgDdGJjUuUuNyYDdnmMmINniOZzzZIiYSsyeEYnNizdDAaZIUuytTmMfeENNVvnnZzsUuSGUuglLKGgCQqckMmEPpeZnjNniItTJSXNyYZzAanlLkKQdjJDqLoOKxrRXklsoODdCwWjUoOgGKkTtTbBtMjFfaEHhGHeEkgGPHhmMeEHEuMmaABbUpPGgHYKkCcoOiIMmVjJlLIiTwUuIizZHhdkTtcCYvxCcXSaAarxFfXYhHQqaWwLHXUuKXxdLIiZzzPpZoaAiEvVeAMmaCJbBMGgyXYIiyPsGgEbBcEeJxmsSyYQPJIijaAYLsSWkKAuUiIWwpIjwWTtbDgGdtTvqQVBZpJfFjPQLZGgzlHzZhCcqJuUjrTDFYTtmaAMWwyUuSsFgZzaKIikUvcrRhHCkHMEeGgkKcFfkyyRrgjJnNGlLYqeEQgVvGiICcYKiyizZuvVfNnTPptJjypPigfcColIilLupPzLlZUjJYhqQcFfCwWDiIsdqQVhHagGjZzOEeOOoCSsccCmMoRRazwZzWkwWTnNHSsFOLQqlnZPpzNrOoRoqdDQqPQqpjJQfZNntTqQZzMdDmHkKSbBZzABbkkVfFiLlIipmRrVvTGgzZzZxXEIwEUGguDoOMnwWcuUwWtXxxMmXHnNhHbRXxrLlwWbBsSsXzPppebKkBvbBUoOOolbNnBSseZDdhHKkgXhHjJAwRlEeWPXEeUIuUiMAammMgwWYyGIWiIwPuKkZhEeHePHheeiZbuZzVvwdDxyYVYzZWwCcJjxwAnCSvkKVODuBAabTMmjuPpamMAAaPHhpMvVpbIqkEeKQkGkKgwiIWIMmIizZWsScCOuUBWSsgGJhHjWftTFwRHhSsUcCucUuCrEeCxXcVFfXjiIjnNGghHpYyfqQFaAPJYnAYVMmbWweEsKyHwHhWGTtQQmMFfuUqnaaXxhWwrRiDjJuvpcBbpyYuUfiCcIvkVfNnPVooOfFMYcCcRrkRYyVVYydJFQqZXucfmMRHhrprFfvVzbBuQqbskRRrrWoOYBoOtCnxXeEcCzZNnsQXxqpUuPtTDuUAadcCjuUjJJqnNMcDMMLlvVlLmtcFfAaiIvVriYuURrsSWiIAaNOonJjyhHFfjJJSOgAIiaVvmzOowMmoRXNnCuUczgGUuJlLPrHhwqbRmFfDdrPtIfFEegjLnNUulpDjtzMmZeEQclLnNHweawWksrwiIWEIitqQTazcyuUIIiaAiwyvNnVcQqCsSHdDhYSDdZzsWzqQZpIHhmMESsgGWROokkCYVgzZGvmMyVvNnZoOzDdoEeFJjfOoJxXjxXxyYXOJQqEogGfFbBOmsShMPpHOfQqhAdnNnEeMSsmFNlhHdvVDLtSBbsBhkKHbGTVvyXAaxYoOPpnNDdPTtpPRrPsSJDdcCfFjoOphHHxXjJCIPpXdEekkPpjJKZzLlHpfFBarRACSscCtTBZzRrygGYbUuUucXjJxSjJTfyYgGwWwPoxFfEexKPxKkwWXpcrCLHdyEeYoOiRrANnaIvfVvUsSTtAacCuXLIilGJBqQpkKPdUufLlFMoOHhSVvsmyFffIiHyYSskJyDfApitTIzZoOdDGyYgyYXtTxXhHxXvUFfuVvksCaAaLlqdDQAYXRrpuUPxaAfwWFBkbgGwWIilLsEQqJjUUrlLwWRUIioOuOIixrRWwcCXaoqqDrRdQxXRrzZiOFfomJjMAadDWrPkKZNzBnNbBbZUQJJDgGdjjBbMmqVvPpDdMmcIGgtXxjhuUQpFfcCAhHMmSsotTSsQqIMmiOoJjbjJXxXSFvVfbMWuUjJFfzZoNnPpOlLlLPpleELGgPpVvLvcfFVvcCCUuZmMnNzWweEvTXxtuUHpPCtTcCOocJHlLWyYGgzSSdDsEbGgzZcCBETtpfAaFscUuCffqQFzPueFfuUEIyqQnbEMSsOoEejFqIiQfJGgYytTjDhsSyYxskNnKSXUuWwPpMmBnNbjJSrwWiQqIRspPGuTOlLlwtTtTiLlYzkKZPpQqyIZzZwWzPBbeEpHEGaAkKguUiIfiIpPLqbOwTLHPpQqOohbBfWwFPiKQqkvVXzZEeqQfzFAGZpVjPqdDQxXSssSnNzZeUuckYdDWdpsuUtTSWwORIiVEeBbXXxmMBWwZvVjAvHhVxGggSYykCcKkoAaOKsYyswizAaZUuYBQqZwWrRGgzjJLyyYAaEeBbhsATtaShbBHQwWZzeFJQUEeuqgJjceRrmMEpPAEeyHrPpRATtHhsTVvGgyrnNzZRWNnwZIMFBbfoOKndyYlKPpxXWwEZzVXxvIilYyGLlofxXqQNnmMxXYUuyJjFPpWBHhAdXkKfxXuZzVssAhLlNgGbBuUnwWcWYywCnaAeEeIiENUzZfxXMmNnFuLlLStiGgdDIuUUMegWwhwWBbusNnSNgUuilLNkKYyviwATtPFfJjpaNupLqQUuKPpklCcxvVMmXqBbQPNneWwEUxXnCwWwcCIiWiSrFvXxBFfhHQaAAgGBbrRAaKkbxXJjBaAPpGgaGBbmYCFMmfZRraaAUutTVNnwbrUZzUgfnNPrwWDdUueEFuUussQVOovzqQZzXxZtgdeEjgjWbBGgwJIxXLGgldrnNRmaOosSnZzNyBSTtQHhbBSPpNnsdDyYAaSvVRhaARAzgGazZLwXZzxWCclbBIiaANnWGTtXittwWUEelLYyTlLNddQqtTJjyPpqGlJdWRrtTUuwVoOyYBIDdYybxWLTkKeAaTFYyfnlLTbwWBbpPLuUlvYrRyQqOvDdzaAZUEeuzHhoqQGWwASsUuaxHeEHLVXToOgZzGSvVPuHcmMEehGgNzpPZKkIoOoUuKkuuUeEyTUuRrtYxXdDaVqQiNyvVroORiIOFfYjJyFVAaLkKRrmMuUrzZBbCcLlGXxoeESsknxXNuUDdSsAanNOsSIioGgMiOfKuQpuXxUUuKkfzCbgGBYyAaedjKkSbFaAmMrBbRfBsLlQSVEeHyYtAsBbeOoUueEELpPPIijpPMmNsqdDsSQSiIBbUuOZzoCPvjJuujJvuUVhHXxMmHhKkStTEaAcCHyYkEeaAXqkSfFSNVvrLTfqQlgGLlxoNdxHAaRWweEXxeRrdsSkQqZzOdDgGoLfFYujSsJnNMmboOgyBbGnNoegBbQncfTtgLLjJfKgeEGxXVlAhCSsczxXXxLlTSstTMbgGHhDsDdqQTtRrCcLphcCHnxItTaIMmmhHMMEerRmLlkpPYpPRbSsvVfdDFWIRkvVKuyGtQqtTnNEeTlLvrqQRvGgVyuUUkgGwWZJjzFffLDfZwWwRrWwIYhHyjKXxkJipPzuAaPpdJjDlTtLhSsMSshAadnGgNDzwWZxKkqQnUuwLlEeEfkxXlHhyYnmjJvVYUGaAdDeEhqQFfvqYyQqiIQhHVmFKkJjxXfaAfpKJdDuckmMYICYyLlquHAJLlEeNnbkSNnWwQNnnNqsoOrbxXBoafigCYPpTobThHNnDduUGgtAacCyqgrRctTnNlcCLRAkuIlsSjJLlXmMeExJoOjuKZzkUgGtTTDdvPaApVtLljQqJuUJuUkpKkkKCeENnKkxmMGeEgXckKgCVpPvqFdVvvVpPktVIfgGkXxpDSscENUuaEbRgEeJjKGWwyWOMlEvLcClVdmMDFiIkzZKzXxZtcCbBZzdkKIVvkHhuNnVHhvcCKJsSweNnhHXxDdLlwamAaSAarRsqfFXGTtgxBIPCcpBjQqJbMhUukgzZGKHWtTwYyXEUXxuEZlwWLCcGgsrROoSHhzngQqmMjJGJdDHhovVTtOwTlXENCnNcLlzZoOnzISFfsMNfFnHHLFfkKlhRMmIiQqQqYmFfqQvVMynkoeoOqPTtLpTvVtrJjnNRssYnNdDkWwDzIkOohKJBbjWVvUoOtTuwWZJswBXxbHGguLlGzdGqUuVYMWwrcQqFfRwEebBNnpQqDtTLKmMkLlWYVblLLlYyKaxsBbsSecCEybFfhHBvVfaAFKkYwiVVPpSRqJjNnwfFbSdXbzUuwWhHLEVSxlLsSZnNkKNnGSrRYNnsSvFaAiIOqnWtTKIiNnjhHrRKJVvjWwifKUukcgYyUplFfLDQLlqcCSAaaAfaAFDdsuUEqiIZhKdDkKxXFSsfxVvPocCOKnssuUvVdDhHbBaAmJwHiIExoFfdfvVFgGDqGgEezZEcidDIHeESsmkKuUZLgLlGwvbwbYyBWNHiPpKkWqQyJsIinKkNBDLlMmGXLlCdzZmMeEdDfsSVWGkKPpMmLlAgGsSLIihHGgLluQlLkKqQqzkWwjfFSszZJjThWwwJFKkfgGDdFftpEeMmjxCcXBbdDMXxOnMmWwHhSVeEZGAaHhlLgnhHzvXEYtZMmzruUKkVictbBBmMOosSbTvPpPpEEhIZdDLlFfViIeNJCjJcgGpPZzsaDdlLASQKKMLLXExYyYyFfvVImqWkKLqJqQKGIiCcgyzZmBTMmtqQuUFKGZiPTtLliIKkGuXqQxXxXiIXxxMqQyOwWZiIcmFUQqxrjMmJkKOrRoVFohHeEQqSseECcrRKkOfKmvVTCctMQcyYCvIiIiMmGgKbBkwWjSmMGXxTcCaAwfFcHTtdDhWYySsBbZfAOoKkavVFfFkjJgRrGiYyzGZuYyfyAVjJvaYFUhrpkXMLldDmyoOYnBbNSsWQqsCUuYycHhtTNDdlLoBbGgnNnnNNehWDdLcxXWFGTxXtABAasSbaZYeEyRmNzZDyEoOjJSTtrRsHhyYLlVtTIDhbbBYyxyYHkBbyLNnfpyvydRrvUlLuJjuyYSRrRIFfZPiNnjsSqHhZzQOoJIFfBPdDpyYbbSstPSJuUCulLYybWLVvyiXFfxlLIqQOyYyNnrRYLlozvVpAfFZzZzmzZDdMTyYipvVPLlCcfmLXQqjJAabqQRwMgVYnNjlLYlLflLeEYoWUNnrRuwdEYyeTtCdUkrRqeExXQXxQapPslTtLRDtTdaZziIbjlaAZfFzJjIzaSAaUjWwJcAairRaZJjNfVvMzZmvVGIidDrXxcrgOhSsLlQGgqZzHXqRrhOogGfpPdwHheccCCgHhaAaLlGbBBRrbGFfHGanNnkKgGdDnXUuOqQoAaFGeEAaAjJPYiFkDDlLuMhHWyLlKkJsShHmwpDeEiZzITtqFjKTWSsGbEyYeYDRPEKkKMmMmbBwLeGgGXbmQFWTtwEerRfqGgaPpwQqCcWvxsSXcCWGgEEeLNPpxfcGfFgsSnNnNCbBuDIqtQqusBbSUbBRXxEerWdDEUnOlrZEyvVmBuHhxDdQUkKhHuUuMmdMmrRDqYaAyePknNKlQfFXxbOqLlQbBVbENIiJgzKEeKkpbfFBcyFFfkUuKfUfSHmMSIdwjSemiQkKMDKwWZzpSxXsWVmMeEWyYoqDaAJsmKkuloqjRTLHPhHpgGubBRrFmMBxUupPpqQmMnNlZzDiULlxmnZjWwxXJenNpPEziIPUuEepbWUpxXPaAuCeEiIwWcbBHhfFaAJziIqQKtTkZDCcdXxQqlLhJjoaizYydDZeOoEXxwWqQNdDbBGaAwWgoXxlhMtSsTyPEepWrRwYMURFpvlLVPuFfFUgGuQqfpPXxVvwWAaLaUgGXRfFoIdjJdBbDDhHaHkKSxHNTAixXUykKYlLuLJXxBEmMuUOoqTtQefLyYbBlUowWnFnNKhHkSsGLbBlMmgLlpTleJApABHkWwoEFYywWRvVthHTOFfDioKoOCcTtNWkQIUQquhcCqQHPHhcmhHZeEScDgPpSDdIiLCcjXxJWcClLhbSssSJjpPBoZzebBkdjnNaDNyOoYHbGLlgGgBXxfIiFmrMpnHTtHxCcXcgQxkaAoOveEValLAEeKAbBGyYgVGgHDyPDZrYfFfjzVPsSpvTtZYrSvVOmtVVvvTWwiLlXxRkKrmjWwWHhWvxXkEeKtTvxpPTMUwWFaBbFOlLIGlHJGgSHDdhsjWwhqQZmMsuUDsSdtJjTNHVvjoORYijBpsSRrbrigrRAaehHgcjZzJMtKEeHDKBeEbYybmMFbQqKAakcbOutnNTUonOQqGKkbBgRqQUHVvjPpJhItTiWgGWwnoOcyYfFsNwJjwsSWWJKkxcfFdYKkyfFseExXkrtTFfyoOsadDASEeoOfWySteApmyYzjduRyYbxeEjJTLwbBWGgHhEuCcPpHrcCFdnHfFhnNLlgIiGNvVGgTkKFftlWTaWquWwALRrRwWCQqyQqAqbthERbTtKHhvVkUomCcMmMKFVbBSDdLlqAZzbBeULlqQKjZWjblaGgcPIipdDurRUBbMmVPZouaJjXxUoepPIgHOoYTnyQquUeQqocQtPpuUTqpPCcCbBtTRqQCOXnldIVvirWwaoOfFHgxXSwmXadncEeRrDHvVuLGEefFUjNnrYyRrzfiIUWoUmMufoOpMmNyYSEeyMmrRUMmHIuUueEnNocZzfFGoOfFocXCcHhmMhYyHWwckKacFshRjLBbaIiDdreiPLlpDduUdjJFfpnQqjNuQqrRGpAjJiIPXgGQfFTtqaABbaIVvBnRrzZZhkKClrRRPIiOyYsSJjOophHRmMFfYyOTtHrkJjvvsSVziIvIiTRfFrKLlkvVZjMJtTxTtqUumMHqcZdDzCwlLMcidRBbcCddjJLpiPpkBtkDTbBIqjJNjNjHhJDXdUckKmtZUNkKXxnMmuMbBVoAqaADzyTJpcBEFGOodDQqiIpfmMFPYymPpDQqUuYydMkKWwaAHqHjbXYTtYyyxlDgIwWKkNnJjPNxXnpwWvEeVYnvVNzZnNwISszLlJxIFMVvPparRZzZTVvGkSsKYhHHDlLtXVvXxNvbGzZRAaRcCrivwWphHaAAaHSshRrXRrxTSSpaxXAJjAszPpZFuVkNOeGMmgXSzZDApatTOCcKeUuNnZzodDkKOfMvXYyIixvHhVVbGgGgsSXKkVFHhJfFcClNxXQtGgjNnwsScCYBbyPcsNNnBbPVchlsCczEerqzcnNCoOCyYFPRrpWwRruxXUMmlCrXxReEcLQqdDAbIiTtfiIaAFSPGGggUuDsSPffiCNncwwpPaGiIjDdIgGiWwantTOLlcCoNdRuvgGVUQAOomsSMcCDdLsSjBXvGgVbBxkKBNFffHhpMmuUdBNnzbBOwWnNRtTrbyYBsqQSuVvUqeFhHJVMbxXzZiIPXFfXIixxrbBHsSvqQxJjmMNeEqlLTrEyYCcXxUQqkYyKoqVvpPzvbBvVjJEeVHGocCOghmuFTtdQTrRXxthauAaPpsNBTtbnKoTKksSYytOvVwWuZzvVwSIVguaUugGAUFfNlIWwFhGvVNwrRGgPpEeiSsaGhUvNnhzJalLKXsZztTUzmHhMbIiOoXEeMNJvAaOpPGgoMAlLsfFDVvnRqjaAJNnDnJkjJxXUSMozqBOjuxXUJfFnMOKkoqNQqxWCYKMeEVxXeEOzZoyYnrRNamQqsvVlfFLQqBzzoXzZxOLdlQqrROecCtbDoOMGvFJOoeoOPUuHFfrGmPOkKWKebBEZzOacoBACTLKkRrlgOEeYyxBbcXxIiVJjzZjJEFIuBbrZzPpRxbvZnNgMmqrRsSzZWwWwKoRqAaUdLdbnbQqFfnvVvKFaARnlLlGfwSkKsrkKTGPgGJUuQqjiDdILRrVvlNVvnlsSHhNpBfCqKGRrKNURrivxGUfRrNnFsSGXxpWUCYwKSeNFfdlLGZzgMSsSNwWwnNnNrnzWgjJeqQEppPgdDwOAaCxXgGNnIitTXxoOFfoWaANWAgGRrbbBBGggSRocQfyYeoaAhcKkOeESSxXslLCcKimiLDCoOPpBWkNFfnNFEyPpPoONBKDdqQVKkLBwWvVBbHivVIPpJGgehHzZeEdDyYWwGPpkDnIMYYgdDsSPlmOeEkKMTtPpTyAaYrRbBilFfCcLIcXxCnNGgaZRrxXzmAwWYyAogGITtiJjHxjJXHHabqpPbaXxIGFrOGgMncGlRvVrbbzHhZYyBFddDIKkwWVggcGCcGByktQiIqsMujqQLOmMglUqQuZCoSsOYhHrcCTtCcgGRIoOGeshHaBbApVOoCcREerZfFteRgDTNKksSiyYDdIntdJGnSspCSscGgiIPwIjlmxOSUuOGgJLljpcTtRFnpPzYRrNnzGPrLlRvVxTtyobBzZiIJjEbHjJhgYeZURgZzvVsCcTtBJoqOogKfFJAKkMTtdHhPJjkuUPiIauRrUlvVaVFFrNNnKoOokyzZPpySsjwWhqtBIVvrbCdDtSWwsTVIpXNoqhvitTJPpOopMmXxlLpxRrOnXNnwWxoOrUuQqpPQqCdFtuiHhqAIVeRQquwWUWJjwEpRrPEepVvqxXQaAwiIZFfQqLdAGgapZzOoORrJjVDplLeEgcGgRlcCzFfpIiGQqAeJiIXrmHiLgGIivDBbdEehjJquMmPpodDzTtZJuUGbiTtgGDdlonlLNUAHUxyYPRxXBqQbDUGWwgubFTyYrQMdIkZzwNniLnNlIJjWtTULluArSshtSxXojMGcDlLBYySMoOokKvdHwIqvVJjwKVnNCcPlLtgDTMkrYqpPQpomMFfsByjJYbeEsrRpCeEniJjmMbKkKgwWyyYTtYiITCcdtCcPQqNNvoOVdbBkZXEexjJzKKeLlomUmMLcqvVtgGERrDUuRBjZVhhigGlLbBGgJqdCPZzpqQPYEBMWmkKnXbBzZxpCclyYBIibkKjCmCcPpSqQqQSsGzJhHJjtTmhLYaAPiBshHSEFbBDToWhCNkIPpiHyYYAafigNnjKHhvmwDWtToaYyAOwpzHhZPRrbBLnYpPOodpCcJsiISViIyXyYzVtuUOIioRfFVrTtRvPHhpITvtFriIrqLVvlIRrigvBwSzadGKmYEVMmmxXpPatlLTsSgCcGmfFqIiPJjpQMmPeEdjJDpMYEeQAahwWiDdLlPONpPkvgGwjFosRKkraAdDSdZnYpTiItGtTyUJjuCcYeLlgGnNRtjJgUmNrMmuURajUYoiXuUmgAKXBqkKvVmMywWRrRfFUuIrmGQqoBkpqhgbBWwrBbOacCYyAofIvVkKxXLqQDdsxlsVvQqyYSaALEeyEkKEGgfFMrhHzZGcocCVvGQbBIiDxrRrRCcVAahfiITtOonjrxSSKOoRrTtfPupPUgjHsWwmMSXxWLBWuUIiwvcCXxVNnMVIivdJjNnxBvwKbwLRrlWiIvmMVVtOHBHMrRmhxSseBGSLDdlNcsSsQzZtTpPwWFbCiIKkmPpAdkdrROTNjjLJtNIlbRHIERrorROePTtpJoOfZBYyXoMMqSaVvAszwWZQfFjJEezZTtjyYfSMdqmRdDTHAauwWMlLmHmNnPplLSeHhrmMctaFQqfFpVIpkChUmXCczZEDMmyVvtaUqQrMmRumRolLvVZZzoNOFEefIeEhyYWeEgGwWwkmMKsSNqyveEQqQqSsNnuDWwdXKKEIvVEemMVUHtBbTRRGrhHaARjJgraAnNrtWGmMZqQWHhEeZzlMGgJeafFAEgGFfStjJYyeHjzSsdnRwWhAzvHhFexfFXIiEwQqgvFssBGiIWTLlkOsCrjJGnNPpVXBKiIqerrKkKyMOFCmMNxYyoQCSmgSHhlcPJOoQCpPqQiFpPfaiIgGANbBXxSmKzTNglqQLGMmWwnNRrIvHSsbqQZCexrtzdcTiLlGgSshpPMGDdUAFjyrRYoUsXxSRhjJkKtTzFfZdvVDwuUWVXvaAeEgMmGVoOQVkLXxlCcIbBrRiLHXYylLfFGLaAkZzKtqQDYydIiFfTtAbnntThHhmJntkLlQhNLUoVgPpzIaAwmMwILXdDxhEtUuNyPLVdbBDgGvVQoXCcxuUqApqQurLupXxaAfUXXDpPfGnVlgLlFBeMoweEHhgYbtsgGUutTPJjpPenJjQgiptIOokbaAcpPxSxXsrwWbKkHfFGZzDdgiTtIifFeESgGsgPagGASsLlVvowjnNnVlLjJrRvGRGjJtfuJFfjbUnNuBXxIXSOocCkjkjLAAaayPpCcHhvdDfrdUbBBcCcKqhWPpwFfDiIYyeSsEFfqhBGQiQDdqIqBVfHhCglwWRPybBDrLSzmMWIiKEQjxEeOoSsxXbVnNDdboOBqCvRKCsCQiIqKkcScLlDjmYyMInPsNzLvNLCIeYhKkHWFutbBNnwWHIVcCqQVljQfFeNnApjPlzZLjJmMpUjeHlfnNyzpKwbBfMzZctjcCIiKkyRCEOoyDJSHhSsVhvlLrmJjKkMRxPpwoOsSCEXOxXcCAaOtToptmMrRTuCPorPpUuVXNnCPpmvrRTWwtVPFCrSKkHhAaNkgGdDxXvNnvVvsGgPdWKkwYIiNzQqmkjoOBbgZzkLlKGgRhXxcCXjJxrxvhHVXRZzeElrRXmMWqxJuvKNljZOJjoPfXkxXfKMmadJjpaALDdMmOxXeEUuoOQcCqpMmqXxQKkwWDtAarLNwWndMfooOROorqhHYygtTGzTbBxZLoWOJiWwxXIjxXWwzmMkEeyJMmteEcWuQQqidDpPkKBPpecFfhqFlrRCNRpPRmMrHzZhkyeRZzgHAahNTtEezdaADkKrRTCcXpGgOoPhsWjASHnNZzTiIUuYXssdDMtTKDdyMmbBVEYyHZzheLoOUHzZdVhuQaAOcNkPoYXxrmMFbbUutTEeSNZzHhPfqNnOfFoGmMgRFxXcCFVponmMTWdXMyYyOSnSWwllEdcCTkKtHUTtEAaJOBeESrTtxTkKoGwWJVSspGgCAnNdRCWtTwDQqdWQvAHAaIzCcoHUTtcBxXiVvkKwRHhWcuUCwtVQqqfFSOzORrlSsLoZhtGsSjJAEuUeaWRyeEYQyfFjfgydDXxpbBPqXkfFUdDovmlWzZKkyrRYmMXYQGgOrRMmqpxeEYKvWjxXYyNfAGcCdUFZcCWmrMReEnNraKuWwLyZzcoOJmMkpHYAJjnNRjJrFfXNkbBKQqKBBbNbByYhHqHhUuKkQgmMGLaqxYytOdDdRrXxYyDoWyEWEeBrnNhJjMqNzPKkxkIyTtoMCmMcQqJrkKRjmOYbBBbHrRKlxfRnKYlvVlJjNnLNwWHNCcoOqhPEBaYyuUjTArRMmfhHcPKvtmhQqpPHMCrWruUbqEVQqvaKkpmeAyjJYaEPpVGgLlTtvmvVBiIkdDFQYSUVvKkuFfsLvVpPlyXTHhmgGMtKiQqGdDgepPBVvbpPmMLYnTtgAVzYWhVPYwWRoFnMhFfGgGgSUuiIlVnkKvlKoBBbbHhCXPOdzIsSeEZtTSxXuUXxXxzcIxFfFsSfUuTBbcQMmGGgOxXoVvoOOpZsAaBpoOPyjBZzjJbeWUCOARngilyvVVjEuwvVHKxZzkKUtefFefOZCmNNnsEevoTOpdDPzbZzkRCEepPlNyHhZmfrXbXSOoZeEmVvyefIPpKFkKfiIbgdfvVCcnAawWAraARIQqJBpOowPpVnWzkhHXPpYhyYNqgGWQFveEYPWaJQtTtTdDyqQDocRbsNTtnSdgjjlhtDcwWCdNmeEMpIMLMkrPtIiTPppRnhkmXZzfFISscCtTwZzQlLRrHGgiIMYqgGDnNdgnxYyXUzYIWsNpNnPLAasSkKcyYCEeJODoZeaAEvsdZGfDvVjUzSXxlRrLRlEazZPvJjIiYdvreWvYypvhSsjJUuwWjJiiaRtTrbBAouCciqSPzCcZpUWwzgXQNLMkGgKmbBSRrtTHXzsjkAaLXvVlLnLFfrjlJqmnVvgZIJJjRKJjkMXFfrzSAWSJjNDdSsKDhHXxPpGgXPeaAkdDDnueuhHQoPCvVWgGwginCVvCoodKyGCnZAayYTtWwzYypgQqGVvPYErFfMsBbkbbsmlMmLCcMoluGcNOLlmMMmjsIDaAAzsZRNFfndYQqgtqpapPWnNwZBfFOyYgxXGbGxXTDaFfdqLleTixXbBrGgIikMjZzzAferRhHUuyRrfFHIpPifupPUGYywwWHZtPCcHtTOlVqQqOZGtKfNuEKUxDMNnjmrxsSXuaAUUXELAHlDdLtjJjJKkuUbBNPBbDIAaYMmxXmaPppPAMsqQrJvRjJjxQvxqQXhYXxOafZEeECoBbrcCRJjJIiQqjOrRqULlxJVPpBRrjZeKOhytTdBotTmMAyYHhTMmRRrriItDdkiIIiCUAaPpqQpiHhyYSIMssDJjSwWKAOEOoAaBIxXsEeZmMdCclbVLoEpVvcKUukCeEhHUFlPmIEeiVvBbRKVfZzQFFKQqryiLlExPWxrRgGvVUXMmWPpmMwafFAQVvgGqvVMmxucCcsSLOAauUwesKHFffuUScKGxgGxQthfFCIiQOoQgGhHOUNnbFpecHyKJSjJUmMuNnnOMdDdrAyNzUWADdQCcqacFpPdDFvMiegkDULtpLwuALluryYKkjJRlQqJjLmdDvuUcsJTOnIiablBRSHZrrJjQqZzlLRiIRBbSiIsGYZXxZZzTtDWXAaxwrFfkjJkKohmMgGOBWiOluULiAaiEjJtTyYhNnqQMPkKrRSoViGYXxyiIFfcCgsSkKuUDWoptTUThhCQsYLlzuUljZzKkOovjJOUDwWdtFaDPSWZzzFfzcCZAwQqUnrBgGEXLlmMPpDdAzmVvKvSsFbBGyYgfpPqZFBBblTqWwGTQLlCcqtdcCJGctgxrRJjlPMCCccDdXxKmXxiRcCQqmIyYajgLdDBxUCQqcmrRcXxSswWohHOkuWVeNKLExXnNIvViWYQSeynNtDDytFMOhavJjQqawWAlLKkVPpsSvZNlvVgGPlJbOoBPpbJInVvtpcQnNWebTydzZdIhdDHVYARRrrHpYUumMaABOoCbIdtCTIhVhHsSpdgGbIWGOqLCcbzFfSsgWwFfjvVXcHaSsklBbcueEkQvVbBjjJHhdQTtsSmQqCsSPFxUXTcwWClgikKIiEkkJEKaBbAkwWMzIRIhqhgRBbdDVvULXAuUaxVYyDKiIyYeEEGgjJjpdiHhFTtfcPpizCBckKxXFfuhJjUJGggrRmuUsobvcTtvJWwxXeOosOdDoxdDExHhHNcEvggAwrAasasSABitXEdmbBEeJjZnbIaoyYOGQymMayYPpbvVRduYYyGoOjCBhVwlwmAqQaMxUXEeucXxbTtPpBbcQqWpPwWMmrVvHTtGIicaafEFvVZzvFwZwCTfwDeXxDoDwBbgGWKFqbBQfltTtTbGgPTsSjUHwrrwfkuWAgOWwjvVFidjbYqfFpTZOnhztiOoXwWXqyxkQHhVKkqoqQfFftfbBbEeRmMzLlTXyYxwWRriUUDfVtTEvVKkRFFhYmCcOovVMmdOoOoRrBoBmMmKuUccrfFNXxenNtKkTEOgGoMXnwizTtLGglwWNdFEcHhGIdDrQbGQyYSHhshoPWsxunxsSZxEGpVuxXglLJeEjGEYmQumatEUPBVmMgGJHUuhqdDPrXxpPpPPHhrDdShXMmDtUMmsSgGqNQJjTgSLyJjKKSskWYWtgGTRfFHjJmMaIiAkKixCkqadegVdNcNXCcZPktFuYyvCcoOsFDAEteGDdXxDKkIXGpgXnyWbtvMmrNnRBrHhuMPoefFEevYyaoeJjCbBQgmSsDdocEEqWwtTxoLUFZzzXtCesShHPpaTvleBIwWoqRrQialJaIiAbHMTzZEethHuBWnZSsofyZrQUDgrRHhGUgJCBoRrRoqGNOSsdAHocRtNqlbOoBzJcxFLlfAaWoObKlggXSloyYadyYtTUjoOnqOZiCIgpPGMAOodrrJYMdCTpPtdABbZowWKdIFNnfiuRQNjJtTdDJkmMZYygGVvlKSjJsSskFXdPyYmfBSQqsxXOosKvrZoQPbuUwwLlSUKCcKgvDdSWUuyYvVwIxlhJjHlEZzaAaIiKpPtCcTLlLCclkkfDdeEsmMjwcDNbPDdDdpBTteqQEnoOdRrClfxOtTIehgueEDQEeTbTCrRaAHaZAFPpfwWxXvHhtTVMfeuUjqAaQTaAqQIILUaQvVjJXyYCcmMaPQqAzdbBAELlbEbUtGIvVCUpPupSgWRcDdlLUZzucOoCavLbcaVKmIiMkgZeEzxOokFvxXVfwWMmKOVvFfPdDpIkSbIoZzYyRrOTQqQqblLkKRPxTRoDLlqtiIiQqIsCczPMjMIczkNnKyWwXxKhHwZzEQAaqpqWtUnebEeVAfxuNjJgwiHADdqcPQqpMmucGWpQnNFcSYnYyLmRQzZqrMmJPpjMMoOHhJbBOaAcImlnWwRrqQicSenBXWCrZzAYjIRCcCcrVviIlxXFmMuUwWBSTyFfMmXxvhSsHDnSsQVvqnsRRrrSemFhhMfFluUreEfuajbOSDVFYVFWwDYytQGgJvZsSxXVOsFJFfBqbBPpvZEAaeCbBuzZUjtMjYyJXSHpNQxXqwUulLmcCTnKFOTYgTkuUabWiWwRnNeIVlLRdWpGEwMzdaFOonkEcRvVvbBrbEeBRbBoSlLsPpOoOVrCeKNfADNnZmWegPwUuDrviQqErQqOUuyoOYoxFfRrXfKkFIwBAKNnwWtGytofkNgGtMUuWnPUzZuhsxmTJrRzZcqQzVQbGSTtsTtgGgjfSovVUuvLlxXwWzguUGVjqTTtyYdfvyfvdsoBJAUAaFXjJxRuUwWQqLmHrRHfMENNdVYVzRrZkRMmrGSZzsgQqVvKFfvtsbfLiJyaRjpPJcwxbNEsCINQEerMmVvRqsSnNpPLMXxiCovVRQqrAuUQqaFfqdlLDQjvVmlNysCfqPwgGdDgCUMmCQLlahIWGzZaAnUXFavBENubyqQYBTOhnNHIirRowrRQPeZzWkrRYZCimJxXmpZSSsTQXxLlyYdOrtXpNyYnHhrBuUhHtxOoXoOiBsKgQqWwGsSbTtSsBijJwWoXJjyYGeEOovLlACQqBlVACrwGsPVvcZUuzVvkKigTuBeBeaDfFpPZtTapAAamMDdJjqQpPxBbqAulsSAaiYyiTteELloOPptixXIeUuEJnRrNEFmSsfFnNazALlhrRctBtqdGmMgdTtDUGHEidDoXeEFLYyWJSvAaVFKAeLhHLXirRgoOWwGsVGkkuhHsWWBIipVJjvqOzRrRVkSTtSlLWwsbFaAMpDxfLzvVKjnqrUIxxXXiDXAaxkOzaLvVlDdDchHDmyjREeAaRDOobBayXeEuLlUbBUuxYmicIzoQlLSsNJuZzDAPpOLsxGGLkBwvcCVAaXCjZcCLaAQnTrCLlYyOhaDonVvyEeYgiIQOWwrGgObcjGuduqRBbzoOYFOzNwbUXkKxEemhBjLAIOibEEeLVtASsEcTxZJjYyWwdZzDfulOXhHtTQeeCOwmMWMGqiIcEkKOAVEOnNpmULlRoObVTBaAXxwYGgNBbxGPgBbjJxidgFfEZzztTZTeaMbBmdfKkSVUfTKpzNKknaAoOxsSpPwWnCRrnDvPpGEXxDAQKcXIDdhrwywffFFYykYlsGtqnQZzpPgGuTdMmxHsRpRrUuMmRpJjQjOoFfvtTbpueTAMGgUqWiIUuwMyevWwVxXUvPgeXzXNUMmXScLlzZCwpOHqWwQqgkIicCgwWDdGKBqRigWwCefDNnnZIWNxZzmZpPznvIiSsVXxRzWUuwZCgGYyCkMbOMmbDMyHffrevFduuXxItAaXxZHhrBFTFfcCFOQvqPpKXIVviYNnQxUuXiIxxITZHNoztPZzQyBJDIiIfIiJoGauUwUWwKFWRRWhuJtpOoXxBLkxXdOdEdWKkFtjJcJjWzWvVfVfeFAACvVRrghRwCrZzRrRGgZBbzBCURrOoxuXQqTTttWbaABLqQWvqQbBHbceEJgyIhtTcCHTtiUDrBAiWwaiIAIYqOogAiZzBNVHhvOozSsMDexTIUubFfrRSRWaGorbjvqQVJBROVvGVeCnhXeXSMmEjVTtUuCVBOSuUMlLGjuZzHUeECbcZIOoCMmlLvSsVIDPJekdvHhhHuUlurGHFfqQMmQHiriZuyYBwWbBbUmejKTtKeIgGhHGLtxufFXfprRclLMZzHhPpqDJqKMtTmFfUzZCLbjLlJSpPsBlLKSPpsAhDdCtTxXxHDdhAaJpnNPGZvVBlQogwiBtTDPveEHitcTuCjJcUDiBcbgZzoOTQNCcoOnqYyttTGyPhPpHhawWyviDZzDvVYtBEvVwqCPTNijIMcCmiBjLpLnzlLVAHTtomfTFfYddTYEsqHzZhywuUelLQqlMmknpPEvwZzUaAKoOCMuXblIiGJWXxJjwAitPpTEeMrIMkfWwTtFmpYyLxXTtmMXGTCgjCcDqQAausSUgQtLcCbfzQsaASrRmMPpVOokMZapPxedDbRNuWatTvVZeEwspdAoOfJjTzZuXxoVSshHZhHzJLZySqcHSsHtuPOwdIoOvOsLlxXpmEgGaaAhjJgFfUuUuGHAeHvWwPptAaBbTVfFeIIoIwbDdoPpiIHOYyKRFfdzJjzyqQgYyTtkvVKzhsvVrbLBAWwwUufFWNotjfFUuSCVMajJAkjJKIiqQbBAaQqOoUatTUWMmXxcClPwWiITlkbBKudKGEIYymVfQqAJvVjafCNnwFfuZnYaDdRDmoVvNvVsjkKskYUuhCEPyxXYIWwiffFBpPuoqDdqcfFFEjJOoSseUufTtHTqXXgFKkfsSkCsFhjJkeESEWAQdDqBMmbaolCOoQkKuUGgqXwpXHheIYRYyVvkffqYqyYBbQOoqQPpypRrPFvkKkrMpLcTtQqCfuZzPeOlEevBLEaEIieKkAeDzSiUubeoavVksdTtZzSJjSmisCcIPucjJOoKLIuUilwWjJaObDBbzZlLYHotTkEzJbqQDdYyvqQzZjXBbhHuQcezFrRAqQoyHYylLdDxoOXVKklLqXJXxHCdMmOoDchrVjRSyiIidPAappwWneEpPoOzZcHaAhCThalexzZkKjJZzJjuSslLsSRMJBbmdXukeUnFuUxXQrRqkTaAgzOSsPpoiIoQvLbBohpzZnNTzhWMmgrRFhkKZzDdYEFaGgtTZJWwxXmKRItEQDAdjJtBbgBobIizAPQTGyDrzqQSZbBadiSJxXoFpAFfiIaPfnCgULrROSlLBBKStTmRjJeyNqQcgYpPxtTzZXiIkDbaABlCcKkLOOqQccdDNIGcBbWwLlmMpOqUEeEssSSDdAaUNdKyYaAEIipxdkStTsnWwswasYyDdZxXPpyYgGRNnxoOmtTaArjizGNMQBbjQqLiIJRlNhHvVUuxlKJPpmMSrRZxhslnlLqiIxGZbBOousQIUudDUIiOIIHVPnNVwrRERVWXxwDdDGgyVpAFfeQqLrsZsSuJQqdFgRrztTDSVzOGgdojMnNNnmlkKnmMSwiDdyQqZuNGQymCcCchqZYyNtTnzWiLlxMaAkKKHEdGgBbuAaUDeNVvKmzRrZyYujJwXxMmWUEelmicCkKnNiIUtwWTuPBbtTHWwjJFqQfhnmMTHhHLJJGDxXPpMmBrCOdrRWwVvnNYoOkUSsuKqaSsAjAkKJjwpyVfqqQKkwQtTnHyxKZLlRrwNvWPaAoOmMbjwWilLaCcVvhHcCNZzWwtTFDdDGBxXkiFYyEYMRFfwWrzsxuUBxRFMzYUunvaABbSsVLcroOKZzpPYyBZotOVxXSHhpcCPnMcRWwzZdDrzoFEiIeEErRQqTukKXkhWUeJvYLUuIGNraocpPuBbwEjJJuUOfFoYDdbSzPlLopPgNnqCBsSbVvtXiCZsziZDiIopmSsMxcOkLkKVNvIiLsHJjmCcNqQfmMOrypvHwyZvaGNylAuUaxXEIilLIkxYcCyqfLlKxXIiMmOjJobhHTtMMPAeQBRMmwRcTVkpCFqQatNnJAbepHQnhDlLAadnlkKLlLRCcrLylLkNrFeEXLnXxNkjkKJhiPpKXpZiInQmHRPpbBihHIbtTweUuYXxwufsSFUTXQApPpsSPlqQxsSXnbfFkmnNMnxRrRrIiayhPKjCqQYlTAatUCCcpPckjJAmRVvMwLlzKWwkQqfFfuDgaFrRntTJwRrFfVkyXMmBbWwkKPQXxrRBboqyxmMWwwLqQMIiVvVOuKxLlQYGFJgGYqxXrwOogSOuULKklosTHokKsQvTrWiIIfNnFbCuhOZiuUQqhaUuOoVqKkyYwcrDnNGgacCcPvMuUvVmsSRrjNngOtXOuUoRsFfbojeuhhHDeWwLLfFsNsoKkYmzZxDwtNOPvffrKkQhHFFuUfpoOoOtTtTNnnsIiyzZYBBffFCqQgGcFfRyhHOpKnCoqUHvDhulvsgGiIoOSQqYkSsmSFfLltTSLlxyyYtRwWiIaArhQqsaJwSHTtxtUuvAaVvVdDXxZngGzZGrEYKrPpncAaLfQHCExXDdbIqUFfwCTjYMmNnESsIieKZRrgGJjiEeNNnnIowOlzXQqtZQSsOFmDkWwKRrlRJjFfuUSiIsbBTdPQgGcCqoXgmMGxEeAaloOPDAKkkFKxFUupzYyrRJlLLnkVUjXQwxMmrRLXyYxIiTtlLHrRraAGJuxwGgWXUKDdMrkKRZnyeEOoNnDpCcPiRruUICcpSOMmoVVTtUuKaAnsRjCcJcgGfFcCfpMcxvuUROpchHglLGjJUMrRmPmMHhOooxmMecWduUBbDcCXYNnyPsSpVHvqTtQsjdYdDmMecrLlmMwWYJTCmFWSsaAkPeEZYFLZzhEJuPvVkKpJpPPaEqJLlLkKvvlCcLihTnNUfwbBUuyEtTiclnVlZnXxSnNpNfFiJdbBkrVhHxwWZzXcQvBSsGgvVgGXJqekFfrBoObjJRqQwZswWlyUuYIihHRdYpvVvVrZzIiSsLGcFTtRrvAfFabQqVvgbHQdHPpFnNfQkZzCbSsuOoDQqeEMmRFVWwYlJtWwTKJKsWsYySwiIxymBbMYiXxRruUYyBbAaBbUeEFkKRPprTqQiIgrgSUuZzsNGgJWOLljUubBJpbRrIiBjJGIhBlLtTRfFXCBKAaiTPIGqUJjlLuNrSRrsRkLlKEjJpIiWwmMSTByGHhWOmEbpPfGLtxXTvNgFdxxEeyLlYuFJHhjrRQqNnSrRsPUlRHhGgUSsPaQmzZLlaAzNgGnZMoOSsOqKkvlpYcCnhHTebBHJjlCciWAaCcVvWiZGvnNOulnHqdDHhKTNjMHtTKkNNBaTWqQIiVvwSsyYlgvVxhlKvqwWSsrRxFfCcjJRrvHrnrRdDxHvVhnNXNbBuOJfaugmaAHdDZzPmMpItCcXxCDZTRdDXEmMczBhAaVgGJjintZkMsyYhHXxUunIqQcqLcCwWljXhHxpCLHhGgsGMsuUcquUfFCvVcOXmMqQncfbBEsSeomYkXxRRqQEQiIkbiIxvNngRcSoKtwgMmbSSfVjJfFGWfVOoZaHrZzNDZJhETsSsjmRrxXdqQDLwzZFfzDdAaOogwZzHhThuviIVgGviekkxiIUVYQVvnHionwWOzPpJjOTtrMsSATYdeORroxMuHcKPQRrqiUcCKkuvPfATCVvRQkKqECcstTMtTgGwWFfhbBmaAHhnNMbBUrRwWGkKgGghmMtrOoMQLlDmsiIYVvyYyjxXJFJgGSrRslLmmCadDAKkcIiOxYybzFwOoWjTkKtsSixEeXhVvruZzUZvVzBLinTjOosSFflnNJJntoDKLlmMDaMmMLlceEBbBRrfiHhItHhTqSjJCnoOsgbNnEXbnNhXxoTtTvBkWVbXDxXmtLlJvVjTeEgGVYyvblwMmhJucCUAaEeGpFJjkssMtTmQqXsXxSRJcCNNnLlFHvrRXdIUuiFfnNqDdgVGgvPpOCDdguUnzZoOPbBpNPpRjJnNTtmeeoOYZzQqXSsShPpHliFZzRGHQATtaPKbOgMRiJjrDdYEeQbeEYyxeYyEkawxXHhWGMiImMxISNnsOoOpAasSHhPyIilQqLuJvHAahVArRaAnfFMuGTrEgPyNzDzZOfJWVvVKnopIHqVvJjymGgMAxXMveyMdDkvVgDGgAZsZzWbVGMmQRRfTVIiWwtirTvZmMzZxmMYvLljCvVcPZzDyNjJlTtQqwWeEMmdWMhHVkJGIFyhtTKLlncHwkKOtdbBtTqQfqQebgGIpOoyuUlHpvDLZzldVKkGgmMPMjPpZglLsQqMcJUuOoRrnNLPhzZHXxAaiIXxNMwmbeToOtwCmLlMcWyprTthRNngGrHRcDQPrRpLANAtTanEealjmMITtHCcHvYyzJcCGGggNnFfbrZzdovVnNOeTTaAtQCXxlqIiQuMOEkkKcCDnnpTDnNAatGkBgGINcPSSXxmuUMOIihHIiPqNnQyRHhKiSsImtdQqGTGglLkKpvkHhWQiqQQqqQEeWhDVfFOmsOIiobdyYCgmJOsTHRaYyKFfiyYPTtiIpDmczZCWwqRYybBtfBiIdrpXRrunoUuONhauOnNLYyKVvsSkJjTtoOIGgBgjFfOUQHPNnzZpxXVlkKzZIhcCMRxjJaAjEatTRJjrapPAgPZLhHrCGeEPdHzZhvlLYyAaHfFhoPnNDrRlwWzrgGRWqlLQPeseESpPqQcCrdDOoEvyYyYnNveEVXxIiiWwaQbBIQqUTfDcQqRoONoXVgGkKitTIvPPfwWFjeEIYyVHQoOOuUnxPivqKkqwWQeEQcBRibTBbQHPpJYNnYKOJjkwWpPnIiyYRffvjJALAptTKOopDmuUajCckGQOjrRbyYyYPpSGruhHzEyGSsPpBrRekKOEeYXpgZyCcZQqNfrCPwpPrRPpXxWoiIsBboXMLJYyXxiWGmIiGgMWwoOgNcCguUjGrETUuXxzuUaAJjHhvPBbSEgaAdDyYfBbFiFfylhHLczLGJjNkKnoPplWwLlJLlUmXxSTKrRzZYbggCDdGGviDJjUukKfqQBLgGDdgVvHhgGCNmcCoRmMfgAaiABQBXxBbbBdDAWThHEeqVvQtwhhhORdDraFfaMAYytmoMxXLpGdDyymiNdKgqQNnGgfsSWwFEqQjhblvVvaAAakbnpkKnkKNYmMeGgGgXxfnKwwWdqQDbbBfFaATzNfFDdJjnZtcdUOoulIaAMkKIksogGCMlLmHOZzGnNgEPpsSFqCFfOrsvVGsSawnwWwMaJjAmOasSdDWwxXAcoOoWdrRvVvJjVDQqGPGAaDdwfFZNPoOpwWRQDdqWsSkKnsmDnciEeICEDdsZzRrkWycIjJiUumMuLlwPcCgxXJjvVyYugXVCcvLwWlvTtVOoVIunkgsSpPLlkQJjcVyYvFOobPCcnLoOHhpgtRgGrRuenNEUWCcFkKgXxLKuUkKkNbkKHzZhWzZwBbBkKGMuUmIigrYyMmUufbBQdDqkeEokKcCVMmvZzuUOVNBNBDDdlDuQrOoEeOTjTHhtJtpPdDknxXNQIbBiGIiKkzVBoOBJjLlOoaAMmbthHTXrnNRUsSifevCXYyoLlGFfaAtcbBapPbZzOybBVvYvVCAoyYkwopbBKAaWwkMgRAPpaKkhOVvoHhpHhLlEtTjfVgmDoOddBsSTEoLDlWwZZdDbNhHnbBSZzpPXZzxMLlAjJEeOovmhHlLMmnNlLkCLlLiIlcYyCcycMmwHhXnQmNDdvVoQqgGbQZOeEonNOmsuKeRDdrEjNCcdQGZqQzgaANtTLldSamVKkjnmyYWwxBmMFfZSsuSyYxklLAjZHVumMPpHgAIWnghHHUufWdNaAYyLlnDwcCiDdLnGvisWUkSUAHquUVvNeEayYAnDNnfiIUMZdZzDQOcCupPvNuUnBbVJjOoeRtQjJKXxknXVvbhHBVhRpBmRrWwvjfEuUUuQsSjJoZZzFfbGggGDkKOopPPAapzZPpPmMFTWwtsXxSnbqQiIHhfFdDyYbJlhHaDIidiIqrDnNAIiJgRrGcCgAWWIFFpdGgtuUTtTpsTtqlLQqQtaAEeEeTBaGgnNJDdRrjCVvcfcWwZrRyYQRKWwkZSLyOoYoOrRUuHEeiICvXpPxpnSCgGpQqWJTqAagGnbBeELjfvbBxEeBmVDdvpPFCcpPEkoiIAQqnNPadsxKsSkZzEomMNnnKvURrfSaPsstjGgKknTtIGgiNTvVtJCcUuZzPVTthHuUIrgVvBVnxTdhPpZzWwygtzAQqmfiXjTLltzZcCZiXxWyTCctFtTnNfFfiGdLNSYysnpPBbXIiiIxBCcJhQLlhgGgGGggfebCPjtYZHhVvHlLhdFflLDdGgEeQaOvjJmFfzTVvMCuDxhHdnsuUSOoJnvVrRQitdKTbuUKnrRlbBLNIWwicCPfFpCcmMIPlpPOoDdbBbwWBDDoOwaAOoWrDiIyVvYzZICmWQhQTvYyVtXjmJzPplLKVvrRSmMsGgkaAtXWwxLlVFfZVMmyYTuUtKRhSSslLsuUNnDdyYDdudDXxHhLTtlUotTrZzOopPPOoophHrLuUNndDcHzQsSqNbqQiAxpGgacCPxXgNnSsUyYXxyQkKqYncCJQqNPHhDIETtCcRAlJjAaJrmMHRrSgGgGfCwWAgGCxyYDdmMtTDdCOfFgCOxiIXXwWxUihurRUuYIisnPiIVvFOwMmuFvVZRSbBsJuggGJKkjlIiUuUuUWwvVvsSVhWwdCYJjyNDyYUuAxjJMWzZjJsEeJjQoJfFjOCcqNKknUuGhAkvVwsSWKRDeEbBOoLNrRxoPppPcrmMvVFfhHOElFfLCcYgGOoaGgoOAtTNGTuUtZzgtyAaBbhLDpPdlGyYFfwWqQiEOuArRUOtTzVvIiXxpGgvIiCNnEeAxXLLlBtTjJJpnNPwzJkrvVpPRuDdIiIoOiEusSUoEeOktTKaQsvwMmWfkiIOsSuHtThzZYyTtBreHTBlyYLQaxXYjCcJcrkKlafUunNFUrIiiIRpPcCqQATiItaQIikKwAtUuWwwLlLFfDxXfZzVvRhUQnNqeGgjJifFUuIesSEYyLllBBbbtXBEeHhNnrUDJZGgMPaEUuTsYRrwFYOGgowWRKShYycCjJHeEDCXjnSBIipPblLCNgGwInNiDdBbuwWGgKksSXxroNVIMgGmIiivBCBfBZzNdDnYywWkdhkfFTnNmkKCGkgGKEdDGIRNnBbBsSPbJIiIyrJhnnNZzwWSXxzLgirlLRXxnNobgGBfAfuaEfFeAIiXGgxmaAtRrRrvYyVFfXeEVVCcwwJfFEeUGgzZuUkKOouMRrVPGggGpmMEefFvmMSsIMosAaRrRyJRrFyRUuzdpYIiXIixaAdhvaXkKqGCzZhwWVFfvQqhNPmUuRbZzrRVvEePpjJBMCBbcxFfUuqQXSvVoQqOshSvVBjJbsnDATtaddAJDiIeEVvKXzZxQqszZSESLlsDdOHLlwdHBZzbhDDdleEKksGdCsKkzMCpiMlSHhsKuUkLmqKwnMmkOxzZAaXbBIdorDdmMfeOQJjqKgGDCccYyNnCwTtWdZVvoOzhbwSsWaPaSsjJxXSwWzZsjocCOCcEeCcEFftTYyYykKLlLtPqQfNxqQXOuffTtFEeFcCQqFbjlIWwatnIihXEeraARHhGlnNbBLbBrRdDgaAshuUABbiOYyrxuAMSsmnNmMLllzZUfrurRmmHbFfBLOcCnZzIAOHIijHhwBSDPpdseEIiNMSsKkbBeEXuxXIdLoOQqPSsXbMmfUhIiltrTnNtlIQqiLJQIiOLUMfFSjSsdQOwrRzZgGWwvwbBLlhHPkdmqIZzMUuiSiIHhHhsIhHWeEwEXxsKkRBbrJWDSkKdDUusiQqshsFuIikyYKYCPkZprRkKeEPGjJjneBsSvmMoOoBqLpEXxXSDBbdsUbMYezRLopPNxXuewTmMQidUcCcCSsZzFXPpnlemMwSsVeaAEAQwWeEqMBGgxgElCcrFfEeRWSskelLhHKkCcprGgMmxXdyBgNnwtDdkdYyDJfQdPWMcCjYqQHhwmAJTtvVjaaxXAhHkKURrddqQJjKfqQIyQqpaghZzqboOHhBQHtTCcfxNYyNHhNneBbEGglLAlLghsSgBbVVvzZOiInNkKkeEEeKHhYUuyKkooOvVvgABbGEWDFHQxXxQEeEeqoKyYkGRCRaAUvVzZKkhHvVufFdDgFnwWzeEAIEesSsSCuAasAZjJzUUuuZiBbLJByYZzwWArxXTVvtSPpAErReqKueEDcDOyFnrRlLkfFrRxXKNyJyvGfFmWrSsVvBxXQsSqCcxeElMFItDdaPZyEeYCcCcYldDwZtTzBvVUcjyYUyYufFVvXxspUuTBpzirsUVDYVPprRbBojJSsoOOYyYPFlYKdDIihKCckcCXFfbBBymMDdYHdwWivejJYddDMmfFnpFfPMrzgfwClwHERrOlmMLjJnFfSwORrMmoxYyKfFUuPRHskKNYynSzgZtVvTIGwWgKCczwCWtgsJIFfiFfVqkPpvBbErReEeRXYycCCcmMgGjdDkOoQqKJufMCIizojJwWYgGYyzZmlLUrRgSsjJGlLpPgqQpnNIzgIiDdkfbMUuCcYkjdDQlwQMiqQXexlwWhHluYyUbBoOmzZkkqZzWwjnEvziWwvVHeQqeMmLlyYaANWtTbBjJZzwnVCIvRTyGgkKbBSseYyyYxUuVCcSsZBbdDvVNxXzvsfFNomMmXxYyJPcCToORrtIiJjLDdlKkTjJWtTwjWXxZzuUHxXtPpnNJKZAacCzjJZBbUgdDGMmlbBnMoOmNaRrgwvbBSHhsVvFDcxFZzfCcuUgkKdDAadbvVGoOgpPSjyYYqohHOQwIhnwWBrRVPpWlzMPoOpZzzZBUubhCnNlLvjJVeyYzCcZQOXJjeWwlTVvlLUuYyXxtLhWjMSSRrNkpLlXkHHZzhzfFxXQeJVaWzZwARBbrvHhjdPuGlLPpCFxXIIikTtyYYydnNDJkwOoNQgGofJjVwtRrTCcWewWIiEncCiINyFfbnBbNBjJsgzlfFLXrRPpgGGgrSsRsvelZBCXxjJczuUNnZxXxrRDFfsSsBWQrsIKAaNvSsVnkivvIWnNvVSXYlLykKAkUuAaIiBvyGlLgwldPGHhgWrbBCRbBeEFzZfVvgpPrsyYSRwLlpPWMmarRAiIGZzmyvQgDRrZgUhBIibWlLSjzPpWwwkJjHKitTZdqQnWwuuUUyYNKySSuUPlprRQEOyYjJKhHNrTthmiInfFNiZQCcglLCcqQtTOoGdDqBlLbBbexLJjtWRMmrjwmMyYWHhgGNeVxEeXXxhHPpvXxejJQqKkxmizZjJqQbWwTtieEIecCUHhuESsQFfXxzZFfMAWIiEWjkVvmMuUUJjKikhHKDTwWfeLmowYgXxFAaBbfkGrBeMmAaAnzZeojJVvOCWwdLlhHPlLdDEVvoOeKFiCcvTUuKDfQcOBbcCoEeOoqQGPKMmjaALiUzaAZKqQarhigGIHvUuiIVCczZVeEvlJyYjLCGQGaupPKbBkUAgbBYbcCeEeEBBOtycGIPpFAORTtookKfFObBOKBjlLahUNnaaAASSTIitsJjKksQciyKCUdeEDEeFbvxXVBfdpPDLlhHWwjkmwWcCMPqzZQFMHgQqLIiUuluyMNLKFyYYnNyeWQtTqNXHlPpvVLmdqFfQDHJjfEkKmRvVrMiIeFcCVvUFKkfZWzFdUulFfFKwSsWuYSsDWwtTdbHhBVgYUrTtfFqQfEnNeFUTtuikgGKUufFlTtLwBiIEeryKoOiKkSscCAiFfWwkYSsUAauyKrRXNOofFPlnNTbBtSdKkPpBmtZTtTtHaLvkFWSswllGFCxhaAHXNKkqUuRnNrGEOgvVdpuUPnNDYGBLlhHXxUXxQqylKoODErGghXDneEODeEdXfFGgKkLhHFWujJNnUKkwtbBlfFRnssKQQnuUNpZzPqxmMKhesUUnYkKyNVpzZyYjJcUunuUJdDpPmMBbYymMplTbBcgqQGsSiICiSsItZziIrfFRSamMTyYhveEsqFfZTtzJDVvEcCccCZFJjuUPqUlLkFoTtLlIRrtTmqQKWwsSIKkvVitDdTOgRnNFlLQqflDdvfokKYJpPjnNnIvqQARAapPIXxMmPpiqUuQrUloOLpPOlLzndDNZRrigGnHLlvaAVuUCdDtThtrRjJaAVvBbJjCcTnNUrRpstOoxvlChHchTWwthAaXsyYBbXxSHhpYyPMmgfFDdOzaAZyphHPYDdZzZVoQqCcDdVxXBlLCcfFnNtfFNeExXzZtCcZzEtlBhHUubZzwQTtqXjJnNDdBULlukpPKiOobvWwDOZzhzZHWwojEeoVMmvOLZzBbWiLleEIWwiIwKksSgQYDIiDlLPbBpntuTTrRIxgoOrRwAHhZtTarIiHQnNqrsqsQqbKkzZYAVvNkKIinszZSDIidMDeEiuUIiTnNtGJDGSsBbTqSSUAafxXxXRpFGugGGguaARDdBNnPpEeWvXxAzcJjyMgDdDoOaAdIiqbqQgGVVvCcfRuUsIcoOWHhEuYyUeIVnIJjGbBEenUNnHNnGEQqxkCMmcKXmuTsrRRrlXozZwVvQqWPpOouUOxZznNvVpPXUuxXxHeEBbcJjLlCvVaSSvUFxeEDmMaQqbwOgLSsSseTtOovTtVqQkLzZDSsNKOokkFbBjgGJYyqQfmieEzyPpYuUfFTWwIUuitYSsLltpPPJjpSbBJjLladDherRESsYaGgsSMmpPCGBbjfQqxXuUEAaqHvVdDYlGgmMbyIWSGmMXaJAaBUubzbxvcCrWwoPDwnNuUtTyKCKkyYEjJbBpCcJviIPzghHXxhPpHawWfsDdiIsSSmMBbqQxJkKbBjuzZSsUnNXTtZFzZAaxIuUWwhHTCctpeEZzAalfFmgNnGMtCcMCcWwmWozZEeBQlFehIiTtmMjoOJdDTtSApPaDkKaAHQqhdNnPpsWLotwWUjJAZziIeEaAahVvHGgbBJRrjgfCcwWDTtdFHIidcKkbBCcoOUuCNmMmLlMnFqQYyfJeECmVeEIivMcvVmjJeuUBgGtDdCbBcZzfVvVvFTUudDNYHbkKBhwWiUGUuFsSfgpZFsSSPwWLlBQqbQqkWwHDdDdDdoOhHhXxKuUdDeeTtsZwhlLFfaDdAjnNCRrcjJhkKLlViIwWsSVlIeEilYyLwMmIimUtTurRaVvAOoVuUvBFfOoAasvVxzZBfFiIOawWPxXWwWwKmMVrRvoOvVmMXxyYvVynNYkqkKEeHJTioOgGCOjJocCuxXnzppPRUurRwSVvEesIFfQOTtACWwcoWwuSsuQqwQbBqqQyYWSseSBKbycSKVsSLlxPLlaFgGdfFYjBmrJjRMbUuKhFlLmMYVvHpPNnhgGhHDSsSsbfQqFIibyyYXxrRAaYBjKkgwWSzZsIDdiKkERreJdDjaZSszAxCcFVTtldUuDLbBrRDhUupljJLCcPlcRfFkKdDmeEzFfZMCkRrXuUXkKOpWFIieEKktsnNbcCPhgjJzgdDGwWZGKDdDVvxicWwbBhptUuglLTKkqQVvlOFfojJRrnNLnfYyNnwWNDYyRraiIHFoHhhsSShHsmKkuUIioOHMaAesvVSjclLKfFJjnNYyKrwekKijJmMaOoAPHhHhCcYqQCZASseRSCcKrAEWhCqTipHhPzZIJAadYyrzZRrIiRPJGarTtRXxFfAdDKkiTpbBRMrJjDrRsSdBIikKQWYyMmRPppcvLlVPpCblLlLAaYyFsSfuUBnDdLlNpPvVpPfFjsSZKkaVvTtAvVxrOWZMRYyrGoLlWwsjnNYbBwrRiiPtTxXpIEeIYyyIyYRCKKkkTuUmcCpPXxQnNqdCmQSNFfcTqjJFfQZvVzXxDdbOoywkAaZrRNnPpzfFkKYyKKkKSBUTtZRPkKFCJjeEGgWwRrMmUFOofBbxkKhHzYyfiINnlLjDvgGvrJjvJzZjdDVKfFCymdDWWwwOhHvpFeRrEvUucCNnKVFoOsSPEPpeClLPmTtPNnpMVUdmMIHAdDdlLvVDMDdlLmANqWiIwgCchYkHhUuWwSZcCzBBbvyfFaNVvyGrRgfFJqAaQxvwbowNnIsSilLuUJjsSXxcfFCiKoOGgeEiBPHToOthmKkUJjGgJuUtaAUdqQoscCcNasSsSWXLlyvXWjsSJUBzIOoEEoOAaQLlqSSsFfQqGgsjJbTtbBBpCyYcEzVUuvQqXRrOoxUpNlLQqzZjJnmMzZDdjJiWwUuqQqQuxpwLmMQcCFfsXxSoOqCcTtrRrWuUaGgsSxGnNBbNLlnzELsSJjuVEPlCcLvAaIiSsVZzOoZfFrXxRUfHGghFuxFfSnIikKFfNnNHhBYydDhHQqhpIiPHhTCMHWwhmNmGHhcClLgdeDdZzgGWzZOoFftOeEoToOiwWeJjtnNKkEeVvMqQRrPSsOoGgDdIUuiZaAPpzIveEfFKKayYcfFCsIcCBbvaAPpVihqQzFfhQqdDvVaAtekKEKZnNAuUkKrroJlLfKkMmFFiIfAoOvDsSKkNEeeEzZnCcMGgLlmSyYyYdIgGiHyLOeEFwIiyYRrWGOodxXmMXxzZDIYBbFUlIiLIYHZzJjhqQICPphHlLewWLlEmBbQqgGhKHhVexXlLESsuKHhyYkAGAJZzjaLlNnffhHdVvwWtTtDdUumMRzJnwWNsSoOWwiPawlyJFsVvHhShHfjDdOopqMkhHwWKXjBbCegGmMSCcmMpaKTtkAxYHhmjcIeugGUfFEOoOeEfFjwWAaJlIxXJjiDrRksStjrzZReEYYyymMZzJTxaAdDhlhHAXxvVyRAsVyKzZDWXxtlLvaOoxXAQBbWwaAqyhKkeTtaAhpKVvhglLeAJmuJccCSxnAakKhHlLHKkgGhNNnGgCcJtTDdjsNNXxnmMXxMmzFDdoCWwcTtjJvVJjEekKuUMDXxBarRCvVgbBvVgkGGgJjDdgryYzZBmCcpOoPMmDtTnzZNdDhHXHPNnpAahxdArBKkTSstulLCfFRrcBmTtLlMbUetTidDIBpIbhHpPByYHMjaJjAJzeMagOoGYmMSNnXxwBdDbwnNcCeeEAaoOZzHZztxXTtxXFfvnzZNoSsBcCWwLlqQhxHkKUvVuqJxPpXxWuUwliSaoLlOKuUkqYyRKbBAakaAtTtTrVvQqMmbIiCpPxXxhAaHXOYyFfoZvVzxUrRJbrCcRXxzvVidDaAnmiXxImQLUmvVfFiGRvWDtwKfFkWiKkITBqQTMmtbEeoOIiBpPTtSIisbMmMBKkbWwJjglLGPUupNnZtTRjHlCmMcZWwDEPperYUzEeZuoaAOMHhEecDdCgGnvVEeAepsSPEuxXUNaAIiPyYQqKkSsJSZzrRlFfMCctDdSuUGgXZzGgXyBIIIiYygGNnvnNiIYyRwtTWFSsVvfPQgGZzQbZzBHnNJjSshxaAXrRPpusUutTYyCiJjIZSszSswbBvAolLOacAaCVdpPDWaAwFfAaAeEtNgGnUupPzYySsTOXxoTtvQqSsuUhHVHKkHhpLlbBCdLlbBbhHBtTkXlLxFftzlLZRpJjoZzOPrwWwWQvVyYwzZDfFKoAXxaqmMBbxXLBbtTHhIihhHHfFlGgZzjJLlufbBFQqyYPrxYyeyYVuXCzpPZcCcxvVyIirlLJPYKkLlzAavjDdkCcKfTtFJPpgdDGRrJgGDdIfAavVYypeENnSLleEsPlLlGgLyZzYJjExRqQugGuUNhHaiIAnEnNSsqyYyYNnYyCwSJjoXhhHzZKHhkECcksSKjdDLlKDdkGVCcePpvVEFoNnVhHvsSOsSuUfeEMmVvLlNuflLbBFUnSLyjXMmIEeiFnNfAaacCZzLBbtTbBDBzZbdWnNwMzuUZWwtTmhHVNMjJcCrRXRfFruJNQqhHVyeEcCqliILCOunrRHhoOCBeSlhHbBYydDOonNJjHHdDhhmMYMmcnoONXyYDQqSsPbBnInRapdQqhSSsstCJptTlLPsCcSxoOXnNQqLnNljoKkOxwWHnHhNBbnNNnVWwrjJROUuFKkfoRrsiEjJjyoiwWsSjJlLmMIzZBbPpOYVvWZztMmhHgSsGlwWLxXreQnNkhHCgGcbBqyYQVpaADGjaAJMsSgGmbbIibBBtoOTvVlBbLkKlLEeoOjJFfkKVvURruzZBgdDGgjJdDXfFxyYLSgGvVsPpCtTSscSsVZVypPSsYiIQqBbDRrNndNWwnoODEedVBblFfxZwWGCcjtTJgzNnQOoWwqrtTlGgSsphoYyOHdoJsSTtevVMmDmuUoqQOEeLlbBGwqQESTtKTFuUPlLpidDpPIftcCkwkYyOxIiBbiYoOyIXzbBbBJjSsZzZtTBbucCeEUiIjbBhHnNUHRrNkKiIfFGZzgzZUwrRRRrrWuNzLlOiIdDiItWNnqQtTJeyYPtmhMmUDWwdbBSsvtTVgGrZzRkShHqQsnNKDdQqkKrRuFfEiIemMVvHmwwWxoOZzXGgxWwXaPpABRNCcnUPoONnpAiIeEwWXxXcBbyYGPpexKkcCkKoOXguIiSsSIUuirRsSHpPbBhTHupPUAzZahHfAaFhFqQMmVmMgGUmMUpPeXxeEqijJInNKkQSMmPRuUfmMJzFfsffulLoUudDobBOKkTcCtQBbnNqvSQGKkglwtDoOJIfFgmdFfQTtYyufbBhHFeEcJjCfFgFfKktTGgykVUCxEepPFfAayYJiIWwhHzZjNSsnLlNnzOooOZVvWTtWwrDdQMCcmqRWjJWwRrWwCchHWVsSVvHhphHPJjgGMmrtKkkKDHhBbYmMydaAWwzzZzPtTpQqZeEZTRgvRrVQqbVYTtcCAaymWwQqNVDdKXxmMxBbWwKkXCcAakxqQIxizJApxXEePvVzZxoOTtbESgdDGeBatTDOodAgfCzZcFLlbTtOyYdSLHhDdSnNnNFMcCLXSUPMovVOdDYVDdpPvwFUFYyzZGgMmpvRrLlVPfTTiIXxtGOogSsrrUaXyUuvVVvJPpCcMCcsgaAYyxXGkKSshXUuJjFfAaBbGgQSsqxuyYSswAyspjJAZzsQqSsSvVIzjgGJbXxZfFGSsgtTwDOomuGgcaACUWJKkjVvQsSqkKilFfqbBQvVWwWNnTtwLVvwWQQqqcHOWwGlcBwrRWAqnBUubNyvVYahUuqQHGyAaYFxdDLlhAXxnsSHhwDdHhUuWouUXxrROVvQqXDdWgGweExFPpVqAamJaAMlLHhQYyqmUugRrScpPMsSrFLiIjJMRrmmKKkkMATtactiSsIKQqPhHOyUuBbNnhHAaXDDdNnrWwIYyavYyVojJzZeSiIszZExhHhhHrYyRzpPxiIYgGySsXcCOhHnNuuUUTthNnuUHbBdzZDkfFhwzZuUVvWHmyYmyiIWwIIxXdDifFiXFfMOomuUlDdNYynNnDYKbBJqQjkMybBzZBbYfFQwWaFfZzBbeKDzZdiIMqQOooWwPpxoOFziZzVOfFDmMFnbrhHAalLRrztKkqTttTkjJpPJBYyKkJWHhpPpPYTtywllLUHhQqTsSaAtrpRrnNgGECcPpLlzZpRtTaBRPprbiIGAagtTTthyYZzhuiRrIjWKkwJpZNhHqGhHJjcCaAGiIZtJjTUumbBizOoZIftTyZzwWUuMhHDdmaAZzlLrKkRNiIxXnoOZJJqQAajClEvVPpeWwLloOLfIiFsCcoSiInNxXtTEemhIEeeEiPpdDHQbBqTTiIqRrsXRoPLBDdFVvUuWwzZYyfXzEMmeZxosFfSOdkGnNgRrOpPVvyYxOmMOncCNooXDXxHhOhHznqQNZzZCcrRiIXxoVvUunxaAXNnNaApPJjNqQFfnMnoDGGgyYUBbuyYgRrlLCCcdDmkKIipPIiMhHZzWwlBbLclLFwWIMmifBHENnkRrVvKehzZHRrtAcKkeEjJsSeECCgGcaCcLcCDdoAZzaOojfZLlzjJFhHhJjmCcxXOohFiINnKpPqQkDddtTsqQefFJfzBTFfrRtpPbXxuxhHSsXvVRrKkUOFiICBbuUpgGJjwWPHJjIiiCcZzuUvNtnNTWwnVPfFaApIQqCcCcVejJEgmdDoUuOnNKqeEfJjFOKkoDzZcpPAaZiILlMmwWVvKbiIBkUgGuhGxXqDdQNnGgrWdVvDwbBkKJjRuUtTAaNKkngukSskQqHhuHhUSJIpUuAIymMYVvBbacCApPJjhbBHZVvWXxdDtTobFkrRKfBXDiZzvZzVXlfXUuqQVqQoUuIvViTrlLRrRiVvImVNnrRIivMXxIyDdYPpkxiIZzRwWBbrTiIHhDFiXxmMKHhrbBRkIZzfdUQYyqlLoWPMmpWwwsKkPpeGgAaqaAvVQNnLmMlyYQqElLSwWOKksqTtfFwQqWQSAaEPpgGedDxXnNANncroCBbLlZzJTtketSsHDQqdrZziaysSYSyYhHsAazsSqTrRtuFfOonNlpwPpWayYaAzZIWpQqQqsShqQHQtTUuqOXrfFRlaALIirDQqMmRCstHhTSbvVrRBNnBbIfTtFoOUHhmMJHXPpxkGgaAEbBeKSshaAMvmMbkLlKEaAMJjmiIILkKuUlbBgZDdXxXPsWRrwSzpOoFsSfGuUtdDYylLaAwWTaAMmmMNeEpPngqclkKLIruOoYyUrRusbBSjJUTtRKkkKGgFfVvaAHhXxyYimEpPejJTBbzSiIhlLvgGnohRrMzZmgfFEeNjJEXXgGxFfzukKULcLyYBHhoiISsdecWbfIiFfvVJsSjJfFjzheNSRVvrdDsSmJjDdMXbBKKkaAkxpUoqQuUOufFJjZzmNnMoorROomgoOGMZzOMmOTtrAamhHMwWeERLluUjbPpbBBniINCcJHhnOXxoNBbyYhHvaAVbBSsPZJtTqbtiaAIFfTtTWAawSsBBzZbKkFfLlLltAKoOkaNUtkOotbSsdDWwqkKQZzdDtkKTbBIiuOoYymCcMDIWwjIngGNcCHhXvYPpKkyNnlLWwAZzZzxcWVvlLwmMCiIXailLIQkKaLlUuGgpPADdEwWyuUYPpENpPkKMTtEeLxptmWwyrRbuvCgGclzAtgGDdniITtRQinNfFHhrCcKkRhHvVByYbKOQqtTokfFhnNHWwouUGgSsOtvVSsTWCcwkKNnZzZzmMWwWqQKvVFfkoOwNvsuUOoMmzaAZvVmbBGgbQqBQfEeIiFqlLsSqeEfFQMyYGggGoOcCUudDdDxZzzlLUBbbOzAaaZGgThZztTHEtrRTetEbBalIiIizjJIimMQqWRraSxYEDdOoKkwHhqzRsSrvVZLZzgGacgIiGCNnADMmoqoOQPpOdVvrRDLhHxXpPeIfFmMeGgEvVpYyPmvVMQqVvXxBblLuLlSsaACcQqxXUvgGVyYqQHhhHJjLqjJTtQfFUuQYyRZzzpUuPjJEewWKkZWwoAaOYyTwWCcnNhHECceZYMZzonNOoOmqfSsFQDdxtZzTXwWyvAasGgmMSaAnNhHyskapPRrAXxNjmMJVvnKSsfFPpKkSNaAqQnNNnlLsSFTtfFfnCcnNIirgGRYVKbBkEebKkSsDsSuUGgbMmWwVveQsSTtZzNndDiIUuDdoOKcChHkwoOgDefFEkEeJjOVeFfHhEvcCYyRbDdBrcIiNUbBWwuQKtTHhdDkxXxXoOgGhwWHbBJXxRJjbBWNsSnQRrqBbXdxsSXDBbRraAxSvVNDEedlLTtfFfFnWwSssRrURMmrwuOoWwJpPwWjUJQGgqjJoOmMeztTZFfEFcCfFFfAazZqScCsdDINnisSmTtMGBrRJNpPiIWCMiIxXqfFtTGlLkKgQmciJlLjIsSHoUZJVvQrRVBbsSZzvuAojJPpZzsSrsSLbBoOQSEesFfzXVwWbeEBvDdVuZlcCBblWwLLkGgWwauAaUZzFfdYyDnzIiZZzNrRvVXxBUUHhhHuugGbyYtTyYdGgDHIAaihSsQjJUdAaGgoODueERxLlXzhHZiQiIqpPuUrRIDdnNrzCcFFffRXDuUdxXUuSsxANGiErReOAfFanJjNNLldSXWwetTPuaxOoXAUpLlsuBuEefZzFUbrRlLUkKepvVWwPEBWwuUpiIPTtKkOoqmMQbpPpdDWwwWPaoOpPFfJCcOYyogGRJjrlDdDfFFdDkKfHhmMHgGiBTtdmMBbpTVveNnEWJtTUubeEOzcCZzZPYmBAabZzUdDuMfFyUkKQqTtAaUuWwkJjWwPYyGIigqBkYytgSsxXViIwWvXnNEeGgxZzMmxXeEGMmpeRRXIixDWwddSsDyYBbtTmMhmMorjsLlrICcHIihFchHCcrUuoFflLReEragGViLluUAaIvaTtXxwWbQhHnNqCipPIHhDdcSsNvVnvJuUVvjTtVPFAaOkHhKofSPpDrRdPphHsyYJAwWaCsSFfiIAXMmxnNalLVvcSsbBUujbBDbBgGdWwTqyYQshHfFwWfFYTtzrBbRKkZyPoPtTpdyYDhHoOoZzOOOjJgTXxtObokKGgORrBprRMJjKuUocVveEeerRxOxXoEeRrtTFfmrRMXPdDpBpfVCcvmMFPkEyYeKuUbXaAdDTtHQqlLhLlszZrVwWiOoZzDdIPsSlLpwWPpDuDIcCidpacCQqwSAasWAfDdoCcOXZEezkKxLbuOoKkOoUqQYylLlGaTtACpEePBuUbGgBbXjAlLaOoacSsAaClCcBbHhWwLxOHhRVvrhgGkKHpPoWKkYyNnEYyePpxdDXwSTtsOlndDRrNOoLRrWwHhWwTtVCSaAtTsvVyYgGGgmLhsWwSgGQgGBbqJjHUoHhOHHxkKyYXhaNnAHGghHCcrwWRXhHxeZzEWwQqhIiHmMeEhUuMzsrfFRUuSAQqxxXsSSESsetTVvGgtIiTiTtIaAjJbBdZzHhIGgiDryYyYXxqtTcUuMmCAacOoCsrREHheSLrRXxRTttTKCcJOoQqYuUcCyOWwoSswWWYLlneEKkNywVBbvhHfFONnTiIAaJjdDUAfFaznoONZAaPQqrVUEeuQqpPvRpTtTeEVvyYOxXoOoOoOoULsSPDdIsSiplusSyYDFfdDAaxPpwJAaBbvIibBzhyYHIgrRGxXTPptiUuZLcvVCWwlTcGXxbBgUuaANnDLldCcCsLsSlwWYXxnRrNYzZlLrRdxXvVDWiIwSwWsJtTjUVvuFfbsSqQTtGAaPpgTQqNnUcCRruMZCaAcgGFfgqQCcGEfFerRGgAaPpkKOoOojdDkKmEeMyYpviIVnHjJhNPuUSsfFVvSGgrGUuMMmmghHRKZzfFBbGgPbQcyYCqBOZzorRoOnNpgGcWwjpPeEJXxCcofFOXxppQqPmMsSPAQmMFfsShHPpKiIkzZqaAaRrBrRbCcgSNnVvsHCcpPvVKkhTyEeYYvyYVsiIuFYyfYyiInNQqNchHqQCnUbBLdLlgGMmDVvzAafFZMmYypPWwWwleEuKkUWwcCUbSskKsSgzZGKkCcjJXFfRrxAadDnNUjNnHhOorClTKktjJGgbBDdVAavrgcCkKqQsSKSskeEOoPmMpeIxXiEFfoymLlMYVvWwrROkKUsLUuIZgGziNnrRxhHXgGoORrHhnNgqQdDGuUlFfVvZzSMqybSssSwLlWMOovZzdaADVxXhHQqHuNnNuUnUhFftsSdDxRrpcCPgGXtmMxWKIeEiVcIiQuKkUqCslLhzAaZiIEeowWOkKEeZxFfQIiRrqXKuUkeEEBbjJerRgGJjyYFfZzFfjGgvVRBbFtTXxZzgGYyneEzZhHQqWIWwXxixLltTXwRrNDsSQprRvVPxXDdFfTtqEeEeQqaHzdDZEehsMmPpPpSGQqgzZGgoOAZzBANJjlLSgGsBfFfFbxXsxXSnLxSsHhiICQqzZvVrbBFfAaRcXbBnNlaYlLHffMmzRrZQqIiOoOWwqQovVqQlLFNnyYpoOagBbuUHhWwoOqQtTiIAAUoOxXuyRrCcYXvVpPtTOoBjJbCczzOlLlLhHIioBbmMZWpaAPwZmGgQYcqCcJjdDpPQMmXxrUucCNWwnNDdxXYuUvPpVPpAHWwhaCcxzZCmMcxBbHjJhwvVWyYZMmMmzPpvVXXBbZzlWwYtTysSRTNntUrRiIurylIeeFfEEpPiGVvgpsSPSQqJiIjJwWVvZLlLgyYapPlLtTzZAGlzOopPNncCUlLQqNnGguCJMaAmjnNwWoOJePpdrRDoJjeEcCWAaeEwOrPfAaFcCsSsKkNnVrmMRjJvVgAaGZznNjcCIiJveEMmVhHWwSsWwevgzZcrqQuURCHDdgGTtkKYyhGgOZzoIwWaRrDdNnDdAGqQvVnNqQXWwJjJjxPkCcKNIihHnwWIirRpBHhbsSfFoOuFjJhwWaGgiyYUutEepdNnDRrPPpwWTgGkwWKVvCcMmgqYNnyQqSyYoObvViIHvVSGgjJsiSeEMmslLsHhSIOSsEBrRbeoFBbfPzZCYYyyEEeecSYyfFGAaRrFfZwaAWUudDxXjJCcjkKJoOEeqQMPSspfFaYyAmrRqQEoOeyyFfgGYYNOonAcSVvTtOoyYsCJjiEgGeSbBiIFfSiIsaAYXPpxyqQwWbyYBiIiIsSfFsIbBRriAXUuxaCcBbvVCccEeZMmYyzCMPpDqQCcqAaQWwQzZqiIXxwKqeZzhHEeEQcUuceEpPCKkCjJQNnqaAkFypLqQlaAXxfBbFnrRNpTUumWwKkvVoOSoOsklLlLCdDdrRlLsSBbmbBMDwIAvVKOokaieEWMxXmtTdHMmtTMiImRcCrDddUumseEwWSeEyYnrRWwNHhMnsJjSOotTrRNQqyEDdetTYwQKkqWkYygGKQqaArRSdDNnGgsRrZzvfHhgiIGkopPJjCeEuxXUcPpOnNeTtwWZQkKzZzcCLkKlpPLrRlyYTRrTtrRCclTtLtFfQpPqyHcCyYRrhGvVIrwWNnRGIigmMfFNTnNUwWuUdarRADczZJjCzVvKkfFZEdDecsSrRwKkHhWBbHhXxZWrtTcCraAJjnaJhHuUTtniINcCOoUYbByuwWYpPOoyMvVSsKkmjnNuKbBkzZUQqYxYyXfFkKyhHAJjSsNngGVvgIihYyHtDdeOoOYMmyoeEEJjHCchjNtWwJjTtUupPCvVRrkJjKeEtOouUTfOoxgbBcNnCQqGXxXlLPSvVNnGTtqQqCcQITtirRFiIfSPCcGgWwpsUNnZEecCzoOuuqtTfFEJswWSjbBdDVwWveQUYYyWwsSwWldDJjDdyMmMmyoOYiIguUGAaYMmWaApPFfwaYybBiIfFDdALZzEpdDPyiIjAatTbBiIHYyaArRQqdDMmhzQqZSsWwFfjwWtZvVzTJdRrPpDJEumRrMsSHhUeZzYQSsqOoCcJjoOeJjnfhHFVuUvIiztTeEClfFLpcNBuUCcbnWBbwqVvIizZvAasPpSwOTtoWxqQXfFGgwiIJaAjWwWBbcCVuUzZyYWwQkFfQqJjxXKzzAaZFTtNVvnjJZzfFfEedDwWUPpnWwNlLGguXxqQlLMmJjiIluUuUiIZzOoWwiIXxCcVvYIGgiaAZWFfwzZyYzhHPpNnyjZzJLDdYyfqQFZxXWwDdgDvVdQMmZziIqtVvTGgFfCcKAaHUqQuhkGnNBKkbgvjJVuUGNnhHClNnLoObhHHhBVvkzqDdZKkKihHmCcMIPQqNRrnoOjWWOokKXPHPpwWhAaJjuUpOUuogZzGcCpPZOofFgWwFfaSszZACcGzPIiKNnkcCxXKJjkkKwWmMvVftTFTtuUcYyMmYhHhHcCyTtCfFWqQwFfnNVRrlVbBWwvUlcqQCYyLsSaIiAaApYzgerREGrpPRrRZByCcYkKyYFfFfRMmrBbBpPbGgGiIPpgtTLlbtTBuUIWDdwGdDCcEegJjgfFLlGDdgmSsMBboNnOaAGUuYgGaASsfqQDdFYkvVKyAeEbiIBhHlLaDwWdAaleBbPfKkFZEeCIicPpjUXdDxaAuJcfOosStTFxXCoONnzfBbTtMtWZznNwTJiIjXJjMvyYVjJowWOfFmUuBtqQTchHCeEHhQZHhzqJjbmMpvTMCcmaxXAtpPjmxXMIiJmMXxqQRFfsSrWzBbFoOOBbofPpZHhwmiIMSspCcPEeiSoOsEJjCcXxefvIiVSsiIiIZydRrjJDsSYfFFfxqQJjXeEYBbyBHYyhbFfFWwDdfpPFFfOoOoWwfpPbBIYyizkoOgzZGAaKFfMppPcKkCIiYAayYoOyAagGBxXbIDdisFflLSRrGKiIgQqGiIYCcykeEKkjzZJixXIoOgtOrMmREVvxXeRiIrzdvWjJwVDvVZiLeEcCTtMmfHhFlIovVJjiYvbBwWEeVSsvVaAWwbBPeEOovVpPOAaVvcCopdDkKyYtTeQwtTWqENnQqyhHntTNxXMmxOoqQnwWMeEmEpPeNOoXtPpTnSsjJEeOoNpPUuQoOxvVXkzZKIxXAIiarEeMmuURyYnNiXTtxwxXYyWoOoOoOadVvDzZZaAMmzhJjHdDPiIpHyYaATthQpPzZOoWwfFnNaAfPpFpFdOoDnNTtfPxsbBSuUreERXBbNaAnqGghHtTxXAiVFfveEIIlLHhVviAatfNnFDdTlzZyYMnNmUufyYFzaAZLoOkKtTpPfcCFqFIifxXUGgZsSzupEXxvVDdLleCciSgpPGPpjJpPTSstqQUyIiXxYPpupPsOoSuUspPICMmcAzFfZLlPplLzZacOoUuVvfFpPGgTOotuOocCUCtTHlLrRxXFfPhWwHphPvfFuUQqDdVxXISsWwJRrjfbhHBzZvVQqDdkKtTFDKCcXxkrRdnEPpsSeHhcaAzZCSsfQqBbrRFNylLYyYSsJjxXnNtTtTaAiIuUDYxXydpAaHhPgGblLBuUjJBbFApPafdSsDbBRrUoOuDdtTmMiWshYyHjJSwIKkirRIhHxXDfQqFduUGgGgxXBhHKzZNnkuUbJjXLlvVahvBbVHhHWOowRRrrmMBbvVUiIumMOqQuImXGgxMkKVvNnpPQqOozvVWwDkKrRdYCcrRyzwWZCcwmMWzZZoOSsxXifmMwWSabBANnswguUMmzFfZGzOoZqQTMmkjHhUuJoOhHKCcDdQqtuaAkMmvVKUDoOYyjnZzsSNJhkMmKNnHTmwWKkEexTtXMCcowaAWOxXcYQKkqyPpQpPrRqCRrzZZztcCTlvVLtMmOoqQEeCpPcqQeDsSdhHIiYjJiIsSydqQDEevVOMAanNiImYJjyHOohodDERrLlefAaFdDgMmGyCqQzZcFfXxYmgGMyAFflwsgGYsSfFySWlLYbBiHhIIivVUuygGyYLiWVgGvmOvVoMwZzIXxWrRQqwamMiWwNnYyWIiwNnmMdZZzzQqDKkvVYyrRIPpQqaAOFsSfoToOtjJnNaAKUuqQVOovlLxAakKYOoyIIiUuiXxFfZMmsSnbBNzwWRrxXiIaAWGgwmqQCcTtdDwWfFMeEipPIXFLAaljtTXcCccCCIQqibBxwWJf \ No newline at end of file diff --git a/2018/5/main.rb b/2018/5/main.rb new file mode 100644 index 0000000..55c90eb --- /dev/null +++ b/2018/5/main.rb @@ -0,0 +1,49 @@ +require 'pry' + +input = File.open('input') {|file| file.readline} + +('a'..'z').each do |letter| + output = input + temp = "" + + i = 0 + while i != output.length + if output[i].downcase != letter + temp += output[i] + end + i += 1 + end + + output = temp + temp = "" + + removed = true + + while removed + removed = false + + i = 1 + while i < output.length + if output[i - 1] != output[i] && output[i - 1].downcase == output[i].downcase + removed = true + i += 2 + + if i == output.length + temp += output[-1] + end + else + temp += output[i - 1] + i += 1 + + if i == output.length + temp += output[-1] + end + end + end + + output = temp + temp = "" + end + + puts "#{letter}: #{output.length}" +end \ No newline at end of file diff --git a/2018/6/input b/2018/6/input new file mode 100644 index 0000000..667d0f9 --- /dev/null +++ b/2018/6/input @@ -0,0 +1,50 @@ +135, 127 +251, 77 +136, 244 +123, 169 +253, 257 +359, 309 +100, 247 +191, 323 +129, 323 +76, 284 +69, 56 +229, 266 +74, 216 +236, 130 +152, 126 +174, 319 +315, 105 +329, 146 +288, 51 +184, 344 +173, 69 +293, 80 +230, 270 +279, 84 +107, 163 +130, 176 +347, 114 +133, 331 +237, 300 +291, 283 +246, 297 +60, 359 +312, 278 +242, 76 +81, 356 +204, 291 +187, 335 +176, 98 +103, 274 +357, 144 +314, 118 +67, 196 +156, 265 +254, 357 +218, 271 +118, 94 +300, 189 +290, 356 +354, 91 +209, 334 \ No newline at end of file diff --git a/2018/6/main.rb b/2018/6/main.rb new file mode 100644 index 0000000..6fbec7c --- /dev/null +++ b/2018/6/main.rb @@ -0,0 +1,75 @@ +require 'pry' + +coords = [] + +# Parse input file. + +File.open("input", "r") do |f| + f.each_line do |line| + x, y = line.split(", ").map(&:chomp).map(&:to_i) + coords.push({ + x: x, + y: y, + }) + end +end + +# Create matrix with correct size + +left_bound = right_bound = coords.first[:x] +top_bound = bottom_bound = coords.first[:y] + +coords.each do |coord| + if coord[:x] < left_bound + left_bound = coord[:x] + end + + if coord[:x] > right_bound + right_bound = coord[:x] + end + + if coord[:y] < top_bound + top_bound = coord[:y] + end + + if coord[:y] > bottom_bound + bottom_bound = coord[:y] + end +end + +height = bottom_bound - top_bound + 1 +width = right_bound - left_bound + 1 + +coords.map!{|coord| {x: coord[:x] - left_bound, y: coord[:y] - top_bound}} + +matrix = Array.new(height){Array.new(width){0}} + +# Fill the matrix with lowest distance to coordinates + +(0...height).each do |y| + (0...width).each do |x| + coords.each_with_index do |coord, i| + distance = (x - coord[:x]).abs + (y - coord[:y]).abs + + matrix[y][x] += distance + end + end +end + +=begin +# Count the area for each coordinate. + +(0...height).each do |y| + (0...width).each do |x| + if (y == 0 || x == 0 || y == height - 1 || x == width - 1) && matrix[y][x][:coords].length == 1 + coords[matrix[y][x][:coords].first][:infinite] = true + else + if matrix[y][x][:coords].length == 1 + coords[matrix[y][x][:coords].first][:area] += 1 + end + end + end +end +=end + +puts matrix.flatten.select{|point| point < 10000}.length \ No newline at end of file diff --git a/2018/6/sample b/2018/6/sample new file mode 100644 index 0000000..523169c --- /dev/null +++ b/2018/6/sample @@ -0,0 +1,5 @@ +0, 0 +0, 10 +10, 0 +10, 10 +3, 4 \ No newline at end of file diff --git a/2018/7/input b/2018/7/input new file mode 100644 index 0000000..d8bb0dd --- /dev/null +++ b/2018/7/input @@ -0,0 +1,101 @@ +Step Z must be finished before step B can begin. +Step X must be finished before step D can begin. +Step D must be finished before step P can begin. +Step O must be finished before step C can begin. +Step C must be finished before step Y can begin. +Step K must be finished before step J can begin. +Step H must be finished before step T can begin. +Step B must be finished before step Q can begin. +Step V must be finished before step M can begin. +Step E must be finished before step W can begin. +Step S must be finished before step J can begin. +Step I must be finished before step N can begin. +Step T must be finished before step L can begin. +Step N must be finished before step M can begin. +Step P must be finished before step G can begin. +Step F must be finished before step Q can begin. +Step J must be finished before step G can begin. +Step L must be finished before step G can begin. +Step Y must be finished before step R can begin. +Step U must be finished before step A can begin. +Step W must be finished before step G can begin. +Step R must be finished before step G can begin. +Step G must be finished before step M can begin. +Step A must be finished before step Q can begin. +Step M must be finished before step Q can begin. +Step N must be finished before step F can begin. +Step Y must be finished before step W can begin. +Step J must be finished before step W can begin. +Step U must be finished before step G can begin. +Step X must be finished before step L can begin. +Step P must be finished before step J can begin. +Step L must be finished before step Y can begin. +Step G must be finished before step Q can begin. +Step K must be finished before step G can begin. +Step V must be finished before step J can begin. +Step F must be finished before step U can begin. +Step V must be finished before step N can begin. +Step I must be finished before step T can begin. +Step U must be finished before step W can begin. +Step S must be finished before step A can begin. +Step C must be finished before step G can begin. +Step L must be finished before step A can begin. +Step E must be finished before step L can begin. +Step D must be finished before step H can begin. +Step Z must be finished before step E can begin. +Step J must be finished before step U can begin. +Step R must be finished before step A can begin. +Step C must be finished before step J can begin. +Step T must be finished before step R can begin. +Step Z must be finished before step D can begin. +Step Y must be finished before step G can begin. +Step Y must be finished before step M can begin. +Step X must be finished before step H can begin. +Step S must be finished before step Q can begin. +Step R must be finished before step Q can begin. +Step D must be finished before step Q can begin. +Step G must be finished before step A can begin. +Step N must be finished before step A can begin. +Step F must be finished before step L can begin. +Step O must be finished before step N can begin. +Step T must be finished before step J can begin. +Step S must be finished before step T can begin. +Step O must be finished before step M can begin. +Step P must be finished before step Y can begin. +Step I must be finished before step U can begin. +Step V must be finished before step S can begin. +Step F must be finished before step G can begin. +Step P must be finished before step M can begin. +Step C must be finished before step S can begin. +Step A must be finished before step M can begin. +Step C must be finished before step Q can begin. +Step Y must be finished before step Q can begin. +Step O must be finished before step P can begin. +Step S must be finished before step R can begin. +Step S must be finished before step Y can begin. +Step I must be finished before step Q can begin. +Step O must be finished before step T can begin. +Step F must be finished before step W can begin. +Step U must be finished before step R can begin. +Step O must be finished before step U can begin. +Step D must be finished before step L can begin. +Step H must be finished before step I can begin. +Step P must be finished before step R can begin. +Step J must be finished before step L can begin. +Step P must be finished before step W can begin. +Step W must be finished before step Q can begin. +Step X must be finished before step Q can begin. +Step Z must be finished before step U can begin. +Step T must be finished before step U can begin. +Step D must be finished before step S can begin. +Step U must be finished before step Q can begin. +Step N must be finished before step G can begin. +Step E must be finished before step Q can begin. +Step X must be finished before step K can begin. +Step J must be finished before step R can begin. +Step X must be finished before step R can begin. +Step T must be finished before step W can begin. +Step K must be finished before step S can begin. +Step S must be finished before step G can begin. +Step P must be finished before step F can begin. +Step X must be finished before step C can begin. \ No newline at end of file diff --git a/2018/7/main.rb b/2018/7/main.rb new file mode 100644 index 0000000..2388ac3 --- /dev/null +++ b/2018/7/main.rb @@ -0,0 +1,101 @@ +require 'pry' + +orders = [] +instructions = [] + +# Parse input file. + +File.open("input", "r") do |f| + f.each_line do |line| + first, second = line.scan(/\s[A-Z]{1}\s/).map(&:strip) + orders.push({ + first: first, + then: second + }) + instructions.push(first) + instructions.push(second) + end +end + +instructions.uniq! + +result = "" + +workers = 5.times.map do + { + current_instruction: nil, + time_left: 0 + } +end + +time = 0 + +while !instructions.empty? + # Get a list of the next instructions available. + next_instructions = instructions.select do |instruction| + orders.none? do |order| + order[:then] == instruction && order[:first] != nil + end and workers.none? do |worker| + worker[:current_instruction] == instruction + end + end.sort + + # Give free workers instructions. + workers.each_with_index do |worker, i| + if worker[:current_instruction].nil? and !next_instructions.empty? + workers[i][:current_instruction] = next_instructions[0] + workers[i][:time_left] = next_instructions[0].ord - "A".ord + 1 + 60 + next_instructions.delete(next_instructions[0]) + end + end + + elapsed_time = workers.select do |worker| + !worker[:current_instruction].nil? + end.map do |worker| + worker[:time_left] + end.min + + time += elapsed_time + + workers.each_with_index do |worker, i| + if !workers[i][:current_instruction].nil? + workers[i][:time_left] -= elapsed_time + + if workers[i][:time_left] == 0 + instructions.delete(workers[i][:current_instruction]) + orders.each do |order| + if order[:first] == workers[i][:current_instruction] + order[:first] = nil + end + end + + workers[i][:current_instruction] = nil + end + end + end + + #binding.pry +end + +=begin + +while !instructions.empty? + next_instruction = instructions.select do |instruction| + orders.none? do |order| + order[:then] == instruction && order[:first] != nil + end + end.sort.first + + result += next_instruction + + instructions.delete next_instruction + orders.each do |order| + if order[:first] == next_instruction + order[:first] = nil + end + end +end + +=end + +puts time \ No newline at end of file diff --git a/2018/7/sample b/2018/7/sample new file mode 100644 index 0000000..1dfd2ea --- /dev/null +++ b/2018/7/sample @@ -0,0 +1,7 @@ +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. \ No newline at end of file diff --git a/2020/.formatter.exs b/2020/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/2020/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/2020/lib/days/day1.ex b/2020/lib/days/day1.ex new file mode 100644 index 0000000..796c6f0 --- /dev/null +++ b/2020/lib/days/day1.ex @@ -0,0 +1,19 @@ +defmodule AOC.Day1 do + def part1 do + l = AOC.Util.input_integers(1, 1) + [x, y] = Enum.filter(l, &((2020 - &1) in l)) + x * y + end + + def find_three([h | tl]) do + case Enum.filter(tl, &((2020 - h - &1) in tl)) do + [x, y] -> h * x * y + _ -> find_three(tl) + end + end + + def part2 do + AOC.Util.input_integers(1, 1) + |> find_three() + end +end diff --git a/2020/lib/days/day10.ex b/2020/lib/days/day10.ex new file mode 100644 index 0000000..669f808 --- /dev/null +++ b/2020/lib/days/day10.ex @@ -0,0 +1,48 @@ +defmodule AOC.Day10 do + def find_diffs(xs), do: find_diffs(xs, %{}) + def find_diffs([_], acc), do: acc + + def find_diffs([x1, x2 | xs], acc) do + acc = Map.update(acc, x2 - x1, 1, &(&1 + 1)) + + find_diffs([x2 | xs], acc) + end + + def count_walks([x | _] = xs) do + memo = + Enum.into(xs, %{}, &{&1, 0}) + |> Map.put(x, 1) + + count_walks(xs, memo) + end + + def count_walks([x], memo), do: memo[x] + + def count_walks([x | xs], memo) do + memo = + Enum.take(xs, 3) + |> Enum.reduce(memo, fn + next, memo when next - x <= 3 -> + Map.update!(memo, next, &(&1 + memo[x])) + + _, memo -> + memo + end) + + count_walks(xs, memo) + end + + def parts do + input = + AOC.Util.input_integers(10, 1) + |> Enum.sort() + + input = [0 | input] ++ [Enum.max(input) + 3] + + %{1 => ones, 3 => threes} = find_diffs(input) + part1 = ones * threes + part2 = count_walks(input) + + {part1, part2} + end +end diff --git a/2020/lib/days/day11.ex b/2020/lib/days/day11.ex new file mode 100644 index 0000000..7904911 --- /dev/null +++ b/2020/lib/days/day11.ex @@ -0,0 +1,91 @@ +defmodule AOC.Day11 do + @x_size 95 + @y_size 93 + + def parse_input do + AOC.Util.input_lines(11, 1) + |> Enum.with_index() + |> Enum.reduce(%{}, fn {line, y}, acc -> + line + |> String.split("", trim: true) + |> Enum.with_index() + |> Enum.reject(&(elem(&1, 0) == ".")) + |> Enum.map(fn {_, i} -> {false, i} end) + |> Enum.into(acc, fn {c, x} -> {{x, y}, c} end) + end) + end + + def count_direct_adj(seats, {x, y}) do + [ + {x - 1, y - 1}, + {x - 1, y}, + {x - 1, y + 1}, + {x, y - 1}, + {x, y + 1}, + {x + 1, y - 1}, + {x + 1, y}, + {x + 1, y + 1} + ] + |> Enum.count(fn coords -> Map.get(seats, coords) end) + end + + def look_direction(seats, coords, next_fun) do + {x, y} = coords = next_fun.(coords) + + if x not in 0..@x_size or y not in 0..@y_size do + false + else + case Map.get(seats, coords) do + nil -> look_direction(seats, coords, next_fun) + x -> x + end + end + end + + def count_sight_adj(seats, {x, y}) do + [ + fn {x, y} -> {x + 1, y + 1} end, + fn {x, y} -> {x + 1, y - 1} end, + fn {x, y} -> {x - 1, y + 1} end, + fn {x, y} -> {x - 1, y - 1} end, + fn {x, y} -> {x + 1, y} end, + fn {x, y} -> {x - 1, y} end, + fn {x, y} -> {x, y + 1} end, + fn {x, y} -> {x, y - 1} end + ] + |> Enum.count(&look_direction(seats, {x, y}, &1)) + end + + def simulate_round(seats, count_adj, min) do + Enum.reduce(seats, {%{}, false}, fn {coords, x}, {acc, changed} -> + new = + case {x, count_adj.(seats, coords)} do + {false, 0} -> true + {true, count} when count >= min -> false + _ -> x + end + + {Map.put(acc, coords, new), changed or new != x} + end) + end + + def find_stable(seats, count_adj, min) do + {seats, changed} = simulate_round(seats, count_adj, min) + + if changed do + find_stable(seats, count_adj, min) + else + seats + end + end + + def parts do + input = parse_input() + stable = find_stable(input, &count_direct_adj/2, 4) + part1 = Enum.count(stable, &elem(&1, 1)) + stable = find_stable(input, &count_sight_adj/2, 5) + part2 = Enum.count(stable, &elem(&1, 1)) + + {part1, part2} + end +end diff --git a/2020/lib/days/day12.ex b/2020/lib/days/day12.ex new file mode 100644 index 0000000..da25742 --- /dev/null +++ b/2020/lib/days/day12.ex @@ -0,0 +1,93 @@ +defmodule AOC.Day12 do + @turn_right %{ + N: :E, + E: :S, + S: :W, + W: :N + } + + def parse_input do + AOC.Util.input_lines(12, 1) + |> Enum.map(fn line -> + {action, value} = String.split_at(line, 1) + action = String.to_atom(action) + value = String.to_integer(value) + + {action, value} + end) + end + + def handle_instruction1({:N, value}, acc), do: Map.update!(acc, :y, &(&1 - value)) + def handle_instruction1({:E, value}, acc), do: Map.update!(acc, :x, &(&1 + value)) + def handle_instruction1({:S, value}, acc), do: Map.update!(acc, :y, &(&1 + value)) + def handle_instruction1({:W, value}, acc), do: Map.update!(acc, :x, &(&1 - value)) + + def handle_instruction1({:F, value}, %{dir: dir} = acc), + do: handle_instruction1({dir, value}, acc) + + def handle_instruction1({:L, value}, acc), do: handle_instruction1({:R, -value}, acc) + + def handle_instruction1({:R, value}, %{dir: dir} = acc) do + value = rem(div(value, 90), 4) + + value = + if value < 0 do + value + 4 + else + value + end + + dir = + List.duplicate(nil, value) + |> Enum.reduce(dir, fn _, d -> Map.get(@turn_right, d) end) + + Map.put(acc, :dir, dir) + end + + def handle_instruction2({:N, value}, acc), do: Map.update!(acc, :wpy, &(&1 - value)) + def handle_instruction2({:E, value}, acc), do: Map.update!(acc, :wpx, &(&1 + value)) + def handle_instruction2({:S, value}, acc), do: Map.update!(acc, :wpy, &(&1 + value)) + def handle_instruction2({:W, value}, acc), do: Map.update!(acc, :wpx, &(&1 - value)) + + def handle_instruction2({:F, value}, %{x: x, y: y, wpx: wpx, wpy: wpy} = acc), + do: %{acc | x: x + value * wpx, y: y + value * wpy} + + def handle_instruction2({:L, value}, acc), do: handle_instruction2({:R, -value}, acc) + + def handle_instruction2({:R, value}, %{wpx: wpx, wpy: wpy} = acc) do + value = rem(div(value, 90), 4) + + value = + if value < 0 do + value + 4 + else + value + end + + {wpx, wpy} = + case value do + 0 -> {wpx, wpy} + 1 -> {-wpy, wpx} + 2 -> {-wpx, -wpy} + 3 -> {wpy, -wpx} + end + + %{acc | wpx: wpx, wpy: wpy} + end + + def handle_instructions(instructions, instruction_handler) do + acc = %{x: 0, y: 0, dir: :E, wpx: 10, wpy: -1} + Enum.reduce(instructions, acc, instruction_handler) + end + + def parts do + input = parse_input() + %{x: x, y: y} = handle_instructions(input, &handle_instruction1/2) + part1 = abs(x) + abs(y) + + %{x: x, y: y} = handle_instructions(input, &handle_instruction2/2) + part2 = abs(x) + abs(y) + + {part1, part2} + end +end diff --git a/2020/lib/days/day13.ex b/2020/lib/days/day13.ex new file mode 100644 index 0000000..828b20d --- /dev/null +++ b/2020/lib/days/day13.ex @@ -0,0 +1,45 @@ +defmodule AOC.Day13 do + def parse_input do + [depart, buses] = AOC.Util.input_lines(13, 1) + depart = String.to_integer(depart) + + buses = + buses + |> String.split(",") + |> Enum.map(fn + bus when bus == "x" -> :x + bus -> String.to_integer(bus) + end) + + {depart, buses} + end + + def find_earliest_bus(depart, buses), do: find_earliest_bus(depart, buses, {nil, :infinity}) + def find_earliest_bus(_, [], earliest), do: earliest + + def find_earliest_bus(depart, [bus | tl], {_, earliest} = acc) do + rounds = div(depart, bus) + rounds = if rounds * bus < depart, do: rounds + 1, else: rounds + wait = rounds * bus - depart + + acc = if wait < earliest, do: {bus, wait}, else: acc + + find_earliest_bus(depart, tl, acc) + end + + def find_offsets(buses) do + buses + |> Enum.with_index() + |> Enum.reject(&(elem(&1, 0) |> is_atom())) + end + + def parts do + {depart, buses} = parse_input() + {bus, earliest} = find_earliest_bus(depart, Enum.reject(buses, &is_atom/1)) + part1 = bus * earliest + + offsets = find_offsets(buses) + + {part1, offsets} + end +end diff --git a/2020/lib/days/day2.ex b/2020/lib/days/day2.ex new file mode 100644 index 0000000..b373564 --- /dev/null +++ b/2020/lib/days/day2.ex @@ -0,0 +1,36 @@ +defmodule AOC.Day2 do + def parse_line(line) do + [min, max, char, password] = String.split(line, [" ", "-", ":"], trim: true) + password = String.to_charlist(password) + [char] = String.to_charlist(char) + min = String.to_integer(min) + max = String.to_integer(max) + [password, char, min, max] + end + + def validate_password1(password, char, min, max) do + count = Enum.count(password, &(&1 == char)) + count in min..max + end + + def part1 do + AOC.Util.input_lines(2, 1) + |> Enum.map(&parse_line/1) + |> Enum.map(&apply(__MODULE__, :validate_password1, &1)) + |> Enum.count(&Function.identity/1) + end + + def validate_password2(password, char, pos1, pos2) do + m1 = Enum.at(password, pos1 - 1) == char + m2 = Enum.at(password, pos2 - 1) == char + + (m1 or m2) and not (m1 and m2) + end + + def part2 do + AOC.Util.input_lines(2, 1) + |> Enum.map(&parse_line/1) + |> Enum.map(&apply(__MODULE__, :validate_password2, &1)) + |> Enum.count(&Function.identity/1) + end +end diff --git a/2020/lib/days/day3.ex b/2020/lib/days/day3.ex new file mode 100644 index 0000000..74660e5 --- /dev/null +++ b/2020/lib/days/day3.ex @@ -0,0 +1,33 @@ +defmodule AOC.Day3 do + @line_length 31 + + def count_trees(lines, jump), do: count_trees(lines, jump, 0, 0) + def count_trees([], _, _, acc), do: acc + + def count_trees([hd | tl], jump, x, acc) do + acc = + acc + + if String.at(hd, x) == "#" do + 1 + else + 0 + end + + x = rem(x + jump, @line_length) + count_trees(tl, jump, x, acc) + end + + def part1 do + AOC.Util.input_lines(3, 1) + |> count_trees(3) + end + + def part2 do + lines = AOC.Util.input_lines(3, 1) + + count_down2 = Enum.take_every(lines, 2) |> count_trees(1) + tree_counts = Enum.map([1, 3, 5, 7], &count_trees(lines, &1)) + + Enum.reduce([count_down2 | tree_counts], &*/2) + end +end diff --git a/2020/lib/days/day4.ex b/2020/lib/days/day4.ex new file mode 100644 index 0000000..e9d37b0 --- /dev/null +++ b/2020/lib/days/day4.ex @@ -0,0 +1,82 @@ +defmodule AOC.Day4 do + def parse_input(lines), do: parse_input(lines, [], %{}) + def parse_input([], acc, el), do: [el | acc] + def parse_input(["" | tl], acc, el), do: parse_input(tl, [el | acc], %{}) + + def parse_input([hd | tl], acc, el) do + el = + String.split(hd) + |> Enum.map(&String.split(&1, ":")) + |> Enum.map(fn [k, v] -> {k, v} end) + |> Enum.into(el) + + parse_input(tl, acc, el) + end + + def validate_field_presence(%{ + "byr" => _, + "iyr" => _, + "eyr" => _, + "hgt" => _, + "hcl" => _, + "ecl" => _, + "pid" => _ + }), + do: true + + def validate_field_presence(_), do: false + + def part1 do + AOC.Util.input_lines(4, 1) + |> parse_input() + |> Enum.filter(&validate_field_presence/1) + |> Enum.count() + end + + def validate_height(height) do + if String.ends_with?(height, ["cm", "in"]) do + {height, measure} = String.split_at(height, -2) + height = String.to_integer(height) + + case measure do + "cm" -> height >= 150 and height <= 193 + "in" -> height >= 59 and height <= 76 + end + else + false + end + end + + def validate_fields(%{ + "byr" => byr, + "iyr" => iyr, + "eyr" => eyr, + "hgt" => hgt, + "hcl" => hcl, + "ecl" => ecl, + "pid" => pid + }) do + byr = String.to_integer(byr) + iyr = String.to_integer(iyr) + eyr = String.to_integer(eyr) + + [ + byr >= 1920 and byr <= 2002, + iyr >= 2010 and iyr <= 2020, + eyr >= 2020 and eyr <= 2030, + validate_height(hgt), + hcl =~ ~r/^#([a-f]|[0-9]){6}$/, + ecl in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"], + pid =~ ~r/^[0-9]{9}$/ + ] + |> Enum.reduce(&and/2) + end + + def part2 do + AOC.Util.input_lines(4, 1) + |> parse_input() + |> Enum.filter(&validate_field_presence/1) + |> Enum.filter(&validate_fields/1) + |> Enum.count() + end +end diff --git a/2020/lib/days/day5.ex b/2020/lib/days/day5.ex new file mode 100644 index 0000000..7f4f325 --- /dev/null +++ b/2020/lib/days/day5.ex @@ -0,0 +1,42 @@ +defmodule AOC.Day5 do + @upper 'BR' + @lower 'FL' + + def search_range([], x, x), do: x + + def search_range([hd | tl], low, high) when hd in @lower do + search_range(tl, low, div(high + 1 + low, 2) - 1) + end + + def search_range([hd | tl], low, high) when hd in @upper do + search_range(tl, div(low + high + 1, 2), high) + end + + def search_seat({row_search, col_search}) do + row = search_range(row_search, 0, 127) + column = search_range(col_search, 0, 7) + {row, column} + end + + def part1 do + AOC.Util.input_lines(5, 1) + |> Enum.map(&String.to_charlist/1) + |> Enum.map(&Enum.split(&1, 7)) + |> Enum.map(&search_seat/1) + |> Enum.map(fn {r, c} -> r * 8 + c end) + |> Enum.max() + end + + def find_missing_seat([l, r | _]) when r != l + 1, do: l + 1 + def find_missing_seat([_ | tl]), do: find_missing_seat(tl) + + def part2 do + AOC.Util.input_lines(5, 1) + |> Enum.map(&String.to_charlist/1) + |> Enum.map(&Enum.split(&1, 7)) + |> Enum.map(&search_seat/1) + |> Enum.map(fn {r, c} -> r * 8 + c end) + |> Enum.sort() + |> find_missing_seat() + end +end diff --git a/2020/lib/days/day6.ex b/2020/lib/days/day6.ex new file mode 100644 index 0000000..84c8ac6 --- /dev/null +++ b/2020/lib/days/day6.ex @@ -0,0 +1,29 @@ +defmodule AOC.Day6 do + def part1 do + AOC.Util.input_file(6, 1) + |> String.split("\n\n") + |> Enum.map(fn group -> + group + |> String.replace("\n", "") + |> String.to_charlist() + |> Enum.uniq() + |> Enum.count() + end) + |> Enum.sum() + end + + def part2 do + AOC.Util.input_file(6, 1) + |> String.split("\n\n") + |> Enum.map(fn group -> + count = String.split(group, "\n") |> Enum.count() + + group + |> String.replace("\n", "") + |> String.to_charlist() + |> Enum.frequencies() + |> Enum.count(fn {_, v} -> v == count end) + end) + |> Enum.sum() + end +end diff --git a/2020/lib/days/day7.ex b/2020/lib/days/day7.ex new file mode 100644 index 0000000..62aabc5 --- /dev/null +++ b/2020/lib/days/day7.ex @@ -0,0 +1,61 @@ +defmodule AOC.Day7 do + def parse_input(lines), do: parse_input(lines, %{}) + def parse_input([], acc), do: acc + + def parse_input([str | tl], acc) do + [container, str] = String.split(str, " bags contain ") + + inner = + str + |> String.split(", ") + |> Enum.map(fn + "no other bags." -> + [] + + bags -> + [num, adj1, adj2, _] = String.split(bags) + {String.to_integer(num), "#{adj1} #{adj2}"} + end) + |> List.flatten() + + parse_input(tl, Map.put(acc, container, inner)) + end + + def find_golden_containers(map) do + map + |> Map.keys() + |> Enum.filter(fn + "shiny gold" -> false + bag -> find_golden_containers(map, bag) + end) + end + + def find_golden_containers(_, "shiny gold"), do: true + + def find_golden_containers(map, bag) do + map[bag] + |> Enum.map(fn {_, x} -> find_golden_containers(map, x) end) + |> Enum.any?() + end + + def part1 do + AOC.Util.input_lines(7, 1) + |> parse_input() + |> find_golden_containers() + |> Enum.count() + end + + def count_bags(map), do: count_bags(map, "shiny gold") + + def count_bags(map, bag) do + map[bag] + |> Enum.map(fn {n, x} -> n * (count_bags(map, x) + 1) end) + |> Enum.sum() + end + + def part2 do + AOC.Util.input_lines(7, 1) + |> parse_input() + |> count_bags() + end +end diff --git a/2020/lib/days/day8.ex b/2020/lib/days/day8.ex new file mode 100644 index 0000000..efe5897 --- /dev/null +++ b/2020/lib/days/day8.ex @@ -0,0 +1,60 @@ +defmodule AOC.Day8 do + def get_input do + AOC.Util.input_lines(8, 1) + |> Enum.map(fn line -> + [opcode, arg] = String.split(line) + {String.to_atom(opcode), String.to_integer(arg)} + end) + |> Enum.with_index() + |> Enum.into(%{}, fn {v, k} -> {k, v} end) + end + + def find_loop(program), do: find_loop(program, 0, MapSet.new(), 0) + + def find_loop(program, acc, seen, ip) do + cond do + MapSet.member?(seen, ip) -> + acc + + ip >= length(Map.keys(program)) -> + {true, acc} + + true -> + seen = MapSet.put(seen, ip) + + {acc, ip} = + case program[ip] do + {:acc, arg} -> {acc + arg, ip + 1} + {:nop, _} -> {acc, ip + 1} + {:jmp, arg} -> {acc, ip + arg} + end + + find_loop(program, acc, seen, ip) + end + end + + def part1 do + get_input() + |> find_loop() + end + + def perturb_program(program) do + program + |> Stream.reject(fn {_, {opcode, _}} -> opcode == :acc end) + |> Stream.map(fn + {ip, {:nop, arg}} -> {ip, {:jmp, arg}} + {ip, {:jmp, arg}} -> {ip, {:nop, arg}} + end) + |> Stream.map(fn {ip, v} -> + Map.put(program, ip, v) + end) + end + + def part2 do + get_input() + |> perturb_program() + |> Stream.map(&find_loop/1) + |> Stream.filter(&is_tuple/1) + |> Enum.to_list() + end +end diff --git a/2020/lib/days/day9.ex b/2020/lib/days/day9.ex new file mode 100644 index 0000000..2c86b28 --- /dev/null +++ b/2020/lib/days/day9.ex @@ -0,0 +1,46 @@ +defmodule AOC.Day9 do + @preamble_len 25 + + def find_invalid(queue, [hd | tl]) do + sums = + :queue.to_list(queue) + |> Combination.combine(2) + |> Enum.map(&Enum.sum/1) + + queue = + :queue.in(hd, queue) + |> :queue.drop() + + if hd in sums do + find_invalid(queue, tl) + else + hd + end + end + + def find_weakness(invalid, [_ | tl] = nums) do + result = + Enum.reduce_while(nums, {0, []}, fn num, {sum, l} -> + sum = sum + num + if sum < invalid, do: {:cont, {sum, [num | l]}}, else: {:halt, {sum, l}} + end) + + case result do + {sum, l} when sum == invalid -> Enum.min_max(l) + _ -> find_weakness(invalid, tl) + end + end + + def parts do + input = AOC.Util.input_integers(9, 1) + {preamble, nums} = Enum.split(input, @preamble_len) + + invalid = + preamble + |> :queue.from_list() + |> find_invalid(nums) + + {min, max} = find_weakness(invalid, input) + {invalid, min + max} + end +end diff --git a/2020/lib/util.ex b/2020/lib/util.ex new file mode 100644 index 0000000..3d08723 --- /dev/null +++ b/2020/lib/util.ex @@ -0,0 +1,21 @@ +defmodule AOC.Util do + def input_file_name(day, input) do + Path.join([File.cwd!(), "inputs", "day#{day}", "input#{input}.txt"]) + end + + def input_file(day, input) do + input_file_name(day, input) + |> File.read!() + end + + def input_lines(day, input) do + input_file_name(day, input) + |> File.stream!() + |> Enum.map(&String.trim/1) + end + + def input_integers(day, input) do + input_lines(day, input) + |> Enum.map(&String.to_integer/1) + end +end diff --git a/2020/mix.exs b/2020/mix.exs new file mode 100644 index 0000000..7e1f9a1 --- /dev/null +++ b/2020/mix.exs @@ -0,0 +1,27 @@ +defmodule Aoc2020.MixProject do + use Mix.Project + + def project do + [ + app: :aoc2020, + version: "0.1.0", + elixir: "~> 1.12-dev", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:combination, "~> 0.0.3"} + ] + end +end diff --git a/2020/mix.lock b/2020/mix.lock new file mode 100644 index 0000000..3129145 --- /dev/null +++ b/2020/mix.lock @@ -0,0 +1,3 @@ +%{ + "combination": {:hex, :combination, "0.0.3", "746aedca63d833293ec6e835aa1f34974868829b1486b1e1cb0685f0b2ae1f41", [:mix], [], "hexpm", "72b099f463df42ef7dc6371d250c7070b57b6c5902853f69deb894f79eda18ca"}, +} diff --git a/2020/test/test_helper.exs b/2020/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/2020/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/2021/.formatter.exs b/2021/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/2021/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/2021/lib/days/day1.ex b/2021/lib/days/day1.ex new file mode 100644 index 0000000..d2d682e --- /dev/null +++ b/2021/lib/days/day1.ex @@ -0,0 +1,17 @@ +defmodule AOC.Day1 do + def part1 do + AOC.Util.input_integers(1, 1) + |> Enum.chunk_every(2, 1, :discard) + |> Enum.map(fn [x, y] -> y > x end) + |> Enum.count(& &1) + end + + def part2 do + AOC.Util.input_integers(1, 1) + |> Enum.chunk_every(3, 1, :discard) + |> Enum.map(&Enum.sum/1) + |> Enum.chunk_every(2, 1, :discard) + |> Enum.map(fn [x, y] -> y > x end) + |> Enum.count(& &1) + end +end diff --git a/2021/lib/days/day2.ex b/2021/lib/days/day2.ex new file mode 100644 index 0000000..6bab739 --- /dev/null +++ b/2021/lib/days/day2.ex @@ -0,0 +1,27 @@ +defmodule AOC.Day2 do + def parse_input do + AOC.Util.input_lines(2, 1) + |> Enum.map(fn l -> + [dir, amount] = String.split(l, " ") + {String.to_atom(dir), String.to_integer(amount)} + end) + end + + def part1 do + parse_input() + |> Enum.reduce({0, 0}, fn + {:forward, amount}, {distance, depth} -> {distance + amount, depth} + {:down, amount}, {distance, depth} -> {distance, depth + amount} + {:up, amount}, {distance, depth} -> {distance, depth - amount} + end) + end + + def part2 do + parse_input() + |> Enum.reduce({0, 0, 0}, fn + {:down, amount}, {distance, depth, aim} -> {distance, depth, aim + amount} + {:up, amount}, {distance, depth, aim} -> {distance, depth, aim - amount} + {:forward, amount}, {distance, depth, aim} -> {distance + amount, depth + aim * amount, aim} + end) + end +end diff --git a/2021/lib/util.ex b/2021/lib/util.ex new file mode 100644 index 0000000..3d08723 --- /dev/null +++ b/2021/lib/util.ex @@ -0,0 +1,21 @@ +defmodule AOC.Util do + def input_file_name(day, input) do + Path.join([File.cwd!(), "inputs", "day#{day}", "input#{input}.txt"]) + end + + def input_file(day, input) do + input_file_name(day, input) + |> File.read!() + end + + def input_lines(day, input) do + input_file_name(day, input) + |> File.stream!() + |> Enum.map(&String.trim/1) + end + + def input_integers(day, input) do + input_lines(day, input) + |> Enum.map(&String.to_integer/1) + end +end diff --git a/2021/mix.exs b/2021/mix.exs new file mode 100644 index 0000000..8108e67 --- /dev/null +++ b/2021/mix.exs @@ -0,0 +1,28 @@ +defmodule Aoc2021.MixProject do + use Mix.Project + + def project do + [ + app: :aoc2021, + version: "0.1.0", + elixir: "~> 1.12", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/2022/.formatter.exs b/2022/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/2022/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/2022/Makefile b/2022/Makefile new file mode 100644 index 0000000..369016a --- /dev/null +++ b/2022/Makefile @@ -0,0 +1,2 @@ +day%: + mix run -e "AOC.Day$*.solve()" diff --git a/2022/README.md b/2022/README.md new file mode 100644 index 0000000..d22c678 --- /dev/null +++ b/2022/README.md @@ -0,0 +1,21 @@ +# Aoc2022 + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `aoc2022` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:aoc2022, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/2022/day10.py b/2022/day10.py new file mode 100755 index 0000000..4ced0db --- /dev/null +++ b/2022/day10.py @@ -0,0 +1,41 @@ +#!/bin/python3 + +program = list() + +with open('day10.txt', 'r') as f: + for line in f: + line = line.strip() + if line == "noop": + program.append("noop") + else: + [cmd, arg] = line.split(" ") + program.append((cmd, int(arg))) + +states = list() + +state = 1 +for instruction in program: + if instruction == 'noop': + states.append(state) + else: + (cmd, arg) = instruction + states.append(state) + states.append(state) + state += arg + +part1 = 0 + +for i in range(19, len(states), 40): + part1 += (i+1) * states[i] + +print(part1) + +for y in range(6): + for x in range(40): + index = y * 40 + x + state = states[index] + if x == state or x == state-1 or x == state+1: + print('#', end='') + else: + print('.', end='') + print('') diff --git a/2022/day10.txt b/2022/day10.txt new file mode 100644 index 0000000..c26a664 --- /dev/null +++ b/2022/day10.txt @@ -0,0 +1,139 @@ +noop +addx 12 +addx -5 +addx -1 +noop +addx 4 +noop +addx 1 +addx 4 +noop +addx 13 +addx -8 +noop +addx -19 +addx 24 +addx 1 +noop +addx 4 +noop +addx 1 +addx 5 +addx -1 +addx -37 +addx 16 +addx -13 +addx 18 +addx -11 +addx 2 +addx 23 +noop +addx -18 +addx 9 +addx -8 +addx 2 +addx 5 +addx 2 +addx -21 +addx 26 +noop +addx -15 +addx 20 +noop +addx 3 +noop +addx -38 +addx 3 +noop +addx 26 +addx -4 +addx -19 +addx 3 +addx 1 +addx 5 +addx 3 +noop +addx 2 +addx 3 +noop +addx 2 +noop +noop +noop +noop +addx 5 +noop +noop +noop +addx 3 +noop +addx -30 +addx -4 +addx 1 +addx 18 +addx -8 +addx -4 +addx 2 +noop +addx 7 +noop +noop +noop +noop +addx 5 +noop +noop +addx 5 +addx -2 +addx -20 +addx 27 +addx -20 +addx 25 +addx -2 +addx -35 +noop +noop +addx 4 +addx 3 +addx -2 +addx 5 +addx 2 +addx -11 +addx 1 +addx 13 +addx 2 +addx 5 +addx 6 +addx -1 +addx -2 +noop +addx 7 +addx -2 +addx 6 +addx 1 +addx -21 +addx 22 +addx -38 +addx 5 +addx 3 +addx -1 +noop +noop +addx 5 +addx 1 +addx 4 +addx 3 +addx -2 +addx 2 +noop +addx 7 +addx -1 +addx 2 +addx 4 +addx -10 +addx -19 +addx 35 +addx -1 +noop +noop +noop diff --git a/2022/day10test.txt b/2022/day10test.txt new file mode 100644 index 0000000..37ee8ee --- /dev/null +++ b/2022/day10test.txt @@ -0,0 +1,146 @@ +addx 15 +addx -11 +addx 6 +addx -3 +addx 5 +addx -1 +addx -8 +addx 13 +addx 4 +noop +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx -35 +addx 1 +addx 24 +addx -19 +addx 1 +addx 16 +addx -11 +noop +noop +addx 21 +addx -15 +noop +noop +addx -3 +addx 9 +addx 1 +addx -3 +addx 8 +addx 1 +addx 5 +noop +noop +noop +noop +noop +addx -36 +noop +addx 1 +addx 7 +noop +noop +noop +addx 2 +addx 6 +noop +noop +noop +noop +noop +addx 1 +noop +noop +addx 7 +addx 1 +noop +addx -13 +addx 13 +addx 7 +noop +addx 1 +addx -33 +noop +noop +noop +addx 2 +noop +noop +noop +addx 8 +noop +addx -1 +addx 2 +addx 1 +noop +addx 17 +addx -9 +addx 1 +addx 1 +addx -3 +addx 11 +noop +noop +addx 1 +noop +addx 1 +noop +noop +addx -13 +addx -19 +addx 1 +addx 3 +addx 26 +addx -30 +addx 12 +addx -1 +addx 3 +addx 1 +noop +noop +noop +addx -9 +addx 18 +addx 1 +addx 2 +noop +noop +addx 9 +noop +noop +noop +addx -1 +addx 2 +addx -37 +addx 1 +addx 3 +noop +addx 15 +addx -21 +addx 22 +addx -6 +addx 1 +noop +addx 2 +addx 1 +noop +addx -10 +noop +noop +addx 20 +addx 1 +addx 2 +addx 2 +addx -6 +addx -11 +noop +noop +noop diff --git a/2022/day12.py b/2022/day12.py new file mode 100755 index 0000000..099a009 --- /dev/null +++ b/2022/day12.py @@ -0,0 +1,104 @@ +#!/bin/python3 + +import sys +sys.setrecursionlimit(1500) + +hmap = list() + +with open('day12.txt', 'r') as f: + for line in f: + hmap.append(line.strip()) + +h = len(hmap) +w = len(hmap[0]) + +for y in range(h): + for x in range(w): + if hmap[y][x] == 'S': + start = (x, y) + if hmap[y][x] == 'E': + end = (x, y) + +def get_elevation(char): + if char == 'S': + return ord('a') + if char == 'E': + return ord('z') + return ord(char) + +def get_adjacents(pos): + (x, y) = pos + return [(x-1, y), (x+1, y), (x, y-1), (x, y+1)] + +def in_bounds(pos): + (x, y) = pos + return x >= 0 and x < w and y >= 0 and y < h + +def get_char(hmap, pos): + (x, y) = pos + return hmap[y][x] + +def valid_jump(hmap, pos, adj): + poschar = get_char(hmap, pos) + adjchar = get_char(hmap, adj) + poselev = get_elevation(poschar) + adjelev = get_elevation(adjchar) + return poselev + 1 >= adjelev + +best_cost = {} + +def find_path(hmap, path, pos): + if get_char(hmap, pos) == 'E': + return [path] + + paths = list() + for adj in get_adjacents(pos): + if adj not in path and in_bounds(adj) and valid_jump(hmap, pos, adj): + if adj not in best_cost or best_cost[adj] > len(path): + best_cost[adj] = len(path) + new_path = set.copy(path) + new_path.add(adj) + paths.extend(find_path(hmap, new_path, adj)) + return paths + +shortest = None + +paths = find_path(hmap, set([start]), start) +for path in paths: + if not shortest or len(path) < shortest: + shortest = len(path) + +print('part1', shortest - 1) + +trail_lengths = {} + +def valid_jump2(hmap, pos, adj): + poschar = get_char(hmap, pos) + adjchar = get_char(hmap, adj) + poselev = get_elevation(poschar) + adjelev = get_elevation(adjchar) + return adjelev + 1 >= poselev + +def find_trail(hmap, trail, pos): + for adj in get_adjacents(pos): + if adj not in trail and in_bounds(adj) and valid_jump2(hmap, pos, adj): + trail_length = len(trail) + 1 + if adj not in trail_lengths or trail_lengths[adj] > trail_length: + trail_lengths[adj] = trail_length + new_trail = list.copy(trail) + new_trail.append(adj) + find_trail(hmap, new_trail, adj) + +find_trail(hmap, [end], end) + +shortest = None + +for y in range(h): + for x in range(w): + if (x, y) in trail_lengths: + if get_elevation(get_char(hmap, (x, y))) == ord('a'): + trail_length = trail_lengths[(x, y)] + if not shortest or trail_length < shortest: + shortest = trail_length + +print('part2', shortest - 1) diff --git a/2022/day12.txt b/2022/day12.txt new file mode 100644 index 0000000..3005358 --- /dev/null +++ b/2022/day12.txt @@ -0,0 +1,41 @@ +abacccaaaacccccccccccaaaaaacccccaaaaaaccccaaacccccccccccccccccccccccccccccccccccccccccccaaaaa +abaaccaaaacccccccccccaaaaaaccccccaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccaaaaa +abaaccaaaacccccccccccaaaaacccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccaaaaa +abccccccccccccccccccccaaaaacccaaaaaaaaaaaaaaaacccccccccccccccccccccccccccaaaccccccccccccaaaaa +abccccccccccccccccccccaacaacccaaaaaaaaccaaaaaccccccccccccccccccccccccccccaaaccccccccccccaccaa +abcccccccccccccaacccaaaccccccaaaaaaaaaccaaaaaccccccccccccccccccccccccccccccacccccccccccccccca +abcccccccccccaaaaaaccaaaccacccccaaaaaaacccccccccccccccccccccccccciiiicccccccddddddccccccccccc +abcccccccccccaaaaaaccaaaaaaaccccaaaaaacccccaacccccccaaaccccccccciiiiiiiicccdddddddddacaaccccc +abccccccccccccaaaaaaaaaaaaacccccaaaaaaacaaaacccccccaaaacccccccchhiiiiiiiiicddddddddddaaaccccc +abcccccccccccaaaaaaaaaaaaaacccccccaaacccaaaaaacccccaaaaccccccchhhipppppiiiijjjjjjjddddaaccccc +abcccccccccccaaaaaaaaaaaaaaccccccccccccccaaaaaccccccaaaccccccchhhpppppppiijjjjjjjjjddeeaccccc +abcccccccccccccccccaaaaaaaacccccccccccccaaaaaccccccccccccccccchhppppppppppjjqqqjjjjjeeeaacccc +abccccccccccccccccccaaaaaaaacccccccccccccccaacccccccccccccccchhhpppuuuupppqqqqqqqjjjeeeaacccc +abcccccccccccccccccccaacccacccccccccccccccccccccccccccccccccchhhopuuuuuuppqqqqqqqjjjeeecccccc +abacccccccccccccaaacaaaccccccccccccccccccccccccccccaaccccccchhhhoouuuuuuuqvvvvvqqqjkeeecccccc +abaccccccccccccaaaaaacccccaaccccccccccccccccccccccaaaccccccchhhooouuuxxxuvvvvvvqqqkkeeecccccc +abaccccccccccccaaaaaacccaaaaaaccccccccccccccccccaaaaaaaaccchhhhooouuxxxxuvyyyvvqqqkkeeecccccc +abcccccccccccccaaaaacccaaaaaaaccccccccccccccccccaaaaaaaaccjjhooooouuxxxxyyyyyvvqqqkkeeecccccc +abccccccccccccccaaaaaacaaaaaaaccccccccaaaccccccccaaaaaaccjjjooootuuuxxxxyyyyyvvqqkkkeeecccccc +abccccccccccccccaaaaaaaaaaaaacccccccccaaaacccccccaaaaaacjjjooootttuxxxxxyyyyvvrrrkkkeeecccccc +SbccccccccccccccccccaaaaaaaaacccccccccaaaacccccccaaaaaacjjjoootttxxxEzzzzyyvvvrrrkkkfffcccccc +abcccccccccccaaacccccaaaaaaacaaaccccccaaaccccccccaaccaacjjjoootttxxxxxyyyyyyvvvrrkkkfffcccccc +abcccccccccaaaaaacccaaaaaacccaaacacccaacccccccccccccccccjjjoootttxxxxyxyyyyyywvvrrkkkfffccccc +abcccccccccaaaaaacccaaaaaaaaaaaaaaaccaaacaaacccccaacccccjjjnnnttttxxxxyyyyyyywwwrrkkkfffccccc +abcaacacccccaaaaacccaaacaaaaaaaaaaaccaaaaaaacccccaacaaacjjjnnnntttttxxyywwwwwwwwrrrlkfffccccc +abcaaaaccccaaaaacccccccccaacaaaaaaccccaaaaaacccccaaaaacccjjjnnnnnttttwwywwwwwwwrrrrllfffccccc +abaaaaaccccaaaaaccccccaaaaaccaaaaacaaaaaaaaccccaaaaaaccccjjjjinnnntttwwwwwsssrrrrrllllffccccc +abaaaaaaccccccccccccccaaaaacaaaaaacaaaaaaaaacccaaaaaaacccciiiiinnnntswwwwssssrrrrrlllfffccccc +abacaaaaccccccccccccccaaaaaacaaccccaaaaaaaaaaccccaaaaaaccccciiiinnnssswwsssssllllllllfffccccc +abccaaccccccccccccccccaaaaaaccccccccccaaacaaaccccaaccaacccccciiiinnsssssssmmllllllllfffaacccc +abccccccccccccccccccccaaaaaaccccccccccaaaccccccccaaccccccccccciiinnmsssssmmmmlllllgggffaacccc +abcccccccccccccccaccccccaaacccccccccccaaccccccccccccccccccccccciiimmmsssmmmmmgggggggggaaacccc +abcccccccccaaaaaaaaccccccccccccccccccccccccccccaaaaaccccccccccciiimmmmmmmmmgggggggggaaacccccc +abccccccccccaaaaaaccccccccccccccccccaacccccccccaaaaacccccccccccciiimmmmmmmhhggggcaaaaaaaccccc +abccccccccccaaaaaacccccccccccccccccaacccccccccaaaaaacccccccccccciihhmmmmhhhhgccccccccaacccccc +abccccaacaaaaaaaaaaccccccccccccccccaaaccccccccaaaaaaccccccccccccchhhhhhhhhhhaaccccccccccccccc +abccccaaaaaaaaaaaaaaccccccccccaaccaaaaccccccccaaaaaacccaaacccccccchhhhhhhhaaaaccccccccccccccc +abcccaaaaaaaaaaaaaaaccccccccaaaaaacaaaacacaccccaaaccccaaaacccccccccchhhhccccaaccccccccccaaaca +abcccaaaaaacacaaacccccccccccaaaaaaaaaaaaaaacccccccccccaaaacccccccccccaaaccccccccccccccccaaaaa +abcccccaaaacccaaaccccccccccaaaaaaaaaaaaaaaaccccccccccccaaacccccccccccaaacccccccccccccccccaaaa +abcccccaacccccaacccccccccccaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccccccccaaaaa diff --git a/2022/day12test.txt b/2022/day12test.txt new file mode 100644 index 0000000..86e9cac --- /dev/null +++ b/2022/day12test.txt @@ -0,0 +1,5 @@ +Sabqponm +abcryxxl +accszExk +acctuvwj +abdefghi diff --git a/2022/day14.py b/2022/day14.py new file mode 100755 index 0000000..e68bc47 --- /dev/null +++ b/2022/day14.py @@ -0,0 +1,89 @@ +#!/bin/python3 + +from collections import defaultdict +from enum import Enum +from itertools import pairwise + +class Tile(Enum): + AIR = 1 + ROCK = 2 + SOURCE = 3 + SAND = 4 + +grid = defaultdict(lambda: Tile.AIR) + +with open('inputs/day14.txt', 'r') as f: + for line in f: + for (start, end) in pairwise(line.strip().split(' -> ')): + [sx, sy] = map(int, start.split(',')) + [ex, ey] = map(int, end.split(',')) + + dx = 0 + dy = 0 + if ex > sx: + dx = 1 + elif ex < sx: + dx = -1 + + if ey > sy: + dy = 1 + elif ey < sy: + dy = -1 + + curx = sx + cury = sy + grid[(curx, cury)] = Tile.ROCK + while curx != ex or cury != ey: + curx += dx + cury += dy + grid[(curx, cury)] = Tile.ROCK + +highest_y = -1 +for (x, y), tile in grid.items(): + if y > highest_y: + highest_y = y + +def query_grid(x, y): + if y == highest_y + 2: + return Tile.ROCK + return grid[(x, y)] + +(sourcex, sourcey) = (500, 0) + +def abyss_underneath(x, y): + for (gridx, gridy), tile in grid.items(): + if gridy > y and gridx == x and tile != Tile.AIR: + return False + return True + +# voided = False +blocked = False +while True: + (x, y) = (sourcex, sourcey) + while True: + # if abyss_underneath(x, y): + # voided = True + # break + if query_grid(x, y+1) == Tile.AIR: + y += 1 + elif query_grid(x-1, y+1) == Tile.AIR: + y += 1 + x -= 1 + elif query_grid(x+1, y+1) == Tile.AIR: + y += 1 + x += 1 + else: + if (x, y) == (sourcex, sourcey): + blocked = True + break + # if voided: + # break + if blocked: + break + grid[(x, y)] = Tile.SAND + +rest_count = 0 +for (x, y), tile in grid.items(): + if tile == Tile.SAND: + rest_count += 1 +print(rest_count + 1) diff --git a/2022/day15.py b/2022/day15.py new file mode 100755 index 0000000..0337487 --- /dev/null +++ b/2022/day15.py @@ -0,0 +1,101 @@ +#!/bin/bash + +# thanks github.com/bernadetten +import sys +import re +from itertools import pairwise + +test = bool(int(sys.argv[1])) +file_path = "" +data = "" +prodata = [] +given_y = [int(sys.argv[2])] +absent_points = [] +part1 = bool(int(sys.argv[3])) +max_y = int(sys.argv[4]) + +if test: + file_path = "test_day_15.txt" +else: + file_path = "input_day_15.txt" + +with open(file_path, "r") as f: + data = f.read().split("\n") + +# The anhatten distance +def md(x1, y1, x2, y2): + return abs(x1 - x2) + abs(y1 - y2) + +# Processing the data. +for line in data: + if line != "": + m = re.match( + r"Sensor at x=(?P-?\d+), y=(?P-?\d+): closest beacon is at x=(?P-?\d+), y=(?P-?\d+)", + line.strip(), + ) + x_s = int(m.group("sx")) + y_s = int(m.group("sy")) + x_b = int(m.group("bx")) + y_b = int(m.group("by")) + + dis = md(x_s, y_s, x_b, y_b) + prodata += [((x_s, y_s), (x_b, y_b), dis)] + +# All y-values we want to loop over if part 2 +if not part1: + given_y = [x for x in range(0, max_y + 1)] + +# Merge all ranges +def mergeranges(ranges): + super_range = ranges[0] + ranges = ranges[1:] + + for (xl, xh) in ranges: + # print('super', super_range) + #print('comparing to', xl, ' ', xh) + + if not (xl - 1 <= super_range[1] and xl >= super_range[0]): + return xl - 1 + + if xh > super_range[1]: + super_range = (super_range[0], xh) + + return None + +# Now we calculate the impossible ranges +for y in given_y: + if part1: + beacon_on_y = [b[0] for _, b, _ in prodata if b[1] == y] + + absent_points = [] + #print(y) + # We need to add the ranges of points that are not available. + for source, beacon, dis in prodata: + height_diff = abs(source[1] - y) + + remain_dist = dis - height_diff + + if remain_dist >= 0: + # print('Source ', source, ' y ', y, ' dis ', dis, ' diff ', height_diff) + lower_x = source[0] - remain_dist + higher_x = source[0] + remain_dist + + if part1: + absent_points += [ + x for x in range(lower_x, higher_x + 1) if x not in beacon_on_y + ] + else: + absent_points += [(lower_x, higher_x)] + + # If we are doing part two we need to post process the output per line. + if not part1: + # print(absent_points) + absent_points = sorted(absent_points) + #print(absent_points) + result = mergeranges(absent_points) + if result != None: + print('part2, x:', result, 'y:', y, 'output:', result *4000000 +y) + sys.exit() + +if part1: + print('part1', len(set(absent_points))) diff --git a/2022/day16.py b/2022/day16.py new file mode 100755 index 0000000..c09465d --- /dev/null +++ b/2022/day16.py @@ -0,0 +1,103 @@ +#!/bin/python3 + +import re +from dijkstar import Graph, find_path +import numpy as np +from itertools import combinations +import itertools as it +from tqdm import tqdm + +valves = list() + +with open('inputs/day16.txt', 'r') as f: + for line in f: + m = re.match(r"Valve (?P[A-Z]{2}) has flow rate=(?P\d+); tunnels? leads? to valves? (?P.*)", line.strip()) + name = m.group("name") + rate = int(m.group("rate")) + tunnels = m.group("tunnels").split(", ") + + valves.append({"name": name, "rate": rate, "tunnels": tunnels}) + +indices = {} +for i, valve in enumerate(valves): + indices[valve["name"]] = i + +graph = Graph() +for v1 in valves: + for v2 in v1["tunnels"]: + graph.add_edge(v1["name"], v2, 1) + graph.add_edge(v2, v1["name"], 1) + +adjs = np.zeros((len(valves), len(valves))) +for v1, v2 in combinations(map(lambda v: v["name"], valves), 2): + cost = find_path(graph, v1, v2).total_cost + adjs[indices[v1], indices[v2]] = cost + adjs[indices[v2], indices[v1]] = cost + +class Valve: + def __init__(self, name, rate): + self.name = name + self.rate = rate + + def value(self, start, time_left): + cost = adjs[indices[start], indices[self.name]] + 1 + return (self.rate * (time_left - cost), cost) # one off? + +valve_map = dict() +valve_set = set() +for valve in valves: + if valve["rate"] > 0: + valve_set.add(valve["name"]) + valve_map[valve["name"]] = Valve(valve["name"], valve["rate"]) + +def search(valve_set, current, time_left, visited): + to_visit_set = valve_set.difference(visited) + best_score = 0 + for to_visit in to_visit_set: + # print("time left:", time_left) + # print("current:", current) + # print("going to visit:", to_visit) + visited_copy = visited.copy() + visited_copy.add(to_visit) + score, dtime = valve_map[to_visit].value(current, time_left) + # print("+score:", score, "+time", dtime) + if time_left - dtime >= 0: + score = score + search(valve_set, to_visit, time_left - dtime, visited_copy) + if not best_score or score > best_score: + best_score = score + return best_score + + +# print('part1', search(valve_set, "AA", 30, set())) + +# part2 idea +# BIGBRAIN +# divide valve set in two disjoint sets +# apply same search algorithm to both sets. +# sum the scores of the sets to get total score +# brute force set distribution + +def partition(pred, iterable): + t1, t2 = it.tee(iterable) + return it.filterfalse(pred, t1), filter(pred, t2) + +def partitions(l): + return list(filter(lambda x: [] not in x, [[[x[1] for x in f] for f in partition(lambda x: x[0], zip(pattern, l))] for pattern in it.product([True, False], repeat=len(l))])) + # for [lhs, rhs] in parts: + # if (set(lhs), set(rhs)) not in result and (set(rhs), set(lhs)) not in result: + # result.append((set(lhs), set(rhs))) + # return result + +best_score = 0 + +for part in tqdm(partitions(list(valve_set))): + [part1, part2] = part + part1 = set(part1) + score1 = search(part1, 'AA', 26, set()) + part2 = set(part2) + score2 = search(part2, 'AA', 26, set()) + grand_score = score1 + score2 + if grand_score > best_score: + best_score = grand_score + +print('part2', best_score) diff --git a/2022/day17.py b/2022/day17.py new file mode 100755 index 0000000..4a709b4 --- /dev/null +++ b/2022/day17.py @@ -0,0 +1,311 @@ +#!/bin/python3 + +from enum import Enum +from collections import defaultdict +from itertools import pairwise, combinations + +class Move(Enum): + LEFT = 1 + RIGHT = 2 + DOWN = 3 + +moves = list() + +with open('inputs/day17.txt', 'r') as f: + for line in f: + for char in line.strip(): + if char == '<': + moves.append(Move.LEFT) + elif char == '>': + moves.append(Move.RIGHT) + +def move_stream(): + while True: + for i, d in enumerate(moves): + yield (i, d) + yield (i, Move.DOWN) + +move_map = {Move.LEFT: (-1, 0), Move.RIGHT: (1, 0), Move.DOWN: (0, -1)} + +class Rock(): + def __init__(self, shape): + self.blocks = shape + + def init_position(self, y_top): + self.blocks = list(map(lambda pos: (pos[0] + 2, pos[1] + y_top + 4), self.blocks)) + + def move(self, chamber, move): + new_blocks = self.move_blocks(move) + if self.check_valid(chamber, new_blocks): + self.blocks = new_blocks + return True + else: + return False + + def move_blocks(self, move): + (movex, movey) = move_map[move] + return list(map(lambda block: (block[0] + movex, block[1] + movey), self.blocks)) + + def check_valid(self, chamber, blocks): + for (x, y) in blocks: + if x > 6 or x < 0 or chamber[y][x]: + return False + + return True + +shapes = [ + [(0, 0), (1, 0), (2, 0), (3, 0)], + [(0, 1), (1, 1), (2, 1), (1, 0), (1, 2)], + [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], + [(0, 0), (0, 1), (0, 2), (0, 3)], + [(0, 0), (1, 0), (0, 1), (1, 1)] +] + +def rock_stream(): + while True: + for i, shape in enumerate(shapes): + yield (i, Rock(shape.copy())) + +chamber = defaultdict(lambda: defaultdict(lambda: False)) +for i in range(7): + chamber[-1][i] = True + +def print_chamber(chamber, rock, print_index): + keys = list(reversed(sorted(chamber.keys()))) + for key in keys: + if print_index: + print(f'{key}\t', end='') + for i in range(7): + if chamber[key][i]: + print('#', end='') + elif rock and (i, key) in rock.blocks: + print('@', end='') + else: + print('.', end='') + print('') + +def prune_chamber(chamber): + ys = list(reversed(sorted(chamber.keys()))) + prune_height = None + for y_high, y_low in pairwise(ys): + prunable = True + for x in range(7): + if not chamber[y_high][x] and not chamber[y_low][x]: + prunable = False + break + if prunable: + prune_height = y_low + break + if prune_height: + for y in ys: + if y < prune_height: + del chamber[y] + return prune_height != None + +def row_to_mask(row): + mask = 0 + bit = 1 + for x in range(6, -1, -1): + if row[x]: + mask = mask | bit + bit = bit << 1 + return mask + +barrier_fingerprints = defaultdict(lambda: list()) + +rock_count = 20220 +prune_freq = 100 +y_top = -1 +moves_gen = move_stream() +rocks_gen = rock_stream() +rocks_fallen = 0 +rock_idx = None +for rock_idx, rock in rocks_gen: + rock.init_position(y_top) + for move_idx, move in moves_gen: + moved = rock.move(chamber, move) + if not moved and move == Move.DOWN: + for (x, y) in rock.blocks: + if y > y_top: + y_top = y + chamber[y][x] = True + rocks_fallen += 1 + break + + ys = set(map(lambda x: x[1], rock.blocks)) + for y in ys: + all_filled = True + for x in range(7): + if not chamber[y][x] and not chamber[y-1][x]: + all_filled = False + break + if all_filled: + mask_high = row_to_mask(chamber[y]) + mask_low = row_to_mask(chamber[y-1]) + fingerprint = (rock_idx, move_idx, mask_high, mask_low) + barrier_fingerprints[fingerprint].append((rocks_fallen, y)) + + if rocks_fallen == rock_count: + break +print('part1', y_top + 1) + +candidate_fp = None +candidate_ys_count = 0 +for fp, ys in barrier_fingerprints.items(): + l = len(ys) + if l > candidate_ys_count: + candidate_ys_count = l + candidate_fp = fp +# print('candidate FP:', candidate_fp) +first_occ = barrier_fingerprints[candidate_fp][0] +second_occ = barrier_fingerprints[candidate_fp][1] +height_cycle = second_occ[1] - first_occ[1] +rock_cycle = second_occ[0] - first_occ[0] +# print('first occurance:', 'height', first_occ[1], 'fallen', first_occ[0]) +# print('second occurance:', 'height', second_occ[1], 'fallen', second_occ[0]) +# print('height cycle:', second_occ[1] - first_occ[1]) +# print('rock cycle:', second_occ[0] - first_occ[0]) + +rocks_left = 1000000000000 - first_occ[0] +superheight = first_occ[1] +superheight += (rocks_left // rock_cycle) * height_cycle +rocks_left %= rock_cycle +print(rocks_left, superheight) + +# We just need $rocks_left rocks more! +# Move to the next cycle point +# Then simulate $rocks_left movements to get the height this generates. +# Add this to superheight then subtract one height_cycle. + +for rock_idx, rock in rocks_gen: + rock.init_position(y_top) + for move_idx, move in moves_gen: + moved = rock.move(chamber, move) + if not moved and move == Move.DOWN: + for (x, y) in rock.blocks: + if y > y_top: + y_top = y + chamber[y][x] = True + rocks_fallen += 1 + break + + ys = set(map(lambda x: x[1], rock.blocks)) + cycle_start = False + for y in ys: + all_filled = True + for x in range(7): + if not chamber[y][x] and not chamber[y-1][x]: + all_filled = False + break + if all_filled: + mask_high = row_to_mask(chamber[y]) + mask_low = row_to_mask(chamber[y-1]) + fingerprint = (rock_idx, move_idx, mask_high, mask_low) + if fingerprint == candidate_fp: + cycle_start = True + break + if cycle_start: + break + +start_height = y_top + +for rock_idx, rock in rocks_gen: + rock.init_position(y_top) + for move_idx, move in moves_gen: + moved = rock.move(chamber, move) + if not moved and move == Move.DOWN: + for (x, y) in rock.blocks: + if y > y_top: + y_top = y + chamber[y][x] = True + rocks_left -= 1 + break + + if rocks_left == 0: + break + +end_height = y_top +superheight += end_height - start_height +print('part2', superheight + 3) + +# for fp, ys in barrier_fingerprints.items(): +# print('fingerprint:', fp) +# print('count:', len(ys)) + +# NEW IDEA +# Find a cycle. +# A cycle can be characterized by: rock rotation, direction rotation and rock formation. +# Problem is, we need to save a lot of the rock formation, because new rocks can fall down a long while. +# Additionally, we cannot just save the height of each column, because rocks can move underneath hanging arches. +# Possible solution: find lines that block this. +# Possibly in one line, definitely in two lines. + +# IDEA: +# Create bitmap. +# Easily compare bitmaps with eachother to find cycle + +# def print_mask(mask): +# bit = 1 << 6 +# for i in range(7): +# if mask & (bit >> i): +# print('1', end='') +# else: +# print('0', end='') +# print('') + +# def print_bitmap(bitmap): +# for row in bitmap: +# print_mask(row) + +# bitmap = [] +# ys = list(reversed(sorted(chamber.keys()))) +# y_min = min(ys) +# y_max = max(ys) +# for y in range(y_min + 1, y_max + 1): +# mask = 0 +# bit = 1 +# for x in range(6, -1, -1): +# if chamber[y][x]: +# mask = mask | bit +# bit = bit << 1 + # print_mask(mask) + # bitmap.append(mask) + +# def in_order(l): +# last = None +# for x in l: +# if last == None or x > last: +# last = x +# else: +# return False +# return True + +# def same_distance(l): +# [y1, y2, y3] = l +# return y2 - y1 == y3 - y2 + +# def is_cycle(bitmap, l): +# [y1, y2, y3] = l +# distance = y3 - y2 +# for i in range(distance + 1): +# if bitmap[y1+i] != bitmap[y2]+i: +# return False +# return True + +# Now try to find the cycle! +# We loop over every row. +# We find all indices of this row in the whole chamber +# checked = [] +# print('finding cycle') +# for row in bitmap: +# print('row:', row) +# if row not in checked: +# checked.append(row) +# indices = [i for i, x in enumerate(bitmap) if x == row] +# if len(indices) >= 3: +# for maybe_cycle in combinations(indices, 3): +# if in_order(maybe_cycle) and same_distance(maybe_cycle): +# if is_cycle(bitmap, maybe_cycle): +# print('FOUND CYCLE:', maybe_cycle) + +# # print_bitmap(bitmap) diff --git a/2022/day18.py b/2022/day18.py new file mode 100755 index 0000000..546561c --- /dev/null +++ b/2022/day18.py @@ -0,0 +1,113 @@ +#!/bin/python3 + +from collections import defaultdict +from queue import Queue + +cubes = set() + +with open('inputs/day18.txt', 'r') as f: + for line in f: + [x, y, z] = line.split(',') + cubes.add((int(x), int(y), int(z))) + +def ordered(pos1, pos2): + if pos1 > pos2: + return (pos1, pos2) + else: + return (pos2, pos1) + +sides = defaultdict(lambda: 0) +for cube in cubes: + (x, y, z) = cube + cube_sides = [] + cube_sides.append(ordered(cube, (x+1, y, z))) + cube_sides.append(ordered(cube, (x-1, y, z))) + cube_sides.append(ordered(cube, (x, y+1, z))) + cube_sides.append(ordered(cube, (x, y-1, z))) + cube_sides.append(ordered(cube, (x, y, z+1))) + cube_sides.append(ordered(cube, (x, y, z-1))) + + for side in cube_sides: + sides[side] += 1 + +outer_sides = set() +for side, count in sides.items(): + if count == 1: + outer_sides.add(side) + +print("part1", len(outer_sides)) + +# Determine max and min coords +x_min = min(map(lambda a: a[0], cubes)) +x_max = max(map(lambda a: a[0], cubes)) +y_min = min(map(lambda a: a[1], cubes)) +y_max = max(map(lambda a: a[1], cubes)) +z_min = min(map(lambda a: a[2], cubes)) +z_max = max(map(lambda a: a[2], cubes)) + +# Increase bounds by 1 in all directions +x_min -= 1 +x_max += 1 +y_min -= 1 +y_max += 1 +z_min -= 1 +z_max += 1 + +# Flood fill from 1 corner to find all reachable cubes. +class SetQueue(Queue): + def _init(self, maxsize): + self.queue = set() + def _put(self, item): + self.queue.add(item) + def _get(self): + return self.queue.pop() + +cube_queue = SetQueue() +cube_queue.put((x_min, y_min, z_min)) +reachable_cubes = set() + +max_cubes = (x_max - x_min) * (y_max - y_min) * (z_max - z_min) +while True: + if cube_queue.empty(): + break + cube = cube_queue.get() + (x, y, z) = cube + reachable_cubes.add(cube) + + neighbors = [] + neighbors.append((x+1, y, z)) + neighbors.append((x-1, y, z)) + neighbors.append((x, y+1, z)) + neighbors.append((x, y-1, z)) + neighbors.append((x, y, z+1)) + neighbors.append((x, y, z-1)) + + for neighbor in neighbors: + (nx, ny, nz) = neighbor + if nx < x_min or nx > x_max or ny < y_min or ny > y_max or nz < z_min or nz > z_max: + continue + if neighbor in reachable_cubes or neighbor in cubes: + continue + + # Found a new empty cube! + cube_queue.put(neighbor) + +# Okay, found all empty cube outside the droplet. + +surface_sides = set() + +for empty in reachable_cubes: + (x, y, z) = empty + cube_sides = [] + cube_sides.append(ordered(empty, (x+1, y, z))) + cube_sides.append(ordered(empty, (x-1, y, z))) + cube_sides.append(ordered(empty, (x, y+1, z))) + cube_sides.append(ordered(empty, (x, y-1, z))) + cube_sides.append(ordered(empty, (x, y, z+1))) + cube_sides.append(ordered(empty, (x, y, z-1))) + + for side in cube_sides: + if side in outer_sides: + surface_sides.add(side) + +print("part2", len(surface_sides)) diff --git a/2022/day8.py b/2022/day8.py new file mode 100755 index 0000000..26fc339 --- /dev/null +++ b/2022/day8.py @@ -0,0 +1,54 @@ +#!/bin/python3 + +forest = [] + +with open('day8.txt', 'r') as f: + for line in f: + forest.append(list(map(int, list(line.strip())))) + +height = len(forest) +width = len(forest[0]) + +heighest = -1 +heighest_x = -1 +heighest_y = -1 + +for y in range(height): + for x in range(width): + h = forest[x][y] + tree_count = 1 + + tree_count_cur = 0 + for cur_x in range(x+1, width): + tree_count_cur += 1 + if forest[cur_x][y] >= h: + break + tree_count *= tree_count_cur + + tree_count_cur = 0 + for cur_x in range(x-1, -1, -1): + tree_count_cur += 1 + if forest[cur_x][y] >= h: + break + tree_count *= tree_count_cur + + tree_count_cur = 0 + for cur_y in range(y+1, height): + tree_count_cur += 1 + if forest[x][cur_y] >= h: + break + tree_count *= tree_count_cur + + tree_count_cur = 0 + for cur_y in range(y-1, -1, -1): + tree_count_cur += 1 + if forest[x][cur_y] >= h: + break + tree_count *= tree_count_cur + + if tree_count > heighest: + heighest = tree_count + heighest_x = x + heighest_y = y + +print(x, y, heighest) diff --git a/2022/day8.txt b/2022/day8.txt new file mode 100644 index 0000000..8c85240 --- /dev/null +++ b/2022/day8.txt @@ -0,0 +1,99 @@ +113003322412033102023303501444545044215232525401341546163452453404402234201151432242402140110220101 +332001304022012142421445502213221330453061535265122314201352335233021055055200345412200440033322200 +011113132214324432134325045311145402450516101640412524056254134552334050434552541351100000142223210 +120100233011423423144030334144351644642605521663331053414601341464201040045104150001214204243212330 +032313022420343002352401031112122630544621450306410014210122655033613410314450242104133332033433110 +330133431221024552500405304311611205251454505525065601244143364343441153320511500334525320443331122 +232021314224321045040222145130205324423110304256225426345644345334310200416004113133521143332200422 +312322022143422250013255366221252062135020112327134227764002156152041134323314242255102200014240004 +212411010402324310541162616440606266620317315234166112525535542054554446314636025435501101142314410 +130420010020500305012262532345565125253527765422533261626735742433241362062404452514044512024131310 +241211034142224054050344306633445512263575724527746635663111434536510100261040501431453540340134211 +241313213114241230212646636605641533121654131662127125143714342377771455431346140255405303533314030 +200214302143123545226333105604234323144236661442633717414531213335635263423430225510502553055320124 +432210433113545424321340236152364457166745737761176472274142327714574465315263302246430530531052340 +044321111115013046066155407144655275272121513224325736736453741437462322257332111603344504052313220 +423214232334431334032453034121465736632235428586864276787383246667147623517713521254056250023050122 +341124205512002021001520535463145337475482376656634323542842654415315313467514115356311404235042224 +132001402100660310301501776141144746672773424257875288227677277663442356545463514004411150412531212 +001052001350350313612735275534436625275423778573334245773528222523563225127612470242660400232440014 +000112513501320042013743116251356437388536835723273464367352632733656224242323651012010230151310024 +432343513243516355144362617334462875826626872624526547773732534284688857151541627654520220114445210 +030155000415201011165562424113226826748747748853864385358746645352362468546644524342115335322112153 +521354124325146425431532157187775456325686557739354768338786565328828884835715454276200630310531024 +453541003326165663116714725533384334462564846638857736639973473868246353547315725644665433532024310 +550412430051564655211263423273445384473677893666497965987545884578247877687261326676604334421513240 +413054444206603631433161684337566624388758573363447988796769799695582635658423643315241325425634024 +215150330040102563666211553675525355868889739969438648979533595459347577832874756321426443250541325 +421424650534663421741533522275548697677937396576933765698789956783468276533784535453223333266121254 +422144151564541614312463257866683347483647399747895987469373443743399762878755625665635533442122100 +142126413036631514413457664863683937946499766465555784756389698779343558673226534437441452602242233 +305201320636671251145832252388563746733774564949748445664654449965453936743822654651524764154313443 +011300622102111771164477857675385967936859964787497949987577437799784855267278677674646432241223234 +340321113267666756754785648366853336456946997569954774746449465943647534953257556352535151305025463 +541411012547643576586448655984493857478575997945994447954587596973768677885376565465523461502535643 +444321100654632152854364424757747839747855469574958798776977549543479354379242483435267721134026240 +020626205154575316847673866764644374748789977457499575788744688854499953995222366237635424744520350 +335506510045711628565868794334457797677874456886875779795697459467453749364727248672726163736041204 +500111603536263112863778287468558998649869948858895979757648556554566675849574438477347434571054505 +122000100243546685578334388934875844674864976796788677978555975645687865954363424837536471770452415 +141414215752566148738527647673948945657599775586897776875597686768689334698832463748744764733053124 +100340653262173232623746876388947885855898958859977856795865855466954797947557362275815142426540331 +466303032723142355554844869739456445889568997967558595977567767954454556686589744843263767635404425 +004613266772514623473428884775998765955988667675865595697667595999549844548767382824562175546612214 +223062321176322437826876799485789855749797897795766857786556556466469876653886288833557467773301562 +413332261232125275243773533956777794896856665777776697967896558687464977634963578724434267752313063 +552404621241274462672869963657657685959857786696669988675856559577744587934439473355436162566631240 +435165353647675322378767844955594694568958979668688889986755769858696479453833942343873533447232052 +244432367557727222376845574654778567657966566799677789797957677969848457379553465846862364131450331 +500160365677454526747395979487899988575755756767767688698968968964795455975647975338665645777505164 +102431235675118652565457756594548744578555576979976998997755878856465958937486343448585657465615526 +246165542416756587676444776898888956766578897997878779867867799995588485976853457557557151277215635 +001643325345324464653748985776747945569696578767779897778688898756644945899654857626437342132540232 +012101664761176266736346897839595848575598988867686699987969655574844656549763626542283366457311330 +561504075335422826822483989945889874569866596668697889889787698578564685356683642368537236162426203 +352203514134651772748288733934776699589795768989986896977876655856647995457449532883535245357460413 +033642404423741338448747543456567587875878659898696769778857567974989696766857638532623516361132200 +616444206117715325587799743549596679896878996579778797758659755584898985549986338256726477267555103 +520455143625244274365846334377848464679657799659996799959789655886895549885388585227864441542440633 +301346217675555884462648646383444656479799855995796958569776779656497648598636775768426556776465212 +520404231326621664428744458384498945886755796967559979558788575647874897993564426835362551773515204 +316242511662326327222423774658467889697656957595795766869586965778777639684376585246752671616104436 +415146426112762185773325386754349955694758878879858887885879799994465943455896555866711732413133541 +355625411617227324663526785865944884474696755859788678978799585984575877863878686426651623174052622 +250022125746424524625262754995697689898769757895898887999798967686567449959582647242127737515510342 +525264040416627662865878845844435466984695749789657699584976867495646849545456285287242646554654353 +036123646424431555263267827839763498876769495677697448449595455554764947373454763645727333510646146 +204566364235641316654753765445963394466448895664985649465498769864394998376778764453573662441355520 +220335031661255773663868585338574847865979585777445874888879656858779783486746544464161776603563641 +222513656331342447187422756294679343838685457555849784967456454674489536467765228571211235451313300 +420041535613636672654268683685394696895377789594449696975655499485443388622338663537334646443120355 +525056224212611227113776876877874646779895859895448998785578796984395868862632743546145340000633644 +404314430546135313471247434875543567783736878545548779967377554684776373253726223752325712616213051 +353422360566111142127744587245868774578548754579967945935667489466386244448265471714226610251556141 +240135510612042471674334266253242658953336636546539684393847584358732442564537232411555541300234143 +555204024234655515726125842362866243634643845579964798949797638778425653264527614711662106606433551 +203524350135524444622315434263233285368993457879757738399643368354787234632745135155274525361620440 +340532455653452155645722264385685523579545388464998647475936784423755683487133452753535123313604354 +352152244221611331745526617386458872637865488449639856654753583624523335337272114515341203461045505 +312033003454166053225452625154365544367483828667456379835556776344278883841652574422331646601235245 +354330514213011046317425234714582372762675574834484437275552425744868747672133251365644033361512332 +044021444522010141412515121117476227878457643873272338756238823637528547351444752605411146631314215 +232413442230001100251223172352214643455635846823657522575345326788747411734266577565251164231145220 +131504320306315625216346311325345143883224276853882277427888248757813625336722630560555630113015013 +024451223151264563630623162617513241445834482436236846786748364751551471325535132540104323422105400 +124420553125506323053405346614111134556285246233525828237347884315614217572766434350535521515101401 +130200351112000250166105345316513263244676855323883356633222244252121772667652426014110503513555221 +400241412230012102424516231766252561312255446621244373337355416351623124213640652213520151043110444 +322440423504102454033133351036544434155137522762124773455775324625526553424524313460144053442544330 +324303335402501236440552111053234114555641277255456252443511634243752643304353256666504353255522122 +241434204225354100532033205000145461776516534477176114531271372735543451231303326454043352113013420 +334124213300015522546105345511323376357312632521613774424256342133105114520414061451141133554301031 +211304431150451251125020043053260563634374764226536222654742522421115640025331113215553523303422011 +123324243323523142132445503461621106650437431517676417742653314226115466013230223030345414021112341 +100121244242050431353422620202033056213213561562676642451361622463016135301034322504250003434240420 +202331344430130314251310046312513630614136423111235233115234253411664210435541154434125202004300041 +311142442400021052335032430131001522121243633355511015105456130306054020525345400331240114301233431 +303333210333101445104545232532514231420245342044224564606555504302423403203123103211431303412444103 +322112022033322224210512330414230625446520203533135512231066520423212314402311345154232414213413203 +210220340333424334214524143431005502542403323230305103516410534415015522312221415410344021130000212 diff --git a/2022/day9.py b/2022/day9.py new file mode 100755 index 0000000..f90e7ba --- /dev/null +++ b/2022/day9.py @@ -0,0 +1,106 @@ +#!/bin/python3 + +moves = [] + +with open('day9.txt', 'r') as f: + for line in f: + [direc, count] = line.split(' ') + count = int(count) + for i in range(count): + moves.append(direc) + +hlocs = [] +hloc = (0, 0) + +for move in moves: + if move == 'U': + hloc = (hloc[0], hloc[1]-1) + if move == 'D': + hloc = (hloc[0], hloc[1]+1) + if move == 'R': + hloc = (hloc[0]+1, hloc[1]) + if move == 'L': + hloc = (hloc[0]-1, hloc[1]) + hlocs.append(hloc) + +tlocs = set([(0, 0)]) +tloc = (0, 0) + +for hloc in hlocs: + if abs(hloc[0] - tloc[0]) > 1 or abs(hloc[1] - tloc[1]) > 1: + if hloc[0] < tloc[0]: + tloc = (tloc[0]-1, tloc[1]) + elif hloc[0] > tloc[0]: + tloc = (tloc[0]+1, tloc[1]) + if hloc[1] < tloc[1]: + tloc = (tloc[0], tloc[1]-1) + elif hloc[1] > tloc[1]: + tloc = (tloc[0], tloc[1]+1) + else: + if hloc[0] == tloc[0]+2: + tloc = (tloc[0]+1, tloc[1]) + elif hloc[0] == tloc[0]-2: + tloc = (tloc[0]-1, tloc[1]) + elif hloc[1] == tloc[1]+2: + tloc = (tloc[0], tloc[1]+1) + elif hloc[1] == tloc[1]-2: + tloc = (tloc[0], tloc[1]-1) + tlocs.add(tloc) + +print("part1", len(tlocs)) + +def print_state(n, parts): + for y in range(-n, n): + for x in range(-n, n): + printed = False + for i in range(10): + if parts[i][0] == x and parts[i][1] == y: + printed = True + print(str(i), end='') + break + if not printed: + print('#', end='') + print('') + print('') + +parts = [] +visited = set([(0, 0)]) +for i in range(10): + parts.append((0, 0)) +for move in moves: + print(move) + for i in range(10): + if i == 0: + if move == 'R': + parts[0] = (parts[0][0]+1, parts[0][1]) + if move == 'L': + parts[0] = (parts[0][0]-1, parts[0][1]) + if move == 'U': + parts[0] = (parts[0][0], parts[0][1]-1) + if move == 'D': + parts[0] = (parts[0][0], parts[0][1]+1) + else: + (prevx, prevy) = parts[i-1] + if abs(prevx - parts[i][0]) > 1 or abs(prevy - parts[i][1]) > 1: + if prevx < parts[i][0]: + parts[i] = (parts[i][0]-1, parts[i][1]) + elif prevx > parts[i][0]: + parts[i] = (parts[i][0]+1, parts[i][1]) + if prevy < parts[i][1]: + parts[i] = (parts[i][0], parts[i][1]-1) + elif prevy > parts[i][1]: + parts[i] = (parts[i][0], parts[i][1]+1) + else: + if prevx == parts[i][0]+2: + parts[i] = (parts[i][0]+1, parts[i][1]) + elif prevx == parts[i][0]-2: + parts[i] = (parts[i][0]-1, parts[i][1]) + elif prevy == parts[i][1]+2: + parts[i] = (parts[i][0], parts[i][1]+1) + elif prevy == parts[i][1]-2: + parts[i] = (parts[i][0], parts[i][1]-1) + if i == 9: + visited.add(parts[-1]) + print_state(5, parts) + +print('part2', len(visited)) diff --git a/2022/day9.txt b/2022/day9.txt new file mode 100644 index 0000000..cfb7438 --- /dev/null +++ b/2022/day9.txt @@ -0,0 +1,2000 @@ +U 2 +L 2 +U 1 +R 2 +D 2 +L 1 +R 1 +U 2 +D 1 +L 2 +D 2 +R 2 +D 1 +L 1 +U 2 +D 2 +R 1 +U 1 +L 1 +D 1 +L 1 +R 2 +U 1 +D 2 +U 2 +D 1 +L 1 +D 1 +L 2 +R 2 +D 2 +R 1 +D 2 +R 1 +D 2 +R 1 +U 2 +L 1 +U 2 +R 2 +D 2 +U 1 +R 1 +L 2 +D 1 +L 1 +R 1 +D 2 +R 2 +L 1 +R 2 +U 1 +L 2 +R 1 +D 1 +R 2 +U 2 +R 2 +L 1 +U 2 +R 1 +L 1 +U 2 +R 2 +D 2 +U 1 +L 2 +D 2 +R 1 +L 2 +D 2 +L 2 +R 1 +L 1 +U 2 +D 1 +U 1 +D 1 +L 1 +D 2 +U 1 +L 2 +R 2 +D 1 +U 1 +D 2 +L 2 +D 1 +R 1 +U 2 +D 2 +L 2 +R 2 +U 1 +D 1 +U 1 +L 1 +D 2 +R 1 +D 2 +U 1 +D 2 +U 2 +L 2 +R 2 +D 2 +R 1 +U 2 +R 2 +L 2 +U 1 +L 3 +U 3 +D 1 +U 2 +R 1 +U 3 +R 2 +U 3 +D 1 +R 1 +U 2 +D 2 +U 2 +D 2 +R 2 +U 3 +D 1 +L 1 +R 2 +U 2 +L 3 +U 3 +D 2 +L 3 +U 3 +R 2 +D 3 +L 3 +U 2 +D 2 +U 3 +R 1 +D 1 +R 2 +U 3 +D 3 +R 3 +D 2 +L 3 +D 2 +R 3 +D 1 +R 2 +U 1 +D 3 +R 2 +D 1 +U 3 +L 1 +U 2 +L 1 +R 3 +D 1 +L 1 +D 1 +R 2 +U 2 +R 1 +D 1 +R 2 +D 1 +R 3 +L 3 +U 1 +R 2 +U 1 +L 1 +D 1 +U 3 +D 1 +L 1 +R 1 +U 1 +D 3 +U 1 +R 3 +U 1 +L 1 +D 2 +R 2 +U 1 +R 1 +L 2 +R 1 +U 2 +L 3 +R 3 +L 1 +R 3 +D 3 +U 3 +R 1 +U 2 +L 2 +D 2 +R 3 +L 2 +R 3 +U 1 +L 1 +R 2 +D 2 +R 3 +U 2 +D 3 +R 2 +L 1 +D 3 +R 2 +L 3 +U 2 +L 1 +U 2 +R 1 +U 2 +D 1 +L 2 +U 3 +R 1 +U 4 +R 1 +U 4 +R 1 +L 1 +D 3 +L 3 +R 3 +U 4 +L 1 +R 2 +D 4 +U 2 +L 3 +U 1 +R 4 +D 1 +L 1 +U 4 +D 4 +L 3 +R 2 +D 4 +R 4 +D 1 +U 2 +L 4 +U 3 +D 2 +L 4 +D 2 +L 4 +U 2 +D 4 +L 1 +D 2 +U 4 +L 2 +U 1 +D 3 +U 4 +D 2 +L 1 +R 2 +L 4 +U 4 +L 3 +R 4 +D 3 +R 4 +D 2 +L 3 +U 2 +L 3 +U 1 +D 3 +L 4 +R 2 +D 2 +L 1 +U 2 +R 2 +L 1 +D 2 +U 3 +L 1 +U 1 +L 4 +U 4 +L 2 +R 1 +U 1 +R 4 +L 4 +D 2 +L 4 +D 4 +L 3 +U 4 +D 4 +L 2 +U 1 +L 1 +R 1 +L 4 +U 4 +L 2 +D 1 +R 2 +D 2 +L 2 +R 2 +L 1 +U 3 +L 1 +U 2 +D 2 +R 2 +D 3 +L 4 +R 2 +L 3 +R 3 +U 3 +L 5 +U 1 +D 3 +L 1 +U 5 +L 3 +U 4 +L 4 +R 5 +D 5 +R 1 +L 3 +D 1 +U 5 +R 3 +U 4 +D 4 +U 1 +D 4 +U 4 +R 4 +U 4 +R 4 +U 5 +R 3 +D 3 +L 1 +D 3 +U 4 +R 2 +U 2 +R 2 +U 2 +L 3 +R 4 +L 2 +D 5 +U 4 +D 4 +L 4 +R 4 +U 5 +R 1 +D 4 +L 4 +U 1 +L 2 +U 3 +D 1 +R 5 +U 4 +D 5 +L 5 +D 2 +L 1 +U 3 +D 4 +R 4 +L 2 +R 4 +D 3 +R 5 +L 4 +R 1 +D 3 +L 2 +R 5 +D 3 +R 1 +U 1 +L 5 +D 1 +U 4 +L 2 +U 4 +D 5 +L 4 +D 5 +L 2 +D 3 +R 5 +L 2 +D 1 +R 5 +D 1 +L 2 +U 1 +D 1 +L 3 +R 4 +L 1 +D 1 +U 3 +D 1 +R 2 +D 5 +R 3 +D 5 +L 2 +D 2 +U 5 +D 3 +R 5 +D 3 +R 4 +U 2 +L 5 +R 2 +D 5 +R 1 +U 5 +R 6 +D 6 +U 2 +R 3 +L 2 +U 4 +R 1 +D 6 +L 3 +U 5 +R 2 +L 6 +U 1 +D 5 +L 3 +R 3 +U 5 +L 1 +R 3 +U 3 +L 3 +R 6 +D 6 +L 3 +U 2 +R 1 +L 4 +R 5 +L 6 +R 4 +D 6 +U 6 +L 6 +U 2 +L 4 +D 6 +R 2 +D 2 +R 3 +D 2 +L 1 +U 4 +R 4 +D 1 +R 2 +L 1 +D 5 +L 6 +U 6 +D 2 +L 2 +D 1 +U 3 +D 1 +L 4 +U 5 +R 6 +U 5 +L 2 +R 6 +D 5 +R 3 +L 4 +U 6 +L 3 +D 6 +L 4 +R 5 +L 5 +R 4 +D 4 +L 5 +R 3 +U 6 +D 6 +L 3 +D 6 +U 1 +D 5 +L 5 +R 3 +L 4 +R 1 +L 1 +U 3 +D 6 +U 6 +R 2 +D 1 +U 2 +L 1 +R 5 +U 1 +L 5 +U 3 +R 3 +D 3 +L 4 +D 6 +U 1 +R 5 +L 3 +U 5 +R 2 +U 5 +L 3 +D 6 +R 6 +D 2 +R 5 +U 3 +D 6 +U 7 +R 7 +L 7 +U 2 +L 6 +U 2 +R 5 +L 7 +U 2 +D 5 +U 2 +R 2 +U 2 +L 1 +D 5 +U 5 +R 2 +U 6 +R 2 +D 3 +R 1 +D 4 +L 3 +R 5 +U 7 +D 6 +U 5 +D 2 +L 5 +U 5 +L 5 +R 7 +U 3 +L 7 +U 7 +L 3 +U 5 +D 7 +L 4 +D 6 +L 2 +U 7 +D 1 +L 6 +R 6 +D 7 +U 5 +L 2 +D 7 +U 1 +D 5 +L 2 +U 2 +D 1 +U 7 +R 1 +D 3 +L 4 +D 5 +R 4 +L 6 +R 1 +L 1 +D 2 +R 5 +U 4 +L 2 +D 7 +R 1 +U 3 +L 2 +U 3 +L 2 +U 6 +D 1 +U 3 +L 2 +U 4 +R 3 +L 7 +D 7 +R 6 +L 1 +R 3 +U 1 +R 3 +D 5 +R 2 +U 4 +R 1 +U 1 +L 6 +D 7 +U 5 +D 1 +R 2 +U 1 +L 6 +R 6 +U 6 +D 1 +U 4 +D 4 +U 4 +L 2 +D 5 +U 4 +R 4 +U 7 +D 4 +U 5 +D 5 +U 8 +L 6 +U 5 +L 1 +D 5 +R 1 +D 7 +L 8 +U 4 +R 7 +U 7 +D 4 +L 4 +U 7 +D 1 +R 4 +L 2 +U 2 +R 7 +L 1 +R 2 +L 2 +R 1 +L 3 +D 7 +L 3 +D 7 +U 6 +L 1 +D 4 +U 2 +D 8 +R 4 +D 2 +R 7 +L 8 +U 5 +L 7 +U 5 +R 1 +D 4 +R 8 +L 2 +R 7 +L 4 +U 6 +R 3 +D 6 +L 8 +R 5 +U 5 +R 1 +D 3 +U 8 +R 3 +D 5 +L 1 +D 2 +R 8 +D 3 +R 6 +L 2 +R 1 +U 5 +R 5 +U 7 +L 3 +R 3 +L 8 +D 5 +L 2 +D 3 +L 5 +D 6 +L 5 +U 2 +R 3 +U 5 +R 7 +D 2 +U 5 +R 2 +D 3 +L 5 +R 1 +U 7 +L 5 +D 5 +R 4 +U 6 +D 8 +R 2 +D 4 +L 3 +R 4 +D 1 +L 7 +U 8 +L 3 +U 6 +D 6 +L 4 +D 1 +U 6 +L 4 +R 2 +L 5 +D 5 +L 5 +D 6 +R 2 +U 1 +L 7 +R 4 +D 9 +U 1 +L 3 +D 7 +L 9 +D 3 +U 9 +L 6 +D 6 +U 5 +D 5 +R 2 +D 8 +R 2 +D 1 +U 9 +D 7 +R 2 +D 3 +U 1 +L 3 +D 5 +R 3 +L 6 +D 7 +U 2 +R 8 +U 2 +L 6 +D 4 +L 5 +R 5 +L 6 +D 5 +L 1 +U 8 +D 1 +L 9 +D 6 +R 5 +D 4 +U 2 +R 9 +D 1 +U 4 +D 1 +U 7 +L 4 +R 4 +D 8 +U 3 +R 7 +L 1 +D 4 +L 9 +U 7 +L 6 +R 2 +L 6 +D 4 +L 8 +U 8 +L 2 +R 1 +L 9 +D 9 +L 2 +U 7 +L 5 +D 2 +U 1 +L 6 +D 6 +L 1 +R 8 +D 3 +R 8 +L 6 +U 7 +D 9 +U 7 +L 7 +D 4 +R 8 +D 3 +R 9 +L 1 +U 4 +L 2 +R 9 +L 3 +D 9 +R 7 +D 3 +U 4 +D 9 +R 4 +L 6 +U 9 +D 7 +U 8 +D 7 +L 1 +R 2 +U 3 +D 7 +U 5 +R 4 +L 8 +D 9 +L 1 +U 9 +L 1 +D 1 +L 2 +U 2 +R 8 +D 6 +L 4 +U 9 +L 3 +R 9 +U 4 +L 5 +R 6 +U 6 +D 6 +L 5 +D 4 +L 9 +R 1 +L 3 +D 8 +L 1 +R 2 +D 8 +U 10 +L 1 +D 8 +L 4 +U 7 +D 4 +R 10 +D 5 +L 5 +U 10 +R 3 +U 6 +L 10 +R 2 +U 5 +R 7 +L 5 +R 6 +U 4 +D 8 +U 8 +D 7 +R 8 +U 3 +D 7 +R 4 +D 4 +L 8 +R 2 +U 9 +R 1 +L 7 +R 6 +D 2 +U 9 +R 4 +D 9 +R 7 +D 6 +U 3 +L 4 +D 9 +L 9 +D 8 +L 4 +R 4 +U 6 +D 2 +U 3 +D 1 +L 1 +R 10 +L 1 +D 2 +R 4 +U 6 +L 3 +D 4 +L 4 +D 1 +L 9 +D 8 +R 5 +D 3 +U 2 +D 9 +R 10 +D 10 +R 10 +U 5 +D 4 +R 4 +D 4 +L 8 +D 4 +R 10 +D 9 +L 8 +D 1 +R 1 +D 8 +L 1 +D 8 +R 4 +U 8 +R 4 +U 4 +L 4 +U 8 +D 4 +L 8 +D 3 +U 3 +R 5 +D 9 +L 10 +R 8 +U 5 +L 4 +U 8 +R 6 +D 3 +L 8 +U 11 +D 4 +R 3 +L 5 +D 10 +U 11 +D 2 +L 5 +D 4 +R 4 +D 5 +R 11 +L 7 +U 9 +R 6 +L 7 +D 6 +R 4 +D 4 +U 9 +R 6 +D 2 +U 3 +D 8 +L 6 +U 6 +R 11 +U 10 +R 6 +L 5 +R 4 +D 1 +L 10 +R 5 +U 4 +R 3 +D 4 +U 9 +R 8 +D 4 +U 11 +L 2 +D 9 +U 5 +R 3 +D 4 +R 6 +U 11 +R 4 +D 2 +L 1 +R 1 +U 4 +L 5 +U 9 +L 8 +R 6 +D 11 +L 4 +D 5 +L 11 +D 7 +U 11 +D 3 +U 3 +L 5 +R 9 +D 2 +L 9 +R 7 +L 3 +D 7 +L 10 +D 1 +L 5 +U 8 +D 1 +L 5 +U 11 +D 8 +R 6 +D 9 +U 2 +D 11 +R 8 +U 5 +D 6 +R 1 +U 7 +D 10 +L 8 +D 2 +L 7 +D 9 +R 12 +U 11 +R 8 +D 9 +R 1 +D 10 +L 3 +R 10 +D 9 +L 2 +R 3 +D 6 +L 12 +U 3 +R 2 +U 11 +R 8 +L 12 +D 9 +R 10 +L 2 +D 6 +L 8 +U 4 +R 5 +U 8 +L 11 +R 7 +D 3 +L 2 +R 2 +U 4 +R 12 +L 8 +U 1 +R 5 +L 9 +D 7 +R 9 +D 8 +L 2 +R 12 +L 5 +D 6 +R 10 +U 11 +R 12 +L 9 +D 5 +L 7 +U 7 +R 9 +L 10 +R 11 +U 11 +D 8 +L 3 +U 10 +D 1 +R 11 +L 7 +R 5 +L 11 +D 6 +U 5 +D 5 +U 12 +D 7 +L 1 +R 3 +D 8 +L 10 +R 2 +D 10 +R 12 +U 10 +R 7 +U 12 +R 11 +U 5 +D 12 +R 6 +D 1 +U 2 +L 8 +R 7 +D 12 +U 5 +R 10 +L 2 +R 3 +D 10 +U 2 +L 8 +D 6 +R 12 +L 5 +R 7 +U 1 +R 2 +L 5 +D 1 +U 12 +L 2 +U 6 +D 8 +U 3 +D 11 +L 5 +R 6 +L 10 +U 9 +D 6 +R 5 +L 4 +R 6 +L 9 +D 12 +U 7 +L 2 +D 6 +L 1 +U 1 +R 7 +L 13 +D 8 +U 4 +L 5 +D 11 +U 12 +R 5 +U 7 +D 5 +L 4 +D 9 +L 9 +U 1 +L 9 +U 1 +L 2 +U 13 +L 2 +R 11 +L 7 +R 8 +U 11 +D 13 +U 10 +R 5 +U 5 +L 6 +R 7 +D 5 +L 1 +R 5 +U 6 +D 13 +U 4 +L 10 +U 6 +L 3 +U 7 +R 6 +U 4 +L 11 +U 7 +L 6 +R 13 +U 10 +R 11 +D 11 +U 9 +D 2 +U 4 +R 9 +L 11 +R 7 +U 1 +L 5 +U 8 +D 5 +L 12 +U 3 +D 7 +L 2 +R 6 +L 4 +D 12 +U 5 +R 12 +L 13 +D 6 +U 3 +L 11 +R 4 +L 3 +R 8 +U 12 +D 11 +U 3 +R 10 +U 12 +L 7 +D 10 +R 1 +U 5 +L 1 +U 13 +D 12 +U 1 +L 2 +R 12 +D 13 +R 2 +D 6 +L 12 +U 10 +R 14 +U 14 +R 2 +D 4 +L 10 +R 7 +U 14 +L 5 +D 7 +L 12 +R 2 +D 9 +R 8 +D 2 +R 4 +U 5 +L 9 +R 13 +L 14 +R 1 +U 8 +R 12 +U 10 +D 2 +R 5 +U 8 +D 4 +U 9 +D 3 +R 5 +D 7 +L 8 +R 11 +D 2 +U 11 +L 4 +R 2 +U 2 +D 10 +U 14 +L 3 +R 3 +D 3 +R 14 +L 2 +R 6 +D 9 +U 1 +L 14 +R 9 +L 7 +R 10 +U 7 +L 14 +R 11 +L 11 +D 10 +R 11 +U 13 +L 2 +D 7 +L 4 +D 10 +L 10 +R 12 +D 7 +R 14 +L 13 +D 8 +R 5 +L 12 +D 6 +R 5 +D 3 +U 6 +L 10 +D 6 +R 8 +U 9 +R 4 +D 7 +R 6 +D 12 +R 5 +D 6 +L 14 +U 12 +L 10 +U 14 +D 12 +L 12 +R 2 +U 14 +R 14 +D 11 +R 14 +U 12 +D 2 +U 10 +R 4 +U 7 +D 9 +U 10 +D 12 +U 8 +D 10 +L 3 +R 8 +L 5 +D 2 +R 6 +L 1 +D 8 +U 3 +L 4 +U 3 +R 5 +L 10 +D 10 +U 14 +D 2 +U 3 +R 13 +L 7 +R 12 +L 10 +R 14 +D 4 +L 10 +R 3 +U 14 +L 2 +D 15 +R 14 +D 2 +R 14 +L 12 +D 10 +R 3 +D 2 +L 3 +R 3 +D 5 +L 2 +R 1 +L 5 +D 14 +L 8 +R 10 +L 14 +D 8 +L 8 +D 8 +R 15 +D 12 +U 7 +D 13 +L 13 +U 4 +L 7 +U 13 +R 7 +U 12 +R 1 +D 7 +R 5 +L 10 +R 11 +L 15 +D 13 +L 8 +D 12 +U 15 +L 11 +R 10 +U 13 +R 12 +U 6 +R 11 +D 13 +R 8 +D 15 +L 2 +D 5 +U 11 +R 5 +L 13 +D 4 +R 15 +D 13 +R 10 +L 10 +U 1 +R 11 +U 3 +R 5 +D 11 +U 5 +R 6 +U 6 +D 14 +L 2 +R 14 +U 2 +R 1 +L 11 +U 15 +R 2 +D 10 +L 5 +D 3 +U 4 +D 9 +U 2 +L 13 +R 2 +D 7 +R 15 +D 1 +U 9 +R 15 +L 5 +D 4 +L 10 +D 16 +U 8 +R 11 +L 12 +U 5 +L 16 +R 1 +D 10 +R 11 +L 16 +D 4 +U 8 +D 7 +U 13 +D 3 +R 5 +U 9 +R 6 +U 12 +D 4 +U 15 +L 5 +U 15 +L 6 +U 12 +R 8 +L 3 +R 2 +U 3 +L 3 +R 10 +L 11 +U 6 +D 11 +L 4 +R 6 +D 8 +U 14 +L 5 +D 13 +R 13 +D 9 +L 10 +D 16 +R 14 +L 6 +D 7 +U 2 +L 11 +D 14 +R 4 +U 6 +R 7 +L 13 +U 6 +L 8 +D 13 +R 4 +U 13 +L 15 +U 16 +L 8 +D 14 +L 3 +R 7 +D 3 +U 9 +D 7 +U 12 +R 4 +D 3 +U 11 +D 7 +L 9 +U 6 +L 5 +U 12 +D 6 +R 5 +D 9 +U 14 +D 9 +R 6 +U 16 +R 11 +U 16 +L 15 +R 15 +U 10 +L 13 +D 12 +R 4 +D 5 +L 5 +U 1 +D 11 +R 10 +U 7 +R 13 +U 6 +L 6 +D 5 +R 13 +U 13 +D 3 +U 11 +L 4 +R 5 +U 4 +D 5 +L 17 +R 2 +L 12 +R 10 +L 17 +U 1 +R 11 +D 12 +L 10 +U 8 +L 15 +R 8 +U 9 +L 17 +D 13 +L 5 +R 7 +L 1 +D 8 +R 6 +D 1 +U 3 +D 10 +R 6 +L 6 +U 15 +R 1 +U 17 +L 17 +R 4 +U 4 +R 10 +U 12 +L 5 +D 12 +R 14 +D 17 +R 1 +U 1 +R 9 +U 2 +D 4 +R 17 +L 9 +D 5 +U 2 +L 7 +D 8 +R 11 +U 12 +D 13 +R 16 +L 15 +D 15 +L 2 +R 10 +D 16 +R 13 +D 2 +R 6 +D 16 +L 8 +D 2 +L 10 +U 7 +L 14 +R 16 +L 5 +D 5 +R 10 +L 2 +U 13 +R 10 +L 9 +U 1 +L 10 +R 10 +U 14 +D 6 +R 11 +D 4 +R 12 +D 4 +L 1 +D 14 +L 2 +U 3 +L 15 +U 9 +D 12 +R 13 +D 14 +R 5 +L 6 +D 14 +R 14 +L 16 +R 7 +U 7 +L 14 +R 11 +U 9 +D 11 +U 9 +L 10 +R 13 +L 4 +R 12 +U 15 +R 9 +D 10 +U 3 +R 7 +U 1 +R 6 +D 17 +U 16 +D 4 +R 12 +U 3 +R 18 +D 17 +L 8 +U 11 +D 6 +L 9 +R 17 +L 14 +D 1 +L 2 +D 6 +U 13 +L 3 +R 18 +D 4 +L 13 +U 7 +D 6 +U 11 +L 11 +U 8 +R 10 +L 15 +U 4 +D 6 +R 18 +U 17 +R 16 +D 11 +U 5 +R 16 +L 5 +D 16 +U 1 +R 9 +L 10 +U 7 +R 17 +U 8 +L 7 +R 14 +L 11 +R 9 +D 8 +R 9 +U 1 +R 14 +L 15 +U 6 +L 4 +R 3 +L 15 +U 15 +D 17 +U 12 +D 14 +R 13 +U 11 +D 10 +U 16 +L 8 +R 11 +U 6 +D 11 +U 9 +R 15 +L 12 +U 6 +L 13 +U 12 +R 3 +U 16 +L 2 +U 15 +L 15 +R 4 +D 5 +R 8 +D 9 +L 8 +U 7 +R 2 +D 10 +L 12 +R 1 +U 11 +R 17 +U 18 +D 6 +L 12 +U 2 +R 2 +U 14 +D 17 +L 7 +R 12 +U 13 +D 18 +L 8 +R 4 +U 10 +R 10 +L 8 +U 4 +L 1 +U 15 +L 6 +D 6 +L 10 +R 12 +D 2 +R 10 +U 16 +L 12 +D 1 +R 11 +D 10 +U 19 +R 7 +D 18 +U 1 +D 7 +R 3 +U 19 +R 12 +U 5 +L 11 +U 8 +D 12 +R 2 +D 16 +U 14 +R 14 +D 1 +U 17 +L 15 +D 8 +L 18 +D 2 +L 14 +U 10 +L 17 +D 2 +U 14 +L 17 +U 15 +R 18 +L 11 +R 15 +U 4 +L 8 +D 10 +L 17 +U 13 +R 1 +L 10 +U 16 +R 9 +L 4 +D 13 +R 13 +U 10 +R 12 +L 14 +U 10 +D 5 +R 18 +L 8 +D 8 +R 5 +D 19 +U 10 +R 8 +U 12 +R 12 +D 6 +U 7 +L 2 +U 5 +L 6 +R 1 +D 16 +R 16 +U 15 +R 2 +D 15 +R 2 +D 10 +L 4 +D 8 +R 17 +D 6 +R 7 +U 10 +R 8 +D 16 +R 3 +D 17 +R 11 +D 18 +L 3 +R 11 +D 8 +R 14 +D 7 +U 14 +R 12 +L 2 +R 18 +L 6 +R 2 +D 3 +R 18 diff --git a/2022/day9test.txt b/2022/day9test.txt new file mode 100644 index 0000000..9874df2 --- /dev/null +++ b/2022/day9test.txt @@ -0,0 +1,8 @@ +R 4 +U 4 +L 3 +D 1 +R 4 +D 1 +L 5 +R 2 diff --git a/2022/lib/day.ex b/2022/lib/day.ex new file mode 100644 index 0000000..db3ec5d --- /dev/null +++ b/2022/lib/day.ex @@ -0,0 +1,46 @@ +defmodule AOC.Day do + defmacro __using__(opts) do + day = Keyword.get(opts, :day) + debug = Keyword.get(opts, :debug, false) + trim = Keyword.get(opts, :trim, true) + input_file = Keyword.get(opts, :input, nil) + + quote do + def solve do + input = + AOC.Day.input_lines(unquote(day), unquote(trim), unquote(input_file)) + |> parse_input() + + if unquote(debug) do + IO.inspect(input) + end + + part1_solution = part1(input) + IO.puts("Part 1: #{part1_solution}") + + part2_solution = part2(input) + IO.puts("Part 2: #{part2_solution}") + end + end + end + + def input_lines(day, trim, input_file) do + lines = + input_file_name(day, input_file) + |> File.stream!() + + if trim do + Enum.map(lines, &String.trim/1) + else + lines + end + end + + def input_file_name(day, input_file) do + if input_file do + Path.join([File.cwd!(), "inputs", "day#{day}_#{input_file}.txt"]) + else + Path.join([File.cwd!(), "inputs", "day#{day}.txt"]) + end + end +end diff --git a/2022/lib/days/day1.ex b/2022/lib/days/day1.ex new file mode 100644 index 0000000..f15b5f8 --- /dev/null +++ b/2022/lib/days/day1.ex @@ -0,0 +1,24 @@ +defmodule AOC.Day1 do + use AOC.Day, day: 1 + + def parse_input(lines) do + lines + |> Enum.chunk_by(&(&1 == "")) + |> Enum.reject(&(&1 == [""])) + |> Enum.map(fn l -> Enum.map(l, &String.to_integer/1) end) + end + + def part1(input) do + input + |> Enum.map(&Enum.sum/1) + |> Enum.max() + end + + def part2(input) do + input + |> Enum.map(&Enum.sum/1) + |> Enum.sort(:desc) + |> Enum.take(3) + |> Enum.sum() + end +end diff --git a/2022/lib/days/day11.ex b/2022/lib/days/day11.ex new file mode 100644 index 0000000..17c4c55 --- /dev/null +++ b/2022/lib/days/day11.ex @@ -0,0 +1,93 @@ +defmodule AOC.Day11 do + use AOC.Day, day: 11 + alias AOC.Day11.{MonkeyRegistry, Monkey} + + def parse_input(lines) do + monkeys = + lines + |> Enum.chunk_by(&(&1 == "")) + |> Enum.reject(&(&1 == [""])) + |> Enum.map(&parse_monkey/1) + + supermod = + monkeys + |> Enum.map(& &1.modulo) + |> Enum.reduce(&Kernel.*/2) + + {:ok, _} = Registry.start_link(keys: :unique, name: MonkeyRegistry) + + Enum.each(monkeys, fn %{id: id} = monkey -> + GenServer.start_link(Monkey, Map.put(monkey, :supermod, supermod), + name: {:via, Registry, {MonkeyRegistry, id}} + ) + end) + + Enum.count(monkeys) + end + + def parse_monkey([ + "Monkey " <> monkey_id, + "Starting items: " <> items, + "Operation: " <> operation, + "Test: divisible by " <> modulo, + "If true: throw to monkey " <> true_monkey_id, + "If false: throw to monkey " <> false_monkey_id + ]) do + %{ + id: monkey_id |> String.slice(0..-2) |> String.to_integer(), + items: items |> String.split(", ") |> Enum.map(&String.to_integer/1), + operation: parse_operation(operation), + modulo: String.to_integer(modulo), + true_monkey_id: String.to_integer(true_monkey_id), + false_monkey_id: String.to_integer(false_monkey_id) + } + end + + def parse_operation(operation) do + ["new", "=", lhs, op, rhs] = String.split(operation) + + fn old -> + lhs = if lhs == "old", do: old, else: String.to_integer(lhs) + rhs = if rhs == "old", do: old, else: String.to_integer(rhs) + + op = + case op do + "*" -> &Kernel.*/2 + "+" -> &Kernel.+/2 + end + + op.(lhs, rhs) + end + end + + def part1(monkey_count) do + # monkey_business(monkey_count, 20, false) + end + + def part2(monkey_count) do + monkey_business(monkey_count, 10000, true) + end + + def monkey_business(monkey_count, rounds, ridiculous) do + execute_rounds(monkey_count, rounds, ridiculous) + + Enum.map(0..(monkey_count - 1), fn id -> + [{pid, _}] = Registry.lookup(MonkeyRegistry, id) + Monkey.get_activeness(pid) + end) + |> Enum.sort(:desc) + |> Enum.take(2) + |> Enum.reduce(&Kernel.*/2) + end + + def execute_rounds(monkey_count, rounds, ridiculous) do + Enum.each(0..(rounds - 1), fn _ -> execute_round(monkey_count, ridiculous) end) + end + + def execute_round(monkey_count, ridiculous) do + Enum.each(0..(monkey_count - 1), fn id -> + [{pid, _}] = Registry.lookup(MonkeyRegistry, id) + Monkey.execute_turn(pid, ridiculous) + end) + end +end diff --git a/2022/lib/days/day11/monkey.ex b/2022/lib/days/day11/monkey.ex new file mode 100644 index 0000000..f84c0b0 --- /dev/null +++ b/2022/lib/days/day11/monkey.ex @@ -0,0 +1,63 @@ +defmodule AOC.Day11.Monkey do + use GenServer + alias AOC.Day11.{MonkeyRegistry, Monkey} + + @impl true + def init(state) do + {:ok, Map.put(state, :activeness, 0)} + end + + def execute_turn(pid, ridiculous) do + GenServer.call(pid, {:execute_turn, ridiculous}, :infinity) + end + + def throw(pid, item) do + GenServer.call(pid, {:throw, item}) + end + + def get_items(pid) do + GenServer.call(pid, :get_items) + end + + def get_activeness(pid) do + GenServer.call(pid, :get_activeness) + end + + @impl true + def handle_call( + {:execute_turn, ridiculous}, + _from, + %{ + items: items, + operation: operation, + modulo: modulo, + true_monkey_id: true_monkey_id, + false_monkey_id: false_monkey_id, + activeness: activeness, + supermod: supermod + } = state + ) do + Enum.each(items, fn item -> + item = operation.(item) + item = if ridiculous, do: item, else: Integer.floor_div(item, 3) + item = Integer.mod(item, supermod) + recipient = if Integer.mod(item, modulo) == 0, do: true_monkey_id, else: false_monkey_id + [{pid, _}] = Registry.lookup(MonkeyRegistry, recipient) + Monkey.throw(pid, item) + end) + + {:reply, :ok, %{state | items: [], activeness: activeness + length(items)}} + end + + def handle_call({:throw, item}, _from, %{items: items} = state) do + {:reply, :ok, Map.put(state, :items, items ++ [item])} + end + + def handle_call(:get_items, _from, %{items: items} = state) do + {:reply, items, state} + end + + def handle_call(:get_activeness, _from, %{activeness: activeness} = state) do + {:reply, activeness, state} + end +end diff --git a/2022/lib/days/day13.ex b/2022/lib/days/day13.ex new file mode 100644 index 0000000..7ec754c --- /dev/null +++ b/2022/lib/days/day13.ex @@ -0,0 +1,67 @@ +defmodule AOC.Day13 do + use AOC.Day, day: 13 + alias AOC.Day13.Packet + + defmodule Packet do + def compare({p1, p2}) do + compare(p1, p2) + end + + def compare([], []), do: :eq + def compare([], _l), do: :lt + def compare(_l, []), do: :gt + def compare(x, l) when is_number(x) and is_list(l), do: compare([x], l) + def compare(l, x) when is_number(x) and is_list(l), do: compare(l, [x]) + + def compare([h1 | tl1], [h2 | tl2]) do + case compare(h1, h2) do + :eq -> compare(tl1, tl2) + x -> x + end + end + + def compare(x, y) when x < y, do: :lt + def compare(x, y) when x == y, do: :eq + def compare(x, y) when x > y, do: :gt + end + + def parse_input(lines) do + lines + |> Enum.chunk_by(&(&1 == "")) + |> Enum.reject(&(&1 == [""])) + |> Enum.map(fn [p1, p2] -> + {parse_packet(p1), parse_packet(p2)} + end) + end + + def parse_packet(packet) do + packet + |> String.to_charlist() + |> Code.string_to_quoted() + |> elem(1) + end + + def part1(pairs) do + pairs + |> Enum.map(&Packet.compare/1) + |> Enum.with_index() + |> Enum.filter(&(elem(&1, 0) == :lt)) + |> Enum.map(&elem(&1, 1)) + |> Enum.map(&Kernel.+(&1, 1)) + |> Enum.sum() + end + + @divider_packets [[[2]], [[6]]] + + def part2(pairs) do + pairs + |> Enum.flat_map(fn {p1, p2} -> [p1, p2] end) + |> Kernel.++(@divider_packets) + |> Enum.sort(Packet) + |> Enum.with_index() + |> Enum.filter(&(elem(&1, 0) in @divider_packets)) + |> Enum.map(&elem(&1, 1)) + |> Enum.map(&Kernel.+(&1, 1)) + |> Enum.reduce(&Kernel.*/2) + end +end diff --git a/2022/lib/days/day16.ex b/2022/lib/days/day16.ex new file mode 100644 index 0000000..4f3a84a --- /dev/null +++ b/2022/lib/days/day16.ex @@ -0,0 +1,81 @@ +defmodule AOC.Day16 do + use AOC.Day, day: 16, debug: true, input: "example" + alias AOC.Day16.{ValveRegistry, Valve} + + defmodule Valve do + use GenServer + + @impl true + def init(state) do + state = Map.put(state, :released, 0) + state = Map.put(state, :open?, false) + {:ok, state} + end + + def get_rate(valve) do + GenServer.call(valve, :get_rate) + end + + def tick(valve) do + GenServer.call(valve, :tick) + end + + def open(valve) do + GenServer.call(valve, :open) + end + + @impl true + def handle_call(:get_rate, _from, %{rate: rate} = state) do + {:reply, rate, state} + end + + def handle_call(:tick, _from, %{open?: open?, released: released, rate: rate} = state) do + released = if open?, do: released + rate, else: released + {:reply, :ok, %{state | released: released}} + end + + def handle_call(:open, _from, state) do + {:reply, :ok, %{state | open?: true}} + end + end + + @line_regex ~r/Valve (?[A-Z]{2}) has flow rate=(?\d+); tunnels? leads? to valves? (?.*)/ + + def parse_input(lines) do + {:ok, _} = Registry.start_link(keys: :unique, name: ValveRegistry) + + lines + |> Enum.map(fn line -> + %{"name" => name, "rate" => rate, "tunnels" => tunnels} = + Regex.named_captures(@line_regex, line) + + %{name: name, rate: String.to_integer(rate), tunnels: String.split(tunnels, ", ")} + end) + |> Enum.into(%{}, fn %{name: name} = valve -> + {:ok, pid} = + GenServer.start_link(Valve, valve, name: {:via, Registry, {ValveRegistry, name}}) + + {name, pid} + end) + end + + def part1(valves) do + Enum.map(valves, fn {name, valve} -> + rate = Valve.get_rate(valve) + {name, rate} + end) + |> Enum.sort_by(&elem(&1, 1), :desc) + |> IO.inspect() + + :ok + end + + def tick(valves) do + Enum.each(valves, fn {_, valve} -> + Valve.tick(valve) + end) + end + + def part2(_input) do + end +end diff --git a/2022/lib/days/day2.ex b/2022/lib/days/day2.ex new file mode 100644 index 0000000..71e0a48 --- /dev/null +++ b/2022/lib/days/day2.ex @@ -0,0 +1,68 @@ +defmodule AOC.Day2 do + use AOC.Day, day: 2 + + def parse_input(lines) do + Enum.map(lines, fn line -> + [move1, move2] = + line + |> String.split(" ") + |> Enum.map(fn c -> + c + |> String.to_charlist() + |> hd() + end) + + {move1, move2} + end) + end + + def part1(input) do + input + |> Enum.map(fn {move1, move2} -> + score = + case move2 do + ?X -> 1 + ?Y -> 2 + ?Z -> 3 + end + + score + + case {move1, move2} do + {?A, ?Y} -> 6 + {?B, ?Z} -> 6 + {?C, ?X} -> 6 + {?A, ?X} -> 3 + {?B, ?Y} -> 3 + {?C, ?Z} -> 3 + _ -> 0 + end + end) + |> Enum.sum() + end + + def part2(input) do + input + |> Enum.map(fn {move1, result} -> + score = + case result do + ?X -> 0 + ?Y -> 3 + ?Z -> 6 + end + + score + + case {move1, result} do + {?A, ?X} -> 3 + {?A, ?Y} -> 1 + {?A, ?Z} -> 2 + {?B, ?X} -> 1 + {?B, ?Y} -> 2 + {?B, ?Z} -> 3 + {?C, ?X} -> 2 + {?C, ?Y} -> 3 + {?C, ?Z} -> 1 + end + end) + |> Enum.sum() + end +end diff --git a/2022/lib/days/day3.ex b/2022/lib/days/day3.ex new file mode 100644 index 0000000..a65de7b --- /dev/null +++ b/2022/lib/days/day3.ex @@ -0,0 +1,39 @@ +defmodule AOC.Day3 do + use AOC.Day, day: 3 + + def parse_input(lines), do: lines + + def part1(input) do + input + |> Enum.map(fn line -> + comp_size = line |> String.length() |> div(2) + {comp1, comp2} = line |> String.to_charlist() |> Enum.split(comp_size) + comp1 = MapSet.new(comp1) + comp2 = MapSet.new(comp2) + + MapSet.intersection(comp1, comp2) + |> MapSet.to_list() + |> hd() + |> get_priority() + end) + |> Enum.sum() + end + + def part2(input) do + input + |> Enum.chunk_every(3) + |> Enum.map(fn group -> + group + |> Enum.map(&String.to_charlist/1) + |> Enum.map(&MapSet.new/1) + |> Enum.reduce(&MapSet.intersection/2) + |> MapSet.to_list() + |> hd() + |> get_priority() + end) + |> Enum.sum() + end + + def get_priority(char) when char >= ?a, do: char - 96 + def get_priority(char), do: char - 38 +end diff --git a/2022/lib/days/day4.ex b/2022/lib/days/day4.ex new file mode 100644 index 0000000..24af04f --- /dev/null +++ b/2022/lib/days/day4.ex @@ -0,0 +1,38 @@ +defmodule AOC.Day4 do + use AOC.Day, day: 4 + + def parse_input(lines) do + Enum.map(lines, fn line -> + [assign1, assign2] = + line + |> String.split(",") + |> Enum.map(fn assign -> + [from, to] = + assign + |> String.split("-") + |> Enum.map(&String.to_integer/1) + + MapSet.new(from..to) + end) + + {assign1, assign2} + end) + end + + def part1(input) do + input + |> Enum.map(fn {set1, set2} -> + MapSet.subset?(set1, set2) or MapSet.subset?(set2, set1) + end) + |> Enum.count(& &1) + end + + def part2(input) do + input + |> Enum.map(fn {set1, set2} -> + MapSet.intersection(set1, set2) + |> Enum.any?() + end) + |> Enum.count(& &1) + end +end diff --git a/2022/lib/days/day5.ex b/2022/lib/days/day5.ex new file mode 100644 index 0000000..41c9675 --- /dev/null +++ b/2022/lib/days/day5.ex @@ -0,0 +1,70 @@ +defmodule AOC.Day5 do + use AOC.Day, day: 5, trim: false + + def parse_input(lines) do + [init, ops] = + lines + |> Enum.chunk_by(&(&1 == "\n")) + |> Enum.reject(&(&1 == ["\n"])) + + {parse_init(init), parse_ops(ops)} + end + + def parse_init(init) do + init + |> Enum.split(-1) + |> elem(0) + |> Enum.map(fn line -> + line + |> String.to_charlist() + |> tl() + |> Enum.take_every(4) + end) + |> Enum.zip_with(&Function.identity/1) + |> Enum.map(fn stack -> + Enum.reject(stack, &(&1 == ?\s)) + end) + end + + def parse_ops(ops) do + Enum.map(ops, fn op -> + %{"count" => count, "from" => from, "to" => to} = + Regex.named_captures(~r/move (?\d+) from (?\d+) to (?\d+)\n/, op) + + %{ + count: String.to_integer(count), + from: String.to_integer(from) - 1, + to: String.to_integer(to) - 1 + } + end) + end + + def part1(input) do + move(input, true) + end + + def part2(input) do + move(input, false) + end + + def move({init, ops}, reverse) do + ops + |> Enum.reduce(init, fn %{count: count, from: from, to: to}, acc -> + {acc, removed} = remove(acc, from, count) + removed = if reverse, do: Enum.reverse(removed), else: removed + add(acc, to, removed) + end) + |> Enum.map(&hd/1) + end + + def remove(stacks, from, count) do + {removed, new} = Enum.split(Enum.at(stacks, from), count) + stacks = List.update_at(stacks, from, fn _ -> new end) + {stacks, removed} + end + + def add(stacks, to, removed) do + added = Enum.concat(removed, Enum.at(stacks, to)) + List.update_at(stacks, to, fn _ -> added end) + end +end diff --git a/2022/lib/days/day6.ex b/2022/lib/days/day6.ex new file mode 100644 index 0000000..7f25037 --- /dev/null +++ b/2022/lib/days/day6.ex @@ -0,0 +1,29 @@ +defmodule AOC.Day6 do + use AOC.Day, day: 6 + + def parse_input(lines), do: lines |> hd() |> String.to_charlist() + + def part1(input) do + find_marker(input, 0, 4) + end + + def part2(input) do + find_marker(input, 0, 14) + end + + def find_marker(signal, index, length) do + distinct = + signal + |> Enum.take(length) + |> MapSet.new() + |> Enum.count() + + if distinct == length do + index + length + else + signal + |> tl() + |> find_marker(index + 1, length) + end + end +end diff --git a/2022/lib/days/day7.ex b/2022/lib/days/day7.ex new file mode 100644 index 0000000..b331908 --- /dev/null +++ b/2022/lib/days/day7.ex @@ -0,0 +1,82 @@ +defmodule AOC.Day7 do + use AOC.Day, day: 7 + + def parse_input(lines) do + Enum.map(lines, fn + "$ cd " <> arg -> + {:cd, arg} + + "$ ls" -> + :ls + + "dir " <> arg -> + {:dir, arg} + + line -> + [size, file] = String.split(line) + {:file, String.to_integer(size), file} + end) + end + + def part1(input) do + input + |> get_file_sizes() + |> get_directory_sizes() + |> Enum.map(fn {_, size} -> size end) + |> Enum.filter(&(&1 <= 100_000)) + |> Enum.sum() + end + + def part2(input) do + file_sizes = get_file_sizes(input) + + total_size = + file_sizes + |> Enum.map(&elem(&1, 1)) + |> Enum.sum() + + size_needed = total_size - 40_000_000 + + file_sizes + |> get_directory_sizes() + |> Enum.map(&elem(&1, 1)) + |> Enum.filter(fn size -> size >= size_needed end) + |> Enum.min() + end + + def get_file_sizes(input) do + Enum.reduce(input, {[], []}, fn + {:cd, "/"}, {_, sizes} -> + {["/"], sizes} + + {:cd, ".."}, {[_ | path], sizes} -> + {path, sizes} + + {:cd, dir}, {path, sizes} -> + {[dir | path], sizes} + + {:file, size, file}, {path, sizes} -> + {path, [{[file | path], size} | sizes]} + + _, acc -> + acc + end) + |> elem(1) + end + + def get_directory_sizes(file_sizes) do + file_sizes + |> Enum.reduce(%{}, fn {[_ | path], size}, acc -> + path = Enum.reverse(path) + update_directory_size(acc, size, path) + end) + end + + def update_directory_size(sizes, file_size, file_path) do + Enum.reduce(file_path, {sizes, []}, fn dir, {sizes, cur_path} -> + cur_path = [dir | cur_path] + {Map.update(sizes, cur_path, file_size, &(&1 + file_size)), cur_path} + end) + |> elem(0) + end +end diff --git a/2022/lib/days/day8.ex b/2022/lib/days/day8.ex new file mode 100644 index 0000000..a39612f --- /dev/null +++ b/2022/lib/days/day8.ex @@ -0,0 +1,53 @@ +defmodule AOC.Day8 do + use AOC.Day, day: 8, debug: true + + def parse_input(lines) do + Enum.map(lines, fn line -> + line + |> String.split("", trim: true) + |> Enum.map(&String.to_integer/1) + end) + end + + def part1(rows) do + rows = with_index(rows) + + cols = Enum.zip(rows) |> Enum.map(&Tuple.to_list/1) + rrows = Enum.map(rows, &Enum.reverse/1) + rcols = Enum.map(cols, &Enum.reverse/1) + + [rows, cols, rrows, rcols] + |> Enum.map(&count_visible/1) + |> Enum.reduce(&MapSet.union/2) + |> Enum.count() + end + + def part2(rows) do + rows + end + + def with_index(rows) do + Enum.with_index(rows, fn row, y -> + Enum.with_index(row, fn el, x -> + %{height: el, x: x, y: y} + end) + end) + end + + def count_visible(rows) do + rows + |> Enum.map(&count_visible_row/1) + |> Enum.map(&elem(&1, 0)) + |> Enum.reduce(&MapSet.union/2) + end + + def count_visible_row(row) do + Enum.reduce(row, {MapSet.new(), -1}, fn + %{height: h, x: x, y: y}, {trees, highest} when h > highest -> + {MapSet.put(trees, {x, y}), h} + + _, acc -> + acc + end) + end +end diff --git a/2022/mix.exs b/2022/mix.exs new file mode 100644 index 0000000..8cfd890 --- /dev/null +++ b/2022/mix.exs @@ -0,0 +1,28 @@ +defmodule Aoc2022.MixProject do + use Mix.Project + + def project do + [ + app: :aoc2022, + version: "0.1.0", + elixir: "~> 1.14", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/README.md b/README.md new file mode 100644 index 0000000..e15b36c --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# aoc + +Collection of my Advent of Code solutions.