summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2021-11-24 22:25:42 +0000
committerTomasz Kramkowski <tk@the-tk.com>2021-11-24 22:25:42 +0000
commita7a6b86002b595bc167af72606b14c67ed1bdf8f (patch)
treebff94329cf969bd9df68d3b9782fee2107db56c2
downloadaoc2015-a7a6b86002b595bc167af72606b14c67ed1bdf8f.tar.gz
aoc2015-a7a6b86002b595bc167af72606b14c67ed1bdf8f.tar.xz
aoc2015-a7a6b86002b595bc167af72606b14c67ed1bdf8f.zip
init commit
-rw-r--r--1/1.py1
-rw-r--r--1/2.py6
-rw-r--r--1/input1
-rw-r--r--10/input1
-rw-r--r--10/solution.py33
-rw-r--r--11/input1
-rw-r--r--11/solution.py69
-rw-r--r--11/solution_own.py18
-rw-r--r--12/input1
-rw-r--r--12/solution.py25
-rw-r--r--13/input56
-rw-r--r--13/solution.py51
-rw-r--r--14/input9
-rw-r--r--14/solution.py43
-rw-r--r--15/input4
-rw-r--r--15/solution.py86
-rw-r--r--16/input500
-rw-r--r--16/solution.py77
-rw-r--r--17/input20
-rw-r--r--17/solution.py30
-rw-r--r--18/input100
-rw-r--r--18/solution.py38
-rw-r--r--19/input45
-rw-r--r--19/solution.py130
-rw-r--r--2/1.py3
-rw-r--r--2/2.py4
-rw-r--r--2/input1000
-rw-r--r--2/sol.py45
-rw-r--r--20/input1
-rw-r--r--20/solution.c41
-rw-r--r--21/input3
-rw-r--r--22/input2
-rw-r--r--23/input46
-rw-r--r--24/input28
-rw-r--r--25/input1
-rw-r--r--3/1.py10
-rw-r--r--3/2.py13
-rw-r--r--3/input1
-rw-r--r--4/1.c328
-rw-r--r--4/2.c328
-rw-r--r--4/input1
-rw-r--r--5/1.py18
-rw-r--r--5/2.py24
-rw-r--r--5/input1000
-rw-r--r--6/1.c92
-rw-r--r--6/2.c89
-rw-r--r--6/input300
-rw-r--r--6/inputconv.py4
-rw-r--r--7/input339
-rw-r--r--7/solution.py115
-rw-r--r--8/input300
-rw-r--r--8/solution.sh5
-rw-r--r--9/input28
-rw-r--r--9/solution.py40
54 files changed, 5554 insertions, 0 deletions
diff --git a/1/1.py b/1/1.py
new file mode 100644
index 0000000..7c70985
--- /dev/null
+++ b/1/1.py
@@ -0,0 +1 @@
+print(sum({'(': 1, ')': -1}[c] for c in open('input').read().rstrip('\n')))
diff --git a/1/2.py b/1/2.py
new file mode 100644
index 0000000..3bd93d4
--- /dev/null
+++ b/1/2.py
@@ -0,0 +1,6 @@
+def sumiter(i):
+ count = 0
+ for e in i:
+ count += e
+ yield count
+print(next(i + 1 for i, s in enumerate(sumiter({'(': 1, ')': -1}[c] for c in open('input').read().rstrip('\n'))) if s == -1))
diff --git a/1/input b/1/input
new file mode 100644
index 0000000..f7beb58
--- /dev/null
+++ b/1/input
@@ -0,0 +1 @@
+((((()(()(((((((()))(((()((((()())(())()(((()((((((()((()(()(((()(()((())))()((()()())))))))))()((((((())((()))(((((()(((((((((()()))((()(())()((())((()(()))((()))()))()(((((()(((()()))()())((()((((())()())()((((())()(()(()(((()(())(()(())(((((((())()()(((())(()(()(()(())))(()((((())((()))(((()(()()(((((()()(()(((()(((((())()))()((()(()))()((()((((())((((())(()(((())()()(()()()()()(())((((())((())(()()))()((((())))((((()())()((((())((()())((())(())(((((()((((()(((()((((())(()(((()()))()))((((((()((())()())))(((()(()))(()()(()(((()(()))((()()()())((()()()(((())())()())())())((()))(()(()))(((((()(()(())((()(())(())()((((()())()))((((())(())((())())((((()(((())(())((()()((((()((((((()(())()()(()(()()((((()))(())()())()))(())))(())))())()()(())(()))()((()(()(())()()))(()())))))(()))(()()))(())(((((()(()(()()((())()())))))((())())((())(()(())((()))(())(((()((((((((()()()(()))()()(((()))()((()()(())(())())()(()(())))(((((()(())(())(()))))())()))(()))()(()(((((((()((((())))())())())())()((((((((((((((()()((((((()()()())())()())())())(())(())))())((()())((()(()))))))()))))))))))))))))())((())((())()()))))))(((()((()(()()))((())(()()))()()())))(())))))))(()(((())))())()())))()()(())()))()(()))())((()()))))(()))))()))(()()(())))))))()(((()))))()(()))(())())))))()))((()))((()))())(())))))))))((((())()))()))()))())(())()()(())))())))(()())()))((()()(())))(())((((((()(())((()(((()(()()(())))()))))))()))()(()((()))()(()))(()(((())((((())())(())(()))))))))())))))))())())))))())))))()()(((())()(()))))))))())))))(())()()()))()))()))(()(())()()())())))))))())()(()(()))))()()()))))())(()))))()()))))()())))))(((())()()))(()))))))))))()()))))()()()))))(()())())()()())()(()))))()(()))(())))))))(((((())(())())()()))()()))(())))))()(()))))(())(()()))()())()))()))()))()))))())()()))())())))(()))(()))))))())()(((())()))))))))()))()())))())))())))()))))))))))()()))(()()))))))(())()(()))))())(()))))(()))))(()())))))())())()()))))())()))))))))(()))))()))))))()(()())))))))()))())))())))())))())))))))())(()()))))))(()())())))()())()))))))))))))))())))()(())))()))())()()(())(()()))(())))())()())(()(()(()))))())))))))))))())(()))()))()))))(())()())()())))))))))))()()))))))))))))())())))))(()())))))))))))())(())))()))))))))())())(()))()))(())))()))()()(())()))))))()((((())()))())())))))()))()))))((()())()))))())))(())))))))))))))))))()))))()()())()))()()))))())()))((()())))())))(()))(()())))))))()))()))))(())))))))(())))))())()()(()))())()))()()))))())()()))))())()))())))))))(()))))()())()))))))))(()))())))(()))()))))(())()))())())(())())())))))))((((())))))()))()))()())()(())))()))()))()())(()())()()(()())()))))())())))))(()))()))))())(()()(())))))(())()()((())())))))(())(())))))))())))))))))()(())))))))()())())())()(()))))))))(()))))))))())()()))()(()))))))()))))))())))))))(())))()()(())()())))))(((())))()((())()))())))(()()))())(())())))()(((()())))))()(()()())))()()(()()(()()))())()(()()()))())()()))()())(()))))())))))())))(())()()))))(()))))(())(()))(())))))()()))()))))())()))()()(())())))((()))())()))))))()()))))((()(()))))()()))))))())))))())(()((()())))))))))))()())())))()))(()))))))(()))(())()())))(()))))))))())()()()()))))(()())))))))((())))()))(()))(())(())()())()))))))))(())))())))(()))()()))(()()))(()))())))()(())))())((()((()(())))((())))()))))((((())())()())))(())))()))))))())(()()((())))())()(()())))))(()())()))())))))))((())())))))))(()(()))())()()(()()(((()(((()())))))()))))))()(())(()()((()()(())()()))())()())()))()())())())))))))(((())))))))()()))))))(((())()))(()()))(()()))))(()(()()((((())()())((()()))))(()(())))))()((()()()())()()((()((()()))(()))(((()()()))(((())))()(((())()))))))((()(())())))(()())(((((()(()))(()((()))(()())()))))(()(()))()(()))(())(((())(()()))))()()))(((()))))(()()()()))())))((()()()(())()))()))))()()))()))))))((((((()()()))))())((()()(((()))))(()(())(()()())())())))()(((()()))(())((())))(()))(()()()())((())())())(()))))()))()((()(())()(()()(())(()))(())()))(())(()))))(())(())())(()()(()((()()((())))((()))()((())))(((()()()()((((()))(()()))()()()(((())((())())(()()(()()()))()((())(())()))())(((()()(())))()((()()())()())(()(())())(((())(())())((())(())()(((()()))(())))((())(()())())(())((()()()((((((())))((()(((((())()))()))(())(()()))()))(())()()))(())((()()())()()(()))())()((())))()((()()())((((()())((())())())((()((()))()))((())((()()(()((()()(((())(()()))))((()((())()(((())(()((())())((())(()((((((())())()(()())()(())(((())((((((()(())(()((()()()((()()(()()()())))()()(((((()()))()((((((()))()(()(()(()(((()())((()))())()((()))(())))()))()()))())()()))())((((())(()(()))(((((((())(((()(((((()(((()()((((())(((())())))(()()()(()(()))()))((((((()))((()(((()(())((()((((()((((((())(((((())))(((()(()))))(((()(((())()((())(()((()))(((()()(((())((((()(()(((((()))(((()(((((((()(()()()(()(()(()()())(())(((((()(())())()())(()(()(()))()(()()()())(()()(()((()))()((())())()(()))((())(()))()(()))()(((()(()(()((((((()()()()())()(((((()()(((()()()((()(((((()))((((((((()()()(((((()))))))(()()()(())(()))(()()))))(())()))(((((()(((((()()(()(()())(((()))((((()((()(()(()((()(()((())))()(((()((()))((()))(((((((((()((()((()(())))()((((()((()()))((())(((()(((((()()(()(()()((()(()()()(((((((())())()())))))((((()()(()))()))(()((())()(()(((((((((()()(((()(()())(()((()())((())())((((()(((()(((()((((()((()((((()(()((((((())((((((((((((()()(()()((((((((((((((()((()()))()((((((((((((())((((()(()())((()(()(()))()(((((()()(((()()))()())(())((()(((((()((())(((((()((()(((((()))()()((((())()((((())(((((((((()(())(()(())))())(()((())(((())(())(())())(()(()(())()()((()((())()(((()(((((()(())))()(((()((())))((()()()(((()(((()((()(()(())(()((()())(()(()(((()(((((((((())(()((((()()))(()((((()()()()(((()((((((((()(()()((((((()(()()(()((()((((((((((()()(((((((()())(())))(((()()))(((((()((()()())(()()((((())((()((((()))))(())((()(()()(((()(()(((()((((()(((((()))())())(()((())()))(((()())((())((())((((()((()((((((())(()((((()()))((((((())()(()))((()(((())((((((((((()()(((((()(((((()((()()()((((())))(()))()((()(())()()((()((((((((((()((())(())(((((()(()(()()))((((()((((()()((()(((()(((((((((()(()((()((()))((((((()(((())()()((()(((((((()())))()()(()((()((()()(((()(()()()()((((()((())((((()(((((((((()(((()()(((()(()(((()(((()((())()(()((()(()(()(()))()(((()))(()((((()((())((((())((((((())(()))(()((((())((()(()((((((((()()((((((()(()(()()()(())((()((()()(((()(((((((()()((()(((((((()))(((((()(((()(()()()(()(((()((()()((())(()(((((((((()(()((()((((((()()((())()))(((((()((())()())()(((((((((((()))((((()()()()())(()()(()(()()))()))(()))(()(((()()))())(()(()))()()((())(()())()())()(()))()))(()()(()((((((())((()(((((((((((()(())()((()(()((()((()(()((()((((((((((()()())((())()(())))((())()())()(((((()(()())((((()((()(())(()))(((())()((()))(((((())(()))()()(()))(((())((((()((((()(())))(((((((()))))())()())(())((())()(()()((()(()))()(()()(()()((()())((())((()()))((((()))()()))(()()(())()()(((((()(())((()((((()))()))(()())())(((()()(()()))(())))))(()))((())(((((()((((()))()((((()))()((())(((())))(((()())))((()(()()(( \ No newline at end of file
diff --git a/10/input b/10/input
new file mode 100644
index 0000000..ec6ebd7
--- /dev/null
+++ b/10/input
@@ -0,0 +1 @@
+1113222113
diff --git a/10/solution.py b/10/solution.py
new file mode 100644
index 0000000..51a569f
--- /dev/null
+++ b/10/solution.py
@@ -0,0 +1,33 @@
+from collections import Counter
+
+def look_and_say(n: str) -> str:
+ """
+ for every consecutive chunk of characters, count the number of characters, concatenate the chunk length and the character
+ """
+ res = []
+ char = n[0]
+ count = 1
+ for c in n[1:]:
+ if c == char:
+ count += 1
+ else:
+ res.append(str(count) + char)
+ char = c
+ count = 1
+ res.append(str(count) + char)
+ return ''.join(res)
+
+def part1(n: str) -> str:
+ for i in range(40):
+ n = look_and_say(n)
+ return len(n)
+
+def part2(n: str) -> str:
+ for i in range(50):
+ n = look_and_say(n)
+ return len(n)
+
+if __name__ == '__main__':
+ inp = '1113222113'
+ print(part1(inp))
+ print(part2(inp))
diff --git a/11/input b/11/input
new file mode 100644
index 0000000..5915be7
--- /dev/null
+++ b/11/input
@@ -0,0 +1 @@
+cqjxjnds
diff --git a/11/solution.py b/11/solution.py
new file mode 100644
index 0000000..5c044b3
--- /dev/null
+++ b/11/solution.py
@@ -0,0 +1,69 @@
+"""Advent of code 2015 day 11"""
+
+def next_password(password: str) -> str:
+ """Increment the password
+ "a" -> "b"
+ "az" -> "ba"
+ """
+ if password[-1] == 'z':
+ return next_password(password[:-1]) + 'a'
+ else:
+ return password[:-1] + chr(ord(password[-1]) + 1)
+
+def has_straight(password: str) -> bool:
+ """Check if a password contains a sequence of at least three consecutive characters"""
+ for i in range(len(password) - 2):
+ if ord(password[i]) + 1 == ord(password[i+1]) and ord(password[i+1]) + 1 == ord(password[i+2]):
+ return True
+ return False
+
+def has_pair(password: str) -> bool:
+ """Check if a password contains at least one pair of letters"""
+ for i in range(len(password) - 1):
+ if password[i] == password[i+1]:
+ return True
+ return False
+
+def has_pairs(password: str) -> bool:
+ """Check if a password contains at least two different, non-overlapping pairs of letters"""
+ for i in range(len(password) - 1):
+ if password[i] == password[i+1]:
+ return has_pair(password[i+2:])
+ return False
+
+def is_valid(password: str) -> bool:
+ """Check if password is valid
+ Password must:
+ - include one increasing straight of at least three letters
+ - may not contain i, o or l
+ - must contain at least two different, non-overlapping pairs of letters
+ "hijklmmn" -> False
+ "abbceffg" -> True
+ "abbcegjk" -> False
+ """
+ if not has_straight(password):
+ return False
+ if not has_pairs(password):
+ return False
+ if 'i' in password or 'o' in password or 'l' in password:
+ return False
+ return True
+
+def part1(password: str) -> str:
+ """Find the next valid password"""
+ password = next_password(password)
+ while not is_valid(password):
+ password = next_password(password)
+ return password
+
+def part2(password: str) -> str:
+ """Find the next valid password"""
+ password = next_password(part1(password))
+ while not is_valid(password):
+ password = next_password(password)
+ return password
+
+if __name__ == '__main__':
+ inp = 'cqjxjnds'
+ print(part1(inp))
+ print(part2(inp))
diff --git a/11/solution_own.py b/11/solution_own.py
new file mode 100644
index 0000000..0c45bc0
--- /dev/null
+++ b/11/solution_own.py
@@ -0,0 +1,18 @@
+def valid(p: str) -> bool:
+ if {'i', 'o', 'l'}.intersection(set(p)):
+ return False
+
+def next_password(p: str) -> str:
+ if p[-1] == 'z':
+ return next_password(p[:-1]) + 'a'
+ else:
+ return p[:-1] + chr(ord(p[-1]) + 1)
+
+pw = next_password('cqjxjnds')
+while not valid(pw):
+ pw = next_password(pw)
+print(pw)
+pw = next_password(pw)
+while not valid(pw):
+ pw = next_password(pw)
+print(pw)
diff --git a/12/input b/12/input
new file mode 100644
index 0000000..ccdd55b
--- /dev/null
+++ b/12/input
@@ -0,0 +1 @@
+{"e":[[{"e":86,"c":23,"a":{"a":[120,169,"green","red","orange"],"b":"red"},"g":"yellow","b":["yellow"],"d":"red","f":-19},{"e":-47,"a":[2],"d":{"a":"violet"},"c":"green","h":"orange","b":{"e":59,"a":"yellow","d":"green","c":47,"h":"red","b":"blue","g":"orange","f":["violet",43,168,78]},"g":"orange","f":[{"e":[82,-41,2,"red","violet","orange","yellow"],"c":"green","a":77,"g":"orange","b":147,"d":49,"f":"blue"},-1,142,136,["green","red",166,-21],"blue","orange",{"a":38}]},"orange","yellow"],"green",-22,[37,[4,-40,["red","yellow",["yellow",177,"red","blue",139,[55,13,"yellow","violet",-21,140,"yellow",117],"blue","blue",106],"blue",{"a":23}],183,92,"orange","green"],"orange"],-5],"c":[{"e":{"e":-13,"c":-11,"a":{"a":49,"b":189},"g":144,"b":186,"d":{"e":[146,[32,"violet","red","orange",-22],"blue","violet",57,{"e":12,"a":"red","d":37,"c":-13,"h":"green","b":-27,"g":"orange","f":"orange","i":"red"},56,-1,"red",-25],"c":-14,"a":[["orange","green","green","red",-25],-16,104,177,"red"],"g":"red","b":"blue","d":2,"f":"green"},"f":[{"e":{"c":-15,"a":"green","b":144,"d":-32},"c":"yellow","a":["blue","blue"],"b":"yellow","d":135,"f":"violet"}]},"a":{"e":"blue","a":[145,128,"orange","violet",23,["orange",[78,"yellow","orange","orange","orange","green",122,-35,"blue"],159,114]],"d":"yellow","c":{"e":[100,"green",{"e":"blue","a":36,"d":84,"j":"orange","c":"blue","h":118,"b":85,"g":"violet","f":"blue","i":27},"blue","blue"],"a":"red","d":"blue","j":[159,22,"violet","orange","blue","orange","blue",186,175,{"e":29,"a":150,"d":"green","c":129,"h":138,"b":-29,"g":7,"f":"red","i":"violet"}],"c":"yellow","h":["blue",-9,41,{"e":144,"c":"violet","a":161,"b":116,"d":126,"f":197},173,123,50,"red",154],"b":-23,"g":"orange","f":"green","i":"red"},"h":26,"b":30,"g":106,"f":{"c":{"e":-28,"c":["red","violet","blue","orange","yellow","violet",-30,134,0],"a":-37,"b":41,"d":143},"a":121,"b":"yellow","d":[198,"yellow"]}},"d":{"e":-2,"a":"green","d":{"a":0,"b":"blue"},"j":"violet","c":[{"e":"violet","a":"orange","d":"violet","c":-36,"h":68,"b":195,"g":41,"f":63},11,-20,{"e":[100,43,183],"a":"yellow","d":["orange","yellow","violet","yellow",143,162,-23,168,145,-33],"j":80,"c":"orange","h":{"a":"orange"},"b":"violet","g":-21,"f":-38,"i":"green"},{"e":"red","a":81,"d":3,"c":"blue","h":[167,"blue","yellow",135,64,116,134,14,160],"b":"red","g":"blue","f":"green"},["red",[139,"orange","blue","blue","orange","blue"],"orange","red",113,26,"yellow","yellow",85]],"h":[[117],"yellow",{"e":187,"c":"orange","a":-22,"b":["orange"],"d":68},154,["green","orange","blue",87,"green","orange",46,"violet"],{"a":{"e":178,"c":"blue","a":-2,"g":99,"b":"orange","d":-34,"f":"green"}},"blue"],"b":"violet","g":[13,"yellow",43,"orange"],"f":{"e":-40,"a":"blue","d":50,"c":"violet","h":{"e":"orange","a":[-27,159,"violet","red",130,83,"red","violet",-27],"d":-42,"j":"blue","c":9,"h":{"e":"yellow","a":"blue","d":177,"c":156,"h":"violet","b":0,"g":"orange","f":-43,"i":"orange"},"b":"blue","g":[114,"blue",-4,"red","red","yellow","green"],"f":81,"i":"red"},"b":73,"g":176,"f":"red"},"i":{"e":["orange",-16,["violet",63,"blue",-40,119,22,"orange","orange","violet","green"],-30,{"e":"yellow","c":172,"a":"green","g":"yellow","b":"green","d":"yellow","f":"red"},190,28,{"e":"orange","c":"red","a":"orange","b":51,"d":-31,"f":136},"orange",82],"a":"blue","d":"red","c":["blue",81,"blue","blue","green",191,"blue","blue",1],"h":{"e":"orange","c":{"e":"blue","a":"green","d":55,"j":-36,"c":13,"h":"yellow","b":162,"g":82,"f":"red","i":"red"},"a":"violet","b":"yellow","d":-24,"f":190},"b":[{"e":"green","a":"green","d":-49,"j":"green","c":"orange","h":43,"b":"orange","g":35,"f":"violet","i":"blue"},"yellow",32,"yellow"],"g":"blue","f":0}},"c":"blue","h":69,"b":166,"g":[[88,["blue",21,"yellow","violet"]],["red",169],"red"],"f":176},{"e":["yellow",88,164,{"e":"red","c":"yellow","a":[20,"blue","violet"],"g":-31,"b":80,"d":"yellow","f":"green"},{"e":"orange","c":"green","a":149,"b":"orange","d":-46,"f":[160,83,"orange","red",177,-11]},"green",[156,"red",{"c":7,"a":[152,107,130],"b":{"c":"yellow","a":114,"b":38,"d":"blue"},"d":"orange"},{"a":49,"b":-34},34,-32,"green"]],"a":134,"d":-12,"c":[-33,{"e":102,"a":"red","d":{"e":"orange","a":"green","d":43,"c":"violet","h":{"a":"violet"},"b":-24,"g":"blue","f":"blue","i":[68,"blue"]},"j":-28,"c":87,"h":"violet","b":122,"g":"violet","f":"green","i":"violet"}],"h":"violet","b":["orange",-14,{"e":37,"a":86,"d":{"e":186,"a":-25,"d":71,"c":"orange","h":86,"b":113,"g":27,"f":"green","i":"yellow"},"c":16,"h":"orange","b":"green","g":["yellow","yellow",["orange","violet","violet","green",58,"orange"],["orange",131,"red","blue","orange",183,82,"orange","yellow","blue"],49,"orange","violet","violet","yellow","orange"],"f":"yellow"},[141,"violet","red",-24,18,103,88,169,75],["yellow",["green",55,92,"yellow","orange",135,{"e":"green","c":141,"a":-11,"b":129,"d":"orange","f":"green"},"violet"],14,[{"a":130},["red","violet",182,"blue",149,"orange",-25,"blue","blue"],61,-18,"orange",14,{"e":"red","a":135,"d":"yellow","j":"red","c":23,"h":89,"b":82,"g":"orange","f":"red","i":72},"red"],["red","blue","red",78,134,53,160],-20,98,{"e":[198,69,168,145,-29,"red","orange","orange","yellow"],"a":"violet","d":"green","j":184,"c":[7,99,186,"blue"],"h":10,"b":"blue","g":166,"f":"yellow","i":177}],"green",{"e":"red","a":"green","d":-8,"j":-47,"c":{"e":"orange","c":74,"a":"yellow","b":"orange","d":34,"f":124},"h":152,"b":"red","g":"yellow","f":161,"i":["blue","red","orange","orange","orange",-38,"orange","red"]},"yellow","blue",75],"g":[67,["orange",109,114,32,"green","green","yellow",["yellow","orange",-40,["green","orange","yellow",187,3,"yellow","violet","orange",195,"yellow"],"blue","yellow","blue"]],[32,{"c":43,"a":"red","b":"blue","d":25}],{"c":"red","a":24,"b":139},{"e":"orange","a":153,"d":43,"c":143,"h":["violet","yellow","green",159,165,{"a":"blue","b":"violet"}],"b":150,"g":["red","red","orange",[138,"green"]],"f":"green"},"violet",-12,"red",["violet","green"]],"f":{"e":{"e":39,"a":"orange","d":{"e":[11],"c":"violet","a":"orange","g":49,"b":"red","d":0,"f":{"a":45}},"c":"violet","h":-30,"b":[93,-1,"red",[39,"red","green"],"green",[154,"blue","orange",147,"orange","yellow"],106,["green",71,-9],-37],"g":"blue","f":"blue","i":176},"c":98,"a":164,"b":["violet","orange",[85,{"e":"yellow","a":113,"d":176,"c":"green","h":"violet","b":"orange","g":166,"f":"green","i":"green"},[145,"green",-7,"violet"]],{"e":["green","green"],"a":"red","d":79,"j":"blue","c":-41,"h":"yellow","b":"violet","g":"blue","f":148,"i":20}],"d":12,"f":[-34,"yellow"]}},{"e":{"e":[{"a":159},["red",-46,{"a":11},166,116,{"e":-39,"c":-24,"a":194,"b":27,"d":91},-37,85,["green"],61],"yellow",{"a":135},["orange","orange",128,"green",-20,97,{"e":108,"c":195,"a":"blue","g":51,"b":"green","d":"violet","f":28}]],"a":"green","d":164,"c":"violet","h":"orange","b":"green","g":{"e":"red","c":151,"a":"violet","b":46,"d":"yellow","f":["red"]},"f":-35,"i":"orange"},"a":{"e":7,"a":{"a":-28},"d":151,"c":{"c":147,"a":165,"b":[-5,["violet","blue","orange","violet",3,"yellow",86,"orange",197,51],6,156,43,94,"blue",{"e":130,"c":"orange","a":-29,"b":89,"d":-41,"f":"orange"},76]},"h":{"e":153,"a":"violet","d":"yellow","j":"green","c":{"c":"blue","a":"violet","b":113,"d":"yellow"},"h":{"e":"blue","a":["yellow",29,69],"d":"orange","c":"red","h":"green","b":164,"g":"blue","f":{"c":16,"a":191,"b":61}},"b":195,"g":"yellow","f":"green","i":"red"},"b":82,"g":[51,-47,186,{"e":4,"c":27,"a":60,"b":"orange","d":32,"f":"violet"},{"e":"blue","a":72,"d":17,"j":"blue","c":"red","h":0,"b":"yellow","g":195,"f":["red","green",82,-31,"blue",-24,"yellow","red","violet"],"i":43},["green"]],"f":"blue"},"d":["violet",22,118],"j":-45,"c":174,"h":79,"b":180,"g":{"c":-7,"a":{"e":["blue","violet"],"c":"blue","a":"violet","g":"red","b":"orange","d":"orange","f":{"a":"violet","b":33}},"b":183,"d":132},"f":["violet","violet","green",[[[66,"violet","violet","green","green"]],[181,"yellow",167,134,"orange",{"e":"red","c":"violet","a":"violet","b":107,"d":-19},{"e":0,"c":166,"a":"green","b":"blue","d":"red"}],19,-31,108]],"i":["red","red",[159],[139,"blue",{"a":106},48,117,164,["blue",161,"green",174,"orange",152,"red","orange",["red","yellow","blue",-43]],105,22,"green"],[110]]},153,{"a":{"e":"orange","a":[{"e":"red","a":"yellow","d":"green","c":"violet","h":{"e":"blue","c":62,"a":148,"g":"violet","b":6,"d":"yellow","f":-1},"b":"yellow","g":-14,"f":58},"violet","yellow",{"e":4,"a":"blue","d":{"e":"green","a":-49,"d":"yellow","j":-39,"c":"orange","h":"red","b":"blue","g":59,"f":"violet","i":46},"c":195,"h":22,"b":160,"g":"orange","f":"orange","i":38},"red",["orange","red","yellow",34,101,"yellow"],40,["orange",{"e":148,"c":"red","a":85,"g":62,"b":-13,"d":-25,"f":"orange"},-47,34,{"e":"violet","c":80,"a":"red","b":34,"d":100},58,185,"yellow","orange",["yellow","green","violet",84,"blue","orange",13]],183],"d":"red","j":[-2,"red","yellow",176,-24,140,"blue","yellow",155,{"e":-28,"c":"violet","a":{"a":"green","b":3},"b":"red","d":-16}],"c":["violet",-16],"h":"blue","b":"green","g":["yellow","yellow","yellow",44,"orange",50,36,{"e":"green","a":162,"d":112,"c":166,"h":92,"b":31,"g":"blue","f":-12}],"f":"yellow","i":["yellow","violet",[19,"red",["violet","violet",195]],["yellow",[106],"red","orange","blue"],178,{"e":"violet","a":104,"d":"red","c":"yellow","h":{"c":-47,"a":"blue","b":84},"b":"green","g":0,"f":"blue","i":"red"},105]}},{"e":7,"c":[156],"a":{"a":{"e":{"e":"violet","a":["blue","yellow","orange"],"d":"green","c":[159,"blue","violet","red",61,3],"h":"red","b":"green","g":132,"f":130},"c":92,"a":"orange","b":"green","d":[186,122],"f":"yellow"}},"g":["yellow","violet"],"b":"violet","d":{"e":{"c":"orange","a":127,"b":41,"d":[36,61,178,"yellow","green","red","violet",{"e":-18,"a":"yellow","d":"red","c":0,"h":"yellow","b":"yellow","g":6,"f":"yellow"},162]},"c":-6,"a":{"c":{"e":"red","c":78,"a":"blue","b":91,"d":49,"f":14},"a":["green"],"b":{"a":22},"d":{"a":"blue"}},"b":154,"d":"orange","f":{"a":170}},"f":-33},"blue",82],"a":{"c":["green",["red","orange",{"e":-28,"a":{"a":"violet","b":110},"d":[[174,140,72],191,"yellow",108,195,{"a":"violet"},147,53],"c":"yellow","h":"green","b":"violet","g":"red","f":["blue","orange","violet",[48,118],156,144,-46,110,["orange","yellow","blue","red"],149],"i":{"e":"orange","c":101,"a":{"e":111,"a":"blue","d":"orange","j":"orange","c":-40,"h":13,"b":"orange","g":"yellow","f":32,"i":"yellow"},"g":{"e":"orange","a":"blue","d":195,"j":81,"c":185,"h":20,"b":4,"g":"green","f":112,"i":147},"b":-22,"d":199,"f":"yellow"}},"yellow",19,128,-3,27,["orange",{"e":-8,"c":156,"a":"yellow","b":"red","d":20,"f":-37},[{"c":19,"a":"blue","b":150},"orange",-12,9]]],[12,{"e":"blue","c":162,"a":["blue",184,"yellow","orange",{"a":"yellow","b":"green"},88,-19,60,"yellow"],"g":"yellow","b":191,"d":-6,"f":"violet"}],{"c":"yellow","a":"orange","b":{"a":"violet","b":["orange","orange","violet",{"e":"red","a":"red","d":163,"c":153,"h":"green","b":6,"g":"blue","f":17,"i":63},163,[164,-41,"violet","violet",126]]},"d":-38}],"a":{"e":{"c":-1,"a":"orange","b":{"c":131,"a":{"e":-11,"c":120,"a":"green","b":198,"d":152,"f":37},"b":77,"d":{"e":8,"a":21,"d":"blue","c":"yellow","h":"violet","b":11,"g":"violet","f":{"e":148,"c":98,"a":80,"b":78,"d":68}}},"d":"orange"},"a":["violet",[-30,117],[78,31],74,197,"red","orange",95],"d":"green","c":[96,"violet"],"h":{"e":{"c":"green","a":[76,16,125,"green",15,"violet",130,60,"red"],"b":"orange","d":-38},"a":71,"d":158,"j":-16,"c":[["yellow","green",183,165,-28,4,102],-20,"blue","violet",{"e":"yellow","c":{"e":"orange","a":"yellow","d":"red","c":"orange","h":"orange","b":169,"g":"violet","f":48},"a":99,"b":["blue",-1,"blue"],"d":104,"f":20},83],"h":"green","b":[-14,[28],"yellow",[93,"blue",-24,160,35,25,-32,"green"],{"e":[51,"red",64,"red","blue",-16,31,146,"blue","yellow"],"c":122,"a":"orange","b":"yellow","d":{"c":53,"a":179,"b":"blue","d":-44}},17,110],"g":151,"f":"orange","i":{"a":"violet","b":{"a":[-24]}}},"b":["violet",{"e":{"e":91,"a":{"e":"blue","a":-25,"d":70,"c":"green","h":"violet","b":48,"g":"violet","f":"orange"},"d":"yellow","c":136,"h":90,"b":{"e":26,"c":"green","a":"blue","g":"violet","b":192,"d":198,"f":86},"g":"orange","f":"blue"},"a":137,"d":47,"c":11,"h":"yellow","b":"orange","g":"orange","f":{"e":"blue","a":45,"d":"violet","j":146,"c":-38,"h":4,"b":157,"g":104,"f":-13,"i":"yellow"}},{"e":191,"a":"blue","d":"green","c":"blue","h":-19,"b":148,"g":"blue","f":{"e":57,"c":"red","a":167,"b":[-42,147,166,74,-32,"orange","violet","yellow"],"d":"green","f":71}},"green",[184,"yellow",[["yellow","yellow"],"green",{"e":-24,"a":1,"d":44,"c":"yellow","h":"yellow","b":144,"g":"violet","f":"green","i":-7},86,119,52,"orange",["red","red",18,"orange",192,116],120,109]],["violet",-14,"violet",{"e":-29,"c":{"e":"green","a":"red","d":"blue","j":68,"c":9,"h":"orange","b":25,"g":"red","f":10,"i":"green"},"a":-15,"b":"blue","d":"violet","f":125},119,[127,"violet","green",39]]],"g":"green","f":-14},"b":23,"d":{"c":{"c":98,"a":"yellow","b":97},"a":-29,"b":{"a":192,"b":["violet","yellow",65,{"c":{"e":"violet","c":"yellow","a":"violet","b":"blue","d":"orange"},"a":"red","b":176},192]},"d":"orange"}},"b":[{"e":"yellow","c":45,"a":81,"b":["orange"],"d":"violet","f":[-3,"red",146,186,"orange","red","blue",{"e":"green","c":22,"a":"yellow","b":"blue","d":-2,"f":"green"},0,180]},[[-36,["orange",[166],"violet"],{"c":86,"a":[2,173,78,"violet","orange",["violet","yellow","blue",107,24,-1,"orange",13,"green","violet"]],"b":"violet","d":107},100,["yellow",-22,[177,69,144,84,159,"violet"],"green"],{"e":"green","a":78,"d":173,"c":"blue","h":36,"b":[[-48,164,"red","blue",45],["green","orange",23,15,110,49,"blue"],"violet",0,192,53],"g":["blue","violet"],"f":"orange","i":[{"e":186,"c":"orange","a":"green","b":174,"d":"yellow","f":46},"violet",188,"yellow",54,-6,"blue","violet",0,{"e":166,"a":"yellow","d":"red","j":"blue","c":"red","h":97,"b":"violet","g":32,"f":173,"i":95}]},{"a":58,"b":"blue"},"green",["red",150,3,"orange",32,106,[["blue"],118,{"c":178,"a":7,"b":185,"d":"violet"},"red",164,"red",[128,"red"],-44],{"e":"orange","a":"orange","d":130,"c":"yellow","h":"yellow","b":{"e":91,"a":161,"d":-44,"c":-45,"h":"blue","b":"orange","g":122,"f":"orange"},"g":"yellow","f":"blue"},139,{"a":97}]],"orange",["orange",0,"blue","red",{"e":192,"c":92,"a":{"a":["red",164,"yellow",189,"blue",150,"green","violet",-35,33],"b":"red"},"g":"yellow","b":{"a":"blue"},"d":"red","f":-31},111,"yellow","red",[["green","green",42,-47,[88,142,"blue",59,-42,"violet"],"green"],"orange",["violet","yellow","violet",198,94,44,"orange","green","blue",26],"blue","violet"]],{"a":118}],{"e":-35,"a":{"e":["orange",-1,121,"red"],"c":"violet","a":[[127,-18,-4,[-40,42,"violet",167,"orange",112,"orange"],30,31,"violet",37],{"c":"blue","a":"green","b":172},[141,154],146,"yellow"],"b":"blue","d":-3},"d":"red","c":-17,"h":-3,"b":["violet","yellow",19,"red",8,138,37],"g":{"c":{"e":-5,"c":[-23,21,"green",-3,"red"],"a":163,"b":"blue","d":"red","f":["violet",136,"violet"]},"a":183,"b":-36,"d":"violet"},"f":["green",["green",{"e":"red","c":"yellow","a":10,"g":"blue","b":56,"d":"red","f":["green","red","red"]},["violet","orange",{"e":7,"c":170,"a":"green","b":55,"d":115},"green","blue"]]]},{"e":{"e":{"a":"blue","b":[192,"blue",86,93]},"a":"green","d":"yellow","c":186,"h":["violet","orange","orange","violet","red","orange",139,"violet","green",{"e":"red","a":85,"d":"orange","c":"yellow","h":[46,35,"red","green",-11,"blue"],"b":"yellow","g":"yellow","f":"orange"}],"b":{"e":77,"a":"yellow","d":"green","c":144,"h":"green","b":{"e":[27,"blue","yellow",-48,-21,-12,121,"violet"],"a":[-23],"d":"blue","j":{"e":"orange","c":"blue","a":"green","b":-34,"d":"green"},"c":"green","h":"green","b":61,"g":["blue"],"f":19,"i":"violet"},"g":86,"f":"orange"},"g":"yellow","f":"orange"},"c":{"c":["yellow",82,"red","orange",{"e":34,"c":"green","a":"violet","b":182,"d":"orange","f":{"e":-49,"a":184,"d":57,"j":"yellow","c":120,"h":"violet","b":170,"g":159,"f":-3,"i":99}},-37,{"e":84,"a":["violet",154,"violet",123,"violet",148,105,"yellow",195],"d":"orange","c":{"a":140},"h":"yellow","b":159,"g":76,"f":186},183],"a":[{"e":"yellow","a":-2,"d":"green","c":{"c":68,"a":"red","b":"blue"},"h":[140,99,-2,"green","orange","orange",-14,60,"red","green"],"b":"violet","g":1,"f":["yellow","violet"],"i":142},{"e":{"a":76,"b":-17},"c":46,"a":[76,1,79,36,-25,"yellow",0],"g":"yellow","b":185,"d":54,"f":"green"}],"b":{"e":127,"a":[["violet"],115,114,"red","orange",83,-17,-2],"d":{"e":198,"c":"red","a":46,"b":77,"d":"green"},"c":140,"h":"orange","b":89,"g":149,"f":"orange"}},"a":"blue","g":62,"b":"orange","d":"violet","f":{"e":-11,"a":[29,"yellow","yellow",187,"orange",{"e":147,"a":197,"d":["green",182,-2,95,-8,110,-38],"c":"violet","h":187,"b":90,"g":22,"f":"yellow","i":"green"},{"a":["blue","red",140],"b":"violet"},"blue",76,59],"d":-26,"c":[{"a":"orange","b":179},"red",{"e":"violet","c":"orange","a":"blue","g":"violet","b":25,"d":149,"f":-27},{"e":"green","a":"yellow","d":"violet","j":{"c":67,"a":179,"b":53},"c":145,"h":-4,"b":"blue","g":11,"f":"blue","i":"violet"}],"h":"red","b":"blue","g":{"e":"yellow","c":[93,12,118,-7,125,93,"yellow",182,113,"yellow"],"a":"green","b":"green","d":"violet"},"f":"green","i":"green"}},[7]],"d":[[[42,67,{"e":"yellow","a":"orange","d":{"e":"orange","c":"green","a":-26,"g":[68,162,"orange","red"],"b":105,"d":52,"f":"yellow"},"c":{"e":"orange","a":"orange","d":120,"c":"blue","h":[172,"orange",171,-40,139,161,"yellow",197],"b":"yellow","g":[162,"orange",2],"f":"yellow","i":"orange"},"h":-21,"b":"green","g":{"e":33,"a":6,"d":"violet","c":193,"h":89,"b":56,"g":146,"f":{"c":-46,"a":"green","b":161},"i":149},"f":65},[["yellow",31,-4],"red",-27,21,{"e":{"e":-25,"a":-1,"d":"violet","c":"violet","h":"blue","b":"green","g":"violet","f":"orange","i":"yellow"},"c":"orange","a":"orange","g":"orange","b":60,"d":{"e":"yellow","c":"green","a":"yellow","g":"violet","b":134,"d":149,"f":"yellow"},"f":"blue"},"violet",[66,"green",25,106,"red","orange"],{"a":{"e":"orange","a":95,"d":"red","c":176,"h":179,"b":87,"g":195,"f":71,"i":"violet"},"b":14},55],"blue"],[[62,"violet",58,[-42,"orange",{"e":186,"a":"orange","d":"green","j":100,"c":163,"h":-9,"b":"green","g":"orange","f":-8,"i":"orange"},"red",12,"orange",-3,162,"green"],"violet",94,"orange",41,58,"violet"],[["green","green","red"],"red",128,"blue","yellow","yellow",{"e":"yellow","a":193,"d":["orange",134],"j":["green",45,195,123,50,61],"c":"violet","h":-39,"b":13,"g":"yellow","f":{"e":-33,"c":26,"a":83,"b":122,"d":"orange"},"i":"orange"},"blue",46,"yellow"],"yellow","yellow",30,[158,{"c":"green","a":68,"b":122},{"e":95,"c":"orange","a":"green","b":115,"d":180,"f":"yellow"},[194,-29,"orange","violet",{"e":173,"a":193,"d":"green","j":"blue","c":"blue","h":"green","b":"yellow","g":"green","f":186,"i":"red"},135],"violet"]],"yellow",144,["violet","red",{"a":[121],"b":134},{"a":-23,"b":"violet"},[7],[101,181,"yellow",{"e":"violet","c":"green","a":56,"b":"green","d":175}]],"violet",{"c":"green","a":{"e":"green","c":-42,"a":-49,"b":[["orange","yellow",-17,"orange",-11,-41,"red",32],"blue",46,{"a":"yellow","b":"violet"}],"d":"red","f":["violet","violet",-11]},"b":["orange",{"e":62,"c":"violet","a":-5,"b":39,"d":[122,129,"violet","orange"]},"green"]}]],"f":{"e":{"e":[{"e":{"a":"violet"},"c":171,"a":{"a":{"e":122,"a":"blue","d":164,"j":54,"c":"violet","h":-1,"b":148,"g":"blue","f":190,"i":-37}},"b":[{"a":158},"blue",26,{"e":"violet","c":"green","a":64,"g":36,"b":"blue","d":"blue","f":"green"},"violet",125,"orange"],"d":"violet"},"yellow",{"c":{"e":-46,"c":121,"a":191,"g":"blue","b":67,"d":-25,"f":"blue"},"a":"orange","b":{"a":108,"b":["red",-48]}},{"e":116,"c":"green","a":-34,"g":59,"b":"yellow","d":37,"f":{"e":-3,"a":105,"d":"red","c":"red","h":"green","b":27,"g":189,"f":"violet"}},"red",["yellow",152,{"e":"red","a":[164,155,"green","yellow"],"d":79,"c":"violet","h":{"e":"blue","c":53,"a":"orange","b":-43,"d":"violet","f":"orange"},"b":32,"g":"green","f":"green","i":23},"red","violet",-37,[["green","violet",131,-18,"green"],48,6,"red",83],152,181,75],{"e":[116,100,"red",{"a":156},"green"],"c":"red","a":170,"g":[28,59,"violet","violet",144],"b":13,"d":{"a":"yellow","b":"blue"},"f":{"e":-45,"c":"orange","a":"orange","b":"green","d":["orange","orange",98,-13,"yellow",183,193,"green"],"f":"green"}},128,["green"]],"a":{"e":{"e":"green","a":"yellow","d":{"c":-48,"a":["violet",195,77,-13,"green","red"],"b":"blue","d":"red"},"c":"violet","h":[-13,"green"],"b":27,"g":-37,"f":197},"c":68,"a":-23,"b":93,"d":"orange","f":{"a":"green","b":-4}},"d":[-48],"c":[["violet","blue","orange",{"e":42,"c":66,"a":["blue","blue","orange",144,130,"red","violet","red",112],"b":"blue","d":192},"orange",["orange",4,"violet",-47,"orange"],["violet","yellow",54,{"c":47,"a":"yellow","b":"red"},{"a":"violet"},151,-30,"orange","red"],-31,"blue"],135,{"e":"red","a":[5,117],"d":119,"j":189,"c":{"e":134,"a":142,"d":"orange","j":189,"c":"red","h":"violet","b":"yellow","g":122,"f":{"c":"orange","a":"violet","b":"yellow"},"i":107},"h":109,"b":15,"g":[157,135,122,-34,168,"green",-19,13,64],"f":{"e":"blue","c":174,"a":187,"g":"violet","b":36,"d":80,"f":188},"i":-10},60,"orange",146,{"e":-8,"a":{"a":63},"d":"green","c":67,"h":["blue","yellow","red","blue",["yellow",189,"orange","green"],"orange","violet"],"b":-29,"g":"orange","f":["violet","green","orange"]},{"e":"violet","c":"red","a":-45,"g":[45,"green",-24,-7,{"a":67,"b":"red"},"orange",188,["red","blue","red"],47,133],"b":{"e":112,"a":76,"d":"yellow","j":93,"c":"orange","h":137,"b":154,"g":["orange","red","yellow",-26,"orange"],"f":-3,"i":"yellow"},"d":{"e":"violet","c":48,"a":174,"b":"green","d":189},"f":[69,"red",{"a":"green","b":"blue"},"red",{"a":85}]},{"e":"violet","c":{"e":"violet","c":"red","a":-22,"b":3,"d":{"e":185,"c":52,"a":"yellow","b":165,"d":"blue","f":"yellow"}},"a":45,"b":"green","d":"blue"}],"h":"orange","b":{"e":"red","c":68,"a":171,"g":-30,"b":"orange","d":"violet","f":{"c":22,"a":["green"],"b":148}},"g":{"e":77,"c":28,"a":["green","green",{"a":"violet","b":115},{"e":59,"a":198,"d":"violet","c":"yellow","h":-38,"b":"violet","g":69,"f":"violet","i":-12},35],"b":"blue","d":{"e":[-20,"orange","green",116,"yellow",-21],"c":"red","a":"green","b":160,"d":["violet",-49,"yellow",[46,"blue",196]]}},"f":[162,{"c":[-30,"violet"],"a":"blue","b":"blue","d":83},"blue"],"i":"green"},"a":["blue",{"e":{"e":131,"c":"yellow","a":"blue","g":{"e":"yellow","c":70,"a":{"e":53,"c":100,"a":162,"b":-7,"d":-14,"f":"orange"},"b":"yellow","d":"green","f":149},"b":[184,"green","blue",-38,193,75,156],"d":96,"f":{"e":177,"c":0,"a":{"c":"red","a":-23,"b":"yellow","d":-37},"g":149,"b":"blue","d":61,"f":78}},"c":-21,"a":[{"e":{"a":"yellow"},"c":71,"a":{"e":-46,"a":"yellow","d":"green","c":78,"h":59,"b":"green","g":189,"f":"red","i":"red"},"b":"yellow","d":{"e":"violet","c":"violet","a":"orange","b":189,"d":21,"f":71},"f":15},"green",150,"yellow"],"b":101,"d":"blue","f":"blue"},"green",[[-10,{"c":61,"a":99,"b":"green"}],"violet",["blue",-41],54,[194,146,"green",90,"violet","violet",-5,"red"],{"e":114,"a":"green","d":{"e":"blue","a":"blue","d":["yellow",10,"blue",86,44,"violet","red","red"],"c":94,"h":{"e":"red","c":"blue","a":89,"g":197,"b":148,"d":91,"f":52},"b":"orange","g":"red","f":"green"},"c":[96,127,29],"h":"blue","b":"green","g":"yellow","f":{"e":"green","a":"blue","d":"orange","j":40,"c":"red","h":92,"b":-49,"g":-34,"f":8,"i":125},"i":-30},{"a":154,"b":100}]],"d":{"c":{"a":"violet","b":"violet"},"a":"yellow","b":{"e":[83,"red",["green",{"a":"violet"},126,105,86],[["blue",-40,148,"blue"],168,"red","green",["green",41,93,"red",-19],32,"violet","violet","blue","yellow"],{"a":"yellow","b":"green"},[85,164],17,60,66,{"c":"yellow","a":"yellow","b":-10,"d":"yellow"}],"a":[109,28,52,[118,"violet"],{"a":"blue"},10,163,"green",-21],"d":"green","c":"green","h":["violet","violet"],"b":"blue","g":{"e":-22,"c":["yellow",119,127],"a":"green","g":1,"b":[{"a":100,"b":"yellow"},63,41,168,152,"yellow",198,-14,30,103],"d":"violet","f":["blue",135,"yellow","green","yellow",["yellow",35,91,182]]},"f":"yellow","i":{"c":"green","a":[{"a":"yellow"},"green","orange",50,117,94,"red",89],"b":"red"}}},"j":{"e":{"e":{"a":70},"c":["blue","violet"],"a":113,"b":{"e":"yellow","c":-9,"a":135,"b":"yellow","d":81},"d":{"e":189,"a":-19,"d":-14,"j":{"e":"green","a":1,"d":"violet","c":"red","h":106,"b":"green","g":-19,"f":192,"i":"green"},"c":195,"h":"yellow","b":"orange","g":45,"f":"green","i":"violet"},"f":75},"a":"violet","d":"blue","c":"red","h":113,"b":[14,{"e":82,"a":{"e":59,"a":182,"d":"yellow","c":"blue","h":"yellow","b":"green","g":93,"f":"yellow","i":147},"d":58,"c":"violet","h":{"a":{"e":27,"a":"orange","d":181,"c":142,"h":195,"b":"yellow","g":44,"f":"yellow"}},"b":-14,"g":"red","f":{"a":154},"i":90},"orange",{"a":"blue","b":-11},["yellow",[38,-34,"orange",57],"orange",98,"violet","violet",{"a":134},[24,"blue","blue",172,114],10],[{"a":["yellow","green"]},166,"blue",["blue",{"e":"blue","c":-6,"a":"green","b":"green","d":"green","f":50},-44,{"e":"violet","a":"yellow","d":-27,"j":33,"c":"orange","h":146,"b":"green","g":30,"f":"violet","i":"violet"},"blue","red","violet",6]],113],"g":{"e":{"e":"red","a":125,"d":183,"j":74,"c":["green","yellow"],"h":12,"b":["green",-38,"yellow"],"g":71,"f":"blue","i":"blue"},"a":["green",86,28,[55,127,"blue",172,"green",83,"green","violet",{"a":53},"blue"],{"a":181,"b":57},[28,"violet"],"red",{"a":138},198],"d":"yellow","c":[{"e":"violet","c":65,"a":"green","b":{"e":"orange","a":68,"d":"orange","c":"green","h":161,"b":"green","g":"green","f":13},"d":-38},"blue",{"e":73,"a":40,"d":"green","c":"red","h":"yellow","b":117,"g":178,"f":170},"yellow",188],"h":{"a":-21},"b":{"c":86,"a":["green","green",170,"blue",-40,"yellow","red",10],"b":[["green","yellow",2,"violet",-30,"yellow","red",-40,"orange","violet"],"red",58,165,"red"],"d":13},"g":{"a":63},"f":"violet"},"f":["green"],"i":[["yellow","yellow","red",{"e":-5,"c":124,"a":"yellow","g":"violet","b":"orange","d":"violet","f":149},-16,9],"violet",-43,{"c":9,"a":52,"b":179,"d":74},"violet",[{"e":-30,"a":82,"d":"green","j":49,"c":{"e":"green","a":"violet","d":"yellow","j":"blue","c":37,"h":"violet","b":48,"g":12,"f":"green","i":"red"},"h":58,"b":["yellow","blue","blue",29,"orange","green","green",0],"g":128,"f":"orange","i":91},[181,"red","green","violet","red","green","orange",{"e":"green","a":"yellow","d":"green","c":24,"h":194,"b":128,"g":"red","f":162,"i":"violet"},191],"red","violet","yellow","red"],141,123]},"c":{"a":95},"h":{"a":138},"b":118,"g":"green","f":0,"i":"violet"}}
diff --git a/12/solution.py b/12/solution.py
new file mode 100644
index 0000000..f4162fb
--- /dev/null
+++ b/12/solution.py
@@ -0,0 +1,25 @@
+from json import load
+
+def part1(data) -> int:
+ if type(data) is list:
+ return sum(part1(d) for d in data)
+ elif type(data) is dict:
+ return sum(part1(v) for k, v in data.items())
+ if type(data) is int:
+ return data
+ return 0
+
+def part2(data) -> int:
+ if type(data) is list:
+ return sum(part2(d) for d in data)
+ elif type(data) is dict and 'red' not in data.values():
+ return sum(part2(v) for k, v in data.items())
+ if type(data) is int:
+ return data
+ return 0
+
+if __name__ == '__main__':
+ with open('input') as f:
+ d = load(f)
+ print(part1(d))
+ print(part2(d))
diff --git a/13/input b/13/input
new file mode 100644
index 0000000..35be357
--- /dev/null
+++ b/13/input
@@ -0,0 +1,56 @@
+Alice would gain 54 happiness units by sitting next to Bob.
+Alice would lose 81 happiness units by sitting next to Carol.
+Alice would lose 42 happiness units by sitting next to David.
+Alice would gain 89 happiness units by sitting next to Eric.
+Alice would lose 89 happiness units by sitting next to Frank.
+Alice would gain 97 happiness units by sitting next to George.
+Alice would lose 94 happiness units by sitting next to Mallory.
+Bob would gain 3 happiness units by sitting next to Alice.
+Bob would lose 70 happiness units by sitting next to Carol.
+Bob would lose 31 happiness units by sitting next to David.
+Bob would gain 72 happiness units by sitting next to Eric.
+Bob would lose 25 happiness units by sitting next to Frank.
+Bob would lose 95 happiness units by sitting next to George.
+Bob would gain 11 happiness units by sitting next to Mallory.
+Carol would lose 83 happiness units by sitting next to Alice.
+Carol would gain 8 happiness units by sitting next to Bob.
+Carol would gain 35 happiness units by sitting next to David.
+Carol would gain 10 happiness units by sitting next to Eric.
+Carol would gain 61 happiness units by sitting next to Frank.
+Carol would gain 10 happiness units by sitting next to George.
+Carol would gain 29 happiness units by sitting next to Mallory.
+David would gain 67 happiness units by sitting next to Alice.
+David would gain 25 happiness units by sitting next to Bob.
+David would gain 48 happiness units by sitting next to Carol.
+David would lose 65 happiness units by sitting next to Eric.
+David would gain 8 happiness units by sitting next to Frank.
+David would gain 84 happiness units by sitting next to George.
+David would gain 9 happiness units by sitting next to Mallory.
+Eric would lose 51 happiness units by sitting next to Alice.
+Eric would lose 39 happiness units by sitting next to Bob.
+Eric would gain 84 happiness units by sitting next to Carol.
+Eric would lose 98 happiness units by sitting next to David.
+Eric would lose 20 happiness units by sitting next to Frank.
+Eric would lose 6 happiness units by sitting next to George.
+Eric would gain 60 happiness units by sitting next to Mallory.
+Frank would gain 51 happiness units by sitting next to Alice.
+Frank would gain 79 happiness units by sitting next to Bob.
+Frank would gain 88 happiness units by sitting next to Carol.
+Frank would gain 33 happiness units by sitting next to David.
+Frank would gain 43 happiness units by sitting next to Eric.
+Frank would gain 77 happiness units by sitting next to George.
+Frank would lose 3 happiness units by sitting next to Mallory.
+George would lose 14 happiness units by sitting next to Alice.
+George would lose 12 happiness units by sitting next to Bob.
+George would lose 52 happiness units by sitting next to Carol.
+George would gain 14 happiness units by sitting next to David.
+George would lose 62 happiness units by sitting next to Eric.
+George would lose 18 happiness units by sitting next to Frank.
+George would lose 17 happiness units by sitting next to Mallory.
+Mallory would lose 36 happiness units by sitting next to Alice.
+Mallory would gain 76 happiness units by sitting next to Bob.
+Mallory would lose 34 happiness units by sitting next to Carol.
+Mallory would gain 37 happiness units by sitting next to David.
+Mallory would gain 40 happiness units by sitting next to Eric.
+Mallory would gain 18 happiness units by sitting next to Frank.
+Mallory would gain 7 happiness units by sitting next to George.
diff --git a/13/solution.py b/13/solution.py
new file mode 100644
index 0000000..af0362b
--- /dev/null
+++ b/13/solution.py
@@ -0,0 +1,51 @@
+"""Advent of Code 2015, day 15"""
+
+from collections import defaultdict
+from itertools import combinations
+from functools import cache
+from typing import TypeVar, Generic
+
+T = TypeVar('T')
+class WeightedGraph(Generic[T]):
+ nodes: set[T]
+ weights: defaultdict[tuple[T, T], int]
+ def __init__(self):
+ self.nodes = set()
+ self.weights = defaultdict(int)
+ def add_edge(self, a, b, weight):
+ self.nodes.add(a)
+ self.nodes.add(b)
+ self.weights[tuple(sorted((a, b)))] = weight
+ def get_edge(self, a, b):
+ return self.weights[tuple(sorted((a, b)))]
+
+def part1(graph: WeightedGraph[str]) -> int:
+ @cache
+ def max_happiness(first_guest: str, guest: str, remaining: frozenset[str]) -> int:
+ remaining = remaining - {guest}
+ if len(remaining) == 0:
+ return graph.get_edge(first_guest, guest)
+ return max(graph.get_edge(guest, other) + max_happiness(first_guest, other, remaining) for other in remaining)
+ return max(max_happiness(guest, guest, frozenset(graph.nodes)) for guest in graph.nodes)
+
+def part2(graph: WeightedGraph[str]) -> int:
+ for guest in graph.nodes.copy():
+ graph.add_edge(guest, 'Me', 0)
+ return part1(graph)
+
+if __name__ == '__main__':
+ guests = set()
+ edges = dict()
+ with open('input') as f:
+ for l in f:
+ a, _, what, how_much, _, _, _, _, _, _, b = l.rstrip()[:-1].split()
+ guests.add(a)
+ guests.add(b)
+ if what == 'lose':
+ how_much = -int(how_much)
+ edges[(a, b)] = int(how_much)
+ g = WeightedGraph()
+ for a, b in combinations(guests, 2):
+ g.add_edge(a, b, edges[(a, b)] + edges[(b, a)])
+ print(part1(g))
+ print(part2(g))
diff --git a/14/input b/14/input
new file mode 100644
index 0000000..1532578
--- /dev/null
+++ b/14/input
@@ -0,0 +1,9 @@
+Vixen can fly 8 km/s for 8 seconds, but then must rest for 53 seconds.
+Blitzen can fly 13 km/s for 4 seconds, but then must rest for 49 seconds.
+Rudolph can fly 20 km/s for 7 seconds, but then must rest for 132 seconds.
+Cupid can fly 12 km/s for 4 seconds, but then must rest for 43 seconds.
+Donner can fly 9 km/s for 5 seconds, but then must rest for 38 seconds.
+Dasher can fly 10 km/s for 4 seconds, but then must rest for 37 seconds.
+Comet can fly 3 km/s for 37 seconds, but then must rest for 76 seconds.
+Prancer can fly 9 km/s for 12 seconds, but then must rest for 97 seconds.
+Dancer can fly 37 km/s for 1 seconds, but then must rest for 36 seconds.
diff --git a/14/solution.py b/14/solution.py
new file mode 100644
index 0000000..9ce32dd
--- /dev/null
+++ b/14/solution.py
@@ -0,0 +1,43 @@
+from dataclasses import dataclass
+
+@dataclass
+class Reindeer:
+ name: str
+ speed: int
+ fly_time: int
+ rest_time: int
+ def distance_after(self, seconds):
+ cycle_time = self.fly_time + self.rest_time
+ cycles = seconds // cycle_time
+ remaining_time = seconds % cycle_time
+ if remaining_time > self.fly_time:
+ remaining_time = self.fly_time
+ return cycles * self.speed * self.fly_time + remaining_time * self.speed
+
+def part1(reindeer: list[Reindeer]) -> int:
+ return max(r.distance_after(2503) for r in reindeer)
+
+def part2(reindeer: list[Reindeer]) -> int:
+ points = [0] * len(reindeer)
+ for s in range(1, 2504):
+ distances = [r.distance_after(s) for r in reindeer]
+ max_dist = max(distances)
+ for i, d in enumerate(distances):
+ if d == max_dist:
+ points[i] += 1
+ return max(points)
+
+if __name__ == '__main__':
+ reindeer = [
+ Reindeer('Vixen', 8, 8, 53),
+ Reindeer('Blitzen', 13, 4, 49),
+ Reindeer('Rudolph', 20, 7, 132),
+ Reindeer('Cupid', 12, 4, 43),
+ Reindeer('Donner', 9, 5, 38),
+ Reindeer('Dasher', 10, 4, 37),
+ Reindeer('Comet', 3, 37, 76),
+ Reindeer('Prancer', 9, 12, 97),
+ Reindeer('Dancer', 37, 1, 36),
+ ]
+ print(part1(reindeer))
+ print(part2(reindeer))
diff --git a/15/input b/15/input
new file mode 100644
index 0000000..634c6a5
--- /dev/null
+++ b/15/input
@@ -0,0 +1,4 @@
+Frosting: capacity 4, durability -2, flavor 0, texture 0, calories 5
+Candy: capacity 0, durability 5, flavor -1, texture 0, calories 8
+Butterscotch: capacity -1, durability 0, flavor 5, texture 0, calories 6
+Sugar: capacity 0, durability 0, flavor -2, texture 2, calories 1
diff --git a/15/solution.py b/15/solution.py
new file mode 100644
index 0000000..21b4ec8
--- /dev/null
+++ b/15/solution.py
@@ -0,0 +1,86 @@
+from dataclasses import dataclass
+from functools import cache, cached_property
+from itertools import combinations_with_replacement
+
+@dataclass
+class Ingredient:
+ capacity: int
+ durability: int
+ flavor: int
+ texture: int
+ calories: int
+
+ @cached_property
+ def score(self):
+ return max(self.capacity, 0) * max(self.durability, 0) * max(self.flavor, 0) * max(self.texture, 0)
+
+ @cached_property
+ def calories_score(self):
+ return self.score if self.calories == 500 else 0
+
+ def __lt__(self, other):
+ return self.score < other.score
+ def __gt__(self, other):
+ return self.score > other.score
+ def __le__(self, other):
+ return self.score <= other.score
+ def __ge__(self, other):
+ return self.score >= other.score
+ def __add__(self, other):
+ return Ingredient(
+ self.capacity + other.capacity,
+ self.durability + other.durability,
+ self.flavor + other.flavor,
+ self.texture + other.texture,
+ self.calories + other.calories
+ )
+ def __mul__(self, other: int) -> 'Ingredient':
+ return Ingredient(
+ self.capacity * other,
+ self.durability * other,
+ self.flavor * other,
+ self.texture * other,
+ self.calories * other
+ )
+
+ @staticmethod
+ def from_string(string) -> 'Ingredient':
+ _, rest = string.split(': ')
+ capacity, durability, flavor, texture, calories = (int(p.split()[1]) for p in rest.split(', '))
+ return Ingredient(capacity, durability, flavor, texture, calories)
+
+
+# def part1(ingredients: list[Ingredient]) -> int:
+# @cache
+# def max_score(capacity: int) -> Properties:
+# if capacity == 0:
+# return Properties(0, 0, 0, 0, 0)
+# return max(max_score(capacity - 1) + ingredient.properties for ingredient in ingredients)
+# s = max_score(100).score
+# print(max_score.cache_info())
+# return s
+
+# def part1(ingredients: list[Ingredient]) -> int:
+# return max(sum(perm) for perm in combinations_with_replacement([i.properties for i in ingredients], 100)).score
+
+def splits(total: int, segments: int) -> int:
+ if segments <= 1:
+ yield [total]
+ else:
+ for i in range(total + 1):
+ for subsplit in splits(total - i, segments - 1):
+ yield [i] + subsplit
+
+def part1(ingredients: list[Ingredient]) -> int:
+ empty = Ingredient(0, 0, 0, 0, 0)
+ return max(sum((ingredients[i] * q for i, q in enumerate(split)), start=empty).score for split in splits(100, len(ingredients)))
+
+def part2(ingredients: list[Ingredient]) -> int:
+ empty = Ingredient(0, 0, 0, 0, 0)
+ return max(sum((ingredients[i] * q for i, q in enumerate(split)), start=empty).calories_score for split in splits(100, len(ingredients)))
+
+if __name__ == '__main__':
+ with open('input') as f:
+ ingredients = [Ingredient.from_string(line.strip()) for line in f]
+ print(part1(ingredients))
+ print(part2(ingredients))
diff --git a/16/input b/16/input
new file mode 100644
index 0000000..ddaeefc
--- /dev/null
+++ b/16/input
@@ -0,0 +1,500 @@
+Sue 1: cars: 9, akitas: 3, goldfish: 0
+Sue 2: akitas: 9, children: 3, samoyeds: 9
+Sue 3: trees: 6, cars: 6, children: 4
+Sue 4: trees: 4, vizslas: 4, goldfish: 9
+Sue 5: akitas: 9, vizslas: 7, cars: 5
+Sue 6: vizslas: 6, goldfish: 6, akitas: 3
+Sue 7: pomeranians: 5, samoyeds: 0, perfumes: 10
+Sue 8: cars: 10, pomeranians: 7, goldfish: 8
+Sue 9: trees: 2, vizslas: 7, samoyeds: 6
+Sue 10: perfumes: 5, pomeranians: 4, children: 9
+Sue 11: vizslas: 5, perfumes: 8, cars: 10
+Sue 12: children: 10, cars: 6, perfumes: 5
+Sue 13: cats: 4, samoyeds: 7, pomeranians: 8
+Sue 14: perfumes: 6, goldfish: 10, children: 7
+Sue 15: perfumes: 4, pomeranians: 3, cars: 6
+Sue 16: perfumes: 7, cars: 9, pomeranians: 6
+Sue 17: goldfish: 3, cars: 6, vizslas: 7
+Sue 18: perfumes: 6, cars: 7, goldfish: 3
+Sue 19: trees: 0, akitas: 3, pomeranians: 8
+Sue 20: goldfish: 6, trees: 2, akitas: 6
+Sue 21: pomeranians: 9, akitas: 9, samoyeds: 9
+Sue 22: vizslas: 2, cars: 9, perfumes: 5
+Sue 23: goldfish: 10, samoyeds: 8, children: 9
+Sue 24: akitas: 4, goldfish: 1, vizslas: 5
+Sue 25: goldfish: 10, trees: 8, perfumes: 6
+Sue 26: vizslas: 5, akitas: 8, trees: 1
+Sue 27: trees: 3, cars: 6, perfumes: 2
+Sue 28: goldfish: 8, trees: 7, akitas: 10
+Sue 29: children: 5, trees: 1, goldfish: 10
+Sue 30: vizslas: 3, perfumes: 8, akitas: 3
+Sue 31: cars: 6, children: 10, perfumes: 7
+Sue 32: cars: 10, perfumes: 3, goldfish: 10
+Sue 33: perfumes: 9, vizslas: 3, akitas: 4
+Sue 34: perfumes: 10, vizslas: 7, children: 8
+Sue 35: cars: 5, perfumes: 5, vizslas: 9
+Sue 36: trees: 9, cars: 9, akitas: 7
+Sue 37: samoyeds: 9, perfumes: 2, cars: 10
+Sue 38: akitas: 7, cars: 5, trees: 5
+Sue 39: goldfish: 8, trees: 9, cars: 10
+Sue 40: trees: 0, cats: 1, pomeranians: 1
+Sue 41: pomeranians: 6, perfumes: 9, samoyeds: 1
+Sue 42: vizslas: 6, akitas: 3, pomeranians: 1
+Sue 43: vizslas: 2, perfumes: 3, pomeranians: 6
+Sue 44: akitas: 5, pomeranians: 0, vizslas: 10
+Sue 45: vizslas: 4, goldfish: 1, cars: 5
+Sue 46: cars: 4, vizslas: 8, cats: 0
+Sue 47: cats: 5, children: 8, pomeranians: 2
+Sue 48: vizslas: 3, perfumes: 6, cats: 0
+Sue 49: akitas: 7, perfumes: 0, trees: 7
+Sue 50: trees: 4, akitas: 10, vizslas: 2
+Sue 51: goldfish: 10, cars: 9, trees: 4
+Sue 52: cars: 5, children: 9, perfumes: 0
+Sue 53: vizslas: 5, cars: 3, cats: 8
+Sue 54: cars: 5, akitas: 1, goldfish: 10
+Sue 55: akitas: 10, vizslas: 2, cars: 6
+Sue 56: cats: 6, trees: 0, cars: 4
+Sue 57: vizslas: 1, akitas: 1, samoyeds: 7
+Sue 58: samoyeds: 6, vizslas: 1, akitas: 7
+Sue 59: akitas: 9, cars: 8, vizslas: 1
+Sue 60: cars: 6, vizslas: 7, goldfish: 0
+Sue 61: pomeranians: 5, akitas: 6, vizslas: 2
+Sue 62: samoyeds: 2, cats: 8, goldfish: 7
+Sue 63: vizslas: 10, goldfish: 7, samoyeds: 9
+Sue 64: perfumes: 2, trees: 1, akitas: 6
+Sue 65: cars: 8, perfumes: 10, vizslas: 9
+Sue 66: akitas: 8, vizslas: 8, perfumes: 8
+Sue 67: goldfish: 7, cars: 9, samoyeds: 9
+Sue 68: perfumes: 2, children: 7, akitas: 1
+Sue 69: perfumes: 7, vizslas: 9, akitas: 1
+Sue 70: samoyeds: 3, vizslas: 1, trees: 1
+Sue 71: vizslas: 8, goldfish: 7, trees: 9
+Sue 72: goldfish: 8, cars: 6, trees: 9
+Sue 73: perfumes: 5, cars: 10, samoyeds: 7
+Sue 74: pomeranians: 4, perfumes: 3, cars: 5
+Sue 75: samoyeds: 1, perfumes: 1, pomeranians: 1
+Sue 76: goldfish: 4, cats: 6, akitas: 7
+Sue 77: perfumes: 5, akitas: 4, vizslas: 8
+Sue 78: perfumes: 4, cats: 3, children: 4
+Sue 79: vizslas: 5, pomeranians: 9, samoyeds: 7
+Sue 80: cars: 3, samoyeds: 5, pomeranians: 7
+Sue 81: vizslas: 2, samoyeds: 4, perfumes: 2
+Sue 82: trees: 1, akitas: 10, vizslas: 9
+Sue 83: vizslas: 0, akitas: 2, samoyeds: 5
+Sue 84: perfumes: 5, vizslas: 7, children: 8
+Sue 85: cats: 3, children: 2, trees: 0
+Sue 86: cars: 3, perfumes: 2, goldfish: 2
+Sue 87: trees: 1, akitas: 7, vizslas: 0
+Sue 88: trees: 1, akitas: 2, samoyeds: 1
+Sue 89: cars: 4, vizslas: 8, akitas: 1
+Sue 90: perfumes: 5, cats: 3, vizslas: 0
+Sue 91: samoyeds: 7, cats: 6, goldfish: 8
+Sue 92: samoyeds: 10, cats: 0, cars: 7
+Sue 93: cars: 6, akitas: 7, samoyeds: 2
+Sue 94: perfumes: 0, goldfish: 6, trees: 9
+Sue 95: cars: 6, pomeranians: 2, samoyeds: 8
+Sue 96: cars: 2, trees: 9, samoyeds: 4
+Sue 97: goldfish: 5, trees: 1, children: 0
+Sue 98: akitas: 9, goldfish: 7, children: 6
+Sue 99: goldfish: 9, akitas: 0, pomeranians: 0
+Sue 100: samoyeds: 6, children: 8, vizslas: 5
+Sue 101: vizslas: 6, cars: 5, goldfish: 4
+Sue 102: vizslas: 6, akitas: 2, perfumes: 6
+Sue 103: samoyeds: 3, akitas: 7, children: 4
+Sue 104: cars: 3, perfumes: 10, cats: 6
+Sue 105: vizslas: 9, pomeranians: 0, cars: 1
+Sue 106: cats: 6, samoyeds: 8, pomeranians: 5
+Sue 107: cars: 7, trees: 4, akitas: 10
+Sue 108: perfumes: 3, vizslas: 1, goldfish: 9
+Sue 109: trees: 6, cars: 8, goldfish: 5
+Sue 110: pomeranians: 2, children: 1, vizslas: 7
+Sue 111: akitas: 0, vizslas: 8, cars: 0
+Sue 112: goldfish: 3, vizslas: 6, akitas: 2
+Sue 113: akitas: 10, pomeranians: 7, perfumes: 7
+Sue 114: cars: 10, cats: 2, vizslas: 8
+Sue 115: akitas: 8, trees: 1, vizslas: 2
+Sue 116: vizslas: 2, akitas: 7, perfumes: 1
+Sue 117: goldfish: 0, vizslas: 10, trees: 9
+Sue 118: trees: 3, cars: 0, goldfish: 0
+Sue 119: perfumes: 7, goldfish: 5, trees: 9
+Sue 120: children: 9, vizslas: 3, trees: 5
+Sue 121: vizslas: 1, goldfish: 7, akitas: 10
+Sue 122: perfumes: 1, cars: 6, trees: 1
+Sue 123: akitas: 2, vizslas: 0, goldfish: 7
+Sue 124: vizslas: 10, pomeranians: 7, akitas: 0
+Sue 125: perfumes: 4, cats: 5, vizslas: 2
+Sue 126: cars: 6, samoyeds: 8, akitas: 3
+Sue 127: trees: 9, goldfish: 7, akitas: 9
+Sue 128: cars: 8, trees: 0, perfumes: 2
+Sue 129: pomeranians: 7, vizslas: 2, perfumes: 6
+Sue 130: vizslas: 9, pomeranians: 3, trees: 6
+Sue 131: vizslas: 7, cars: 9, perfumes: 1
+Sue 132: akitas: 2, pomeranians: 9, vizslas: 7
+Sue 133: trees: 9, pomeranians: 10, samoyeds: 0
+Sue 134: children: 4, akitas: 10, perfumes: 4
+Sue 135: vizslas: 1, cats: 1, trees: 8
+Sue 136: samoyeds: 7, cars: 8, goldfish: 5
+Sue 137: perfumes: 0, children: 1, pomeranians: 10
+Sue 138: vizslas: 4, perfumes: 5, cars: 5
+Sue 139: trees: 2, perfumes: 8, goldfish: 0
+Sue 140: cars: 10, akitas: 5, goldfish: 7
+Sue 141: children: 4, trees: 3, goldfish: 8
+Sue 142: cars: 8, perfumes: 6, trees: 7
+Sue 143: akitas: 6, goldfish: 0, trees: 10
+Sue 144: akitas: 7, pomeranians: 10, perfumes: 10
+Sue 145: trees: 10, vizslas: 3, goldfish: 4
+Sue 146: samoyeds: 4, akitas: 3, perfumes: 6
+Sue 147: akitas: 8, perfumes: 2, pomeranians: 10
+Sue 148: cars: 2, perfumes: 0, goldfish: 8
+Sue 149: goldfish: 6, akitas: 7, perfumes: 6
+Sue 150: cars: 2, pomeranians: 5, perfumes: 4
+Sue 151: goldfish: 1, cars: 5, trees: 0
+Sue 152: pomeranians: 4, cars: 7, children: 1
+Sue 153: goldfish: 8, cars: 1, children: 10
+Sue 154: cars: 6, perfumes: 8, trees: 1
+Sue 155: akitas: 4, perfumes: 6, pomeranians: 2
+Sue 156: pomeranians: 5, cars: 4, akitas: 1
+Sue 157: cats: 5, cars: 9, goldfish: 8
+Sue 158: vizslas: 5, samoyeds: 1, children: 7
+Sue 159: vizslas: 1, perfumes: 3, akitas: 1
+Sue 160: goldfish: 10, pomeranians: 9, perfumes: 5
+Sue 161: samoyeds: 3, trees: 7, cars: 2
+Sue 162: cars: 2, pomeranians: 1, vizslas: 6
+Sue 163: vizslas: 3, perfumes: 5, akitas: 6
+Sue 164: vizslas: 1, trees: 0, akitas: 5
+Sue 165: vizslas: 5, cars: 6, pomeranians: 8
+Sue 166: cars: 10, perfumes: 2, trees: 9
+Sue 167: cars: 10, pomeranians: 6, perfumes: 4
+Sue 168: akitas: 7, trees: 10, goldfish: 7
+Sue 169: akitas: 1, perfumes: 10, cars: 10
+Sue 170: akitas: 5, samoyeds: 8, vizslas: 6
+Sue 171: children: 3, akitas: 2, vizslas: 3
+Sue 172: goldfish: 5, vizslas: 5, perfumes: 9
+Sue 173: perfumes: 5, goldfish: 10, trees: 5
+Sue 174: akitas: 5, vizslas: 2, children: 7
+Sue 175: perfumes: 5, cars: 7, samoyeds: 2
+Sue 176: cars: 8, vizslas: 10, akitas: 7
+Sue 177: perfumes: 7, children: 8, goldfish: 7
+Sue 178: cars: 1, pomeranians: 9, samoyeds: 0
+Sue 179: perfumes: 6, cars: 2, trees: 6
+Sue 180: trees: 3, vizslas: 7, children: 3
+Sue 181: vizslas: 8, samoyeds: 2, trees: 9
+Sue 182: perfumes: 3, cats: 1, children: 5
+Sue 183: akitas: 9, cats: 6, children: 3
+Sue 184: pomeranians: 9, cars: 6, perfumes: 8
+Sue 185: vizslas: 9, trees: 0, akitas: 9
+Sue 186: perfumes: 6, cars: 5, goldfish: 5
+Sue 187: perfumes: 4, cats: 7, vizslas: 2
+Sue 188: akitas: 7, cars: 4, children: 10
+Sue 189: akitas: 0, goldfish: 7, vizslas: 5
+Sue 190: akitas: 5, cars: 5, cats: 6
+Sue 191: cars: 6, children: 0, perfumes: 3
+Sue 192: cats: 2, perfumes: 10, goldfish: 7
+Sue 193: trees: 1, perfumes: 0, cars: 8
+Sue 194: perfumes: 9, children: 4, cats: 6
+Sue 195: akitas: 7, trees: 3, goldfish: 6
+Sue 196: goldfish: 8, cars: 8, samoyeds: 0
+Sue 197: cats: 0, akitas: 10, vizslas: 0
+Sue 198: goldfish: 1, perfumes: 3, cars: 8
+Sue 199: akitas: 10, vizslas: 5, samoyeds: 6
+Sue 200: pomeranians: 9, goldfish: 9, samoyeds: 7
+Sue 201: samoyeds: 0, goldfish: 7, akitas: 6
+Sue 202: vizslas: 0, goldfish: 2, akitas: 1
+Sue 203: goldfish: 3, children: 0, vizslas: 8
+Sue 204: cars: 8, trees: 2, perfumes: 2
+Sue 205: cars: 4, perfumes: 5, goldfish: 8
+Sue 206: vizslas: 3, trees: 2, akitas: 1
+Sue 207: cars: 7, goldfish: 5, trees: 1
+Sue 208: goldfish: 1, cars: 6, vizslas: 8
+Sue 209: cats: 4, trees: 1, children: 0
+Sue 210: cats: 10, children: 0, perfumes: 0
+Sue 211: cars: 4, pomeranians: 7, samoyeds: 5
+Sue 212: cars: 2, pomeranians: 10, trees: 1
+Sue 213: trees: 10, cats: 5, cars: 10
+Sue 214: perfumes: 5, trees: 1, vizslas: 1
+Sue 215: akitas: 10, vizslas: 8, samoyeds: 8
+Sue 216: vizslas: 2, cats: 5, pomeranians: 3
+Sue 217: akitas: 10, perfumes: 0, cats: 10
+Sue 218: trees: 8, cats: 5, vizslas: 2
+Sue 219: goldfish: 10, perfumes: 8, children: 2
+Sue 220: samoyeds: 9, trees: 8, vizslas: 7
+Sue 221: children: 7, trees: 6, cars: 6
+Sue 222: cats: 4, akitas: 5, pomeranians: 0
+Sue 223: trees: 8, goldfish: 2, perfumes: 8
+Sue 224: pomeranians: 9, cars: 8, akitas: 5
+Sue 225: akitas: 10, vizslas: 0, trees: 2
+Sue 226: akitas: 8, cats: 6, cars: 7
+Sue 227: trees: 1, akitas: 3, goldfish: 4
+Sue 228: pomeranians: 6, cats: 3, goldfish: 3
+Sue 229: trees: 10, perfumes: 3, vizslas: 7
+Sue 230: perfumes: 8, cars: 7, akitas: 0
+Sue 231: perfumes: 10, goldfish: 4, cars: 6
+Sue 232: goldfish: 7, trees: 3, cats: 2
+Sue 233: perfumes: 6, trees: 4, akitas: 4
+Sue 234: goldfish: 9, cats: 4, cars: 7
+Sue 235: pomeranians: 6, vizslas: 0, akitas: 6
+Sue 236: samoyeds: 5, cars: 5, children: 4
+Sue 237: vizslas: 10, cars: 4, goldfish: 4
+Sue 238: goldfish: 3, samoyeds: 7, akitas: 2
+Sue 239: cats: 8, children: 2, vizslas: 7
+Sue 240: cars: 9, perfumes: 4, trees: 9
+Sue 241: trees: 8, vizslas: 2, goldfish: 5
+Sue 242: cars: 6, trees: 3, vizslas: 3
+Sue 243: cats: 6, children: 7, cars: 4
+Sue 244: cats: 10, perfumes: 2, goldfish: 7
+Sue 245: akitas: 8, cats: 10, perfumes: 8
+Sue 246: vizslas: 8, akitas: 5, perfumes: 10
+Sue 247: goldfish: 2, vizslas: 5, akitas: 7
+Sue 248: akitas: 3, perfumes: 0, trees: 10
+Sue 249: cats: 4, vizslas: 5, pomeranians: 6
+Sue 250: children: 3, vizslas: 7, perfumes: 2
+Sue 251: cars: 0, pomeranians: 10, perfumes: 0
+Sue 252: akitas: 0, goldfish: 9, cars: 6
+Sue 253: perfumes: 7, cars: 4, samoyeds: 5
+Sue 254: akitas: 9, trees: 10, cars: 4
+Sue 255: samoyeds: 10, children: 6, akitas: 7
+Sue 256: trees: 8, goldfish: 8, perfumes: 8
+Sue 257: goldfish: 3, akitas: 2, perfumes: 6
+Sue 258: cats: 7, trees: 0, vizslas: 1
+Sue 259: perfumes: 7, cars: 7, akitas: 7
+Sue 260: goldfish: 0, vizslas: 0, samoyeds: 2
+Sue 261: vizslas: 2, children: 2, cats: 3
+Sue 262: vizslas: 2, pomeranians: 9, samoyeds: 3
+Sue 263: cats: 1, akitas: 3, vizslas: 1
+Sue 264: pomeranians: 10, trees: 2, goldfish: 7
+Sue 265: samoyeds: 5, trees: 7, perfumes: 4
+Sue 266: perfumes: 10, cars: 1, pomeranians: 3
+Sue 267: trees: 6, goldfish: 1, cars: 0
+Sue 268: cars: 6, samoyeds: 4, pomeranians: 5
+Sue 269: goldfish: 3, vizslas: 3, akitas: 3
+Sue 270: children: 5, cats: 0, cars: 4
+Sue 271: goldfish: 3, perfumes: 8, pomeranians: 7
+Sue 272: samoyeds: 6, cars: 7, perfumes: 10
+Sue 273: trees: 4, cars: 2, vizslas: 7
+Sue 274: samoyeds: 10, perfumes: 9, goldfish: 6
+Sue 275: cars: 4, trees: 2, perfumes: 7
+Sue 276: akitas: 3, perfumes: 9, cars: 9
+Sue 277: akitas: 8, vizslas: 2, cats: 6
+Sue 278: trees: 5, goldfish: 7, akitas: 3
+Sue 279: perfumes: 9, cars: 8, vizslas: 2
+Sue 280: trees: 3, vizslas: 0, children: 0
+Sue 281: cars: 7, trees: 2, cats: 5
+Sue 282: vizslas: 4, cars: 10, cats: 3
+Sue 283: akitas: 10, cats: 3, samoyeds: 9
+Sue 284: trees: 7, children: 5, goldfish: 6
+Sue 285: cars: 2, perfumes: 5, cats: 7
+Sue 286: samoyeds: 5, trees: 10, goldfish: 6
+Sue 287: goldfish: 10, perfumes: 4, trees: 7
+Sue 288: vizslas: 9, trees: 9, perfumes: 0
+Sue 289: trees: 4, goldfish: 9, vizslas: 8
+Sue 290: vizslas: 3, cars: 3, trees: 2
+Sue 291: goldfish: 2, akitas: 2, trees: 2
+Sue 292: children: 1, cars: 0, vizslas: 5
+Sue 293: trees: 5, akitas: 4, goldfish: 6
+Sue 294: akitas: 3, vizslas: 7, pomeranians: 5
+Sue 295: goldfish: 10, vizslas: 3, trees: 1
+Sue 296: cars: 2, trees: 1, akitas: 0
+Sue 297: akitas: 10, vizslas: 6, samoyeds: 2
+Sue 298: children: 5, trees: 1, samoyeds: 9
+Sue 299: perfumes: 9, trees: 6, vizslas: 1
+Sue 300: akitas: 7, pomeranians: 6, vizslas: 6
+Sue 301: cats: 7, children: 6, vizslas: 7
+Sue 302: trees: 2, vizslas: 7, samoyeds: 4
+Sue 303: goldfish: 0, samoyeds: 10, cars: 4
+Sue 304: pomeranians: 9, children: 3, vizslas: 5
+Sue 305: akitas: 8, vizslas: 4, cars: 5
+Sue 306: akitas: 0, perfumes: 2, pomeranians: 10
+Sue 307: akitas: 9, cars: 0, trees: 2
+Sue 308: vizslas: 10, goldfish: 8, akitas: 6
+Sue 309: trees: 0, cats: 6, perfumes: 2
+Sue 310: vizslas: 10, cars: 1, trees: 4
+Sue 311: goldfish: 8, perfumes: 6, cats: 3
+Sue 312: goldfish: 0, children: 1, akitas: 2
+Sue 313: pomeranians: 10, trees: 6, samoyeds: 6
+Sue 314: vizslas: 5, akitas: 4, pomeranians: 2
+Sue 315: goldfish: 7, trees: 0, akitas: 5
+Sue 316: goldfish: 4, vizslas: 5, cars: 7
+Sue 317: perfumes: 7, cats: 10, cars: 4
+Sue 318: samoyeds: 10, cars: 9, trees: 7
+Sue 319: pomeranians: 8, vizslas: 6, cars: 3
+Sue 320: cars: 4, cats: 9, akitas: 4
+Sue 321: cars: 6, trees: 2, perfumes: 6
+Sue 322: goldfish: 1, cats: 2, perfumes: 4
+Sue 323: akitas: 6, cats: 5, cars: 8
+Sue 324: cats: 4, vizslas: 9, akitas: 0
+Sue 325: children: 8, samoyeds: 9, trees: 4
+Sue 326: vizslas: 2, samoyeds: 10, perfumes: 7
+Sue 327: goldfish: 7, pomeranians: 4, akitas: 10
+Sue 328: perfumes: 8, cats: 4, akitas: 10
+Sue 329: trees: 0, cars: 9, goldfish: 3
+Sue 330: trees: 5, samoyeds: 7, perfumes: 8
+Sue 331: cars: 4, perfumes: 2, goldfish: 0
+Sue 332: vizslas: 4, pomeranians: 7, akitas: 1
+Sue 333: akitas: 4, goldfish: 3, perfumes: 0
+Sue 334: samoyeds: 3, akitas: 10, vizslas: 0
+Sue 335: goldfish: 1, akitas: 7, vizslas: 6
+Sue 336: perfumes: 1, goldfish: 1, pomeranians: 8
+Sue 337: children: 5, cars: 4, cats: 4
+Sue 338: vizslas: 5, cars: 10, cats: 3
+Sue 339: trees: 2, goldfish: 3, cars: 1
+Sue 340: trees: 10, goldfish: 6, perfumes: 2
+Sue 341: akitas: 5, trees: 6, cats: 3
+Sue 342: cars: 10, children: 8, goldfish: 0
+Sue 343: cats: 2, akitas: 0, pomeranians: 4
+Sue 344: perfumes: 1, vizslas: 3, cars: 3
+Sue 345: samoyeds: 8, cats: 5, perfumes: 8
+Sue 346: cars: 5, akitas: 10, trees: 2
+Sue 347: vizslas: 9, akitas: 9, cars: 3
+Sue 348: cars: 3, perfumes: 1, pomeranians: 9
+Sue 349: akitas: 1, cars: 4, perfumes: 0
+Sue 350: perfumes: 8, vizslas: 2, trees: 6
+Sue 351: pomeranians: 5, akitas: 9, cats: 8
+Sue 352: pomeranians: 8, vizslas: 3, goldfish: 10
+Sue 353: trees: 2, pomeranians: 0, goldfish: 6
+Sue 354: cats: 5, akitas: 7, goldfish: 6
+Sue 355: goldfish: 6, children: 4, trees: 10
+Sue 356: children: 1, trees: 3, akitas: 7
+Sue 357: trees: 2, samoyeds: 10, goldfish: 3
+Sue 358: samoyeds: 10, cats: 0, goldfish: 0
+Sue 359: perfumes: 3, children: 6, pomeranians: 1
+Sue 360: cars: 10, pomeranians: 1, samoyeds: 5
+Sue 361: samoyeds: 9, pomeranians: 7, perfumes: 6
+Sue 362: goldfish: 6, trees: 8, perfumes: 9
+Sue 363: samoyeds: 10, pomeranians: 9, children: 10
+Sue 364: perfumes: 3, goldfish: 7, cars: 9
+Sue 365: cats: 3, children: 4, samoyeds: 8
+Sue 366: trees: 0, cars: 10, vizslas: 10
+Sue 367: pomeranians: 10, children: 8, perfumes: 2
+Sue 368: cars: 5, vizslas: 0, samoyeds: 3
+Sue 369: trees: 1, goldfish: 8, cars: 8
+Sue 370: vizslas: 0, cars: 2, perfumes: 5
+Sue 371: trees: 2, cars: 3, vizslas: 8
+Sue 372: trees: 10, children: 9, cats: 1
+Sue 373: pomeranians: 3, perfumes: 1, vizslas: 0
+Sue 374: vizslas: 0, perfumes: 6, trees: 0
+Sue 375: vizslas: 7, pomeranians: 1, akitas: 10
+Sue 376: vizslas: 8, trees: 2, cars: 10
+Sue 377: perfumes: 9, cats: 5, goldfish: 5
+Sue 378: cats: 0, akitas: 10, perfumes: 9
+Sue 379: cars: 4, akitas: 1, trees: 1
+Sue 380: cars: 4, perfumes: 5, trees: 3
+Sue 381: goldfish: 3, akitas: 5, samoyeds: 9
+Sue 382: goldfish: 7, perfumes: 5, trees: 5
+Sue 383: akitas: 4, cats: 6, cars: 8
+Sue 384: children: 6, goldfish: 10, akitas: 7
+Sue 385: akitas: 7, vizslas: 5, perfumes: 10
+Sue 386: children: 7, vizslas: 10, akitas: 10
+Sue 387: goldfish: 6, akitas: 7, trees: 2
+Sue 388: vizslas: 6, trees: 1, akitas: 2
+Sue 389: cars: 5, vizslas: 3, akitas: 7
+Sue 390: vizslas: 4, cats: 8, perfumes: 7
+Sue 391: akitas: 3, trees: 0, children: 2
+Sue 392: cats: 7, cars: 3, children: 9
+Sue 393: trees: 10, vizslas: 3, goldfish: 7
+Sue 394: perfumes: 0, goldfish: 7, akitas: 4
+Sue 395: cats: 6, cars: 7, vizslas: 0
+Sue 396: vizslas: 4, perfumes: 6, goldfish: 5
+Sue 397: pomeranians: 8, trees: 1, akitas: 9
+Sue 398: goldfish: 7, pomeranians: 6, samoyeds: 9
+Sue 399: perfumes: 10, cars: 1, trees: 8
+Sue 400: trees: 0, goldfish: 9, children: 6
+Sue 401: trees: 1, cars: 6, pomeranians: 8
+Sue 402: perfumes: 9, cars: 0, vizslas: 10
+Sue 403: samoyeds: 4, akitas: 1, vizslas: 9
+Sue 404: perfumes: 0, trees: 2, cars: 4
+Sue 405: akitas: 0, perfumes: 5, samoyeds: 4
+Sue 406: akitas: 8, vizslas: 6, children: 2
+Sue 407: children: 1, trees: 8, goldfish: 10
+Sue 408: pomeranians: 4, trees: 10, cars: 9
+Sue 409: perfumes: 5, vizslas: 5, akitas: 4
+Sue 410: trees: 1, akitas: 10, vizslas: 6
+Sue 411: samoyeds: 0, goldfish: 9, perfumes: 7
+Sue 412: goldfish: 7, samoyeds: 10, trees: 1
+Sue 413: samoyeds: 0, pomeranians: 10, vizslas: 6
+Sue 414: children: 2, cars: 10, samoyeds: 2
+Sue 415: trees: 2, goldfish: 8, cars: 0
+Sue 416: samoyeds: 4, goldfish: 9, trees: 2
+Sue 417: trees: 8, akitas: 10, perfumes: 3
+Sue 418: samoyeds: 9, goldfish: 2, cars: 1
+Sue 419: akitas: 2, perfumes: 8, trees: 2
+Sue 420: children: 3, goldfish: 6, perfumes: 5
+Sue 421: akitas: 8, perfumes: 2, samoyeds: 6
+Sue 422: vizslas: 10, akitas: 4, pomeranians: 3
+Sue 423: cats: 8, perfumes: 3, trees: 4
+Sue 424: cars: 2, children: 4, pomeranians: 8
+Sue 425: pomeranians: 4, samoyeds: 2, goldfish: 4
+Sue 426: perfumes: 6, cars: 4, goldfish: 4
+Sue 427: akitas: 0, goldfish: 7, perfumes: 5
+Sue 428: perfumes: 4, cars: 3, akitas: 5
+Sue 429: trees: 0, vizslas: 0, goldfish: 1
+Sue 430: perfumes: 4, vizslas: 2, cars: 7
+Sue 431: goldfish: 7, pomeranians: 8, trees: 0
+Sue 432: goldfish: 7, children: 9, trees: 3
+Sue 433: akitas: 1, vizslas: 10, trees: 2
+Sue 434: perfumes: 2, cars: 4, goldfish: 10
+Sue 435: pomeranians: 6, vizslas: 9, trees: 1
+Sue 436: cars: 9, trees: 0, goldfish: 0
+Sue 437: trees: 1, goldfish: 1, vizslas: 8
+Sue 438: goldfish: 7, samoyeds: 8, children: 2
+Sue 439: children: 1, cats: 7, vizslas: 8
+Sue 440: cats: 2, pomeranians: 6, goldfish: 4
+Sue 441: perfumes: 7, cats: 3, vizslas: 6
+Sue 442: akitas: 4, samoyeds: 5, cars: 2
+Sue 443: akitas: 3, perfumes: 3, cats: 9
+Sue 444: perfumes: 10, akitas: 6, trees: 0
+Sue 445: cars: 5, children: 9, perfumes: 8
+Sue 446: vizslas: 10, cars: 3, perfumes: 5
+Sue 447: children: 9, perfumes: 1, cars: 10
+Sue 448: akitas: 0, goldfish: 8, trees: 3
+Sue 449: cars: 7, akitas: 8, children: 3
+Sue 450: cars: 4, akitas: 9, cats: 0
+Sue 451: perfumes: 4, samoyeds: 5, goldfish: 6
+Sue 452: perfumes: 10, akitas: 1, cars: 7
+Sue 453: trees: 1, goldfish: 3, vizslas: 6
+Sue 454: goldfish: 8, pomeranians: 6, trees: 10
+Sue 455: akitas: 5, vizslas: 8, goldfish: 10
+Sue 456: cats: 5, trees: 4, samoyeds: 0
+Sue 457: perfumes: 8, cars: 0, cats: 3
+Sue 458: akitas: 1, trees: 10, vizslas: 2
+Sue 459: vizslas: 6, akitas: 3, children: 10
+Sue 460: perfumes: 7, trees: 9, goldfish: 8
+Sue 461: children: 6, vizslas: 4, perfumes: 5
+Sue 462: vizslas: 6, akitas: 8, perfumes: 9
+Sue 463: goldfish: 8, cars: 4, trees: 10
+Sue 464: pomeranians: 8, cars: 5, vizslas: 0
+Sue 465: cats: 10, goldfish: 7, akitas: 1
+Sue 466: cats: 2, children: 1, cars: 6
+Sue 467: perfumes: 3, samoyeds: 6, cars: 0
+Sue 468: samoyeds: 10, pomeranians: 6, trees: 2
+Sue 469: children: 2, perfumes: 2, pomeranians: 4
+Sue 470: cats: 1, perfumes: 5, vizslas: 9
+Sue 471: vizslas: 5, perfumes: 2, akitas: 7
+Sue 472: samoyeds: 8, goldfish: 6, cats: 1
+Sue 473: goldfish: 10, perfumes: 9, cars: 4
+Sue 474: samoyeds: 0, cars: 4, vizslas: 4
+Sue 475: trees: 2, cars: 7, akitas: 8
+Sue 476: vizslas: 3, perfumes: 5, goldfish: 1
+Sue 477: cats: 7, cars: 4, trees: 1
+Sue 478: vizslas: 8, akitas: 3, goldfish: 0
+Sue 479: cars: 6, cats: 3, perfumes: 2
+Sue 480: goldfish: 1, children: 9, vizslas: 3
+Sue 481: pomeranians: 5, vizslas: 1, cars: 10
+Sue 482: children: 5, perfumes: 5, cats: 1
+Sue 483: perfumes: 2, goldfish: 7, trees: 6
+Sue 484: akitas: 2, goldfish: 4, perfumes: 10
+Sue 485: samoyeds: 3, goldfish: 0, akitas: 1
+Sue 486: trees: 8, vizslas: 9, goldfish: 0
+Sue 487: goldfish: 8, samoyeds: 0, trees: 0
+Sue 488: perfumes: 7, cars: 5, trees: 0
+Sue 489: vizslas: 3, pomeranians: 2, perfumes: 5
+Sue 490: cars: 5, perfumes: 5, akitas: 5
+Sue 491: children: 8, trees: 1, pomeranians: 4
+Sue 492: pomeranians: 0, akitas: 1, vizslas: 8
+Sue 493: akitas: 10, perfumes: 10, samoyeds: 8
+Sue 494: perfumes: 6, vizslas: 4, cats: 6
+Sue 495: children: 6, pomeranians: 5, samoyeds: 4
+Sue 496: vizslas: 1, trees: 5, akitas: 1
+Sue 497: vizslas: 10, perfumes: 10, pomeranians: 3
+Sue 498: samoyeds: 3, trees: 2, cars: 5
+Sue 499: cats: 6, children: 3, perfumes: 0
+Sue 500: pomeranians: 10, cats: 3, vizslas: 5
diff --git a/16/solution.py b/16/solution.py
new file mode 100644
index 0000000..b7ebc5c
--- /dev/null
+++ b/16/solution.py
@@ -0,0 +1,77 @@
+from dataclasses import dataclass
+
+@dataclass
+class SueQuality:
+ quality: int | None = None
+
+ def __eq__(self, other):
+ return self.quality is None or other.quality is None or self.quality == other.quality
+
+ def __gt__(self, other):
+ return self.quality is None or other.quality is None or self.quality > other.quality
+ def __lt__(self, other):
+ return self.quality is None or other.quality is None or self.quality < other.quality
+
+@dataclass
+class Sue:
+ children: SueQuality = SueQuality()
+ cats: SueQuality = SueQuality()
+ samoyeds: SueQuality = SueQuality()
+ pomeranians: SueQuality = SueQuality()
+ akitas: SueQuality = SueQuality()
+ vizslas: SueQuality = SueQuality()
+ goldfish: SueQuality = SueQuality()
+ trees: SueQuality = SueQuality()
+ cars: SueQuality = SueQuality()
+ perfumes: SueQuality = SueQuality()
+
+ def cmp(self, other: 'Sue') -> bool:
+ for attr in self.__dict__:
+ if getattr(self, attr) != getattr(other, attr):
+ return False
+ return True
+
+ def cmp2(self, other: 'Sue') -> bool:
+ return (
+ self.children == other.children and
+ self.cats > other.cats and
+ self.samoyeds == other.samoyeds and
+ self.pomeranians < other.pomeranians and
+ self.akitas == other.akitas and
+ self.vizslas == other.vizslas and
+ self.goldfish < other.goldfish and
+ self.trees > other.trees and
+ self.cars == other.cars and
+ self.perfumes == other.perfumes
+ )
+
+ @staticmethod
+ def from_string(s: str) -> tuple[int, 'Sue']:
+ number, rest = s.split(': ', 1)
+ number = int(number.split(' ')[1])
+ properties = {p[0]: SueQuality(int(p[1])) for p in (prop.split(': ') for prop in rest.split(', '))}
+ return number, Sue(**properties)
+
+def part1(sues: list[Sue]) -> int:
+ desired = Sue(
+ children=SueQuality(3), cats=SueQuality(7), samoyeds=SueQuality(2),
+ pomeranians=SueQuality(3), akitas=SueQuality(0), vizslas=SueQuality(0),
+ goldfish=SueQuality(5), trees=SueQuality(3), cars=SueQuality(2),
+ perfumes=SueQuality(1)
+ )
+ return next(number for number, sue in sues.items() if sue.cmp(desired))
+
+def part2(sues: list[Sue]) -> int:
+ desired = Sue(
+ children=SueQuality(3), cats=SueQuality(7), samoyeds=SueQuality(2),
+ pomeranians=SueQuality(3), akitas=SueQuality(0), vizslas=SueQuality(0),
+ goldfish=SueQuality(5), trees=SueQuality(3), cars=SueQuality(2),
+ perfumes=SueQuality(1)
+ )
+ return next(number for number, sue in sues.items() if sue.cmp2(desired))
+
+if __name__ == '__main__':
+ with open('input') as f:
+ sues = {number: sue for number, sue in (Sue.from_string(line) for line in f)}
+ print(part1(sues))
+ print(part2(sues))
diff --git a/17/input b/17/input
new file mode 100644
index 0000000..f796965
--- /dev/null
+++ b/17/input
@@ -0,0 +1,20 @@
+11
+30
+47
+31
+32
+36
+3
+1
+5
+3
+32
+36
+15
+11
+46
+26
+28
+1
+19
+3
diff --git a/17/solution.py b/17/solution.py
new file mode 100644
index 0000000..fa3e985
--- /dev/null
+++ b/17/solution.py
@@ -0,0 +1,30 @@
+from collections import Counter
+from functools import cache
+
+def part1(containers: list[int]) -> int:
+ @cache
+ def combinations(index: int, remaining: int) -> int:
+ if index == len(containers):
+ return 1 if remaining == 0 else 0
+ return combinations(index + 1, remaining) + combinations(index + 1, remaining - containers[index])
+ return combinations(0, 150)
+
+def part2(containers: list[int]) -> int:
+ @cache
+ def min_used(index: int, remaining: int, used: int) -> int | float:
+ if index == len(containers):
+ return used if remaining == 0 else float('inf')
+ return min(min_used(index + 1, remaining, used), min_used(index + 1, remaining - containers[index], used + 1))
+ min_used = min_used(0, 150, 0)
+ @cache
+ def count_min(index: int, remaining: int, used: int) -> int | float:
+ if index == len(containers):
+ return 1 if (remaining == 0 and used == min_used) else 0
+ return count_min(index + 1, remaining, used) + count_min(index + 1, remaining - containers[index], used + 1)
+ return count_min(0, 150, 0)
+
+if __name__ == '__main__':
+ with open('input') as f:
+ containers = list(sorted((int(line.strip()) for line in f), reverse=True))
+ print(part1(containers))
+ print(part2(containers))
diff --git a/18/input b/18/input
new file mode 100644
index 0000000..b2a6ab1
--- /dev/null
+++ b/18/input
@@ -0,0 +1,100 @@
+####.#.##.###.#.#.##.#..###.#..#.#.#..##....#.###...##..###.##.#.#.#.##...##..#..#....#.#.##..#...##
+.##...##.##.######.#.#.##...#.#.#.#.#...#.##.#..#.#.####...#....#....###.#.#.#####....#.#.##.#.#.##.
+###.##..#..#####.......#.########...#.####.###....###.###...#...####.######.#..#####.#.###....####..
+....#..#..#....###.##.#.....##...#.###.#.#.#..#.#..##...#....#.##.###.#...######......#..#.#..####.#
+..###.####..#.#.#..##.#.#....#......#.##.##..##.#.....##.###.#..###...###.#.##..#.#..###....####.#.#
+#.#...#......####.#..##.####.#.#.#...##..###.##.#...#..#..###....#.#....#..##..#....##.....##.#...#.
+....##.#.#.#.##..##...##..##..#....#....###...####.###...##.#...#..#....##.....#..#.#####.###.###.##
+#...##..#.#..#....#..########.##....##..##.###..#.#..#..#.##.##.#..##..######....####..#####.#.###..
+.####...######.#..#.##.#.#..####...####.##.#.#......#...##....##..#...###..#.####......###......#.##
+.####.###..#..#####.##...###......#...###..#..##..#.#....##.##.#.##.###..#..#..###.#..#.#....####.##
+#..#..##.##.##.###.#.##.##.#.#.#....#....#.####.#.##...#####...###.#####.#.#.#....####..###..###..##
+#.##....#...########..##...#.#.##.......#.#..##...####...#.####.####..##...##.#....###.#.####...#.##
+#.#...##..#.##.##..##....#.....##.##.....#...###...#..#...####.##.####..#...##..##.##.##.##..##...##
+.#..###...#.#.....#######..##.###....##..#.##.#......###.##....#......###...#.##....#.....##......##
+..##....#.###...###..####.##..#..##.##......##.#.....#...#..#..##...###..#.####...#...#..##.#..##..#
+...#.#.#...#.#..#.##....##..#...#.##..#......#.#.....#####.##.#...#######.#.#..#.####..###.....###.#
+.#....#.#.##..####.#####..#.#######..#.##.###...##.##....##..###..#.##.###.......#....#..######.####
+#..#.##.##..#..#..##.####.#.#.#.#..#.##...#..######....#.##.#..##.##.######.###.###.###...#.....#.#.
+.#.......#...#.####.##...#####..##..#.#....##..#.#.#.####.#.##....#..##.##..#.###.....#.##.##.#.##.#
+#..##..##...#....#.##.#...#.#....#......####...##..#...##.##.#..#########..#..#.##.##..#.#.#######..
+#.......#####..###..######.#..##.#.#####..##...###...#.####.##...###..#.#.#####....#...#.##...#.#..#
+.##..#...#####.##.##......#...#.#.#.###.#.#.#...##.#..#....###.....#..#.#.###......#####.###.#..##.#
+.....###.#.#.#..##...#...###..#...#.#.##..###.##.#####.##..#.#.#.#.#####....#.#.#####...##.#..#.#.#.
+###...##.#..#.####..##.#..##.#.#.#...#.#..#..##..##..#.#.#.#.##...##..#..#.....#....#####.#.#.####.#
+....##....#.#.....#...###.#...##..##.##..#..###..##.###..#####..#...#####.##.#..#.#.#.###...####.###
+##.##.##.#...#..#...........##.##.###.#...###.####.#..#..#...#..#..####.#.###########..#.###.###.#.#
+##.##..##.####..###...##...#....###.###.#..##..#..#.###.#..####.#..##.#.#...#..#.#.##.##...#...#....
+..##...#.#.##....##...#.#.#......##.##.#.#.####.####....####.#.###.##.#.#..####..#..######..#..#.#..
+####.#.##.......##.###....##.#..####.#.#######..#...###..##.##..#...#...####........#.#..##...#....#
+#..#.#.....#..#.###..#.#...###..##...#.#..#.#.##..#...##.##.##.#.#.#..#.####.########....########..#
+#...#..##.##..#.#.#.##.##.##.#..#..#.##....#....###.#.###.#.#..#....#...##..#.....####...##.#..#...#
+.###...##...####....###.##.#..####...##.#.##.#..##..##....#....##.#...#..#..##..##..##.#...#...###..
+.#..##.#..##..####..#.#.##..###.#...#....##.###...#.###....#.#.#........#..#.#.#..##..#####..#..#.#.
+.#.##.....#..#...#.##.....#.##..#..#....#..#..#....#.##..##...#.##.##..##..#.#.#.##..####.##..#.#..#
+...###.#.....#...#.##.#.###.#...##..#.###..#..#..#.#..#...###.#.##.##.##.#.##.#####.#..#.#..#.#...##
+#.#.#.#.##.#.....##..#.###......##.#.##..#...#.########.##.###..#..#..##..##.#..##..###.#.###...#.#.
+..##...##...#...###.#..##..#..#..#.#.##..##......##..##.....##.....####..#.##......#..####...###..##
+##.......#..##....###...###......#.##.##....######..###.##...##.#...#...#.....#.###.#.#..#.##..#..#.
+#.#..#..#.#####.##.##.###..#...###.....#..##..####...#.#.###....#..#.#.###.####..#.#........##.#....
+..###.#...##.#.####.#.##.##.....##...#.##.#.###.#.#..##.#..##..#..##.##....#.#####.##..#######.....#
+###.###..##.#..##...#####..##.####....#.##......##......#.#....##.####.#.#.#.###...#..####..#.######
+#..###...#.#.......#..####.####...#....###.###...#.##..##..#..##.##.......####.##...#.#.#.##.#.#..#.
+..#...#..###.##..#.#.#.##..#..#.#.......###..###..#####.#.#.#.#.#..#.#.#.#..###....#.####..###...#..
+...######.###....#..####.####......#...#.###.#....#...####.##........##...##.#..##.###.#..#..##..###
+.#..###.####.###.#.#..#..#..#.##.#.#.###.##..####.#####..##....##.#.##...###.####.#.#######.#..#..#.
+.#..##.#..##..#...##...#..#..##.#.#....##.##...###.#.#...##..##..#.###.#.#.#.#...#....#.#..#.#.###.#
+.###..#.#..####.#########...####....####.#.##...##.##..#.##.#........#.....###.###.######.##.....###
+..##.##..##..#.####.#..#####.#....##.##.#####.....#.#......##...#####..####....###..#.#...#..####..#
+.#..##..##.##.##.##.#.###.###.#..#..#...###.#.##..##...##...###...##.###..#.#.#####.#.#.##....#.##..
+...#.#....##.#.....###.##...#..##....#...###....#..#.###...##.#...###.#....#...##..###.#.....##....#
+.#######..#...##.#.###.##.#.###...##......#.###.#...#.###.#.#.#..#..#####..#########...##..##...#..#
+.#..#.##...#.#..#.##..#.#.#.##.....####.#..#.###..##.#.#.#...#....#.#..##.######...#.#..##.##...#..#
+#.#######.#####..#####.##.##.#.#.##.###..#....####.#..##.##.######..###...#.#..#.####.##.##....####.
+...##..#...##..#..#.....#.##...#.....##.#####.###.########.######..#...###..#.##.#.#.##..#.#.##..##.
+#..#..#.#....###.#...##..####.#.##..#.####.###..##.#...#.###.#..#.##..#######.#...#..#.#..##.#....##
+..#.##.#.####..##.###.###..#.##.#.####..##....##.###.#..##.#.###.###.##.##.#####..#.#...########....
+.#.#.###..###...#...#..##.##......#..#...#.#.#.######.#.#...##..##........#....###..##...#..##.##...
+##..#....##.###...##.#.##.##.##..#....#.#.#..#..####.##..#...#...#..#..#####.###...#..###..#...#.#..
+##.#.#.##.###.....######.#.....#...#.##....###.#.##.#.#.##..##.######.#####....#.#####...##.#..###.#
+######.#...####..###..##..#..##...#.#....##.#...##...#.....#...##....#.##..###..###...###..#..######
+.....##.........#####.#.##..#..#.#.#.#.##...#....#.....###.########...#..####..#...#...##..#.##.##.#
+#..###...#.##.##.#.#..####.#.....##..###....##..#...#.#...##.##..###..####...#.####..##..#..##..#...
+#.####.#..##.#..#.....#..#.#..###...######.#.........####....###..#.#.#.##.#..#...#..####.....##..#.
+..##....#.###.......##.#...#.####..##....##.#..#....#######...####.##..#####.#.#.#.#.##..##..#.#.#..
+#.#.#.###..#..#.#..#.#.###....#...#####.###...........#.#....#####...#..####....#...###.#..#..####..
+.......#.####.##...#..#.##..###..#..#.#.#.#.###....#....#.#.#..#.#..##.#####.#.....#.##.#.###.###.##
+..###...#..#...####.#..##..##.#.#..#...#.#..#....###.#..####..######...####.#.##..#.#..###...##.####
+..#.###..#.#...##...#.#....#..#...#.#..##.######.######.#.##.....#..##.#..###..#..#.##.###...#..#.##
+####..##.####.....#...#.#.###..#...####.###.#.#.#.......##...#....#..#....#.#......###...#####.#.##.
+#..##..#..#.####...#####.#.###.##.#.##.....#.#..#.##........######.#.#.###....##.##..##..########.##
+#.#....###.##....#######.#...#.#.#.#..##.#.##...#.###...#.#.#..#.#..####.#.#..#..#.##.####....#..##.
+####.##....#.......###..#..##.#.#.##..#...#...##.###....##..###.#.#...#..#.....##.###.##...###....##
+..##.#..#....######..#.##.#.#...##..####.#####...##.#..###.##...#..####..###.##..##.##.#####.#..#.#.
+.#.##..#..##.#.###.###....#.#..#....#...###.##.#.#.####.....#....#...#.....#....#.#.###.#..#.##..###
+..###.#.#.##...##.##.##.#...#####.#..##.#....##..####...###..#....#.##...#........#####.#.###.#..#..
+....#..##..##....#.#....#.#..##...##.#...##.###.#.#..###..##.##.##..#.#.#..#.#.##.......#.##.###..#.
+.#..##.##.####.##....##.##.....###..##.#.##...#..###....###.###....#.#....#....#.##.#.##.#.##.....##
+#.#..#.##.###.#.######.....###.#..#...#.#.....##.###.#...#.#..###.#.....##.###.#.###.####..#####.#..
+#.#.##......#.##.#.#..##....#..###.#.###...##...###.#..#.##...#..#.##..##.#...######.##.....#####.##
+#.#..#####....###.###...#.......#....###.##...#..#.##..#...#####..#..#.##......###...#...###..#.#..#
+#.##..##.##.#..#.##.##..#.###.##.........###.#.#..#.#.....#.#...#.#.##.#.##.#...#...####.#.......##.
+.#...####.##..#..##....####..######...#.#..##.##.....#####.#...#..#.####.#######...#.#####..#.###...
+.#..######.#.##..##...##.....###.#..##..#...####..###...###.###..#..######.#....########..#####...#.
+#..##.......#####...###..#.#.##.#..###.#...##.#..#.##.###...###...##.#..##..########..#.#..##..#.###
+.#.#..#...#.#..#..##...#.#.##...###..#..#....###.#....#.##....###.###..##..#.#.####..####.#######.##
+...##..##.##.###.##.###...##.#.#.....##.####..#..##.#..#.####...##..#..#.##...##...###.##.#.......##
+.#.....#.##..#.#.....#.##.##..###..#....###...#.#....##########.##.###.#...#.####..####.#..#.#..###.
+.##.#.#.##..#..###.###.##.#########.#.#.#.#.##.###..##..#.##.####......#####...#..####.#.##..#####.#
+..#....###...##....#.###..##..#..####.##..####.#..####.###.#....####.....#.###..##...##..####...##.#
+.###.....###.##.##..###.###.....##..#.######.#.#..##..#.##.#..#.#.#....#...#.#.#...#...##....#..##.#
+..##....#..#####....#..####.#.#...##.#....##..##.###.###....###......#...#.#####.......#...#.....###
+###.#..#.#.##..#..#...#.#....###.##.#.###.#...#.##.#..#.#.......#.#.#.###.####.###....#..##..#####..
+.#..#######.#..###.#.##.#####.#####...##..#.####.#.#.##..###...#..##.##..#.#.###..#....#..#...###.#.
+..#####..#.##.....###..##.#...#.#.#..#######.#..#...#.##.##.#.#....####...###..##...#....####.#..#.#
+.####..#.#.##.###.#.##.....#..##.#.....###.....#..##...#....###.###..#......###.#.#.#.##.#.##..#...#
+##.#..##.#..##...#.#....##..######..#.....#..#...#####....##......####.##..#...##..#.##.#.#######..#
+##..####.#...##...#.#####.#.#..#....#.#..##.####.#..######.#..#..#.......#####..#..#..###.##...##.##
+#.####......#.###...#..####.#..##.##..#.#...##.###.#...#####..####.#..#.#.....#.##...###...#.#....##
+###.#.#.##.######......#.#.#.#.#........#..#..###.#.#.#..#.........#..#....#.#..#..#..###.##......##
+##.#########...#...###..#.###.....#.#.##.........###....#.####.#...###.#..##..#.###..#..##......#.##
diff --git a/18/solution.py b/18/solution.py
new file mode 100644
index 0000000..18f378a
--- /dev/null
+++ b/18/solution.py
@@ -0,0 +1,38 @@
+from collections import defaultdict
+
+State = set[tuple[int, int]]
+
+def step(state: State) -> State:
+ def next_cell_state(x: int, y: int) -> bool:
+ neighbors = sum((x + dx, y + dy) in state for dx in (-1, 0, 1) for dy in (-1, 0, 1) if (dx, dy) != (0, 0))
+ if (x, y) in state:
+ return neighbors == 2 or neighbors == 3
+ else:
+ return neighbors == 3
+ next_state: State = set()
+ for x in range(100):
+ for y in range(100):
+ if next_cell_state(x, y):
+ next_state.add((x, y))
+ return next_state
+
+def part1(state: State) -> int:
+ for i in range(100):
+ state = step(state)
+ return len(state)
+
+def part2(state: State) -> int:
+ for i in range(100):
+ state = step(state)
+ state |= {(0, 0), (0, 99), (99, 0), (99, 99)}
+ return len(state)
+
+if __name__ == '__main__':
+ with open('input') as f:
+ state: State = set()
+ for y, line in enumerate(f):
+ for x, c in enumerate(line.strip()):
+ if c == '#':
+ state.add((x, y))
+ print(part1(state))
+ print(part2(state))
diff --git a/19/input b/19/input
new file mode 100644
index 0000000..a245944
--- /dev/null
+++ b/19/input
@@ -0,0 +1,45 @@
+Al => ThF
+Al => ThRnFAr
+B => BCa
+B => TiB
+B => TiRnFAr
+Ca => CaCa
+Ca => PB
+Ca => PRnFAr
+Ca => SiRnFYFAr
+Ca => SiRnMgAr
+Ca => SiTh
+F => CaF
+F => PMg
+F => SiAl
+H => CRnAlAr
+H => CRnFYFYFAr
+H => CRnFYMgAr
+H => CRnMgYFAr
+H => HCa
+H => NRnFYFAr
+H => NRnMgAr
+H => NTh
+H => OB
+H => ORnFAr
+Mg => BF
+Mg => TiMg
+N => CRnFAr
+N => HSi
+O => CRnFYFAr
+O => CRnMgAr
+O => HP
+O => NRnFAr
+O => OTi
+P => CaP
+P => PTi
+P => SiRnFAr
+Si => CaSi
+Th => ThCa
+Ti => BP
+Ti => TiTi
+e => HF
+e => NAl
+e => OMg
+
+CRnCaCaCaSiRnBPTiMgArSiRnSiRnMgArSiRnCaFArTiTiBSiThFYCaFArCaCaSiThCaPBSiThSiThCaCaPTiRnPBSiThRnFArArCaCaSiThCaSiThSiRnMgArCaPTiBPRnFArSiThCaSiRnFArBCaSiRnCaPRnFArPMgYCaFArCaPTiTiTiBPBSiThCaPTiBPBSiRnFArBPBSiRnCaFArBPRnSiRnFArRnSiRnBFArCaFArCaCaCaSiThSiThCaCaPBPTiTiRnFArCaPTiBSiAlArPBCaCaCaCaCaSiRnMgArCaSiThFArThCaSiThCaSiRnCaFYCaSiRnFYFArFArCaSiRnFYFArCaSiRnBPMgArSiThPRnFArCaSiRnFArTiRnSiRnFYFArCaSiRnBFArCaSiRnTiMgArSiThCaSiThCaFArPRnFArSiRnFArTiTiTiTiBCaCaSiRnCaCaFYFArSiThCaPTiBPTiBCaSiThSiRnMgArCaF
diff --git a/19/solution.py b/19/solution.py
new file mode 100644
index 0000000..91106b3
--- /dev/null
+++ b/19/solution.py
@@ -0,0 +1,130 @@
+import re
+from collections import defaultdict, Counter, deque
+from functools import cache
+
+Chemical = tuple # [int, ...]
+
+def part1(reactions: dict[int, set[Chemical]], target: Chemical) -> int:
+ outputs: set[Chemical] = set()
+ counts: Counter[int] = Counter(target)
+ for chemical, results in reactions.items():
+ for result in results:
+ for i in range(counts[chemical]):
+ output: list[int] = list()
+ n: int = 0
+ for c in target:
+ if c == chemical:
+ if n == i:
+ output.extend(result)
+ else:
+ output.append(c)
+ n += 1
+ else:
+ output.append(c)
+ outputs.add(tuple(output))
+ return len(outputs)
+
+# def part2(reactions: dict[int, set[Chemical]], target: Chemical) -> int:
+# unreactions: dict[Chemical, Chemical] = dict()
+# for chemical, results in reactions.items():
+# for result in results:
+# unreactions[result] = chemical
+# @cache
+# def path_len(c: Chemical) -> int:
+# if c == (0,):
+# print('found e')
+# return 0
+# depth = float('inf')
+# for search, replace in unreactions.items():
+# for i in range(len(c)):
+# for j, comp in enumerate(search):
+# if i + j >= len(c):
+# break
+# if c[i + j] != comp:
+# break
+# else:
+# new = c[:i] + (replace,) + c[i + len(search):]
+# depth = min(depth, path_len(new))
+# if depth == float('inf'):
+# return depth
+# return depth + 1
+# l = path_len(target)
+# print(path_len.cache_info())
+# return l
+
+# def part2(reactions: dict[int, set[Chemical]], target: Chemical) -> int:
+# unreactions: dict[Chemical, Chemical] = dict()
+# for chemical, results in reactions.items():
+# for result in results:
+# unreactions[result] = chemical
+# queue: deque[tuple[Chemical, int]] = deque([(target, 0)])
+# while queue:
+# c, depth = queue.popleft()
+# if c == (0,):
+# return depth
+# for search, replace in unreactions.items():
+# for i in range(len(c) - len(search) + 1):
+# for j, comp in enumerate(search):
+# if c[i + j] != comp:
+# break
+# else:
+# new = c[:i] + (replace,) + c[i + len(search):]
+# print(f'{c} -> {new}')
+# queue.append((new, depth + 1))
+# #print(queue)
+
+def part2(reactions: dict[int, set[Chemical]], target: Chemical) -> int:
+ unreactions: dict[Chemical, Chemical] = dict()
+ for chemical, results in reactions.items():
+ for result in results:
+ unreactions[result] = chemical
+ def path_len(c: Chemical) -> int:
+ if c == (0,):
+ return 0
+ for search, replace in unreactions.items():
+ for i in range(len(c)):
+ for j, comp in enumerate(search):
+ if i + j >= len(c):
+ break
+ if c[i + j] != comp:
+ break
+ else:
+ new = c[:i] + (replace,) + c[i + len(search):]
+ l = path_len(new)
+ if l is not None:
+ return l + 1
+ return None
+ return path_len(target)
+
+if __name__ == '__main__':
+ chem_id: dict[str, int] = dict(e=0)
+ next_chem_id: int = 1
+ reactions: defaultdict[int, set[Chemical]] = defaultdict(set)
+ chempattern: re.Pattern = re.compile(r'e|[A-Z][a-z]?')
+
+ def add_chem(chem: str) -> int:
+ global next_chem_id
+ if chem not in chem_id:
+ chem_id[chem] = next_chem_id
+ next_chem_id += 1
+ return chem_id[chem]
+ with open('input_reddit') as f:
+ for line in f:
+ if line == '\n':
+ break
+ chem, expansion = line.strip().split(' => ')
+ reactions[add_chem(chem)].add(tuple(add_chem(c) for c in chempattern.findall(expansion)))
+
+ target = tuple(add_chem(c)
+ for c in chempattern.findall(next(f).strip()))
+ test_reactions: dict[int, set[Chemical]] = {
+ 0: set([(1,), (2,)]),
+ 1: set([(1, 2), (2, 1)]),
+ 2: set([(1, 1)]),
+ # 0: set([(0, 1), (1, 0)]),
+ # 1: set([(0, 0)]),
+ }
+ test_target: Chemical = (1, 2, 1, 2, 1, 2)
+ # test_target: Chemical = (0, 1, 0)
+ print(part1(reactions, target))
+ print(part2(reactions, target))
diff --git a/2/1.py b/2/1.py
new file mode 100644
index 0000000..028dd04
--- /dev/null
+++ b/2/1.py
@@ -0,0 +1,3 @@
+from itertools import combinations
+from functools import reduce
+print(sum(min(box) + 2 * sum(box) for box in ([int(a) * int(b) for a, b in combinations(l.split('x'), 2)] for l in open('input'))))
diff --git a/2/2.py b/2/2.py
new file mode 100644
index 0000000..808c999
--- /dev/null
+++ b/2/2.py
@@ -0,0 +1,4 @@
+from itertools import combinations
+from functools import reduce
+from operator import mul
+print(sum(2 * (sum(box) - max(box)) + reduce(mul, box) for box in ([int(x) for x in l.split('x')] for l in open('input'))))
diff --git a/2/input b/2/input
new file mode 100644
index 0000000..2f04474
--- /dev/null
+++ b/2/input
@@ -0,0 +1,1000 @@
+20x3x11
+15x27x5
+6x29x7
+30x15x9
+19x29x21
+10x4x15
+1x26x4
+1x5x18
+10x15x23
+10x14x20
+3x5x18
+29x23x30
+7x4x10
+22x24x29
+30x1x2
+19x2x5
+11x9x22
+23x15x10
+11x11x10
+30x28x5
+22x5x4
+6x26x20
+16x12x30
+10x20x5
+25x14x24
+16x17x22
+11x28x26
+1x11x10
+1x24x15
+13x17x21
+30x3x13
+20x25x17
+22x12x5
+22x20x24
+9x2x14
+6x18x8
+27x28x24
+11x17x1
+1x4x12
+5x20x13
+24x23x23
+22x1x25
+18x19x5
+5x23x13
+8x16x4
+20x21x9
+1x7x11
+8x30x17
+3x30x9
+6x16x18
+22x25x27
+9x20x26
+16x21x23
+5x24x17
+15x17x15
+26x15x10
+22x16x3
+20x24x24
+8x18x10
+23x19x16
+1x21x24
+23x23x9
+14x20x6
+25x5x5
+16x3x1
+29x29x20
+11x4x26
+10x23x24
+29x25x16
+27x27x22
+9x7x22
+6x21x18
+25x11x19
+14x13x3
+15x28x17
+14x3x12
+29x8x19
+30x14x20
+20x23x4
+8x16x5
+4x11x18
+20x8x24
+21x13x21
+14x26x29
+27x4x17
+27x4x25
+5x28x6
+23x24x11
+29x22x5
+30x20x6
+23x2x10
+11x4x7
+27x23x6
+10x20x19
+8x20x22
+5x29x22
+16x13x2
+2x11x14
+6x12x4
+3x13x6
+16x5x18
+25x3x28
+21x1x5
+20x16x19
+28x30x27
+26x7x18
+25x27x24
+11x19x7
+21x19x17
+2x12x27
+20x5x14
+8x5x8
+6x24x8
+7x28x20
+3x20x28
+5x20x30
+13x29x1
+26x29x5
+19x28x25
+5x19x11
+11x20x22
+4x23x1
+19x25x12
+3x10x6
+3x14x10
+28x16x12
+23x12x2
+23x12x19
+20x28x10
+9x10x25
+16x21x16
+1x18x20
+9x4x26
+3x25x8
+17x16x28
+9x28x16
+27x3x12
+17x24x12
+13x21x10
+7x17x13
+6x10x9
+7x29x25
+11x19x30
+1x24x5
+20x16x23
+24x28x21
+6x29x19
+25x2x19
+12x5x26
+25x29x12
+16x28x22
+26x26x15
+9x13x5
+10x29x7
+1x24x16
+22x2x2
+6x16x13
+3x12x28
+4x12x13
+14x27x21
+14x23x26
+7x5x18
+8x30x27
+15x9x18
+26x16x5
+3x29x17
+19x7x18
+16x18x1
+26x15x30
+24x30x21
+13x20x7
+4x12x10
+27x20x11
+28x29x21
+20x14x30
+28x12x3
+19x1x8
+4x8x6
+21x14x2
+27x19x21
+17x24x14
+15x18x11
+18x7x26
+25x28x29
+27x26x9
+18x12x17
+24x28x25
+13x24x14
+26x9x28
+9x3x30
+9x2x9
+8x1x29
+18x30x10
+18x14x5
+26x8x30
+12x1x1
+30x5x28
+26x17x21
+10x10x10
+20x7x27
+13x17x6
+21x13x17
+2x16x8
+7x9x9
+15x26x4
+11x28x25
+10x6x19
+21x6x29
+15x5x6
+28x9x16
+14x3x10
+12x29x5
+22x19x19
+25x15x22
+30x6x28
+11x23x13
+20x25x14
+26x1x13
+6x14x15
+16x25x17
+28x4x13
+10x24x25
+4x13x10
+9x15x16
+15x24x6
+22x9x19
+11x11x8
+4x19x12
+24x5x4
+27x12x13
+7x27x16
+2x6x9
+29x27x15
+18x26x23
+19x16x15
+14x5x25
+9x16x30
+4x6x4
+13x10x10
+1x8x29
+23x5x17
+19x20x20
+11x27x24
+27x15x5
+15x11x12
+21x11x3
+1x13x22
+17x8x8
+13x14x14
+17x22x7
+9x5x8
+2x6x3
+25x9x15
+11x8x13
+9x25x12
+3x16x12
+12x16x8
+16x24x17
+4x6x26
+22x29x11
+14x17x19
+28x2x27
+24x22x19
+22x20x30
+23x28x4
+16x12x14
+22x24x22
+29x1x28
+26x29x16
+3x25x30
+27x3x13
+22x24x26
+25x3x2
+7x24x2
+10x5x3
+28x8x29
+25x6x4
+12x17x14
+24x3x5
+23x27x7
+26x23x30
+11x10x19
+23x7x11
+26x14x15
+14x3x25
+12x24x14
+2x14x12
+9x12x16
+9x2x28
+3x8x2
+22x6x9
+2x30x2
+25x1x9
+20x11x2
+14x11x12
+7x14x12
+24x8x26
+13x21x23
+18x17x23
+13x6x17
+20x20x19
+13x17x29
+7x24x24
+23x8x6
+19x10x28
+3x8x21
+15x20x18
+11x27x1
+11x24x28
+13x20x11
+18x19x22
+27x22x12
+28x3x2
+13x4x29
+26x5x6
+14x29x25
+7x4x7
+5x17x7
+2x8x1
+22x30x24
+22x21x28
+1x28x13
+11x20x4
+25x29x19
+9x23x4
+30x6x11
+25x18x10
+28x10x24
+3x5x20
+19x28x10
+27x19x2
+26x20x4
+19x21x6
+2x12x30
+8x26x27
+11x27x10
+14x13x17
+4x3x21
+2x20x21
+22x30x3
+2x23x2
+3x16x12
+22x28x22
+3x23x29
+8x25x15
+9x30x4
+10x11x1
+24x8x20
+10x7x27
+7x22x4
+27x13x17
+5x28x5
+30x15x13
+10x8x17
+8x21x5
+8x17x26
+25x16x4
+9x7x25
+13x11x20
+6x30x9
+15x14x12
+30x1x23
+5x20x24
+22x7x6
+26x11x23
+29x7x5
+13x24x28
+22x20x10
+18x3x1
+15x19x23
+28x28x20
+7x26x2
+9x12x20
+15x4x6
+1x17x21
+3x22x17
+9x4x20
+25x19x5
+9x11x22
+14x1x17
+14x5x16
+30x5x18
+19x6x12
+28x16x22
+13x4x25
+29x23x18
+1x27x3
+12x14x4
+10x25x19
+15x19x30
+11x30x4
+11x22x26
+13x25x2
+17x13x27
+11x30x24
+15x1x14
+17x18x4
+26x11x3
+16x22x28
+13x20x9
+1x18x3
+25x11x12
+20x21x1
+22x27x4
+8x28x23
+7x13x27
+17x9x26
+27x27x20
+11x20x12
+26x21x11
+29x14x12
+27x25x1
+28x29x25
+21x23x28
+5x18x18
+19x5x4
+7x6x30
+27x8x11
+12x24x12
+16x25x22
+26x11x29
+25x22x17
+15x23x23
+17x9x6
+30x10x16
+21x3x5
+18x27x2
+28x21x14
+16x18x17
+4x18x2
+9x1x14
+9x1x9
+5x27x12
+8x16x30
+3x19x19
+16x26x24
+1x6x9
+15x14x3
+11x7x19
+8x19x3
+17x26x26
+6x18x11
+19x12x4
+29x20x16
+20x17x23
+6x6x5
+20x30x19
+18x25x18
+2x26x2
+3x1x1
+14x25x18
+3x1x6
+11x14x18
+17x23x27
+25x29x9
+6x25x20
+20x10x9
+17x5x18
+29x14x8
+14x25x26
+10x15x29
+23x19x11
+22x2x2
+4x5x5
+13x23x25
+19x13x19
+20x18x6
+30x7x28
+26x18x17
+29x18x10
+30x29x1
+12x26x24
+18x17x26
+29x28x15
+3x12x20
+24x10x8
+30x15x6
+28x23x15
+14x28x11
+10x27x19
+14x8x21
+24x1x23
+1x3x27
+6x15x6
+8x25x26
+13x10x25
+6x9x8
+10x29x29
+26x23x5
+14x24x1
+25x6x22
+17x11x18
+1x27x26
+18x25x23
+20x15x6
+2x21x28
+2x10x13
+12x25x14
+2x14x23
+30x5x23
+29x19x21
+29x10x25
+14x22x16
+17x11x26
+12x17x30
+8x17x7
+20x25x28
+20x11x30
+15x1x12
+13x3x24
+16x23x23
+27x3x3
+26x3x27
+18x5x12
+12x26x7
+19x27x12
+20x10x28
+30x12x25
+3x14x10
+21x26x1
+24x26x26
+7x21x30
+3x29x12
+29x28x5
+5x20x7
+27x11x2
+15x20x4
+16x15x15
+19x13x7
+7x17x15
+27x24x15
+9x17x28
+20x21x14
+14x29x29
+23x26x13
+27x23x21
+18x13x6
+26x16x21
+18x26x27
+9x3x12
+30x18x24
+12x11x29
+5x15x1
+1x16x3
+14x28x11
+2x18x1
+19x18x19
+18x28x21
+2x3x14
+22x16x5
+28x18x28
+24x16x18
+7x4x10
+19x26x19
+24x17x7
+25x9x6
+25x17x7
+20x22x20
+3x3x7
+23x19x15
+21x27x21
+1x23x11
+9x19x4
+22x4x18
+6x15x5
+15x25x2
+23x11x20
+27x16x6
+27x8x5
+10x10x19
+22x14x1
+7x1x29
+8x11x17
+27x9x27
+28x9x24
+17x7x3
+26x23x8
+7x6x30
+25x28x2
+1x30x25
+3x18x18
+28x27x15
+14x14x1
+10x25x29
+18x12x9
+20x28x16
+26x27x22
+8x26x1
+21x2x12
+25x16x14
+21x19x5
+12x9x22
+16x5x4
+5x4x16
+25x29x3
+4x29x13
+15x16x29
+8x11x24
+30x11x20
+17x21x14
+12x24x10
+10x12x6
+3x26x30
+15x14x25
+20x12x21
+13x11x16
+15x13x3
+5x17x29
+6x3x23
+9x26x11
+30x1x8
+14x10x30
+18x30x10
+13x19x19
+16x19x17
+28x7x10
+28x29x4
+3x21x10
+4x28x24
+7x28x9
+2x4x9
+25x27x13
+6x12x15
+4x18x20
+20x1x16
+5x13x24
+11x11x10
+12x9x23
+1x9x30
+17x28x24
+9x5x27
+21x15x16
+17x4x14
+8x14x4
+13x10x7
+17x12x14
+9x19x19
+2x7x21
+8x24x23
+19x5x12
+11x23x21
+13x3x1
+5x27x15
+12x25x25
+13x21x16
+9x17x11
+1x15x21
+4x26x17
+11x5x15
+23x10x15
+12x17x21
+27x15x1
+4x29x14
+5x24x25
+10x10x12
+18x12x9
+11x24x23
+24x23x3
+28x12x15
+29x9x14
+11x25x8
+5x12x2
+26x26x29
+9x21x2
+8x8x25
+1x16x30
+17x29x20
+9x22x13
+7x18x16
+3x3x23
+26x25x30
+15x23x24
+20x23x5
+20x16x10
+23x7x8
+20x18x26
+8x27x6
+30x23x23
+7x7x24
+21x11x15
+1x30x25
+26x27x22
+30x28x13
+20x13x13
+3x1x15
+16x7x1
+7x25x15
+12x7x18
+16x9x23
+16x12x18
+29x5x2
+17x7x7
+21x17x5
+9x9x17
+26x16x10
+29x29x23
+17x26x10
+5x19x17
+1x10x1
+14x21x20
+13x6x4
+13x13x3
+23x4x18
+4x16x3
+16x30x11
+2x11x2
+15x30x15
+20x30x22
+18x12x16
+23x5x16
+6x14x15
+9x4x11
+30x23x21
+20x7x12
+7x18x6
+15x6x5
+18x22x19
+16x10x22
+26x20x25
+9x25x25
+29x21x10
+9x21x24
+7x18x21
+14x3x15
+18x19x19
+4x29x17
+14x10x9
+2x26x14
+13x3x24
+4x4x17
+6x27x24
+2x18x3
+14x25x2
+30x14x17
+11x6x14
+4x10x18
+15x4x2
+27x7x10
+13x24x1
+7x12x6
+25x22x26
+19x2x18
+23x29x2
+2x15x4
+12x6x9
+16x14x29
+9x17x3
+21x9x12
+23x18x22
+10x8x4
+29x2x7
+19x27x15
+4x24x27
+25x20x14
+8x23x19
+1x24x19
+6x20x10
+15x8x5
+18x28x5
+17x23x22
+9x16x13
+30x24x4
+26x3x13
+12x22x18
+29x17x29
+26x4x16
+15x7x20
+9x15x30
+12x7x18
+28x19x18
+11x23x23
+24x20x1
+20x3x24
+1x26x1
+14x10x6
+5x27x24
+13x21x12
+20x20x5
+6x28x9
+11x26x11
+26x29x12
+21x4x11
+20x11x17
+22x27x20
+19x11x21
+2x11x11
+13x5x7
+12x10x25
+21x28x1
+15x30x17
+28x19x1
+4x19x12
+11x4x12
+4x10x30
+11x18x5
+22x20x12
+3x7x27
+20x26x4
+13x27x26
+23x14x13
+4x19x7
+26x27x16
+20x5x20
+18x5x8
+19x21x1
+22x8x1
+29x4x1
+24x10x15
+24x9x20
+10x3x8
+29x30x3
+2x8x24
+16x7x18
+2x11x23
+23x15x16
+21x12x6
+24x28x9
+6x1x13
+14x29x20
+27x24x13
+16x26x8
+5x6x17
+21x8x1
+28x19x21
+1x14x16
+18x2x9
+29x28x10
+22x26x27
+18x26x23
+22x24x2
+28x26x1
+27x29x12
+30x13x11
+1x25x5
+13x30x18
+3x13x22
+22x10x11
+2x7x7
+18x17x8
+9x22x26
+30x18x16
+10x2x3
+7x27x13
+3x20x16
+9x21x16
+1x18x15
+21x30x30
+4x25x23
+3x11x7
+5x6x12
+27x1x20
+13x15x24
+23x29x2
+13x5x24
+22x16x15
+28x14x3
+29x24x9
+2x20x4
+30x10x4
+23x7x20
+22x12x21
+3x19x11
+4x28x28
+5x4x7
+28x12x25
+2x16x26
+23x20x7
+5x21x29
+9x21x16
+9x6x10
+9x6x4
+24x14x29
+28x11x6
+10x22x1
+21x30x20
+13x17x8
+2x25x24
+19x21x3
+28x8x14
+6x29x28
+27x10x28
+30x11x12
+17x2x10
+14x19x17
+2x11x4
+26x1x2
+13x4x4
+23x20x18
+2x17x21
+28x7x15
+3x3x27
+24x17x30
+28x28x20
+21x5x29
+13x12x19
+24x29x29
+19x10x6
+19x12x14
+21x4x17
+27x16x1
+4x17x30
+23x23x18
+23x15x27
+26x2x11
+12x8x8
+15x23x26
+30x17x15
+17x17x15
+24x4x30
+9x9x10
+14x25x20
+25x11x19
+20x7x1
+9x21x3
+7x19x9
+10x6x19
+26x12x30
+21x9x20
+15x11x6
+30x21x9
+10x18x17
+22x9x8
+8x30x26
+28x12x27
+17x17x7
+11x13x8
+5x3x21
+24x1x29
+1x28x2
+18x28x10
+8x29x14
+26x26x27
+17x10x25
+22x30x3
+27x9x13
+21x21x4
+30x29x16
+22x7x20
+24x10x2
+16x29x17
+28x15x17
+19x19x22
+9x8x6
+26x23x24
+25x4x27
+16x12x2
+11x6x18
+19x14x8
+9x29x13
+23x30x19
+10x16x1
+4x21x28
+23x25x25
+19x9x16
+30x11x12
+24x3x9
+28x19x4
+18x12x9
+7x1x25
+28x7x1
+24x3x12
+30x24x22
+27x24x26
+9x30x30
+29x10x8
+4x6x18
+10x1x15
+10x4x26
+23x20x16
+6x3x14
+30x8x16
+25x14x20
+11x9x3
+15x23x25
+8x30x22
+22x19x18
+25x1x12
+27x25x7
+25x23x3
+13x20x8
+5x30x7
+18x19x27
+20x23x3
+1x17x21
+21x21x27
+13x1x24
+7x30x20
+21x9x18
+23x26x6
+22x9x29
+17x6x21
+28x28x29
+19x25x26
+9x27x21
+5x26x8
+11x19x1
+10x1x18
+29x4x8
+21x2x22
+14x12x8
diff --git a/2/sol.py b/2/sol.py
new file mode 100644
index 0000000..901f9fe
--- /dev/null
+++ b/2/sol.py
@@ -0,0 +1,45 @@
+from dataclasses import dataclass
+from typing import List
+
+@dataclass
+class Box:
+ w: int
+ h: int
+ d: int
+
+ @staticmethod
+ def from_string(s: str) -> 'Box':
+ w, h, d = map(int, s.split('x'))
+ return Box(w, h, d)
+
+ def surface_area(self) -> int:
+ return 2 * self.w * self.h + 2 * self.h * self.d + 2 * self.d * self.w
+
+ def smallest_side_area(self) -> int:
+ return min(self.w * self.h, self.h * self.d, self.d * self.w)
+
+ def wrapping_paper_area(self) -> int:
+ return self.surface_area() + self.smallest_side_area()
+
+ def smallest_perimeter(self) -> int:
+ return 2 * (self.w + self.h + self.d - max(self.w, self.h, self.d))
+
+ def ribbon_length(self) -> int:
+ """The ribbon required to wrap a present is the shortest distance around
+ its sides, or the smallest perimeter of any one face. Each present also
+ requires a bow made out of ribbon as well; the feet of ribbon required
+ for the perfect bow is equal to the cubic feet of volume of the
+ present."""
+ return self.smallest_perimeter() + self.w * self.h * self.d
+
+def part1(boxes: List[Box]) -> int:
+ return sum(box.wrapping_paper_area() for box in boxes)
+
+def part2(boxes: List[Box]) -> int:
+ return sum(box.ribbon_length() for box in boxes)
+
+if __name__ == '__main__':
+ with open('2/input') as f:
+ boxes = [Box.from_string(line.strip()) for line in f]
+ print(part1(boxes))
+ print(part2(boxes)) \ No newline at end of file
diff --git a/20/input b/20/input
new file mode 100644
index 0000000..282bc62
--- /dev/null
+++ b/20/input
@@ -0,0 +1 @@
+33100000
diff --git a/20/solution.c b/20/solution.c
new file mode 100644
index 0000000..cf61687
--- /dev/null
+++ b/20/solution.c
@@ -0,0 +1,41 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void *emalloc(size_t s)
+{
+ void *p = malloc(s);
+ if (p != NULL) return p;
+ fprintf(stderr, "Ran out of memory allocating a buffer of size %zu\n", s);
+ exit(EXIT_FAILURE);
+}
+
+long part1(long input)
+{
+ long res = -1;
+ long *houses = emalloc(sizeof(long) * input / 10);
+ #pragma omp parallel for
+ for (long i = 1; i < input / 10; i++)
+ for (long j = i; j < input / 10; j++)
+ houses[j] += i * 10;
+ puts("filled houses");
+ for (long i = 1; i < input / 10; i++) {
+ if (houses[i] >= input) {
+ res = i;
+ break;
+ }
+ }
+ free(houses);
+ return res;
+}
+
+long part2(long input)
+{
+ return -1;
+}
+
+int main(void)
+{
+ long input = 33100000;
+ printf("%ld\n", part1(input));
+}
diff --git a/21/input b/21/input
new file mode 100644
index 0000000..e749051
--- /dev/null
+++ b/21/input
@@ -0,0 +1,3 @@
+Hit Points: 103
+Damage: 9
+Armor: 2
diff --git a/22/input b/22/input
new file mode 100644
index 0000000..afff321
--- /dev/null
+++ b/22/input
@@ -0,0 +1,2 @@
+Hit Points: 51
+Damage: 9
diff --git a/23/input b/23/input
new file mode 100644
index 0000000..79d9624
--- /dev/null
+++ b/23/input
@@ -0,0 +1,46 @@
+jio a, +16
+inc a
+inc a
+tpl a
+tpl a
+tpl a
+inc a
+inc a
+tpl a
+inc a
+inc a
+tpl a
+tpl a
+tpl a
+inc a
+jmp +23
+tpl a
+inc a
+inc a
+tpl a
+inc a
+inc a
+tpl a
+tpl a
+inc a
+inc a
+tpl a
+inc a
+tpl a
+inc a
+tpl a
+inc a
+inc a
+tpl a
+inc a
+tpl a
+tpl a
+inc a
+jio a, +8
+inc b
+jie a, +4
+tpl a
+inc a
+jmp +2
+hlf a
+jmp -7
diff --git a/24/input b/24/input
new file mode 100644
index 0000000..874e61e
--- /dev/null
+++ b/24/input
@@ -0,0 +1,28 @@
+1
+3
+5
+11
+13
+17
+19
+23
+29
+31
+41
+43
+47
+53
+59
+61
+67
+71
+73
+79
+83
+89
+97
+101
+103
+107
+109
+113
diff --git a/25/input b/25/input
new file mode 100644
index 0000000..08d9d8f
--- /dev/null
+++ b/25/input
@@ -0,0 +1 @@
+To continue, please consult the code grid in the manual. Enter the code at row 2978, column 3083.
diff --git a/3/1.py b/3/1.py
new file mode 100644
index 0000000..0df8d8e
--- /dev/null
+++ b/3/1.py
@@ -0,0 +1,10 @@
+from functools import reduce
+from collections import defaultdict
+d = defaultdict(int)
+d[(0, 0)] = 1
+def reducer(state, move):
+ d, pos = state
+ npos = (pos[0] + move[0], pos[1] + move[1])
+ d[npos] += 1
+ return (d, (npos))
+print(len(reduce(reducer, ({'^': (0, 1), 'v': (0, -1), '>': (1, 0), '<': (-1, 0)}[c] for c in open('input').read().rstrip('\n')), (d, (0, 0)))[0]))
diff --git a/3/2.py b/3/2.py
new file mode 100644
index 0000000..daeaac6
--- /dev/null
+++ b/3/2.py
@@ -0,0 +1,13 @@
+from functools import reduce
+from collections import defaultdict
+d = defaultdict(int)
+d[(0, 0)] = 1
+def reducer(state, move):
+ d, pos = state
+ npos = (pos[0] + move[0], pos[1] + move[1])
+ d[npos] += 1
+ return (d, (npos))
+instrs = [{'^': (0, 1), 'v': (0, -1), '>': (1, 0), '<': (-1, 0)}[c] for c in open('input').read().rstrip('\n')]
+d, _ = reduce(reducer, (instr for i, instr in enumerate(instrs) if i % 2 == 0), (d, (0, 0)))
+d, _ = reduce(reducer, (instr for i, instr in enumerate(instrs) if i % 2 == 1), (d, (0, 0)))
+print(len(d))
diff --git a/3/input b/3/input
new file mode 100644
index 0000000..a5954e7
--- /dev/null
+++ b/3/input
@@ -0,0 +1 @@
+v>v<vvv<<vv^v<v>vv>v<<<^^^^^<<^<vv>^>v^>^>^>^>^><vvvv<^>^<<^><<<^vvvv>^>^><^v^><^<>^^>^vvv^<vv>>^>^^<>><>^>vvv>>^vv>^<><>^<v^>^>^><vv^vv^>><<^><<v>><>^<^>>vvv>v>>>v<<^<><^<v<>v>^^v^^^<^v^^>>><^>^>v<>^<>>^>^^v^><v<v>>><>v<v^v>^v<>>^><v>^<>v^>^<>^v^^^v^^>>vv<<^^><^<vvv>^>^^<^>>^^^^^v^<v>vv<>>v^v<^v^^<><^<^vv^><>><><>v>vvv^vv^^<<><<vvv><<^v^><v<>vvv^<^>vvvv^>^>>^v^<v^vv<^^v<>v>vv^<>><v<<<^v^<<><v<^<^<><^^^>^>>v>^>v^<>v><^<^<v^>^^vv<^^<>v^v^vv<>>>>v^v<>><^^v>vv^^>v^v>v<vv>>v>><v^v^v>vv>^^>^v><<vv^v^^vv<^v><^<<v<v^>vv^^^<v^>v>v^^^>><^^<v^<^>>v><vv<v^^>^^v>>v^^^<^^v>^v>><^<^<>>v<<^^vv>^^^v<^<^<v<v^^vv>^vv^>>v^><v>><<<>^vv^<^<>v^^<<<v<^>^><><v^^>>^^^<^vv<^^^>><^^v>^^v^<v^v^>^^<v>^<^v<^<<<<^<v^>v^<^^<>^^>^><<>>^v><>><^<v><^^^>>vv>^><vv>^^^^^v^vvv><><^<^>v>v^v^>^><><^<^><>v<<vv<^>><>^v^^v>^<<<>^v^>^<<v^vv<>v^<v^^vv><<v^<>>>^<v>vv>v>>>^<^>><vv<>>>>v<v>>>^v>v><>>vvv<^^><<^>^>v<^vvvv<v><vv<><^^^v^^^>v^v<>v<^^v>>><>v<v^>>v><v^>>^^<v<<<^<v<><^^v><<v^><<<<^vv<^<>^><vv<<<<^>>>^v>^v>vv>^v<>v>v<v><^>>v>>^>^><^<v^v^>^v<><><^^>^<vvvv^^<>^^^>vv^v^v>^v^^v^^v><v^<^<>><^<v>v>>vv<<v>>vvvv<vv><>>^v^>^>>v^v^<<<vv<><v<<>>>^v<<v>^^vv^><>v>^>v><<<<<<<^>^^v^<<^^>>vvv^<><>><>^^v<<vv><^^v<^^><vv>v^>>>v^v><v^v<^>v^><>v<<>v>^^v><<<<><^v^v>>^<>^<<>^<v<<>>v<<>><^<<<<^v>^<^v>v>vv<v<v<<>^>v<^<<>v^<vvvv^>v>><<v><v<>v>v>>v^vvv^^>>>v^<^<<^^<<<><v>v^<<v<<<>v<^^<><v<v^^<v>^>v>>v<>^>^^>>^v<<>v^^^>>>^vv<^v<v>^>v>^><>v^^<>^^v^^vv^<^>^<<>><<^>^v>>><<<vvvv><<><v<^v^v<vvv^<><<^<vv><v^v^v^>v>v^<vvv^><^><^<vv><>>v^>^^^<>><v^<^^^<>v<<v<^v>>>^>>v^><<>vvv><^>>v><v><>v>>^>v><<><<>^<>^^^vv><v^>v^^>>^>^<^v<v<^^<^vvvv>v<v>^>v^>^><^<vvvv><^><><<v<>v<v^><^<v^>^v^^<<<<^><^^<^><>>^v<<^<<^vv>v>>v<^<^vv>><v<vv>v<v<v>^v<>^>v<>^v<<<v>>^^v>>><vvv>v^>^v^v>^^^v<vvvv>><^>vvv^<vv^^vv><<<>v<>v>^<vvv^<^<v<v<^vv^^>>vv^<^^v^><^^^^^v<^<v<^>>>vv^v^>^<v>^<><v^<^v>>><^v^<<v<<v<>v>^v<v^v>>^^v<<v<v<<>>>vv>>^v>>^<<<<^><<<><^^>>v<>^vvvv>v^^^>^^^>^<vvvv><^^v<v<>v<^v^v<<v^^^v^<v<^v>v^^<>^>^<^v>vv<v^vv<^<<>v><<^><><^^v<<><^^><>^v>^<><<^<^^<<>vv<>^^<<^>><<<>>vvv>^>v^^v^><<^>v>^>^<^<<>v<^>vv^v^v<>vv<<v>vv<vv><^>v^<>^vv^v^<v<^>>>>v^v><^<><<>vv^<vvv^>>vvv^>v>>><^^vv<vvvv>v<^<^>>^^>^^vv>>><^v<>^v^<<>v^^^<v>^>>^<^<v>>^v<^^^<v>^v>^>>v<vv>>^<v^<<>>^>>><v>v^<<^<v>>^<<^^<>v<^v<^<>v^v>^^v<vvvv>^vv>vvv>v^<^>><v^^vv<<<^>vvvv<>>^^<>v^<><>v<^<>v<>^>v<>vv<v^v>>v<v<^<v^^v^vv^vvv><^^>v>><>>^<^^<>>^>^<v^>>vvv^v><v>>^>^>v><><<><vv^v>v<>^v<^vv^^^<>^^<<^^^v<>><v<^<^<^<^^><v^v<^>v^>vvvv>^^v^>^<v<^^^>>^<<vv^<><><^^^^<<>^<><v>vv^<><^>^^<>v^<>>>v><>vvvvv>v>v^^>^<<vvvv<>vv>>v<<^<>^^^v^<><>>^<<<v<v<>>>><><v>v<v<>>^>^^^^vv^^<<><^^<<vv<^<>v>vv<v<><<<^<<v<<<<>v<>>^<^>^>><v>v>><^^<>><<<><<><v^^v<<><^<^v<v^><^^v<<>><<<<^>v^<v>><v^><v<vvv>v^v^<v><<>>v<><<v>^<>><>>^><>v^v>v<<>v<>v^^><<>>>v<<>>>>^>v>><v<<>>>vv>v>^<^^^<>v<v>^<^^v^vvv^>vv>^<v><vvvv>^<<>vvv<<<vv>^^<^>^>>v>v<<<<<>^^vv^>>v>^<^<v^v^>^v>>v>^v<><>^<^>v>v<<<^^^v>^<<<>vvv^v^^>^>>^>v>v<>^^><>>v>^>v<<<^^^v^<v^vv>><><^<^<><vvv<v^>>^v>vv<^v<<^vv>v^<<v>v>v>^v^>^v<<^v^vv>v<v>^<<><v^>>v<>><v<<<^v<<>vvv^<vv<vvv<<>^vv^^v><^>v^vv<<v^<<^^^<^<>^^<<>v<><<v>^><>^<><<v<v^^>vv<>^<v<^<vvv>vv>v><^^v<>><^v^v><><>><v<v>vv<>>><v^^v<>><<^>>><^^^vvv<<<vv<<^v<<<>><<vv>>>>v<<<<<vv><><v>v^^<<^vv^<vv<>>vv>^<>^v^^<>^^^vv>v^^<v<><v>v<v>>^v<v<>>^<v^^><>v^^^>v^^v<vv><^>v^v^<>v>v<v<^^>>v<^^vv^v<^^^^vv<<><<^>>^^<<v^^<<^>v^>>^^^><^^>^v^v>^<<v<vv<<<v<^^^>^>>^v<>^<^>v>^>^v^<^^^<^vv<v><^^>>v<v>^>^v^>>>>^v>^^<<^<v^v<^<<v<<^><^^<v^<><v>v^<<v^^<><<>>><vv<<><>^<>>>v<<v^^^v^^<<<vv<<^<^<^vv^<><><<^^<^^>v^>^<v<>>v^v<><<v>^^v>^<^<vvv<v>v^v>>>^^<^<v^>^vv<<<v<<>^><><^<>v>>>v<v^<>v>><^^^v^^^v<^^<vv^^^>v>v<>>^^<><>v>^<v<>^>>>><>v>^v>^vv^v<vv<<^^>><v<>^>^^<v<^>^<vvv>><>^<<>>><<<><>^^<<<v<>v^>v>v<v>^^^>^>^v<<>v>vv>><<<v>^^<v><vv<<v^^>^>>^><^>v<^<^v>><^^>v<vv^^><><>^><<><>v^>v<><^^>><>^<^^v<^<<v>><v><<<^^<<v<^vv^v<>><>>>^>v<vvv^>^<><v^><^<<^vv<^v^v^v<>v^^v>v^<^>^vv^>>><<>v^vv^<>^v^><<v^v<v>v^<><>>v^v^><>v^vvv^^^<<^<<v<<v<^vv^>>v^v>^^<v<>><>v>>v^<>^>v>^>><<>v^v><^v>v>>><v<v><^<^^>vv<v><^>^<^>^^v><><v<^^v<<><^<<v^<v<<><^^vvv^v>^>^<>>vv>v^^v^^vv<^^>><v^^vv><^v>v^<<v<^v>vvv<>>^v><<>^v<<<>^><^vv><<^^<v^>v<<v>^vv<>^v>>>><<<<^^<^v>^<^^<^<^^>>^^v>^^^^v^^^<<>^^vv<<v^^><v>><^<<><>^>v<>>v^^^>^v^^v^<v^v>v>>>>>^v>^>^^<vvv^^<v^<<<v<<>v>><^^^v<<^^<v>>^<^<^><^<<v^v><<vv<^<>>v>v>^v<><<v>^>vv^v<v>v><^<v>><>^<vv<v^^^^v<^^>><<^^>v>v>^^^<>v>^v^^>vv^vv<^^>><>^>^<>v>><>^v<<v>v>^><^^^v^<vv><<^v^>v^>vv>v^<>v><vv><^v>v<><v^v^v<^v<>^v<v^<<><<v>>^v><v>^^<>vvv^>^<<v^>><^>><^<>^v<v<v<^vvv<><<^v^<v>><<<v>^<^<v>v>^vv^v>v<^^vv<<vvv^<v>><>vv^>v<<>v<vvvv>>v>^^>>><<<^>^vv>><v>^^^>v<^vv<>v<<<v<<<<v>>>>^<^^^^>v<^^<><v>v>v<v^>vv^>v>v<^>^v^<>v>>vvv>^^><^vvv>><>>>^<<^<v<>>>v^^><v<v>>^><>v<^^v^<<v><>^<>>><^v^v>>>^vvvv^<><<<v<^>>v>^v^<v<v<<^<<v^vv^v>v<v<>>v<v^<<<><v^>><^<<^>^^><v>v<^v^<^>v>^<<v>v^<>v^<>vv^<>^>^>v^>^vv<>^^<<>>v<>^v<><v^><><<<vv>v>v^>vv^><<<<v>^v<><>^^<vv>v^^v^^^<v<^^><v^v<>><v<vv>^<>>><vv<^v<<>>^><>>v<v^v^>>>v<<>v<<<<<<<^v<<^^^v<^v<>v^^<<<^<>>v^vv<v>^<^^<^^<<^>vv><^<^^v<<<^><^v<^><>v<vv^>^v^^>>><<vv^^v><^<<^<>>^>>^<<<<v^vv<>>>v>^v>><>v>>v>><>v>><^^><v>^^vv<^^<^>vv><<^>><<><v>^vvv><^v^>vvv^>>^<><^>^<<>>v^v>v<<>^>>^>v<^^<^<<>^^v<vvvvv^^^<^<>^^v>v<>^<^^<<v>v^^vvv^^v>^vv<v^>^<>v<^v^>^<v><v<<<^v<v<v^^<vvv>vv<<vv>v^<<v<^<vv><^>^><^^<^^<<v^^<v^v<v^^^^>^>vv^<>^<>^>^^<^v><<<^>vv^vv>v^v<>^^v^<^^^vvv^><v^<v^^<v<>v^<><>v>vv<^v^>>^v<^^vv>vv>^>><<<<v^^<^><>^><>>v<>>v>^v<^vv>^^>^<^<<v^>>v^v<^^v<vv<^<><^^>^^<>^^^<vv<v<<^^>^>^vv<^>><^<vvv^<>>vv^><v>v^>^vv>^>v^^<>>^v<>>v<^>^v>vv^<vv<^^>>^<v>>>>vvv>vv>^><^v<<<>^^v>v^v<^^^v^^>^><<^^>^<v>><^^^^^<v<vv<v<^<>^^<^v<^>>vv>>^v^vv<>><>^>>>^<v>^^^^><^<<<v<>^v<><vvv^<^^>vv^>>v<vvvv><v^v><^vv<^v<><vvv<vv>v<>^v^<<>>>>v^^>^vv<<vvv<^^><v><><<>v^v<^<^>><vv>^^><^>^><<><v<^v^><^<><>vv>>>>^><<^^^<^v^>^>^^>^<^><v><^^<^^<>><><v>><<<>^>^^v<>^<<<v>>vv>^>>^>^<>>vv<^^vv<>v<>^^>^v<v^^^^v<>^<v>v^v>^^^<v>v<<<^vv^><>^<v>>^^vv>v^<<^><>>vv^^^^^>v>>v<<<>^<vvv<<><><^v<^v<^>^<>^vvv>^>v><<<vv<>v>vv<v<<v>^<^^>v^v>^<^v^<<vvv^^<>^v<<^>^<><>^^<>>^^<^v^<^<v<><<^><v<>v^^>v^v^^^<^v<<^v>^>>^^^^^><<<vv^>>v^><v^^vv><>v^^<^v<^<v^^><<v>v^^^><^^^><<<<<>^<<^<>>v<<v^v^^v<<>^<vv>>><^^^<>>>>vvv>v<>>>v^v^v<^<<^>^<<>v>>^>^^><^><<^v^^<^<>v^v>vv<>>>>>>v<<><v^<v<>>^^>v<<<>^<<v><^><<^v>vv>>>><><>v^<^v><v^<<<<^v><^>v>>^^^v<^>>^>>v<<^<<>vvv>>^v<>>^v><<<^v^v<><v>^vvv<v<v>^^^<><vv^<<>vvv<v<^^v^^><v<^v<^v^<v<^>^^^>>v>^<v^>>^<><<><vv<>vv>^v^>>^<<v<^^v>v<v<vvv>><><<><vvvvv<^v<^>^^><>^<<>^v<<>>v^vv<<>^^v^v^v><^>v>v<^<<^<^>vv>^v<<^>^>>v^<<v^>v^^v^^<v^v>>><vv><<<>^v>><><v<vv<^>v<>><^v>^^v<<<<^v^vv<<<<><><^<^<^v><<^^v^<<<<<^^><^^>vv<v<^<v>v<^><><v<>vvv^<vv>v^>^>^^^v<<^<^^>vv<v^v^v>^vv^><^v^<<>v<^^>^vv<<>^<<><^>v^<<^<>v><><>v<<^^><^^^v>>v>^vv<v^>>^v^^<><<<<<^>^v^<^<^^>^vv<^>v^^v^<>v<><v>v^v>vvv><><<><>vv<vvv^v>^^>^^^<><^>^^^>v<vvvv<>vv<v<v^^>><>v<>>v^>v^^vv^>v>>><v<<<<v<^v>><^^>^v^v<v^v^^^vvv>>>vv<^>><<<^>><^<^>^<^>^>>v^<^<>^<^^<><vvv^^<>^<>>><<v>^<^<v<<><^<<^><^^>vv<>^^><v^v<vv<^<vvv<<^>v^>>v>>>v<<^vv^<><>>>^^<^v^>>^>>><<v<<^<vv><^<>^>>^v>>><^^^<<<vv<<v<v>^vv><><<>^^^<>^<vv^<^<<v>^^><vv>><>>>^>vv>^<^<>>^<^^><v>v^><v>vv><><>>><><<^^v<<^v<v>vv<><><<^v>^v<>^<^^^v^>^<^><^v>v>^v<>><^^v^^^^^<><v<>>vvv<v^^<>v>>>>^<<><^v>vv>>^^><<><><^^^<^<^<<^v>^^^><v>>>>><<v<v>v^^^<>>v<vv<^<>v^^^v<><^>v>><<><>v<^><<>>><>v>^<>>^>v^v<<<<>^<v^vv^>vv<<><v^vv<v<v<<>>>>>vv<><>^<^v>vv^<<v<^v^^<<^<<^^v^>>><<>^<>><^>>><v<>><<>^^>><<<^^^^^v>>^<<>>vvvv<^v<v^^<^>^vv<vv<>v<<<^><>>>>vv^<^v>v<^<>^v>>^<^^v^>>><>^^<^v>>v<<>vv<vvvv<>vv>^><>v^<>^<<^vv<v^^v<vvvv><^>>^v^>^^<<<^>>^^>^<^^<^<<<v^<^^v<<vv^<<^^^vv><v<vv^>v^^v<v>^^<^v<^>>><<>vv<<^><<v^v^^^v<vv>^>vv<^>>^<v<>vv>>>^>>><<v<^<>^<<<>>^<<>><^<<^^^>>v^^>v<<<>v>v>v<v<^>^<>>>^vvv><<^^<<><v<><^<v<vvv>v>>>>vv^^v<v<^<^><v>^v<<v<vv>>v>v<<<<><<>vv<><^^^<>>v<v<vvv><v^<vv^>>><v^^<>>>^^<><^<^v^><vv>>^^v>^<<v^>v>^^>^v^<v<^<v^v><>>v^^<^v^^<<>^^>v^^>><<<<^<^^v>^^v>v<<vv^^vv>^>v^<v<v><>vv>>^<v^v^<v<^>^v>v^^>vvvvv<v><<>vv>vvvvvv>>v>>^^^<v>vv^^><<v>>v^^^^v>vv>v<^v>>>>^>^><v^>^<v<vv>v>^>><v>><<>>^vv<vv^^<^^>>>>><><<^<v<><<v>^><^vv^v>>>>>v>^>^<vv>^v^>v<^v^<^<<vv<<>v<>>^vv<<>^v^v>><><<>>v^^<<>^^<v><>v<<^^<^^>^^>^<^><>>v<>>^^<^>><<<v<>>>^v^>v>v<<^^<<^>v<v^>>v^^v^^<<>^v>v><v^>v<^^>^<vv><vv^<>v<><^<<<vv<<v>v<^<<<<^^>v^v^^><<><^^^<v>v^^>>>vvv><>vv<>>^^v^v<<^>v^^v^>vv>^<<v<^<v^>^^<<v<^^>^v^^<^^v<<>>vv<^>>^><><>v>>v<>^<v^^><<>>> \ No newline at end of file
diff --git a/4/1.c b/4/1.c
new file mode 100644
index 0000000..155c45b
--- /dev/null
+++ b/4/1.c
@@ -0,0 +1,328 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#ifndef HAVE_OPENSSL
+
+#include <string.h>
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD5_u32plus;
+
+typedef struct {
+ MD5_u32plus lo, hi;
+ MD5_u32plus a, b, c, d;
+ unsigned char buffer[64];
+ MD5_u32plus block[16];
+} MD5_CTX;
+
+extern void MD5_Init(MD5_CTX *ctx);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
+extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
+
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z) (((x) ^ (y)) ^ (z))
+#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them in a
+ * properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned memory
+ * accesses is just an optimization. Nothing will break if it fails to detect
+ * a suitable architecture.
+ *
+ * Unfortunately, this optimization may be a C strict aliasing rules violation
+ * if the caller's data buffer has effective type that cannot be aliased by
+ * MD5_u32plus. In practice, this problem may occur if these MD5 routines are
+ * inlined into a calling function, or with future and dangerously advanced
+ * link-time optimizations. For the time being, keeping these MD5 routines in
+ * their own translation unit avoids the problem.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
+#define SET(n) \
+ (ctx->block[(n)] = \
+ (MD5_u32plus)ptr[(n) * 4] | \
+ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+ (ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update the bit
+ * counters. There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ const unsigned char *ptr;
+ MD5_u32plus a, b, c, d;
+ MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+ STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+ STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+ STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+ STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+ STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+ STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+ STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+ STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+ STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+ STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+ STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+ STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+ STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+ STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+ STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+ STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+ STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+ STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+ STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+ STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+ STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+ STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+ STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+ STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+ STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+ STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+ STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+ STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+ STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+ STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+ STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+ STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+ STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+ STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+ STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+ STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+ STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+ STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+ STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+ STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+ STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+ STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+ STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+ STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+ STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+ STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+ STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+ STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+ STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+ STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+ STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+ STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+ STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+void MD5_Init(MD5_CTX *ctx)
+{
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ MD5_u32plus saved_lo;
+ unsigned long used, available;
+
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if (used) {
+ available = 64 - used;
+
+ if (size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if (size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
+}
+
+#define OUT(dst, src) \
+ (dst)[0] = (unsigned char)(src); \
+ (dst)[1] = (unsigned char)((src) >> 8); \
+ (dst)[2] = (unsigned char)((src) >> 16); \
+ (dst)[3] = (unsigned char)((src) >> 24);
+
+void MD5_Final(unsigned char *result, MD5_CTX *ctx)
+{
+ unsigned long used, available;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ available = 64 - used;
+
+ if (available < 8) {
+ memset(&ctx->buffer[used], 0, available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
+
+ memset(&ctx->buffer[used], 0, available - 8);
+
+ ctx->lo <<= 3;
+ OUT(&ctx->buffer[56], ctx->lo)
+ OUT(&ctx->buffer[60], ctx->hi)
+
+ body(ctx, ctx->buffer, 64);
+
+ OUT(&result[0], ctx->a)
+ OUT(&result[4], ctx->b)
+ OUT(&result[8], ctx->c)
+ OUT(&result[12], ctx->d)
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif
+#include <stdio.h>
+
+int main(void)
+{
+ unsigned int i = 0;
+ char buf[128] = "bgvyzdsv";
+ char *numpos;
+ unsigned char sum[16];
+ MD5_CTX ctx;
+
+ numpos = buf + strlen(buf);
+
+ do {
+ sprintf(numpos, "%u", i++);
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, buf, strlen(buf));
+ MD5_Final(sum, &ctx);
+ } while (!(sum[0] == 0 && sum[1] == 0 && sum[2] < 0x10));
+
+ printf("%s -> ", buf);
+ for (size_t i = 0; i < sizeof sum; i++)
+ printf("%02x", sum[i]);
+ putchar('\n');
+}
diff --git a/4/2.c b/4/2.c
new file mode 100644
index 0000000..c62c41f
--- /dev/null
+++ b/4/2.c
@@ -0,0 +1,328 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#ifndef HAVE_OPENSSL
+
+#include <string.h>
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD5_u32plus;
+
+typedef struct {
+ MD5_u32plus lo, hi;
+ MD5_u32plus a, b, c, d;
+ unsigned char buffer[64];
+ MD5_u32plus block[16];
+} MD5_CTX;
+
+extern void MD5_Init(MD5_CTX *ctx);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
+extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
+
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z) (((x) ^ (y)) ^ (z))
+#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them in a
+ * properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned memory
+ * accesses is just an optimization. Nothing will break if it fails to detect
+ * a suitable architecture.
+ *
+ * Unfortunately, this optimization may be a C strict aliasing rules violation
+ * if the caller's data buffer has effective type that cannot be aliased by
+ * MD5_u32plus. In practice, this problem may occur if these MD5 routines are
+ * inlined into a calling function, or with future and dangerously advanced
+ * link-time optimizations. For the time being, keeping these MD5 routines in
+ * their own translation unit avoids the problem.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
+#define SET(n) \
+ (ctx->block[(n)] = \
+ (MD5_u32plus)ptr[(n) * 4] | \
+ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+ (ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update the bit
+ * counters. There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ const unsigned char *ptr;
+ MD5_u32plus a, b, c, d;
+ MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+ STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+ STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+ STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+ STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+ STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+ STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+ STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+ STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+ STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+ STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+ STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+ STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+ STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+ STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+ STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+ STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+ STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+ STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+ STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+ STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+ STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+ STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+ STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+ STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+ STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+ STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+ STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+ STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+ STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+ STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+ STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+ STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+ STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+ STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+ STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+ STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+ STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+ STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+ STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+ STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+ STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+ STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+ STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+ STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+ STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+ STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+ STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+ STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+ STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+ STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+ STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+ STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+ STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+void MD5_Init(MD5_CTX *ctx)
+{
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ MD5_u32plus saved_lo;
+ unsigned long used, available;
+
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if (used) {
+ available = 64 - used;
+
+ if (size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if (size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
+}
+
+#define OUT(dst, src) \
+ (dst)[0] = (unsigned char)(src); \
+ (dst)[1] = (unsigned char)((src) >> 8); \
+ (dst)[2] = (unsigned char)((src) >> 16); \
+ (dst)[3] = (unsigned char)((src) >> 24);
+
+void MD5_Final(unsigned char *result, MD5_CTX *ctx)
+{
+ unsigned long used, available;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ available = 64 - used;
+
+ if (available < 8) {
+ memset(&ctx->buffer[used], 0, available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
+
+ memset(&ctx->buffer[used], 0, available - 8);
+
+ ctx->lo <<= 3;
+ OUT(&ctx->buffer[56], ctx->lo)
+ OUT(&ctx->buffer[60], ctx->hi)
+
+ body(ctx, ctx->buffer, 64);
+
+ OUT(&result[0], ctx->a)
+ OUT(&result[4], ctx->b)
+ OUT(&result[8], ctx->c)
+ OUT(&result[12], ctx->d)
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif
+#include <stdio.h>
+
+int main(void)
+{
+ unsigned int i = 0;
+ char buf[128] = "bgvyzdsv";
+ char *numpos;
+ unsigned char sum[16];
+ MD5_CTX ctx;
+
+ numpos = buf + strlen(buf);
+
+ do {
+ sprintf(numpos, "%u", i++);
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, buf, strlen(buf));
+ MD5_Final(sum, &ctx);
+ } while (!(sum[0] == 0 && sum[1] == 0 && sum[2] == 0));
+
+ printf("%s -> ", buf);
+ for (size_t i = 0; i < sizeof sum; i++)
+ printf("%02x", sum[i]);
+ putchar('\n');
+}
diff --git a/4/input b/4/input
new file mode 100644
index 0000000..bf3e46f
--- /dev/null
+++ b/4/input
@@ -0,0 +1 @@
+bgvyzdsv
diff --git a/5/1.py b/5/1.py
new file mode 100644
index 0000000..8100d06
--- /dev/null
+++ b/5/1.py
@@ -0,0 +1,18 @@
+vowels = set("aeiou")
+bad = {('a', 'b'), ('c', 'd'), ('p', 'q'), ('x', 'y')}
+def check(w):
+ vcnt = 0
+ dbl = False
+ last = None
+ for c in w:
+ if c in vowels:
+ vcnt += 1
+ if not dbl and c == last:
+ dbl = True
+ if (last, c) in bad:
+ return False
+ last = c
+ if vcnt >= 3 and dbl:
+ return True
+ return False
+print(len([w for w in open('input') if check(w)]))
diff --git a/5/2.py b/5/2.py
new file mode 100644
index 0000000..a172cdd
--- /dev/null
+++ b/5/2.py
@@ -0,0 +1,24 @@
+from collections import defaultdict
+def check(w):
+ pairs = defaultdict(list)
+ rep = False
+ last2 = (None, None)
+ for i, c in enumerate(w):
+ if last2[1] is not None:
+ pairs[(last2[1], c)].append(i)
+ if not rep and last2[0] == c:
+ rep = True
+ last2 = (last2[1], c)
+ if not rep:
+ return False
+ for _, p in pairs.items():
+ if len(p) < 2:
+ continue
+ if len(p) > 2:
+ break
+ if p[1] - p[0] > 1:
+ break
+ else:
+ return False
+ return True
+print(len([w for w in open('input') if check(w)]))
diff --git a/5/input b/5/input
new file mode 100644
index 0000000..f3b13a0
--- /dev/null
+++ b/5/input
@@ -0,0 +1,1000 @@
+zgsnvdmlfuplrubt
+vlhagaovgqjmgvwq
+ffumlmqwfcsyqpss
+zztdcqzqddaazdjp
+eavfzjajkjesnlsb
+urrvucyrzzzooxhx
+xdwduffwgcptfwad
+orbryxwrmvkrsxsr
+jzfeybjlgqikjcow
+mayoqiswqqryvqdi
+iiyrkoujhgpgkcvx
+egcgupjkqwfiwsjl
+zbgtglaqqolttgng
+eytquncjituzzhsx
+dtfkgggvqadhqbwb
+zettygjpcoedwyio
+rwgwbwzebsnjmtln
+esbplxhvzzgawctn
+vnvshqgmbotvoine
+wflxwmvbhflkqxvo
+twdjikcgtpvlctte
+minfkyocskvgubvm
+sfxhhdhaopajbzof
+sofkjdtalvhgwpql
+uqfpeauqzumccnrc
+tdflsbtiiepijanf
+dhfespzrhecigzqb
+xobfthcuuzhvhzpn
+olgjglxaotocvrhw
+jhkzpfcskutwlwge
+zurkakkkpchzxjhq
+hekxiofhalvmmkdl
+azvxuwwfmjdpjskj
+arsvmfznblsqngvb
+ldhkzhejofreaucc
+adrphwlkehqkrdmo
+wmveqrezfkaivvaw
+iyphmphgntinfezg
+blomkvgslfnvspem
+cgpaqjvzhbumckwo
+ydhqjcuotkeyurpx
+sbtzboxypnmdaefr
+vxrkhvglynljgqrg
+ttgrkjjrxnxherxd
+hinyfrjdiwytetkw
+sufltffwqbugmozk
+tohmqlzxxqzinwxr
+jbqkhxfokaljgrlg
+fvjeprbxyjemyvuq
+gmlondgqmlselwah
+ubpwixgxdloqnvjp
+lxjfhihcsajxtomj
+qouairhvrgpjorgh
+nloszcwcxgullvxb
+myhsndsttanohnjn
+zjvivcgtjwenyilz
+qaqlyoyouotsmamm
+tadsdceadifqthag
+mafgrbmdhpnlbnks
+aohjxahenxaermrq
+ovvqestjhbuhrwlr
+lnakerdnvequfnqb
+agwpwsgjrtcjjikz
+lhlysrshsmzryzes
+xopwzoaqtlukwwdu
+xsmfrfteyddrqufn
+ohnxbykuvvlbbxpf
+bbdlivmchvzfuhoc
+vtacidimfcfyobhf
+tinyzzddgcnmiabd
+tcjzxftqcqrivqhn
+vgnduqyfpokbmzim
+revkvaxnsxospyow
+ydpgwxxoxlywxcgi
+wzuxupbzlpzmikel
+nscghlafavnsycjh
+xorwbquzmgmcapon
+asmtiycegeobfxrn
+eqjzvgkxgtlyuxok
+mmjrskloposgjoqu
+gceqosugbkvytfto
+khivvoxkvhrgwzjl
+qtmejuxbafroifjt
+ttmukbmpoagthtfl
+bxqkvuzdbehtduwv
+gvblrpzjylanoggj
+cltewhyjxdbmbtqj
+fbkgedqvomdipklj
+uxvuplhenqawfcjt
+fkdjmayiawdkycva
+gnloqfgbnibzyidh
+kyzorvtopjiyyyqg
+drckpekhpgrioblt
+tvhrkmbnpmkkrtki
+khaldwntissbijiz
+aoojqakosnaxosom
+xfptccznbgnpfyqw
+moqdwobwhjxhtrow
+chfwivedutskovri
+gprkyalfnpljcrmi
+pwyshpwjndasykst
+xuejivogihttzimd
+bugepxgpgahtsttl
+zufmkmuujavcskpq
+urybkdyvsrosrfro
+isjxqmlxwtqmulbg
+pxctldxgqjqhulgz
+hclsekryiwhqqhir
+hbuihpalwuidjpcq
+ejyqcxmfczqfhbxa
+xljdvbucuxnnaysv
+irqceqtqwemostbb
+anfziqtpqzqdttnz
+cgfklbljeneeqfub
+zudyqkuqqtdcpmuo
+iuvhylvznmhbkbgg
+mpgppmgfdzihulnd
+argwmgcvqqkxkrdi
+pdhrfvdldkfihlou
+cbvqnjrvrsnqzfob
+lkvovtsqanohzcmm
+vxoxjdyoylqcnyzt
+kurdpaqiaagiwjle
+gwklwnazaxfkuekn
+rbaamufphjsjhbdl
+tzbrvaqvizhsisbd
+pbcqlbfjvlideiub
+hiwoetbfywaeddtx
+fjirczxtuupfywyf
+omeoegeyyospreem
+ozbbpupqpsskvrjh
+pzvcxkvjdiyeyhxa
+odclumkenabcsfzr
+npdyqezqdjqaszvm
+yodkwzmrhtexfrqa
+rjcmmggjtactfrxz
+mioxfingsfoimual
+aqskaxjjborspfaa
+wientdsttkevjtkf
+tdaswkzckmxnfnct
+voucjhzvkkhuwoqk
+boaaruhalgaamqmh
+iufzxutxymorltvb
+pfbyvbayvnrpijpo
+obztirulgyfthgcg
+ntrenvhwxypgtjwy
+ephlkipjfnjfjrns
+pkjhurzbmobhszpx
+gqbnjvienzqfbzvj
+wjelolsrbginwnno
+votanpqpccxqricj
+bxyuyiglnmbtvehi
+qyophcjfknbcbjrb
+anoqkkbcdropskhj
+tcnyqaczcfffkrtl
+rsvqimuqbuddozrf
+meppxdrenexxksdt
+tyfhfiynzwadcord
+wayrnykevdmywycf
+mhowloqnppswyzbu
+tserychksuwrgkxz
+xycjvvsuaxsbrqal
+fkrdsgaoqdcqwlpn
+vrabcmlhuktigecp
+xgxtdsvpaymzhurx
+ciabcqymnchhsxkc
+eqxadalcxzocsgtr
+tsligrgsjtrnzrex
+qeqgmwipbspkbbfq
+vzkzsjujltnqwliw
+ldrohvodgbxokjxz
+jkoricsxhipcibrq
+qzquxawqmupeujrr
+mizpuwqyzkdbahvk
+suupfxbtoojqvdca
+ywfmuogvicpywpwm
+uevmznxmsxozhobl
+vjbyhsemwfwdxfxk
+iyouatgejvecmtin
+tcchwpuouypllcxe
+lgnacnphdiobdsef
+uoxjfzmdrmpojgbf
+lqbxsxbqqhpjhfxj
+knpwpcnnimyjlsyz
+fezotpoicsrshfnh
+dkiwkgpmhudghyhk
+yzptxekgldksridv
+pckmzqzyiyzdbcts
+oqshafncvftvwvsi
+yynihvdywxupqmbt
+iwmbeunfiuhjaaic
+pkpkrqjvgocvaxjs
+ieqspassuvquvlyz
+xshhahjaxjoqsjtl
+fxrrnaxlqezdcdvd
+pksrohfwlaqzpkdd
+ravytrdnbxvnnoyy
+atkwaifeobgztbgo
+inkcabgfdobyeeom
+ywpfwectajohqizp
+amcgorhxjcybbisv
+mbbwmnznhafsofvr
+wofcubucymnhuhrv
+mrsamnwvftzqcgta
+tlfyqoxmsiyzyvgv
+ydceguvgotylwtea
+btyvcjqhsygunvle
+usquiquspcdppqeq
+kifnymikhhehgote
+ybvkayvtdpgxfpyn
+oulxagvbavzmewnx
+tvvpekhnbhjskzpj
+azzxtstaevxurboa
+nfmwtfgrggmqyhdf
+ynyzypdmysfwyxgr
+iaobtgubrcyqrgmk
+uyxcauvpyzabbzgv
+fbasfnwiguasoedc
+mgmjoalkbvtljilq
+szgkxiqkufdvtksb
+xgfzborpavdmhiuj
+hmuiwnsonvfgcrva
+zolcffdtobfntifb
+mvzgcsortkugvqjr
+pbbpgraaldqvzwhs
+zvsxegchksgnhpuv
+kdpdboaxsuxfswhx
+jdfggigejfupabth
+tpeddioybqemyvqz
+mxsntwuesonybjby
+tzltdsiojfvocige
+ubtdrneozoejiqrv
+fusyucnhncoxqzql
+nlifgomoftdvkpby
+pyikzbxoapffbqjw
+hzballplvzcsgjug
+ymjyigsfehmdsvgz
+vpqgyxknniunksko
+ffkmaqsjxgzclsnq
+jcuxthbedplxhslk
+ymlevgofmharicfs
+nyhbejkndhqcoisy
+rjntxasfjhnlizgm
+oqlnuxtzhyiwzeto
+tntthdowhewszitu
+rmxyoceuwhsvfcua
+qpgsjzwenzbxyfgw
+sumguxpdkocyagpu
+ymfrbxwrawejkduu
+hetgrtmojolbmsuf
+qzqizpiyfasgttex
+qnmoemcpuckzsshx
+ddyqiihagcmnxccu
+oirwxyfxxyktgheo
+phpaoozbdogbushy
+uctjdavsimsrnvjn
+aurbbphvjtzipnuh
+hpbtrubopljmltep
+pyyvkthqfsxqhrxg
+jdxaiqzkepxbfejk
+ukgnwbnysrzvqzlw
+lfkatkvcssnlpthd
+ucsyecgshklhqmsc
+rwdcbdchuahkvmga
+rxkgqakawgpwokum
+hbuyxeylddfgorgu
+tbllspqozaqzglkz
+rqfwizjlbwngdvvi
+xuxduyzscovachew
+kouiuxckkvmetvdy
+ycyejrpwxyrweppd
+trctlytzwiisjamx
+vtvpjceydunjdbez
+gmtlejdsrbfofgqy
+jgfbgtkzavcjlffj
+tyudxlpgraxzchdk
+gyecxacqitgozzgd
+rxaocylfabmmjcvt
+tornfzkzhjyofzqa
+kocjcrqcsvagmfqv
+zfrswnskuupivzxb
+cunkuvhbepztpdug
+pmpfnmklqhcmrtmf
+tfebzovjwxzumxap
+xpsxgaswavnzkzye
+lmwijdothmxclqbr
+upqxhmctbltxkarl
+axspehytmyicthmq
+xdwrhwtuooikehbk
+tpggalqsytvmwerj
+jodysbwnymloeqjf
+rxbazvwuvudqlydn
+ibizqysweiezhlqa
+uexgmotsqjfauhzp
+ldymyvumyhyamopg
+vbxvlvthgzgnkxnf
+pyvbrwlnatxigbrp
+azxynqididtrwokb
+lwafybyhpfvoawto
+ogqoivurfcgspytw
+cinrzzradwymqcgu
+sgruxdvrewgpmypu
+snfnsbywuczrshtd
+xfzbyqtyxuxdutpw
+fmpvjwbulmncykbo
+ljnwoslktrrnffwo
+ceaouqquvvienszn
+yjomrunrxjyljyge
+xpmjsapbnsdnbkdi
+uetoytptktkmewre
+eixsvzegkadkfbua
+afaefrwhcosurprw
+bwzmmvkuaxiymzwc
+gejyqhhzqgsrybni
+gjriqsfrhyguoiiw
+gtfyomppzsruhuac
+ogemfvmsdqqkfymr
+jgzbipsygirsnydh
+zghvlhpjnvqmocgr
+ngvssuwrbtoxtrka
+ietahyupkbuisekn
+gqxqwjizescbufvl
+eiprekzrygkncxzl
+igxfnxtwpyaamkxf
+soqjdkxcupevbren
+fspypobyzdwstxak
+qstcgawvqwtyyidf
+gsccjacboqvezxvd
+bfsblokjvrqzphmc
+srezeptvjmncqkec
+opmopgyabjjjoygt
+msvbufqexfrtecbf
+uiaqweyjiulplelu
+pbkwhjsibtwjvswi
+xwwzstmozqarurrq
+nytptwddwivtbgyq
+ejxvsufbzwhzpabr
+jouozvzuwlfqzdgh
+gfgugjihbklbenrk
+lwmnnhiuxqsfvthv
+bzvwbknfmaeahzhi
+cgyqswikclozyvnu
+udmkpvrljsjiagzi
+zzuhqokgmisguyna
+ekwcdnjzuctsdoua
+eueqkdrnzqcaecyd
+lnibwxmokbxhlris
+fdrbftgjljpzwhea
+iabvuhhjsxmqfwld
+qgogzkynrgejakta
+mfcqftytemgnpupp
+klvhlhuqhosvjuqk
+gdokmxcgoqvzvaup
+juududyojcazzgvr
+fyszciheodgmnotg
+yfpngnofceqfvtfs
+cahndkfehjumwavc
+dxsvscqukljxcqyi
+cqukcjtucxwrusji
+vevmmqlehvgebmid
+ahswsogfrumzdofy
+ftasbklvdquaxhxb
+tsdeumygukferuif
+ybfgbwxaaitpwryg
+djyaoycbymezglio
+trzrgxdjqnmlnzpn
+rumwchfihhihpqui
+ffrvnsgrnzemksif
+oizlksxineqknwzd
+cirqcprftpjzrxhk
+zrhemeqegmzrpufd
+kqgatudhxgzlgkey
+syjugymeajlzffhq
+nlildhmgnwlopohp
+flcszztfbesqhnyz
+ohzicmqsajyqptrw
+ebyszucgozsjbelq
+enxbgvvcuqeloxud
+ubwnvecbsmhkxwuk
+noifliyxvlkqphbo
+hazlqpetgugxxsiz
+ihdzoerqwqhgajzb
+ivrdwdquxzhdrzar
+synwycdvrupablib
+mqkdjkntblnmtvxj
+qmmvoylxymyovrnq
+pjtuxskkowutltlq
+gchrqtloggkrjciz
+namzqovvsdipazae
+yfokqhkmakyjzmys
+iapxlbuoiwqfnozm
+fbcmlcekgfdurqxe
+ednzgtczbplwxjlq
+gdvsltzpywffelsp
+oaitrrmpqdvduqej
+gseupzwowmuuibjo
+dfzsffsqpaqoixhh
+tclhzqpcvbshxmgx
+cfqkptjrulxiabgo
+iraiysmwcpmtklhf
+znwjlzodhktjqwlm
+lcietjndlbgxzjht
+gdkcluwjhtaaprfo
+vbksxrfznjzwvmmt
+vpfftxjfkeltcojl
+thrmzmeplpdespnh
+yafopikiqswafsit
+xxbqgeblfruklnhs
+qiufjijzbcpfdgig
+ikksmllfyvhyydmi
+sknufchjdvccccta
+wpdcrramajdoisxr
+grnqkjfxofpwjmji
+lkffhxonjskyccoh
+npnzshnoaqayhpmb
+fqpvaamqbrnatjia
+oljkoldhfggkfnfc
+ihpralzpqfrijynm
+gvaxadkuyzgbjpod
+onchdguuhrhhspen
+uefjmufwlioenaus
+thifdypigyihgnzo
+ugqblsonqaxycvkg
+yevmbiyrqdqrmlbw
+bvpvwrhoyneorcmm
+gbyjqzcsheaxnyib
+knhsmdjssycvuoqf
+nizjxiwdakpfttyh
+nwrkbhorhfqqoliz
+ynsqwvwuwzqpzzwp
+yitscrgexjfclwwh
+dhajwxqdbtrfltzz
+bmrfylxhthiaozpv
+frvatcvgknjhcndw
+xlvtdmpvkpcnmhya
+pxpemuzuqzjlmtoc
+dijdacfteteypkoq
+knrcdkrvywagglnf
+fviuajtspnvnptia
+xvlqzukmwbcjgwho
+bazlsjdsjoeuvgoz
+nslzmlhosrjarndj
+menvuwiuymknunwm
+uavfnvyrjeiwqmuu
+yrfowuvasupngckz
+taevqhlrcohlnwye
+skcudnogbncusorn
+omtnmkqnqedsajfv
+yqmgsqdgsuysqcts
+odsnbtyimikkbmdd
+vuryaohxdvjllieb
+dhaxldeywwsfamlo
+opobvtchezqnxpak
+pzfnegouvsrfgvro
+rzkcgpxdslzrdktu
+ksztdtqzxvhuryam
+ctnqnhkcooqipgkh
+pyqbbvrzdittqbgm
+koennvmolejeftij
+rvzlreqikqlgyczj
+xrnujfoyhonzkdgd
+mmsmhkxaiqupfjil
+ypjwoemqizddvyfd
+qgugcxnbhvgahykj
+cviodlsrtimbkgmy
+xbfbbechhmrjxhnw
+psuipaoucfczfxkp
+hdhwcpeuptgqqvim
+gsxlruhjeaareilr
+vgyqonnljuznyrhk
+eewezahlumervpyu
+iiolebrxfadtnigy
+tdadlrodykrdfscn
+ocvdtzjxrhtjurpo
+gidljbuvuovkhhrf
+qwfcpilbjwzboohd
+xzohxonlezuiupbg
+vslpbkkqgvgbcbix
+pivzqrzfxosbstzn
+fyqcfboevcqmbhhs
+yqsrneacnlxswojx
+heicqpxxyrwcbsjz
+yzynmnnoumkmlbeh
+bncadbjdvvmczylw
+hlnjskgfzbgmigfn
+fphpszymugpcykka
+zbifcktanxpmufvy
+saklpkhoyfeqbguy
+nqtqfcfxmpivnjyo
+locygrwerxlsvzqm
+qqflecydqvlogjme
+njklmixvgkzpgppf
+ugzkpjwjflaswyma
+lriousvkbeftslcy
+nsvsauxzfbbotgmh
+tblcpuhjyybrlica
+hqwshxcilwtmxrsf
+xojwroydfeoqupup
+tikuzsrogpnohpib
+layenyqgxdfggloc
+nqsvjvbrpuxkqvmq
+ivchgxkdlfjdzxmk
+uoghiuosiiwiwdws
+twsgsfzyszsfinlc
+waixcmadmhtqvcmd
+zkgitozgrqehtjkw
+xbkmyxkzqyktmpfi
+qlyapfmlybmatwxn
+ntawlvcpuaebuypf
+clhebxqdkcyndyof
+nrcxuceywiklpemc
+lmurgiminxpapzmq
+obalwqlkykzflxou
+huvcudpiryefbcye
+zlxbddpnyuyapach
+gqfwzfislmwzyegy
+jhynkjtxedmemlob
+hmrnvjodnsfiukex
+pstmikjykzyavfef
+wuwpnscrwzsyalyt
+hksvadripgdgwynm
+tvpfthzjleqfxwkh
+xpmrxxepkrosnrco
+qjkqecsnevlhqsly
+jjnrfsxzzwkhnwdm
+pehmzrzsjngccale
+bsnansnfxduritrr
+ejzxkefwmzmbxhlb
+pceatehnizeujfrs
+jtidrtgxopyeslzl
+sytaoidnamfwtqcr
+iabjnikomkgmyirr
+eitavndozoezojsi
+wtsbhaftgrbqfsmm
+vvusvrivsmhtfild
+qifbtzszfyzsjzyx
+ifhhjpaqatpbxzau
+etjqdimpyjxiuhty
+fvllmbdbsjozxrip
+tjtgkadqkdtdlkpi
+xnydmjleowezrecn
+vhcbhxqalroaryfn
+scgvfqsangfbhtay
+lbufpduxwvdkwhmb
+tshipehzspkhmdoi
+gtszsebsulyajcfl
+dlrzswhxajcivlgg
+kgjruggcikrfrkrw
+xxupctxtmryersbn
+hljjqfjrubzozxts
+giaxjhcwazrenjzs
+tyffxtpufpxylpye
+jfugdxxyfwkzqmgv
+kbgufbosjghahacw
+xpbhhssgegmthwxb
+npefofiharjypyzk
+velxsseyxuhrpycy
+sglslryxsiwwqzfw
+susohnlpelojhklv
+lfnpqfvptqhogdmk
+vtcrzetlekguqyle
+jlyggqdtamcjiuxn
+olxxqfgizjmvigvl
+cyypypveppxxxfuq
+hewmxtlzfqoqznwd
+jzgxxybfeqfyzsmp
+xzvvndrhuejnzesx
+esiripjpvtqqwjkv
+xnhrwhjtactofwrd
+knuzpuogbzplofqx
+tihycsdwqggxntqk
+xkfywvvugkdalehs
+cztwdivxagtqjjel
+dsaslcagopsbfioy
+gmowqtkgrlqjimbl
+ctcomvdbiatdvbsd
+gujyrnpsssxmqjhz
+nygeovliqjfauhjf
+mmgmcvnuppkbnonz
+bhipnkoxhzcotwel
+wkwpgedgxvpltqid
+mliajvpdocyzcbot
+kqjhsipuibyjuref
+zqdczykothbgxwsy
+koirtljkuqzxioaz
+audpjvhmqzvhzqas
+cxyhxlhntyidldfx
+iasgocejboxjgtkx
+abehujmqotwcufxp
+fmlrzqmazajxeedl
+knswpkekbacuxfby
+yvyalnvrxgstqhxm
+sjnrljfrfuyqfwuw
+ssaqruwarlvxrqzm
+iaxbpeqqzlcwfqjz
+uwyxshjutkanvvsc
+uxwrlwbblcianvnb
+nodtifgrxdojhneh
+mloxjfusriktxrms
+lkfzrwulbctupggc
+gcrjljatfhitcgfj
+tkdfxeanwskaivqs
+ypyjxqtmitwubbgt
+ssxbygzbjsltedjj
+zdrsnoorwqfalnha
+xlgmissaiqmowppd
+azhbwhiopwpguiuo
+fydlahgxtekbweet
+qtaveuqpifprdoiy
+kpubqyepxqleucem
+wlqrgqmnupwiuory
+rwyocktuqkuhdwxz
+abzjfsdevoygctqv
+zsofhaqqghncmzuw
+lqbjwjqxqbfgdckc
+bkhyxjkrqbbunido
+yepxfjnnhldidsjb
+builayfduxbppafc
+wedllowzeuswkuez
+gverfowxwtnvgrmo
+tpxycfumxdqgntwf
+lqzokaoglwnfcolw
+yqsksyheyspmcdqt
+vufvchcjjcltwddl
+saeatqmuvnoacddt
+dxjngeydvsjbobjs
+ucrcxoakevhsgcep
+cajgwjsfxkasbayt
+hknzmteafsfemwuv
+xxwhxwiinchqqudr
+usfenmavvuevevgr
+kxcobcwhsgyizjok
+vhqnydeboeunnvyk
+bgxbwbxypnxvaacw
+bwjzdypacwgervgk
+rrioqjluawwwnjcr
+fiaeyggmgijnasot
+xizotjsoqmkvhbzm
+uzphtrpxwfnaiidz
+kihppzgvgyoncptg
+hfbkfrxwejdeuwbz
+zgqthtuaqyrxicdy
+zitqdjnnwhznftze
+jnzlplsrwovxlqsn
+bmwrobuhwnwivpca
+uuwsvcdnoyovxuhn
+nmfvoqgoppoyosaj
+hxjkcppaisezygpe
+icvnysgixapvtoos
+vbvzajjgrmjygkhu
+jinptbqkyqredaos
+dpmknzhkhleawfvz
+ouwwkfhcedsgqqxe
+owroouiyptrijzgv
+bewnckpmnbrmhfyu
+evdqxevdacsbfbjb
+catppmrovqavxstn
+dqsbjibugjkhgazg
+mkcldhjochtnvvne
+sblkmhtifwtfnmsx
+lynnaujghehmpfpt
+vrseaozoheawffoq
+ytysdzbpbazorqes
+sezawbudymfvziff
+vrlfhledogbgxbau
+bipdlplesdezbldn
+ermaenjunjtbekeo
+eyaedubkthdecxjq
+gbzurepoojlwucuy
+rsiaqiiipjlouecx
+beqjhvroixhiemtw
+buzlowghhqbcbdwv
+ldexambveeosaimo
+fpyjzachgrhxcvnx
+komgvqejojpnykol
+fxebehjoxdujwmfu
+jnfgvheocgtvmvkx
+qmcclxxgnclkuspx
+rsbelzrfdblatmzu
+vexzwqjqrsenlrhm
+tnfbkclwetommqmh
+lzoskleonvmprdri
+nnahplxqscvtgfwi
+ubqdsflhnmiayzrp
+xtiyqxhfyqonqzrn
+omdtmjeqhmlfojfr
+cnimgkdbxkkcnmkb
+tapyijgmxzbmqnks
+byacsxavjboovukk
+awugnhcrygaoppjq
+yxcnwrvhojpuxehg
+btjdudofhxmgqbao
+nzqlfygiysfuilou
+nubwfjdxavunrliq
+vqxmmhsbmhlewceh
+ygavmcybepzfevrp
+kgflmrqsvxprkqgq
+iaqyqmcaedscmakk
+cvbojnbfmrawxzkh
+jjjrprbnlijzatuw
+lcsudrrfnnggbrmk
+qzgxbiavunawfibc
+gnnalgfvefdfdwwg
+nokmiitzrigxavsc
+etzoxwzxqkkhvais
+urxxfacgjccieufi
+lqrioqhuvgcotuec
+dydbaeyoypsbftra
+hhrotenctylggzaf
+evctqvzjnozpdxzu
+tbpvithmorujxlcp
+pllbtcbrtkfpvxcw
+fzyxdqilyvqreowv
+xdleeddxwvqjfmmt
+fcldzthqqpbswoin
+sgomzrpjfmvgwlzi
+axjyskmtdjbxpwoz
+hcvaevqxsmabvswh
+lfdlsfcwkwicizfk
+isjbwpzdognhoxvm
+oqnexibqxlyxpluh
+zqfbgodsfzwgcwuf
+kvmnwruwsjllbldz
+kghazimdyiyhmokj
+uiktgpsxpoahofxn
+zkdwawxargcmidct
+ftbixlyiprshrjup
+nofhmbxififwroeg
+mcdaqrhplffxrcdt
+fbjxnwojcvlawmlb
+rizoftvwfdhiwyac
+eduogrtyhxfwyars
+zoikunqxgjwfqqwr
+zxwbbpmvctzezaqh
+nghujwyeabwdqnop
+vcxamijpoyyksogn
+jnckdbuteoqlsdae
+jurfqqawafmsiqwv
+inepmztrzehfafie
+tznzkyvzodbrtscf
+xewbavjeppflwscl
+ucndzsorexjlnplo
+jpxbctscngxgusvu
+mfmygcllauzuoaok
+oibkuxhjmhxhhzby
+zjkslwagmeoisunw
+avnnxmopdgvmukuu
+jmaargejcwboqhkt
+yacmpeosarsrfkrv
+iqhgupookcaovwgh
+ebjkdnxwtikqzufc
+imdhbarytcscbsvb
+ifyibukeffkbqvcr
+aloighmyvwybtxhx
+yszqwrutbkiwkxjg
+xyholyzlltjhsuhp
+gykhmrwucneoxcrf
+badkdgqrpjzbabet
+sunaucaucykwtkjj
+pumqkglgfdhneero
+usgtyuestahlydxq
+xmfhflphzeudjsjm
+knywgmclisgpootg
+mtojnyrnvxtweuzb
+uuxufbwfegysabww
+vobhwwocqttlbsik
+yuydfezeqgqxqmnd
+wbqgqkwbibiilhzc
+sfdmgxsbuzsawush
+ilhbxcfgordyxwvp
+ahqoavuysblnqaeg
+plwgtvpgotskmsey
+ewjcmzkcnautrrmp
+tyekgzbznlikcyqj
+bqzctiuaxpriuiga
+bimvbfjkiupyqiys
+mpqtbcxfhwymxncw
+htemlptvqhharjgb
+mqbsmsruwzzxgcxc
+zjyedjwhnvteuaid
+pzoelkoidwglpttc
+efydnsvlfimvwxhx
+gfyhgoeiyjcgfyze
+deqtomhwopmzvjlt
+casafubtkoopuaju
+yylsfarntbucfulg
+mgjwsormkjsrrxan
+lkkenpupgmjpnqqd
+tegweszyohsoluot
+lihsfdwxmxvwdxna
+rrefrjjxerphejwb
+guuazonjoebhymtm
+ysofqzmfmyneziki
+lmjgaliatcpduoal
+qzthcpjwtgahbebr
+wvakvephyukmpemm
+simxacxxzfoaeddw
+aetgqmiqzxbvbviz
+jxlmhdmqggevrxes
+mmuglnjmuddzgaik
+svopsqhtrslgycgc
+xnvcsiiqrcjkvecn
+kkvumxtvashxcops
+bduflsdyeectvcgl
+vfrxbwmmytjvqnsj
+eeqtdneiyiaiofxw
+crtbgknfacjtwkfl
+uuutuoxdsxolpbhd
+lcrztwzreaswovtn
+htorkvnvujmjdqzj
+wttzuzvrzlyhfzyf
+oraewznfwgdsnhuk
+rctlkqqvkwbgrcgk
+cfehrsrqhzyiwtmz
+kbvxwcumjkhvjpui
+xxlocexbmniiakfo
+gtknkkzvykmlqghl
+kcjuxvkuimhwqrtk
+vohekwkuyuoacuww
+vorctgughscysyfo
+zmjevqplngzswxyq
+qhswdrhrijnatkyo
+joakcwpfggtitizs
+juzlwjijcmtswdtq
+icbyaqohpkemhkip
+rpdxgpzxncedmvzh
+rozkmimbqhbhcddv
+wkkypomlvyglpfpf
+jcaqyaqvsefwtaya
+ghvmtecoxlebdwnf
+lqrcyiykkkpkxvqt
+eqlarfazchmzotev
+vqwndafvmpguggef
+dbfxzrdkkrusmdke
+cmjpjjgndozcmefj
+hbrdcwjuyxapyhlo
+mmforetykbosdwce
+zynfntqwblbnfqik
+sodwujfwlasznaiz
+yyvrivjiqnxzqkfp
+uldbskmmjbqllpnm
+fyhhrmrsukeptynl
+hpfjekktvdkgdkzl
+bozhkoekcxzeorob
+uvpptyfrzkvmtoky
+hkhfprmjdpjvfkcb
+igxzwktwsqhsivqu
+qceomwysgkcylipb
+cglateoynluyeqgc
+xcsdfkpeguxgvpfh
+owjhxlcncdgkqyia
+rpbmrpcesiakqpna
+lueszxiourxsmezb
+zelvsowimzkxliwc
+vzxbttoobtvdtkca
+pfxvzphzwscqkzsi
+edsjorainowytbzu
+ipsegdaluoiphmnz
+mkhueokfpemywvuw
+urxdnumhylpafdlc
+ggluurzavsxkvwkl
+ctclphidqgteakox
+tfobosynxsktajuk
+jzrmemhxqmzhllif
+eemwekimdfvqslsx
+yjkwpzrbanoaajgq
+rlxghzanuyeimfhx
+hozbgdoorhthlqpv
+obkbmflhyanxilnx
+xojrippyxjmpzmsz
+ukykmbfheixuviue
+qivlmdexwucqkres
+rmyxxipqkarpjmox
+fgaftctbvcvnrror
+raawxozucfqvasru
+dinpjbdfjfizexdh
+gybxubwnnbuyvjcr
+qrqitdvyoneqyxcg
+jqzcfggayzyoqteo
+cikqpvxizpdbmppm
+stfpldgyhfmucjjv
+slzbcuihmimpduri
+aufajwfrsorqqsnl
+iylmzraibygmgmqj
+lcdyfpcqlktudfmu
+pmomzzsdpvgkkliw
+zpplirgtscfhbrkj
+mvhyerxfiljlotjl
+ofkvrorwwhusyxjx
+xngzmvcgkqfltjpe
+yxfxaqipmysahqqq
+sdqafdzgfdjuabup
+qcqajmerahcdgxfv
+xqimrqtupbapawro
+qfvkqwidzzrehsbl
+himixxvueksiqfdf
+vgtfqpuzxxmhrvvd
+adiioqeiejguaost
+jnzxuycjxvxehbvm
+xedbpxdhphamoodk
+jsrioscmwlsfuxrg
+mtsynnfxunuohbnf
+enamqzfzjunnnkpe
+uwcvfecunobyhces
+ciygixtgbsccpftq
+ewjgcronizkcsfjy
+wztjkoipxsikoimv
+jrgalyvfelwxforw
+imylyalawbqwkrwb
+yflwqfnuuvgjsgcj
+wkysyzusldlojoue
+zopllxnidcffcuau
+bscgwxuprxaerskj
+zvnvprxxjkhnkkpq
+nejwxbhjxxdbenid
+chryiccsebdbcnkc
+guoeefaeafhlgvxh
+nzapxrfrrqhsingx
+mkzvquzvqvwsejqs
+kozmlmbchydtxeeo
+keylygnoqhmfzrfp
+srwzoxccndoxylxe
+uqjzalppoorosxxo
+potmkinyuqxsfdfw
+qkkwrhpbhypxhiun
+wgfvnogarjmdbxyh
+gkidtvepcvxopzuf
+atwhvmmdvmewhzty
+pybxizvuiwwngqej
+zfumwnazxwwxtiry
+keboraqttctosemx
+vtlzxaqdetbhclib
+wjiecykptzexuayl
+ejatfnyjjdawepyk
+mpcrobansyssvmju
+gqukndzganeueabm
+ukzscvomorucdnqd
+wfydhtbzehgwfazx
+mtwqdzlephqvxqmx
+dltmlfxbjopefibh
+atcfrowdflluqtbi
+vowawlophlxaqonw
+vblgdjzvwnocdipw
+uzerzksmkvnlvlhm
+ytjwhpaylohorvxd
+siprvfxvnxcdgofz
+cbhjupewcyjhvtgs
+apqtozaofusmfqli
+tmssrtlxfouowqnr
+ntutrvwnzzgmokes
+zrsgpwdzokztdpis
+nrobvmsxtfmrqdhv
+kadkaftffaziqdze
+yrovbgcyqtlsnoux
+modheiwuhntdecqs
+gzhjypwddizemnys
+gaputpwpcsvzxjho
+bgmouxwoajgaozau
+oxuapfrjcpyakiwt
+kntwbvhuaahdixzj
+epqjdjbnkxdnaccx
+dspltdvznhypykri
+tdrgqmbnagrxdwtt
+njfqawzjggmemtbg
+chpemsgwpzjpdnkk
+fpsrobmbqbmigmwk
+flxptsrqaazmprnl
+nzdunrxlcbfklshm
+miuwljvtkgzdlbnn
+xbhjakklmbhsdmdt
+xwxhsbnrwnegwcov
+pwosflhodjaiexwq
+fhgepuluczttfvqh
+tldxcacbvxyamvkt
+gffxatrjglkcehim
+tzotkdrpxkucsdps
+wxheftdepysvmzbe
+qfooyczdzoewrmku
+rvlwikuqdbpjuvoo
+bcbrnbtfrdgijtzt
+vaxqmvuogsxonlgq
+ibsolflngegravgo
+txntccjmqakcoorp
+vrrbmqaxfbarmlmc
+dzspqmttgsuhczto
+pikcscjunxlwqtiw
+lwzyogwxqitqfqlv
+gsgjsuaqejtzglym
+feyeqguxbgmcmgpp
+gmttebyebdwvprkn
+mzuuwbhzdjfdryxu
+fganrbnplymqbzjx
+cvsrbdcvhtxxdmro
+scmgkjlkqukoamyp
+fkgrqbyqpqcworqc
+hjsrvkdibdjarxxb
+sztzziuqroeidcus
+pxdfvcpvwaddrzwv
+phdqqxleqdjfgfbg
+cqfikbgxvjmnfncy
diff --git a/6/1.c b/6/1.c
new file mode 100644
index 0000000..2a8504e
--- /dev/null
+++ b/6/1.c
@@ -0,0 +1,92 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+enum {
+ WIDTH = 1000,
+ HEIGHT = 1000,
+};
+
+struct instr {
+ enum action {
+ A_OFF,
+ A_ON,
+ A_TOGGLE,
+ } act;
+ struct pos {
+ unsigned short x, y;
+ } start, end;
+};
+
+unsigned short read_be16(void *_buf)
+{
+ unsigned char *buf = _buf;
+ return (buf[0] << 8) | buf[1];
+}
+
+bool read_instr(struct instr *i, FILE *f)
+{
+ unsigned char buf[9];
+ unsigned short v;
+
+ assert(i != NULL);
+ assert(f != NULL);
+
+ if (fread(buf, sizeof buf, 1, f) != 1)
+ return false;
+ switch (buf[0]) {
+ case 0xff: i->act = A_OFF; break;
+ case 1: i->act = A_ON; break;
+ case 2: i->act = A_TOGGLE; break;
+ default: return false;
+ }
+
+#define SET(f, p) { \
+ v = read_be16(&buf[p]); \
+ if (v > 999) \
+ return false; \
+ i->f = v; \
+ }
+ SET(start.x, 1);
+ SET(start.y, 3);
+ SET(end.x, 5);
+ SET(end.y, 7);
+
+ return true;
+}
+
+int main(void)
+{
+ char *map[] = { "turn off", "turn on", "toggle" };
+ bool screen[WIDTH][HEIGHT] = { 0 };
+ struct instr i;
+ int count = 0;
+ FILE *f;
+
+ f = fopen("inputbin", "rb");
+ if (f == NULL)
+ exit(EXIT_FAILURE);
+
+ while (read_instr(&i, f)) {
+ for (int y = i.start.y; y <= i.end.y; y++) {
+ for (int x = i.start.x; x <= i.end.x; x++) {
+ switch (i.act) {
+ case A_OFF: screen[x][y] = false; break;
+ case A_ON: screen[x][y] = true; break;
+ case A_TOGGLE:
+ screen[x][y] = !screen[x][y];
+ break;
+ }
+ }
+ }
+ }
+
+ fclose(f);
+
+ for (int y = 0; y < HEIGHT; y++)
+ for (int x = 0; x < WIDTH; x++)
+ count += screen[x][y];
+
+ printf("%d\n", count);
+}
diff --git a/6/2.c b/6/2.c
new file mode 100644
index 0000000..c9d1083
--- /dev/null
+++ b/6/2.c
@@ -0,0 +1,89 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+enum {
+ WIDTH = 1000,
+ HEIGHT = 1000,
+};
+
+struct instr {
+ signed char db;
+ struct pos {
+ unsigned short x, y;
+ } start, end;
+};
+
+unsigned short read_be16(void *_buf)
+{
+ unsigned char *buf = _buf;
+ return (buf[0] << 8) | buf[1];
+}
+
+bool read_instr(struct instr *i, FILE *f)
+{
+ unsigned char buf[9];
+ signed char db;
+ unsigned short v;
+
+ assert(i != NULL);
+ assert(f != NULL);
+
+ if (fread(buf, sizeof buf, 1, f) != 1)
+ return false;
+ if (buf[0] <= 127)
+ db = buf[0];
+ else {
+ db = -0x80;
+ db += buf[0] - 0x80;
+ }
+ if (db < -1 || db > 2) {
+ fprintf(stderr, "this db is crazy: %d -> %d\n", buf[0], db);
+ return false;
+ }
+ i->db = db;
+
+#define SET(f, p) { \
+ v = read_be16(&buf[p]); \
+ if (v > 999) \
+ return false; \
+ i->f = v; \
+ }
+ SET(start.x, 1);
+ SET(start.y, 3);
+ SET(end.x, 5);
+ SET(end.y, 7);
+
+ return true;
+}
+
+int main(void)
+{
+ int screen[WIDTH][HEIGHT] = { 0 };
+ unsigned long long total;
+ struct instr i;
+ FILE *f;
+
+ f = fopen("inputbin", "rb");
+ if (f == NULL)
+ exit(EXIT_FAILURE);
+
+ while (read_instr(&i, f)) {
+ for (int y = i.start.y; y <= i.end.y; y++) {
+ for (int x = i.start.x; x <= i.end.x; x++) {
+ screen[x][y] += i.db;
+ if (screen[x][y] < 0)
+ screen[x][y] = 0;
+ }
+ }
+ }
+
+ fclose(f);
+
+ total = 0;
+ for (int y = 0; y < HEIGHT; y++)
+ for (int x = 0; x < WIDTH; x++)
+ total += screen[x][y];
+ printf("%llu\n", total);
+}
diff --git a/6/input b/6/input
new file mode 100644
index 0000000..d6cfb3a
--- /dev/null
+++ b/6/input
@@ -0,0 +1,300 @@
+toggle 461,550 through 564,900
+turn off 370,39 through 425,839
+turn off 464,858 through 833,915
+turn off 812,389 through 865,874
+turn on 599,989 through 806,993
+turn on 376,415 through 768,548
+turn on 606,361 through 892,600
+turn off 448,208 through 645,684
+toggle 50,472 through 452,788
+toggle 205,417 through 703,826
+toggle 533,331 through 906,873
+toggle 857,493 through 989,970
+turn off 631,950 through 894,975
+turn off 387,19 through 720,700
+turn off 511,843 through 581,945
+toggle 514,557 through 662,883
+turn off 269,809 through 876,847
+turn off 149,517 through 716,777
+turn off 994,939 through 998,988
+toggle 467,662 through 555,957
+turn on 952,417 through 954,845
+turn on 565,226 through 944,880
+turn on 214,319 through 805,722
+toggle 532,276 through 636,847
+toggle 619,80 through 689,507
+turn on 390,706 through 884,722
+toggle 17,634 through 537,766
+toggle 706,440 through 834,441
+toggle 318,207 through 499,530
+toggle 698,185 through 830,343
+toggle 566,679 through 744,716
+toggle 347,482 through 959,482
+toggle 39,799 through 981,872
+turn on 583,543 through 846,710
+turn off 367,664 through 595,872
+turn on 805,439 through 964,995
+toggle 209,584 through 513,802
+turn off 106,497 through 266,770
+turn on 975,2 through 984,623
+turn off 316,684 through 369,876
+turn off 30,309 through 259,554
+turn off 399,680 through 861,942
+toggle 227,740 through 850,829
+turn on 386,603 through 552,879
+turn off 703,795 through 791,963
+turn off 573,803 through 996,878
+turn off 993,939 through 997,951
+turn on 809,221 through 869,723
+turn off 38,720 through 682,751
+turn off 318,732 through 720,976
+toggle 88,459 through 392,654
+turn off 865,654 through 911,956
+toggle 264,284 through 857,956
+turn off 281,776 through 610,797
+toggle 492,660 through 647,910
+turn off 879,703 through 925,981
+turn off 772,414 through 974,518
+turn on 694,41 through 755,96
+turn on 452,406 through 885,881
+turn off 107,905 through 497,910
+turn off 647,222 through 910,532
+turn on 679,40 through 845,358
+turn off 144,205 through 556,362
+turn on 871,804 through 962,878
+turn on 545,676 through 545,929
+turn off 316,716 through 413,941
+toggle 488,826 through 755,971
+toggle 957,832 through 976,992
+toggle 857,770 through 905,964
+toggle 319,198 through 787,673
+turn on 832,813 through 863,844
+turn on 818,296 through 818,681
+turn on 71,699 through 91,960
+turn off 838,578 through 967,928
+toggle 440,856 through 507,942
+toggle 121,970 through 151,974
+toggle 391,192 through 659,751
+turn on 78,210 through 681,419
+turn on 324,591 through 593,939
+toggle 159,366 through 249,760
+turn off 617,167 through 954,601
+toggle 484,607 through 733,657
+turn on 587,96 through 888,819
+turn off 680,984 through 941,991
+turn on 800,512 through 968,691
+turn off 123,588 through 853,603
+turn on 1,862 through 507,912
+turn on 699,839 through 973,878
+turn off 848,89 through 887,893
+toggle 344,353 through 462,403
+turn on 780,731 through 841,760
+toggle 693,973 through 847,984
+toggle 989,936 through 996,958
+toggle 168,475 through 206,963
+turn on 742,683 through 769,845
+toggle 768,116 through 987,396
+turn on 190,364 through 617,526
+turn off 470,266 through 530,839
+toggle 122,497 through 969,645
+turn off 492,432 through 827,790
+turn on 505,636 through 957,820
+turn on 295,476 through 698,958
+toggle 63,298 through 202,396
+turn on 157,315 through 412,939
+turn off 69,789 through 134,837
+turn off 678,335 through 896,541
+toggle 140,516 through 842,668
+turn off 697,585 through 712,668
+toggle 507,832 through 578,949
+turn on 678,279 through 886,621
+toggle 449,744 through 826,910
+turn off 835,354 through 921,741
+toggle 924,878 through 985,952
+turn on 666,503 through 922,905
+turn on 947,453 through 961,587
+toggle 525,190 through 795,654
+turn off 62,320 through 896,362
+turn on 21,458 through 972,536
+turn on 446,429 through 821,970
+toggle 376,423 through 805,455
+toggle 494,896 through 715,937
+turn on 583,270 through 667,482
+turn off 183,468 through 280,548
+toggle 623,289 through 750,524
+turn on 836,706 through 967,768
+turn on 419,569 through 912,908
+turn on 428,260 through 660,433
+turn off 683,627 through 916,816
+turn on 447,973 through 866,980
+turn on 688,607 through 938,990
+turn on 245,187 through 597,405
+turn off 558,843 through 841,942
+turn off 325,666 through 713,834
+toggle 672,606 through 814,935
+turn off 161,812 through 490,954
+turn on 950,362 through 985,898
+turn on 143,22 through 205,821
+turn on 89,762 through 607,790
+toggle 234,245 through 827,303
+turn on 65,599 through 764,997
+turn on 232,466 through 965,695
+turn on 739,122 through 975,590
+turn off 206,112 through 940,558
+toggle 690,365 through 988,552
+turn on 907,438 through 977,691
+turn off 838,809 through 944,869
+turn on 222,12 through 541,832
+toggle 337,66 through 669,812
+turn on 732,821 through 897,912
+toggle 182,862 through 638,996
+turn on 955,808 through 983,847
+toggle 346,227 through 841,696
+turn on 983,270 through 989,756
+turn off 874,849 through 876,905
+turn off 7,760 through 678,795
+toggle 973,977 through 995,983
+turn off 911,961 through 914,976
+turn on 913,557 through 952,722
+turn off 607,933 through 939,999
+turn on 226,604 through 517,622
+turn off 3,564 through 344,842
+toggle 340,578 through 428,610
+turn on 248,916 through 687,925
+toggle 650,185 through 955,965
+toggle 831,359 through 933,536
+turn off 544,614 through 896,953
+toggle 648,939 through 975,997
+turn on 464,269 through 710,521
+turn off 643,149 through 791,320
+turn off 875,549 through 972,643
+turn off 953,969 through 971,972
+turn off 236,474 through 772,591
+toggle 313,212 through 489,723
+toggle 896,829 through 897,837
+toggle 544,449 through 995,905
+turn off 278,645 through 977,876
+turn off 887,947 through 946,977
+turn on 342,861 through 725,935
+turn on 636,316 through 692,513
+toggle 857,470 through 950,528
+turn off 736,196 through 826,889
+turn on 17,878 through 850,987
+turn on 142,968 through 169,987
+turn on 46,470 through 912,853
+turn on 182,252 through 279,941
+toggle 261,143 through 969,657
+turn off 69,600 through 518,710
+turn on 372,379 through 779,386
+toggle 867,391 through 911,601
+turn off 174,287 through 900,536
+toggle 951,842 through 993,963
+turn off 626,733 through 985,827
+toggle 622,70 through 666,291
+turn off 980,671 through 985,835
+turn off 477,63 through 910,72
+turn off 779,39 through 940,142
+turn on 986,570 through 997,638
+toggle 842,805 through 943,985
+turn off 890,886 through 976,927
+turn off 893,172 through 897,619
+turn off 198,780 through 835,826
+toggle 202,209 through 219,291
+turn off 193,52 through 833,283
+toggle 414,427 through 987,972
+turn on 375,231 through 668,236
+turn off 646,598 through 869,663
+toggle 271,462 through 414,650
+turn off 679,121 through 845,467
+toggle 76,847 through 504,904
+turn off 15,617 through 509,810
+toggle 248,105 through 312,451
+turn off 126,546 through 922,879
+turn on 531,831 through 903,872
+toggle 602,431 through 892,792
+turn off 795,223 through 892,623
+toggle 167,721 through 533,929
+toggle 813,251 through 998,484
+toggle 64,640 through 752,942
+turn on 155,955 through 892,985
+turn on 251,329 through 996,497
+turn off 341,716 through 462,994
+toggle 760,127 through 829,189
+turn on 86,413 through 408,518
+toggle 340,102 through 918,558
+turn off 441,642 through 751,889
+turn on 785,292 through 845,325
+turn off 123,389 through 725,828
+turn on 905,73 through 983,270
+turn off 807,86 through 879,276
+toggle 500,866 through 864,916
+turn on 809,366 through 828,534
+toggle 219,356 through 720,617
+turn off 320,964 through 769,990
+turn off 903,167 through 936,631
+toggle 300,137 through 333,693
+toggle 5,675 through 755,848
+turn off 852,235 through 946,783
+toggle 355,556 through 941,664
+turn on 810,830 through 867,891
+turn off 509,869 through 667,903
+toggle 769,400 through 873,892
+turn on 553,614 through 810,729
+turn on 179,873 through 589,962
+turn off 466,866 through 768,926
+toggle 143,943 through 465,984
+toggle 182,380 through 569,552
+turn off 735,808 through 917,910
+turn on 731,802 through 910,847
+turn off 522,74 through 731,485
+turn on 444,127 through 566,996
+turn off 232,962 through 893,979
+turn off 231,492 through 790,976
+turn on 874,567 through 943,684
+toggle 911,840 through 990,932
+toggle 547,895 through 667,935
+turn off 93,294 through 648,636
+turn off 190,902 through 532,970
+turn off 451,530 through 704,613
+toggle 936,774 through 937,775
+turn off 116,843 through 533,934
+turn on 950,906 through 986,993
+turn on 910,51 through 945,989
+turn on 986,498 through 994,945
+turn off 125,324 through 433,704
+turn off 60,313 through 75,728
+turn on 899,494 through 940,947
+toggle 832,316 through 971,817
+toggle 994,983 through 998,984
+toggle 23,353 through 917,845
+toggle 174,799 through 658,859
+turn off 490,878 through 534,887
+turn off 623,963 through 917,975
+toggle 721,333 through 816,975
+toggle 589,687 through 890,921
+turn on 936,388 through 948,560
+turn off 485,17 through 655,610
+turn on 435,158 through 689,495
+turn on 192,934 through 734,936
+turn off 299,723 through 622,847
+toggle 484,160 through 812,942
+turn off 245,754 through 818,851
+turn on 298,419 through 824,634
+toggle 868,687 through 969,760
+toggle 131,250 through 685,426
+turn off 201,954 through 997,983
+turn on 353,910 through 832,961
+turn off 518,781 through 645,875
+turn off 866,97 through 924,784
+toggle 836,599 through 857,767
+turn on 80,957 through 776,968
+toggle 277,130 through 513,244
+turn off 62,266 through 854,434
+turn on 792,764 through 872,842
+turn off 160,949 through 273,989
+turn off 664,203 through 694,754
+toggle 491,615 through 998,836
+turn off 210,146 through 221,482
+turn off 209,780 through 572,894
+turn on 766,112 through 792,868
+turn on 222,12 through 856,241
diff --git a/6/inputconv.py b/6/inputconv.py
new file mode 100644
index 0000000..fa2873d
--- /dev/null
+++ b/6/inputconv.py
@@ -0,0 +1,4 @@
+from struct import pack
+with open('inputbin', 'wb') as f:
+ for action, start, end in (({'turn on': 1, 'turn off': -1, 'toggle': 2}[action], tuple(map(int, begin.split(','))), tuple(map(int, end.split(',')))) for action, begin, end in ((*l.rsplit(' ', maxsplit=1), r) for l, r in (l.rstrip('\n').split(' through ') for l in open('input')))):
+ f.write(pack('>bHHHH', action, *start, *end))
diff --git a/7/input b/7/input
new file mode 100644
index 0000000..56cae92
--- /dev/null
+++ b/7/input
@@ -0,0 +1,339 @@
+af AND ah -> ai
+NOT lk -> ll
+hz RSHIFT 1 -> is
+NOT go -> gp
+du OR dt -> dv
+x RSHIFT 5 -> aa
+at OR az -> ba
+eo LSHIFT 15 -> es
+ci OR ct -> cu
+b RSHIFT 5 -> f
+fm OR fn -> fo
+NOT ag -> ah
+v OR w -> x
+g AND i -> j
+an LSHIFT 15 -> ar
+1 AND cx -> cy
+jq AND jw -> jy
+iu RSHIFT 5 -> ix
+gl AND gm -> go
+NOT bw -> bx
+jp RSHIFT 3 -> jr
+hg AND hh -> hj
+bv AND bx -> by
+er OR es -> et
+kl OR kr -> ks
+et RSHIFT 1 -> fm
+e AND f -> h
+u LSHIFT 1 -> ao
+he RSHIFT 1 -> hx
+eg AND ei -> ej
+bo AND bu -> bw
+dz OR ef -> eg
+dy RSHIFT 3 -> ea
+gl OR gm -> gn
+da LSHIFT 1 -> du
+au OR av -> aw
+gj OR gu -> gv
+eu OR fa -> fb
+lg OR lm -> ln
+e OR f -> g
+NOT dm -> dn
+NOT l -> m
+aq OR ar -> as
+gj RSHIFT 5 -> gm
+hm AND ho -> hp
+ge LSHIFT 15 -> gi
+jp RSHIFT 1 -> ki
+hg OR hh -> hi
+lc LSHIFT 1 -> lw
+km OR kn -> ko
+eq LSHIFT 1 -> fk
+1 AND am -> an
+gj RSHIFT 1 -> hc
+aj AND al -> am
+gj AND gu -> gw
+ko AND kq -> kr
+ha OR gz -> hb
+bn OR by -> bz
+iv OR jb -> jc
+NOT ac -> ad
+bo OR bu -> bv
+d AND j -> l
+bk LSHIFT 1 -> ce
+de OR dk -> dl
+dd RSHIFT 1 -> dw
+hz AND ik -> im
+NOT jd -> je
+fo RSHIFT 2 -> fp
+hb LSHIFT 1 -> hv
+lf RSHIFT 2 -> lg
+gj RSHIFT 3 -> gl
+ki OR kj -> kk
+NOT ak -> al
+ld OR le -> lf
+ci RSHIFT 3 -> ck
+1 AND cc -> cd
+NOT kx -> ky
+fp OR fv -> fw
+ev AND ew -> ey
+dt LSHIFT 15 -> dx
+NOT ax -> ay
+bp AND bq -> bs
+NOT ii -> ij
+ci AND ct -> cv
+iq OR ip -> ir
+x RSHIFT 2 -> y
+fq OR fr -> fs
+bn RSHIFT 5 -> bq
+0 -> c
+14146 -> b
+d OR j -> k
+z OR aa -> ab
+gf OR ge -> gg
+df OR dg -> dh
+NOT hj -> hk
+NOT di -> dj
+fj LSHIFT 15 -> fn
+lf RSHIFT 1 -> ly
+b AND n -> p
+jq OR jw -> jx
+gn AND gp -> gq
+x RSHIFT 1 -> aq
+ex AND ez -> fa
+NOT fc -> fd
+bj OR bi -> bk
+as RSHIFT 5 -> av
+hu LSHIFT 15 -> hy
+NOT gs -> gt
+fs AND fu -> fv
+dh AND dj -> dk
+bz AND cb -> cc
+dy RSHIFT 1 -> er
+hc OR hd -> he
+fo OR fz -> ga
+t OR s -> u
+b RSHIFT 2 -> d
+NOT jy -> jz
+hz RSHIFT 2 -> ia
+kk AND kv -> kx
+ga AND gc -> gd
+fl LSHIFT 1 -> gf
+bn AND by -> ca
+NOT hr -> hs
+NOT bs -> bt
+lf RSHIFT 3 -> lh
+au AND av -> ax
+1 AND gd -> ge
+jr OR js -> jt
+fw AND fy -> fz
+NOT iz -> ja
+c LSHIFT 1 -> t
+dy RSHIFT 5 -> eb
+bp OR bq -> br
+NOT h -> i
+1 AND ds -> dt
+ab AND ad -> ae
+ap LSHIFT 1 -> bj
+br AND bt -> bu
+NOT ca -> cb
+NOT el -> em
+s LSHIFT 15 -> w
+gk OR gq -> gr
+ff AND fh -> fi
+kf LSHIFT 15 -> kj
+fp AND fv -> fx
+lh OR li -> lj
+bn RSHIFT 3 -> bp
+jp OR ka -> kb
+lw OR lv -> lx
+iy AND ja -> jb
+dy OR ej -> ek
+1 AND bh -> bi
+NOT kt -> ku
+ao OR an -> ap
+ia AND ig -> ii
+NOT ey -> ez
+bn RSHIFT 1 -> cg
+fk OR fj -> fl
+ce OR cd -> cf
+eu AND fa -> fc
+kg OR kf -> kh
+jr AND js -> ju
+iu RSHIFT 3 -> iw
+df AND dg -> di
+dl AND dn -> do
+la LSHIFT 15 -> le
+fo RSHIFT 1 -> gh
+NOT gw -> gx
+NOT gb -> gc
+ir LSHIFT 1 -> jl
+x AND ai -> ak
+he RSHIFT 5 -> hh
+1 AND lu -> lv
+NOT ft -> fu
+gh OR gi -> gj
+lf RSHIFT 5 -> li
+x RSHIFT 3 -> z
+b RSHIFT 3 -> e
+he RSHIFT 2 -> hf
+NOT fx -> fy
+jt AND jv -> jw
+hx OR hy -> hz
+jp AND ka -> kc
+fb AND fd -> fe
+hz OR ik -> il
+ci RSHIFT 1 -> db
+fo AND fz -> gb
+fq AND fr -> ft
+gj RSHIFT 2 -> gk
+cg OR ch -> ci
+cd LSHIFT 15 -> ch
+jm LSHIFT 1 -> kg
+ih AND ij -> ik
+fo RSHIFT 3 -> fq
+fo RSHIFT 5 -> fr
+1 AND fi -> fj
+1 AND kz -> la
+iu AND jf -> jh
+cq AND cs -> ct
+dv LSHIFT 1 -> ep
+hf OR hl -> hm
+km AND kn -> kp
+de AND dk -> dm
+dd RSHIFT 5 -> dg
+NOT lo -> lp
+NOT ju -> jv
+NOT fg -> fh
+cm AND co -> cp
+ea AND eb -> ed
+dd RSHIFT 3 -> df
+gr AND gt -> gu
+ep OR eo -> eq
+cj AND cp -> cr
+lf OR lq -> lr
+gg LSHIFT 1 -> ha
+et RSHIFT 2 -> eu
+NOT jh -> ji
+ek AND em -> en
+jk LSHIFT 15 -> jo
+ia OR ig -> ih
+gv AND gx -> gy
+et AND fe -> fg
+lh AND li -> lk
+1 AND io -> ip
+kb AND kd -> ke
+kk RSHIFT 5 -> kn
+id AND if -> ig
+NOT ls -> lt
+dw OR dx -> dy
+dd AND do -> dq
+lf AND lq -> ls
+NOT kc -> kd
+dy AND ej -> el
+1 AND ke -> kf
+et OR fe -> ff
+hz RSHIFT 5 -> ic
+dd OR do -> dp
+cj OR cp -> cq
+NOT dq -> dr
+kk RSHIFT 1 -> ld
+jg AND ji -> jj
+he OR hp -> hq
+hi AND hk -> hl
+dp AND dr -> ds
+dz AND ef -> eh
+hz RSHIFT 3 -> ib
+db OR dc -> dd
+hw LSHIFT 1 -> iq
+he AND hp -> hr
+NOT cr -> cs
+lg AND lm -> lo
+hv OR hu -> hw
+il AND in -> io
+NOT eh -> ei
+gz LSHIFT 15 -> hd
+gk AND gq -> gs
+1 AND en -> eo
+NOT kp -> kq
+et RSHIFT 5 -> ew
+lj AND ll -> lm
+he RSHIFT 3 -> hg
+et RSHIFT 3 -> ev
+as AND bd -> bf
+cu AND cw -> cx
+jx AND jz -> ka
+b OR n -> o
+be AND bg -> bh
+1 AND ht -> hu
+1 AND gy -> gz
+NOT hn -> ho
+ck OR cl -> cm
+ec AND ee -> ef
+lv LSHIFT 15 -> lz
+ks AND ku -> kv
+NOT ie -> if
+hf AND hl -> hn
+1 AND r -> s
+ib AND ic -> ie
+hq AND hs -> ht
+y AND ae -> ag
+NOT ed -> ee
+bi LSHIFT 15 -> bm
+dy RSHIFT 2 -> dz
+ci RSHIFT 2 -> cj
+NOT bf -> bg
+NOT im -> in
+ev OR ew -> ex
+ib OR ic -> id
+bn RSHIFT 2 -> bo
+dd RSHIFT 2 -> de
+bl OR bm -> bn
+as RSHIFT 1 -> bl
+ea OR eb -> ec
+ln AND lp -> lq
+kk RSHIFT 3 -> km
+is OR it -> iu
+iu RSHIFT 2 -> iv
+as OR bd -> be
+ip LSHIFT 15 -> it
+iw OR ix -> iy
+kk RSHIFT 2 -> kl
+NOT bb -> bc
+ci RSHIFT 5 -> cl
+ly OR lz -> ma
+z AND aa -> ac
+iu RSHIFT 1 -> jn
+cy LSHIFT 15 -> dc
+cf LSHIFT 1 -> cz
+as RSHIFT 3 -> au
+cz OR cy -> da
+kw AND ky -> kz
+lx -> a
+iw AND ix -> iz
+lr AND lt -> lu
+jp RSHIFT 5 -> js
+aw AND ay -> az
+jc AND je -> jf
+lb OR la -> lc
+NOT cn -> co
+kh LSHIFT 1 -> lb
+1 AND jj -> jk
+y OR ae -> af
+ck AND cl -> cn
+kk OR kv -> kw
+NOT cv -> cw
+kl AND kr -> kt
+iu OR jf -> jg
+at AND az -> bb
+jp RSHIFT 2 -> jq
+iv AND jb -> jd
+jn OR jo -> jp
+x OR ai -> aj
+ba AND bc -> bd
+jl OR jk -> jm
+b RSHIFT 1 -> v
+o AND q -> r
+NOT p -> q
+k AND m -> n
+as RSHIFT 2 -> at
diff --git a/7/solution.py b/7/solution.py
new file mode 100644
index 0000000..77a1391
--- /dev/null
+++ b/7/solution.py
@@ -0,0 +1,115 @@
+from abc import abstractmethod
+
+class U16:
+ def __init__(self, value: int):
+ self.value = value & 0xffff
+ def __invert__(self):
+ return U16(~self.value)
+ def __and__(self, other):
+ return U16(self.value & other.value)
+ def __or__(self, other):
+ return U16(self.value | other.value)
+ def __rshift__(self, other):
+ return U16(self.value >> other.value)
+ def __lshift__(self, other):
+ return U16(self.value << other.value)
+ def __str__(self):
+ return str(self.value)
+
+class Node:
+ _value: U16 = None
+ @property
+ def value(self) -> U16:
+ if not self._value:
+ self._value = self.eval()
+ return self._value
+ def eval(self, net: dict[Node]) -> U16:
+ return self.eval()
+ @absrtactmethod
+ def eval(self) -> U16:
+ pass
+
+class Reference(Node):
+ def __init__(self, name: str):
+ self.name = name
+ def eval(self, net: dict[Node]) -> U16:
+ return net[self.name].value
+
+class Constant(Node):
+ def __init__(self, value):
+ self._value = value
+
+class BinaryOp(Node):
+ def __init__(self, left, right):
+ self.left = left
+ self.right = right
+
+class And(BinaryOp):
+ def eval(self) -> U16:
+ return self.left.value & self.right.value
+
+class Or(BinaryOp):
+ def eval(self) -> U16:
+ return self.left.value | self.right.value
+
+class LShift(BinaryOp):
+ def eval(self) -> U16:
+ return self.left.value << self.right.value
+
+class RShift(BinaryOp):
+ def eval(self) -> U16:
+ return self.left.value >> self.right.value
+
+class Not(Node):
+ def __init__(self, node):
+ self.node = node
+ def eval(self):
+ return ~self.node.value
+
+def parse_expr(net: dict[Node], expr: str) -> Node:
+ parts = expr.split(' ')
+ if len(parts) == 3:
+ lhs = parse_expr(net, parts[0])
+ rhs = parse_expr(net, parts[2])
+ if parts[1] == 'AND':
+ return And(lhs, rhs)
+ elif parts[1] == 'OR':
+ return Or(lhs, rhs)
+ elif parts[1] == 'LSHIFT':
+ return LShift(lhs, rhs)
+ elif parts[1] == 'RSHIFT':
+ return RShift(lhs, rhs)
+ elif len(parts) == 2:
+ if parts[0] == 'NOT':
+ return Not(parse_expr(net, parts[1]))
+ elif len(parts) == 1:
+ if expr.isnumeric():
+ return Constant(U16(int(expr)))
+ if expr.isalpha():
+ return Reference(net, expr)
+ raise ValueError(expr)
+
+def parse_conn(net: dict[Node], conn: str) -> tuple[str, Node]:
+ expr, target = conn.split(" -> ")
+ return target, parse_expr(net, expr)
+
+def part1(inp: list[str]) -> int:
+ net = dict()
+ for conn in inp:
+ target, node = parse_conn(net, conn)
+ net[target] = node
+ return net['a'].value
+
+def part2(inp: list[str]) -> int:
+ net = dict()
+ for conn in inp:
+ target, node = parse_conn(net, conn)
+ net[target] = node
+ net['b'] = Constant(part1(inp))
+ return net['a'].value
+
+if __name__ == '__main__':
+ with open('input') as f:
+ inp = [line.strip() for line in f]
+ print(part1(inp))
+ print(part2(inp)) \ No newline at end of file
diff --git a/8/input b/8/input
new file mode 100644
index 0000000..94538e7
--- /dev/null
+++ b/8/input
@@ -0,0 +1,300 @@
+"qxfcsmh"
+"ffsfyxbyuhqkpwatkjgudo"
+"byc\x9dyxuafof\\\xa6uf\\axfozomj\\olh\x6a"
+"jtqvz"
+"uzezxa\"jgbmojtwyfbfguz"
+"vqsremfk\x8fxiknektafj"
+"wzntebpxnnt\"vqndz\"i\x47vvjqo\""
+"higvez\"k\"riewqk"
+"dlkrbhbrlfrp\\damiauyucwhty"
+"d\""
+"qlz"
+"ku"
+"yy\"\"uoao\"uripabop"
+"saduyrntuswlnlkuppdro\\sicxosted"
+"tj"
+"zzphopswlwdhebwkxeurvizdv"
+"xfoheirjoakrpofles\"nfu"
+"q\xb7oh\"p\xce\"n"
+"qeendp\"ercwgywdjeylxcv"
+"dcmem"
+"\"i\x13r\"l"
+"ikso\xdcbvqnbrjduh\"uqudzki\xderwk"
+"wfdsn"
+"pwynglklryhtsqbno"
+"hcoj\x63iccz\"v\"ttr"
+"zf\x23\\hlj\\kkce\\d\\asy\"yyfestwcdxyfj"
+"xs"
+"m\"tvltapxdvtrxiy"
+"bmud"
+"k\"a"
+"b\"oas"
+"\"yexnjjupoqsxyqnquy\"uzfdvetqrc"
+"vdw\xe3olxfgujaj"
+"qomcxdnd\"\\cfoe\""
+"fpul"
+"m\"avamefphkpv"
+"vvdnb\\x\\uhnxfw\"dpubfkxfmeuhnxisd"
+"hey\\"
+"ldaeigghlfey"
+"eure\"hoy\xa5iezjp\\tm"
+"yygb\"twbj\\r\"\x10gmxuhmp\""
+"weirebp\x39mqonbtmfmd"
+"ltuz\\hs\"e"
+"ysvmpc"
+"g\x8amjtt\"megl\"omsaihifwa"
+"yimmm"
+"iiyqfalh"
+"cwknlaaf"
+"q\x37feg\xc6s\"xx"
+"uayrgeurgyp\\oi"
+"xhug\"pt\"axugllbdiggzhvy"
+"kdaarqmsjfx\xc3d"
+"\"vkwla"
+"d\""
+"tmroz\"bvfinxoe\\mum\"wmm"
+"\"n\"bbswxne\\p\\yr\"qhwpdd"
+"skzlkietklkqovjhvj\xfe"
+"pbg\\pab\"bubqaf\"obzcwxwywbs\\dhtq"
+"xxjidvqh\"lx\\wu\"ij"
+"daef\x5fe\x5b\\kbeeb\x13qnydtboof"
+"ogvazaqy\"j\x73"
+"y"
+"n\"tibetedldy\\gsamm\"nwu"
+"wldkvgdtqulwkad"
+"dpmxnj"
+"twybw\"cdvf\"mjdajurokbce"
+"ru\"\\lasij\"i"
+"roc\\vra\\lhrm"
+"pbkt\x60booz\"fjlkc"
+"j\x4dytvjwrzt"
+"\\uiwjkniumxcs"
+"cbhm\"nexccior\"v\"j\"nazxilmfp\x47"
+"qdxngevzrlgoq"
+"\"lrzxftytpobsdfyrtdqpjbpuwmm\x9e"
+"mdag\x0asnck\xc2ggj\"slb\"fjy"
+"wyqkhjuazdtcgkcxvjkpnjdae"
+"aixfk\xc0iom\x21vueob"
+"dkiiakyjpkffqlluhaetires"
+"ysspv\"lysgkvnmwbbsy"
+"gy\"ryexcjjxdm\"xswssgtr"
+"s"
+"ddxv"
+"qwt\"\x27puilb\"pslmbrsxhrz"
+"qdg\xc9e\\qwtknlvkol\x54oqvmchn\\"
+"lvo"
+"b"
+"fk\"aa\"\"yenwch\\\\on"
+"srig\x63hpwaavs\\\x80qzk\"xa\"\xe6u\\wr"
+"yxjxuj\"ghyhhxfj\"\xa6qvatre"
+"yoktqxjxkzrklkoeroil"
+"\"jfmik\""
+"smgseztzdwldikbqrh\""
+"jftahgctf\"hoqy"
+"tcnhicr\"znpgckt\"ble"
+"vqktnkodh\"lo\"a\\bkmdjqqnsqr"
+"ztnirfzqq"
+"s"
+"xx"
+"iqj\"y\\hqgzflwrdsusasekyrxbp\\ad"
+"\\xzjhlaiynkioz\"\"bxepzimvgwt"
+"s\x36rbw"
+"mniieztwrisvdx"
+"atyfxioy\x2b\\"
+"irde\x85\x5cvbah\\jekw\"ia"
+"bdmftlhkwrprmpat\"prfaocvp"
+"w\\k"
+"umbpausy"
+"zfauhpsangy"
+"p\"zqyw"
+"wtztypyqvnnxzvlvipnq\"zu"
+"deicgwq\\oqvajpbov\\or\"kgplwu"
+"mbzlfgpi\\\\zqcidjpzqdzxityxa"
+"lfkxvhma"
+"\xf2yduqzqr\"\\fak\"p\"n"
+"mpajacfuxotonpadvng"
+"anb\\telzvcdu\\a\xf2flfq"
+"lrs\"ebethwpmuuc\"\x86ygr"
+"qmvdbhtumzc\"ci"
+"meet"
+"yopg\x0fdxdq\"h\\ugsu\xffmolxjv"
+"uhy"
+"fzgidrtzycsireghazscvmwcfmw\\t"
+"cqohkhpgvpru"
+"bihyigtnvmevx\"xx"
+"xz"
+"zofomwotzuxsjk\"q\"mc\"js\"dnmalhxd"
+"\\ktnddux\\fqvt\"ibnjntjcbn"
+"ia"
+"htjadnefwetyp\xd5kbrwfycbyy"
+"\"\\hkuxqddnao"
+"meqqsz\x83luecpgaem"
+"cvks\x87frvxo\"svqivqsdpgwhukmju"
+"sgmxiai\\o\"riufxwjfigr\xdf"
+"fgywdfecqufccpcdn"
+"faghjoq\x28abxnpxj"
+"zuppgzcfb\"dctvp\"elup\"zxkopx"
+"xqs\x45xxdqcihbwghmzoa"
+"anbnlp\\cgcvm\"hc"
+"xf\"fgrngwzys"
+"nrxsjduedcy\x24"
+"\x71sxl\"gj\"sds\"ulcruguz\\t\\ssvjcwhi"
+"jhj\"msch"
+"qpovolktfwyiuyicbfeeju\x01"
+"nkyxmb\"qyqultgt\"nmvzvvnxnb"
+"ycsrkbstgzqb\"uv\\cisn"
+"s"
+"ueptjnn\"\"sh"
+"lp\"z\"d\"mxtxiy"
+"yzjtvockdnvbubqabjourf\"k\"uoxwle"
+"\x82\"wqm\""
+"\xb5cwtuks\x5fpgh"
+"wd"
+"tbvf"
+"ttbmzdgn"
+"vfpiyfdejyrlbgcdtwzbnm"
+"uc"
+"otdcmhpjagqix"
+"\\\xb1qso\"s"
+"scowax"
+"behpstjdh\xccqlgnqjyz\"eesn"
+"r\xe1cbnjwzveoomkzlo\\kxlfouhm"
+"jgrl"
+"kzqs\\r"
+"ctscb\x7fthwkdyko\"\x62pkf\"d\xe6knmhurg"
+"tc\"kw\x3ftt"
+"bxb\x5ccl"
+"jyrmfbphsldwpq"
+"jylpvysl\"\"juducjg"
+"en\\m\"kxpq\"wpb\\\""
+"madouht\"bmdwvnyqvpnawiphgac\""
+"vuxpk\"ltucrw"
+"aae\x60arr"
+"ttitnne\"kilkrgssnr\xfdurzh"
+"oalw"
+"pc\"\"gktkdykzbdpkwigucqni\"nxiqx"
+"dbrsaj"
+"bgzsowyxcbrvhtvekhsh\"qgd"
+"kudfemvk\"\"\"hkbrbil\"chkqoa"
+"zjzgj\\ekbhyfzufy"
+"\\acos\"fqekuxqzxbmkbnn\x1ejzwrm"
+"elxahvudn\"txtmomotgw"
+"\x2eoxmwdhelpr\"cgi\xf7pzvb"
+"eapheklx"
+"hfvma\"mietvc\"tszbbm\"czex"
+"h\"iiockj\\\xc1et"
+"d\"rmjjftm"
+"qlvhdcbqtyrhlc\\"
+"yy\"rsucjtulm\"coryri\"eqjlbmk"
+"tv"
+"r\"bfuht\\jjgujp\""
+"kukxvuauamtdosngdjlkauylttaokaj"
+"srgost\"\"rbkcqtlccu\x65ohjptstrjkzy"
+"yxwxl\\yjilwwxffrjjuazmzjs"
+"dxlw\\fkstu\"hjrtiafhyuoh\"sewabne"
+"\x88sj\"v"
+"rfzprz\xec\"oxqclu\"krzefp\\q"
+"cfmhdbjuhrcymgxpylllyvpni"
+"ucrmjvmimmcq\x88\xd9\"lz"
+"lujtt\""
+"gvbqoixn\"pmledpjmo\"flydnwkfxllf"
+"dvxqlbshhmelsk\x8big\"l"
+"mx\x54lma\x8bbguxejg"
+"\x66jdati\xeceieo"
+"\"iyyupixei\x54ff"
+"xohzf\"rbxsoksxamiu"
+"vlhthspeshzbppa\x4drhqnohjop\"\"mfjd"
+"f\"tvxxla\"vurian\"\"idjq\x3aptm\xc3olep"
+"gzqz"
+"kbq\\wogye\\altvi\\hbvmodny"
+"j\xd8"
+"ofjozdhkblvndl"
+"hbitoupimbawimxlxqze"
+"ypeleimnme"
+"xfwdrzsc\\oxqamawyizvi\\y"
+"enoikppx\xa1ixe\"yo\"gumye"
+"fb"
+"vzf"
+"zxidr"
+"cu\x31beirsywtskq"
+"lxpjbvqzztafwezd"
+"\\jyxeuo\x18bv"
+"b\"vawc\"p\\\\giern\"b"
+"odizunx\"\"t\\yicdn\"x\"sdiz"
+"\"\"tebrtsi"
+"ctyzsxv\xa6pegfkwsi\"tgyltaakytccb"
+"htxwbofchvmzbppycccliyik\xe5a"
+"ggsslefamsklezqkrd"
+"rcep\"fnimwvvdx\"l"
+"zyrzlqmd\x12egvqs\\llqyie"
+"\x07gsqyrr\\rcyhyspsvn"
+"butg\""
+"gb"
+"gywkoxf\"jsg\\wtopxvumirqxlwz"
+"rj\"ir\"wldwveair\x2es\"dhjrdehbqnzl"
+"ru\"elktnsbxufk\\ejufjfjlevt\\lrzd"
+"\"widsvok"
+"oy\"\x81nuesvw"
+"ay"
+"syticfac\x1cfjsivwlmy\"pumsqlqqzx"
+"m"
+"rjjkfh\x78cf\x2brgceg\"jmdyas\"\\xlv\xb6p"
+"tmuvo\"\x3ffdqdovjmdmkgpstotojkv\"as"
+"jd\\ojvynhxllfzzxvbn\"wrpphcvx"
+"pz"
+"\"twr"
+"n\\hdzmxe\"mzjjeadlz"
+"fb\"rprxuagvahjnri"
+"rfmexmjjgh\\xrnmyvnatrvfruflaqjnd"
+"obbbde\"co\"qr\"qpiwjgqahqm\\jjp\""
+"vpbq\"\"y\"czk\\b\x52ed\"lnzepobp"
+"syzeajzfarplydipny\"y\"\xe8ad"
+"mpyodwb"
+"\x47rakphlqqptd"
+"wa\"oj\"aiy"
+"a"
+"ropozx"
+"q\x51nbtlwa"
+"etukvgx\\jqxlkq"
+"\"tp\"rah\"pg\"s\"bpdtes\\tkasdhqd"
+"dn\"qqpkikadowssb\xcah\"dzpsf\\ect\"jdh"
+"pxunovbbrrn\\vullyn\"bno\"\"\"myfxlp\""
+"qaixyazuryvkmoulhcqaotegfj\\mpzm"
+"bvfrbicutzbjwn\\oml\"cf\"d\"ezcpv\"j"
+"rmbrdtneudemigdhelmb"
+"aq\\aurmbhy"
+"wujqvzw"
+"gf\"tssmvm\"gm\"hu\x9a\xb7yjawsa"
+"hrhqqxow\xe2gsydtdspcfqy\"zw\\ou"
+"ianwwf\\yko\\tdujhhqdi"
+"xylz\"zpvpab"
+"lwuopbeeegp"
+"aoop\x49jhhcexdmdtun"
+"\\\\mouqqcsgmz"
+"tltuvwhveau\x43b\"ymxjlcgiymcynwt"
+"gsugerumpyuhtjljbhrdyoj"
+"lnjm\xb8wg\"ajh"
+"zmspue\"nfttdon\\b\"eww"
+"\"w\x67jwaq\x7ernmyvs\\rmdsuwydsd\"th"
+"ogtgvtlmcvgllyv"
+"z\"fqi\"rvddoehrciyl"
+"yustxxtot\"muec\"xvfdbzunzvveq"
+"mqslw"
+"txqnyvzmibqgjs\xb6xy\x86nfalfyx"
+"kzhehlmkholov"
+"plpmywcnirrjutjguosh\\"
+"pydbnqofv\"dn\\m"
+"aegqof"
+"eambmxt\\dxagoogl\\zapfwwlmk"
+"afbmqitxxqhddlozuxcpjxgh"
+"vgts"
+"bfdpqtoxzzhmzcilehnflna"
+"s\"idpz"
+"\xcfhgly\"nlmztwybx\"ecezmsxaqw"
+"aackfgndqcqiy"
+"\x22unqdlsrvgzfaohoffgxzfpir\"s"
+"abh\"ydv\"kbpdhrerl"
+"bdzpg"
+"ekwgkywtmzp"
+"wtoodejqmrrgslhvnk\"pi\"ldnogpth"
+"njro\x68qgbx\xe4af\"\\suan"
diff --git a/8/solution.sh b/8/solution.sh
new file mode 100644
index 0000000..5b227ec
--- /dev/null
+++ b/8/solution.sh
@@ -0,0 +1,5 @@
+rawlen=$(while read -r; do printf "${REPLY:1:-1}"; done <$1 | wc -c)
+reallen=$(<$1 tr -d '\n' | wc -c)
+echo $((reallen - rawlen))
+quotedlen=$(sed 's/["\\]/\\&/g;s/.*/"&"/' $1 | tr -d '\n' | wc -c)
+echo $((quotedlen - reallen))
diff --git a/9/input b/9/input
new file mode 100644
index 0000000..97a6b63
--- /dev/null
+++ b/9/input
@@ -0,0 +1,28 @@
+Faerun to Tristram = 65
+Faerun to Tambi = 129
+Faerun to Norrath = 144
+Faerun to Snowdin = 71
+Faerun to Straylight = 137
+Faerun to AlphaCentauri = 3
+Faerun to Arbre = 149
+Tristram to Tambi = 63
+Tristram to Norrath = 4
+Tristram to Snowdin = 105
+Tristram to Straylight = 125
+Tristram to AlphaCentauri = 55
+Tristram to Arbre = 14
+Tambi to Norrath = 68
+Tambi to Snowdin = 52
+Tambi to Straylight = 65
+Tambi to AlphaCentauri = 22
+Tambi to Arbre = 143
+Norrath to Snowdin = 8
+Norrath to Straylight = 23
+Norrath to AlphaCentauri = 136
+Norrath to Arbre = 115
+Snowdin to Straylight = 101
+Snowdin to AlphaCentauri = 84
+Snowdin to Arbre = 96
+Straylight to AlphaCentauri = 107
+Straylight to Arbre = 14
+AlphaCentauri to Arbre = 46
diff --git a/9/solution.py b/9/solution.py
new file mode 100644
index 0000000..48b0c7c
--- /dev/null
+++ b/9/solution.py
@@ -0,0 +1,40 @@
+from itertools import permutations, islice
+import collections
+
+def sliding_window(iterable, n):
+ # sliding_window('ABCDEFG', 4) -> ABCD BCDE CDEF DEFG
+ it = iter(iterable)
+ window = collections.deque(islice(it, n), maxlen=n)
+ if len(window) == n:
+ yield tuple(window)
+ for x in it:
+ window.append(x)
+ yield tuple(window)
+
+def part1(nodes: set, distances: dict) -> int:
+ """
+ >>> part1(set('ABC'), {('A', 'B'): 464, ('A', 'C'): 518, ('B', 'C'): 141})
+ 605
+ """
+ return min(sum(distances[tuple(sorted(edge))] for edge in sliding_window(path, 2)) for path in permutations(nodes))
+
+def part2(nodes: set, distances: dict) -> int:
+ """
+ >>> part2(set('ABC'), {('A', 'B'): 464, ('A', 'C'): 518, ('B', 'C'): 141})
+ 982
+ """
+ return max(sum(distances[tuple(sorted(edge))] for edge in sliding_window(path, 2)) for path in permutations(nodes))
+
+if __name__ == '__main__':
+ nodes = set()
+ distances = dict()
+ with open('input') as f:
+ for l in f:
+ l = l.strip()
+ edge, distance = l.split(' = ')
+ edge = tuple(sorted(edge.split(' to ')))
+ nodes.add(edge[0])
+ nodes.add(edge[1])
+ distances[edge] = int(distance)
+ print(part1(nodes, distances))
+ print(part2(nodes, distances))