Move 2015 out of the way.

This commit is contained in:
Bert Peters
2016-12-01 11:25:19 +01:00
parent a75d14ec17
commit b37fd44fa7
50 changed files with 0 additions and 0 deletions

20
2015/README.md Normal file
View File

@@ -0,0 +1,20 @@
# Advent of Code solution repository
In this repository are the programs used to solve the [Avent of
Code](http://adventofcode.com) challenges. Each day has its very own folder
containing a program and optionally an input file.
I am using the Advent of Code to teach myself python. I personally notice an
improvement over time, and thus over the programs I create. Some programs I
have revisited for a more efficient implementation and gave them a small README
detailing my algorithm.
As a coding standard, I try to make code that can be run with:
* Python 2.7
* Python 3
* Pypy
Most of the code runs the fastest in Pypy, but there are exceptions.
All this code is under MIT license. Use it for whatever you want, but please do
credit me.

1
2015/day-01/input.txt Normal file

File diff suppressed because one or more lines are too long

18
2015/day-01/solution.py Normal file
View File

@@ -0,0 +1,18 @@
from __future__ import print_function
import fileinput
floor = 0
seenBasement = False
for line in fileinput.input():
for idx, c in enumerate(line.strip()):
if c == '(':
floor += 1
else:
floor -= 1
if not seenBasement and floor == -1:
seenBasement = True
print("Basement reached at", idx + 1)
print("Finally arrived at", floor)

1000
2015/day-02/input.txt Normal file

File diff suppressed because it is too large Load Diff

21
2015/day-02/solution.py Normal file
View File

@@ -0,0 +1,21 @@
from __future__ import print_function
import fileinput
from operator import mul
from functools import reduce
import itertools
totalArea = 0
totalRibbon = 0
for line in fileinput.input():
parts = [int(i) for i in line.split('x')]
parts.sort()
sides = [x * y for x, y in itertools.combinations(parts, 2)]
totalArea += 2 * sum(sides) + min(sides)
totalRibbon += 2 * (parts[0] + parts[1])
totalRibbon += reduce(mul, parts, 1)
print(totalArea, "paper")
print(totalRibbon, "ribbon")

1
2015/day-03/input.txt Normal file

File diff suppressed because one or more lines are too long

29
2015/day-03/solution.py Normal file
View File

@@ -0,0 +1,29 @@
from __future__ import print_function
import fileinput
def move(pos, c):
if c == '<':
pos = (pos[0] + 1, pos[1])
elif c == '>':
pos = (pos[0] - 1, pos[1])
elif c == '^':
pos = (pos[0], pos[1] + 1)
elif c == 'v':
pos = (pos[0], pos[1] - 1)
return pos
pos = (0, 0)
pos2 = pos
places = set([pos])
for line in fileinput.input():
for idx,c in enumerate(line):
if idx % 2 == 0:
pos = move(pos, c)
places.add(pos)
else:
pos2 = move(pos2, c)
places.add(pos2)
print("Houses:", len(places))

1
2015/day-04/input.txt Normal file
View File

@@ -0,0 +1 @@
bgvyzdsv

32
2015/day-04/solution.py Normal file
View File

@@ -0,0 +1,32 @@
from __future__ import print_function
import sys
from hashlib import md5
import fileinput
def ok(digest, zeroes):
for c in digest[0:zeroes]:
if c != "0":
return False
return True
def solve(word, zeroes):
number = 0
while True:
digester = md5(word.encode("utf-8"))
digester.update(str(number).encode("utf-8"))
if ok(digester.hexdigest(), zeroes):
print(word, number)
break
number = number + 1
return number
for line in fileinput.input():
word = line.strip()
solve(word, 5)
solve(word, 6)

1000
2015/day-05/input.txt Normal file

File diff suppressed because it is too large Load Diff

23
2015/day-05/solution.py Normal file
View File

@@ -0,0 +1,23 @@
from __future__ import print_function
import fileinput
import re
nice1 = 0
nice2 = 0
doubleletter = re.compile(r"(.)\1")
vowels = re.compile(r"[aeiou]")
forbidden = re.compile(r"ab|cd|pq|xy")
inbetween = re.compile(r"(.).\1")
twodouble = re.compile(r"(.)(.)(.*?)\1\2")
for line in fileinput.input():
if len(vowels.findall(line)) >= 3 and doubleletter.search(line) and not forbidden.search(line):
nice1 += 1
if inbetween.search(line) and twodouble.search(line):
nice2 += 1
print(nice1, "nice1 strings.")
print(nice2, "nice2 strings.")

32
2015/day-06/README.md Normal file
View File

@@ -0,0 +1,32 @@
# Day 6 efficient solution
For day 6, we have an array of lights (first booleans, then integers) on which
we want to perform some tasks, and then know the end result. To do so, the
easiest method is to simulate that process.
All operations execute on a specific rectangle of lights. This means that we
need to modify a potentially large number of lights at the same time. This is a
rather costly operation.
To get around this, we use run length encoding. Instead of storing a boolean
for each light, we store, per column, a list of runs of lights that are in the
same state. That way, the complexity of lights to flip is now proportional to
the number of rows we need to flip.
## Updating the runs
When we need to update the runs for a given column, we iterate over all runs
that are in that column. If a run is within the row range that we need to
modify, we can set the state of the run to the proper value. You may need to
split the run in several parts that are not all affected by the modification.
As a second step, we try to combine adjacent runs that are in the same state.
This reduces the cost of iterating over all of them significantly.
## Performance analysis
On my computer, the naive brute force implementation took about 5 seconds for
both part 1 and part 2. When running the run length implementation on the first
part, the algorithm is 20 times faster. However, on the second part, the
algorithm is only slightly faster (3.5 seconds) because runs can have more
values, and are thus not as easily combined.

300
2015/day-06/input.txt Normal file
View File

@@ -0,0 +1,300 @@
turn off 660,55 through 986,197
turn off 341,304 through 638,850
turn off 199,133 through 461,193
toggle 322,558 through 977,958
toggle 537,781 through 687,941
turn on 226,196 through 599,390
turn on 240,129 through 703,297
turn on 317,329 through 451,798
turn on 957,736 through 977,890
turn on 263,530 through 559,664
turn on 158,270 through 243,802
toggle 223,39 through 454,511
toggle 544,218 through 979,872
turn on 313,306 through 363,621
toggle 173,401 through 496,407
toggle 333,60 through 748,159
turn off 87,577 through 484,608
turn on 809,648 through 826,999
toggle 352,432 through 628,550
turn off 197,408 through 579,569
turn off 1,629 through 802,633
turn off 61,44 through 567,111
toggle 880,25 through 903,973
turn on 347,123 through 864,746
toggle 728,877 through 996,975
turn on 121,895 through 349,906
turn on 888,547 through 931,628
toggle 398,782 through 834,882
turn on 966,850 through 989,953
turn off 891,543 through 914,991
toggle 908,77 through 916,117
turn on 576,900 through 943,934
turn off 580,170 through 963,206
turn on 184,638 through 192,944
toggle 940,147 through 978,730
turn off 854,56 through 965,591
toggle 717,172 through 947,995
toggle 426,987 through 705,998
turn on 987,157 through 992,278
toggle 995,774 through 997,784
turn off 796,96 through 845,182
turn off 451,87 through 711,655
turn off 380,93 through 968,676
turn on 263,468 through 343,534
turn on 917,936 through 928,959
toggle 478,7 through 573,148
turn off 428,339 through 603,624
turn off 400,880 through 914,953
toggle 679,428 through 752,779
turn off 697,981 through 709,986
toggle 482,566 through 505,725
turn off 956,368 through 993,516
toggle 735,823 through 783,883
turn off 48,487 through 892,496
turn off 116,680 through 564,819
turn on 633,865 through 729,930
turn off 314,618 through 571,922
toggle 138,166 through 936,266
turn on 444,732 through 664,960
turn off 109,337 through 972,497
turn off 51,432 through 77,996
turn off 259,297 through 366,744
toggle 801,130 through 917,544
toggle 767,982 through 847,996
turn on 216,507 through 863,885
turn off 61,441 through 465,731
turn on 849,970 through 944,987
toggle 845,76 through 852,951
toggle 732,615 through 851,936
toggle 251,128 through 454,778
turn on 324,429 through 352,539
toggle 52,450 through 932,863
turn off 449,379 through 789,490
turn on 317,319 through 936,449
toggle 887,670 through 957,838
toggle 671,613 through 856,664
turn off 186,648 through 985,991
turn off 471,689 through 731,717
toggle 91,331 through 750,758
toggle 201,73 through 956,524
toggle 82,614 through 520,686
toggle 84,287 through 467,734
turn off 132,367 through 208,838
toggle 558,684 through 663,920
turn on 237,952 through 265,997
turn on 694,713 through 714,754
turn on 632,523 through 862,827
turn on 918,780 through 948,916
turn on 349,586 through 663,976
toggle 231,29 through 257,589
toggle 886,428 through 902,993
turn on 106,353 through 236,374
turn on 734,577 through 759,684
turn off 347,843 through 696,912
turn on 286,699 through 964,883
turn on 605,875 through 960,987
turn off 328,286 through 869,461
turn off 472,569 through 980,848
toggle 673,573 through 702,884
turn off 398,284 through 738,332
turn on 158,50 through 284,411
turn off 390,284 through 585,663
turn on 156,579 through 646,581
turn on 875,493 through 989,980
toggle 486,391 through 924,539
turn on 236,722 through 272,964
toggle 228,282 through 470,581
toggle 584,389 through 750,761
turn off 899,516 through 900,925
turn on 105,229 through 822,846
turn off 253,77 through 371,877
turn on 826,987 through 906,992
turn off 13,152 through 615,931
turn on 835,320 through 942,399
turn on 463,504 through 536,720
toggle 746,942 through 786,998
turn off 867,333 through 965,403
turn on 591,477 through 743,692
turn off 403,437 through 508,908
turn on 26,723 through 368,814
turn on 409,485 through 799,809
turn on 115,630 through 704,705
turn off 228,183 through 317,220
toggle 300,649 through 382,842
turn off 495,365 through 745,562
turn on 698,346 through 744,873
turn on 822,932 through 951,934
toggle 805,30 through 925,421
toggle 441,152 through 653,274
toggle 160,81 through 257,587
turn off 350,781 through 532,917
toggle 40,583 through 348,636
turn on 280,306 through 483,395
toggle 392,936 through 880,955
toggle 496,591 through 851,934
turn off 780,887 through 946,994
turn off 205,735 through 281,863
toggle 100,876 through 937,915
turn on 392,393 through 702,878
turn on 956,374 through 976,636
toggle 478,262 through 894,775
turn off 279,65 through 451,677
turn on 397,541 through 809,847
turn on 444,291 through 451,586
toggle 721,408 through 861,598
turn on 275,365 through 609,382
turn on 736,24 through 839,72
turn off 86,492 through 582,712
turn on 676,676 through 709,703
turn off 105,710 through 374,817
toggle 328,748 through 845,757
toggle 335,79 through 394,326
toggle 193,157 through 633,885
turn on 227,48 through 769,743
toggle 148,333 through 614,568
toggle 22,30 through 436,263
toggle 547,447 through 688,969
toggle 576,621 through 987,740
turn on 711,334 through 799,515
turn on 541,448 through 654,951
toggle 792,199 through 798,990
turn on 89,956 through 609,960
toggle 724,433 through 929,630
toggle 144,895 through 201,916
toggle 226,730 through 632,871
turn off 760,819 through 828,974
toggle 887,180 through 940,310
toggle 222,327 through 805,590
turn off 630,824 through 885,963
turn on 940,740 through 954,946
turn on 193,373 through 779,515
toggle 304,955 through 469,975
turn off 405,480 through 546,960
turn on 662,123 through 690,669
turn off 615,238 through 750,714
turn on 423,220 through 930,353
turn on 329,769 through 358,970
toggle 590,151 through 704,722
turn off 884,539 through 894,671
toggle 449,241 through 984,549
toggle 449,260 through 496,464
turn off 306,448 through 602,924
turn on 286,805 through 555,901
toggle 722,177 through 922,298
toggle 491,554 through 723,753
turn on 80,849 through 174,996
turn off 296,561 through 530,856
toggle 653,10 through 972,284
toggle 529,236 through 672,614
toggle 791,598 through 989,695
turn on 19,45 through 575,757
toggle 111,55 through 880,871
turn off 197,897 through 943,982
turn on 912,336 through 977,605
toggle 101,221 through 537,450
turn on 101,104 through 969,447
toggle 71,527 through 587,717
toggle 336,445 through 593,889
toggle 214,179 through 575,699
turn on 86,313 through 96,674
toggle 566,427 through 906,888
turn off 641,597 through 850,845
turn on 606,524 through 883,704
turn on 835,775 through 867,887
toggle 547,301 through 897,515
toggle 289,930 through 413,979
turn on 361,122 through 457,226
turn on 162,187 through 374,746
turn on 348,461 through 454,675
turn off 966,532 through 985,537
turn on 172,354 through 630,606
turn off 501,880 through 680,993
turn off 8,70 through 566,592
toggle 433,73 through 690,651
toggle 840,798 through 902,971
toggle 822,204 through 893,760
turn off 453,496 through 649,795
turn off 969,549 through 990,942
turn off 789,28 through 930,267
toggle 880,98 through 932,434
toggle 568,674 through 669,753
turn on 686,228 through 903,271
turn on 263,995 through 478,999
toggle 534,675 through 687,955
turn off 342,434 through 592,986
toggle 404,768 through 677,867
toggle 126,723 through 978,987
toggle 749,675 through 978,959
turn off 445,330 through 446,885
turn off 463,205 through 924,815
turn off 417,430 through 915,472
turn on 544,990 through 912,999
turn off 201,255 through 834,789
turn off 261,142 through 537,862
turn off 562,934 through 832,984
turn off 459,978 through 691,980
turn off 73,911 through 971,972
turn on 560,448 through 723,810
turn on 204,630 through 217,854
turn off 91,259 through 611,607
turn on 877,32 through 978,815
turn off 950,438 through 974,746
toggle 426,30 through 609,917
toggle 696,37 through 859,201
toggle 242,417 through 682,572
turn off 388,401 through 979,528
turn off 79,345 through 848,685
turn off 98,91 through 800,434
toggle 650,700 through 972,843
turn off 530,450 through 538,926
turn on 428,559 through 962,909
turn on 78,138 through 92,940
toggle 194,117 through 867,157
toggle 785,355 through 860,617
turn off 379,441 through 935,708
turn off 605,133 through 644,911
toggle 10,963 through 484,975
turn off 359,988 through 525,991
turn off 509,138 through 787,411
toggle 556,467 through 562,773
turn on 119,486 through 246,900
turn on 445,561 through 794,673
turn off 598,681 through 978,921
turn off 974,230 through 995,641
turn off 760,75 through 800,275
toggle 441,215 through 528,680
turn off 701,636 through 928,877
turn on 165,753 through 202,780
toggle 501,412 through 998,516
toggle 161,105 through 657,395
turn on 113,340 through 472,972
toggle 384,994 through 663,999
turn on 969,994 through 983,997
turn on 519,600 through 750,615
turn off 363,899 through 948,935
turn on 271,845 through 454,882
turn off 376,528 through 779,640
toggle 767,98 through 854,853
toggle 107,322 through 378,688
turn off 235,899 through 818,932
turn on 445,611 through 532,705
toggle 629,387 through 814,577
toggle 112,414 through 387,421
toggle 319,184 through 382,203
turn on 627,796 through 973,940
toggle 602,45 through 763,151
turn off 441,375 through 974,545
toggle 871,952 through 989,998
turn on 717,272 through 850,817
toggle 475,711 through 921,882
toggle 66,191 through 757,481
turn off 50,197 through 733,656
toggle 83,575 through 915,728
turn on 777,812 through 837,912
turn on 20,984 through 571,994
turn off 446,432 through 458,648
turn on 715,871 through 722,890
toggle 424,675 through 740,862
toggle 580,592 through 671,900
toggle 296,687 through 906,775

87
2015/day-06/solution.py Normal file
View File

@@ -0,0 +1,87 @@
from __future__ import print_function
import fileinput
import re
import sys
def compact(lightList):
last = None
newList = []
for streak in sorted(lightList):
if last is not None:
if streak[2] == last[2]:
# Repeating state, merge
last = (last[0], streak[1], last[2])
continue
else:
newList.append(last)
last = streak
newList.append(last)
return newList
def updateState(sliceList, yStart, yEnd, updateFnc):
newList = []
for start, end, state in sliceList:
if not start <= yStart <= end and not yStart <= start <= yEnd:
# Block not in range, skip
newList.append((start, end, state))
continue
if start < yStart:
# Split the block at the start
newList.append((start, yStart - 1, state))
start = yStart
if end > yEnd:
# Split the block at the end
newList.append((yEnd + 1, end, state))
end = yEnd
newList.append((start, end, updateFnc(state)))
return compact(newList)
def colsum(lightList):
return sum(int(state) * (stop - start + 1) for start, stop, state in lightList)
def getPart1Update(command):
if "toggle" in command:
return lambda x: not x
elif "on" in command:
return lambda _: True
else:
return lambda _: False
def getPart2Update(command):
if "toggle" in command:
return lambda x: x + 2
elif "on" in command:
return lambda x: x + 1
else:
return lambda x: max(0, x - 1)
lights1 = []
lights2 = []
for x in range(1000):
lights1.append([(0, 999, False)])
lights2.append([(0, 999, 0)])
for line in fileinput.input():
match = re.search(r"^(toggle|turn (on|off)) (\d+),(\d+) through (\d+),(\d+)$", line)
xStart = int(match.group(3))
yStart = int(match.group(4))
xEnd = int(match.group(5))
yEnd = int(match.group(6))
command = match.group(1)
for x in range(xStart, xEnd + 1):
lights1[x] = updateState(lights1[x], yStart, yEnd, getPart1Update(command))
lights2[x] = updateState(lights2[x], yStart, yEnd, getPart2Update(command))
print("Lights on:", sum(colsum(x) for x in lights1))
print("Lumen:", sum(colsum(x) for x in lights2))

339
2015/day-07/input.txt Normal file
View File

@@ -0,0 +1,339 @@
NOT dq -> dr
kg OR kf -> kh
ep OR eo -> eq
44430 -> b
NOT gs -> gt
dd OR do -> dp
eg AND ei -> ej
y AND ae -> ag
jx AND jz -> ka
lf RSHIFT 2 -> lg
z AND aa -> ac
dy AND ej -> el
bj OR bi -> bk
kk RSHIFT 3 -> km
NOT cn -> co
gn AND gp -> gq
cq AND cs -> ct
eo LSHIFT 15 -> es
lg OR lm -> ln
dy OR ej -> ek
NOT di -> dj
1 AND fi -> fj
kf LSHIFT 15 -> kj
NOT jy -> jz
NOT ft -> fu
fs AND fu -> fv
NOT hr -> hs
ck OR cl -> cm
jp RSHIFT 5 -> js
iv OR jb -> jc
is OR it -> iu
ld OR le -> lf
NOT fc -> fd
NOT dm -> dn
bn OR by -> bz
aj AND al -> am
cd LSHIFT 15 -> ch
jp AND ka -> kc
ci OR ct -> cu
gv AND gx -> gy
de AND dk -> dm
x RSHIFT 5 -> aa
et RSHIFT 2 -> eu
x RSHIFT 1 -> aq
ia OR ig -> ih
bk LSHIFT 1 -> ce
y OR ae -> af
NOT ca -> cb
e AND f -> h
ia AND ig -> ii
ck AND cl -> cn
NOT jh -> ji
z OR aa -> ab
1 AND en -> eo
ib AND ic -> ie
NOT eh -> ei
iy AND ja -> jb
NOT bb -> bc
ha OR gz -> hb
1 AND cx -> cy
NOT ax -> ay
ev OR ew -> ex
bn RSHIFT 2 -> bo
er OR es -> et
eu OR fa -> fb
jp OR ka -> kb
ea AND eb -> ed
k AND m -> n
et RSHIFT 3 -> ev
et RSHIFT 5 -> ew
hz RSHIFT 1 -> is
ki OR kj -> kk
NOT h -> i
lv LSHIFT 15 -> lz
as RSHIFT 1 -> bl
hu LSHIFT 15 -> hy
iw AND ix -> iz
lf RSHIFT 1 -> ly
fp OR fv -> fw
1 AND am -> an
ap LSHIFT 1 -> bj
u LSHIFT 1 -> ao
b RSHIFT 5 -> f
jq AND jw -> jy
iu RSHIFT 3 -> iw
ih AND ij -> ik
NOT iz -> ja
de OR dk -> dl
iu OR jf -> jg
as AND bd -> bf
b RSHIFT 3 -> e
jq OR jw -> jx
iv AND jb -> jd
cg OR ch -> ci
iu AND jf -> jh
lx -> a
1 AND cc -> cd
ly OR lz -> ma
NOT el -> em
1 AND bh -> bi
fb AND fd -> fe
lf OR lq -> lr
bn RSHIFT 3 -> bp
bn AND by -> ca
af AND ah -> ai
cf LSHIFT 1 -> cz
dw OR dx -> dy
gj AND gu -> gw
jg AND ji -> jj
jr OR js -> jt
bl OR bm -> bn
gj RSHIFT 2 -> gk
cj OR cp -> cq
gj OR gu -> gv
b OR n -> o
o AND q -> r
bi LSHIFT 15 -> bm
dy RSHIFT 1 -> er
cu AND cw -> cx
iw OR ix -> iy
hc OR hd -> he
0 -> c
db OR dc -> dd
kk RSHIFT 2 -> kl
eq LSHIFT 1 -> fk
dz OR ef -> eg
NOT ed -> ee
lw OR lv -> lx
fw AND fy -> fz
dz AND ef -> eh
jp RSHIFT 3 -> jr
lg AND lm -> lo
ci RSHIFT 2 -> cj
be AND bg -> bh
lc LSHIFT 1 -> lw
hm AND ho -> hp
jr AND js -> ju
1 AND io -> ip
cm AND co -> cp
ib OR ic -> id
NOT bf -> bg
fo RSHIFT 5 -> fr
ip LSHIFT 15 -> it
jt AND jv -> jw
jc AND je -> jf
du OR dt -> dv
NOT fx -> fy
aw AND ay -> az
ge LSHIFT 15 -> gi
NOT ak -> al
fm OR fn -> fo
ff AND fh -> fi
ci RSHIFT 5 -> cl
cz OR cy -> da
NOT ey -> ez
NOT ju -> jv
NOT ls -> lt
kk AND kv -> kx
NOT ii -> ij
kl AND kr -> kt
jk LSHIFT 15 -> jo
e OR f -> g
NOT bs -> bt
hi AND hk -> hl
hz OR ik -> il
ek AND em -> en
ao OR an -> ap
dv LSHIFT 1 -> ep
an LSHIFT 15 -> ar
fo RSHIFT 1 -> gh
NOT im -> in
kk RSHIFT 1 -> ld
hw LSHIFT 1 -> iq
ec AND ee -> ef
hb LSHIFT 1 -> hv
kb AND kd -> ke
x AND ai -> ak
dd AND do -> dq
aq OR ar -> as
iq OR ip -> ir
dl AND dn -> do
iu RSHIFT 5 -> ix
as OR bd -> be
NOT go -> gp
fk OR fj -> fl
jm LSHIFT 1 -> kg
NOT cv -> cw
dp AND dr -> ds
dt LSHIFT 15 -> dx
et RSHIFT 1 -> fm
dy RSHIFT 3 -> ea
fp AND fv -> fx
NOT p -> q
dd RSHIFT 2 -> de
eu AND fa -> fc
ba AND bc -> bd
dh AND dj -> dk
lr AND lt -> lu
he RSHIFT 1 -> hx
ex AND ez -> fa
df OR dg -> dh
fj LSHIFT 15 -> fn
NOT kx -> ky
gk OR gq -> gr
dy RSHIFT 2 -> dz
gh OR gi -> gj
lj AND ll -> lm
x OR ai -> aj
bz AND cb -> cc
1 AND lu -> lv
as RSHIFT 3 -> au
ce OR cd -> cf
il AND in -> io
dd RSHIFT 1 -> dw
NOT lo -> lp
c LSHIFT 1 -> t
dd RSHIFT 3 -> df
dd RSHIFT 5 -> dg
lh AND li -> lk
lf RSHIFT 5 -> li
dy RSHIFT 5 -> eb
NOT kt -> ku
at OR az -> ba
x RSHIFT 3 -> z
NOT lk -> ll
lb OR la -> lc
1 AND r -> s
lh OR li -> lj
ln AND lp -> lq
kk RSHIFT 5 -> kn
ea OR eb -> ec
ci AND ct -> cv
b RSHIFT 2 -> d
jp RSHIFT 1 -> ki
NOT cr -> cs
NOT jd -> je
jp RSHIFT 2 -> jq
jn OR jo -> jp
lf RSHIFT 3 -> lh
1 AND ds -> dt
lf AND lq -> ls
la LSHIFT 15 -> le
NOT fg -> fh
at AND az -> bb
au AND av -> ax
kw AND ky -> kz
v OR w -> x
kk OR kv -> kw
ks AND ku -> kv
kh LSHIFT 1 -> lb
1 AND kz -> la
NOT kc -> kd
x RSHIFT 2 -> y
et OR fe -> ff
et AND fe -> fg
NOT ac -> ad
jl OR jk -> jm
1 AND jj -> jk
bn RSHIFT 1 -> cg
NOT kp -> kq
ci RSHIFT 3 -> ck
ev AND ew -> ey
1 AND ke -> kf
cj AND cp -> cr
ir LSHIFT 1 -> jl
NOT gw -> gx
as RSHIFT 2 -> at
iu RSHIFT 1 -> jn
cy LSHIFT 15 -> dc
hg OR hh -> hi
ci RSHIFT 1 -> db
au OR av -> aw
km AND kn -> kp
gj RSHIFT 1 -> hc
iu RSHIFT 2 -> iv
ab AND ad -> ae
da LSHIFT 1 -> du
NOT bw -> bx
km OR kn -> ko
ko AND kq -> kr
bv AND bx -> by
kl OR kr -> ks
1 AND ht -> hu
df AND dg -> di
NOT ag -> ah
d OR j -> k
d AND j -> l
b AND n -> p
gf OR ge -> gg
gg LSHIFT 1 -> ha
bn RSHIFT 5 -> bq
bo OR bu -> bv
1 AND gy -> gz
s LSHIFT 15 -> w
NOT ie -> if
as RSHIFT 5 -> av
bo AND bu -> bw
hz AND ik -> im
bp AND bq -> bs
b RSHIFT 1 -> v
NOT l -> m
bp OR bq -> br
g AND i -> j
br AND bt -> bu
t OR s -> u
hz RSHIFT 5 -> ic
gk AND gq -> gs
fl LSHIFT 1 -> gf
he RSHIFT 3 -> hg
gz LSHIFT 15 -> hd
hf OR hl -> hm
1 AND gd -> ge
fo OR fz -> ga
id AND if -> ig
fo AND fz -> gb
gr AND gt -> gu
he OR hp -> hq
fq AND fr -> ft
ga AND gc -> gd
fo RSHIFT 2 -> fp
gl OR gm -> gn
hg AND hh -> hj
NOT hn -> ho
gl AND gm -> go
he RSHIFT 5 -> hh
NOT gb -> gc
hq AND hs -> ht
hz RSHIFT 3 -> ib
hz RSHIFT 2 -> ia
fq OR fr -> fs
hx OR hy -> hz
he AND hp -> hr
gj RSHIFT 5 -> gm
hf AND hl -> hn
hv OR hu -> hw
NOT hj -> hk
gj RSHIFT 3 -> gl
fo RSHIFT 3 -> fq
he RSHIFT 2 -> hf

66
2015/day-07/solution.py Normal file
View File

@@ -0,0 +1,66 @@
from __future__ import print_function
import fileinput
import re
import sys
recipe = {}
values = {}
def findValue(node):
match = re.search(r"\d+", node)
if match:
return int(match.group(0))
if node in values:
return values[node]
if node not in recipe:
sys.exit("Node without recipe '" + node + "'")
valueA = None
valueB = None
if recipe[node][0]:
valueA = findValue(recipe[node][0].strip())
if recipe[node][2]:
valueB = findValue(recipe[node][2])
action = recipe[node][1]
value = None
if action == "RSHIFT":
value = valueA >> valueB
elif action == "LSHIFT":
value = (valueA << valueB) & 0xffff
elif action == "NOT":
value = (~valueB) & 0xffff
elif action == "IS":
value = valueA & 0xffff
elif action == "AND":
value = valueA & valueB
elif action == "OR":
value = valueA | valueB
else:
sys.exit("Unsupported command " + action)
values[node] = value
return value
opPattern = re.compile(r"(\w+ )?(RSHIFT|LSHIFT|NOT|AND|OR) (\w+) -> (\w+)")
valuePattern = re.compile(r"(\w+) -> (\w+)")
for line in fileinput.input():
match = valuePattern.match(line)
if match:
recipe[match.group(2)] = (match.group(1), "IS", "")
else:
match = opPattern.match(line)
if match.group(4) in recipe:
sys.exit("Node with multiple recipes")
recipe[match.group(4)] = (match.group(1), match.group(2), match.group(3))
a = findValue("a")
print("Initial a is ", a)
values = {}
values["b"] = a
print("Secondary a is", findValue("a"))

300
2015/day-08/input.txt Normal file
View File

@@ -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"

31
2015/day-08/solution.py Normal file
View File

@@ -0,0 +1,31 @@
from __future__ import print_function
import fileinput
import re
totalLess = 0
totalMore = 0
for line in fileinput.input():
original = len(line)
diff = 2
plus = 2
escaped = False
for c in line:
if c == "\\" or c == "\"":
plus += 1
if c == "\\" and not escaped:
escaped = True
diff += 1
continue
if escaped and c == "x":
diff += 2
escaped = False
totalLess += diff
totalMore += plus
print(totalLess, "less")
print(totalMore, "more")

28
2015/day-09/input.txt Normal file
View File

@@ -0,0 +1,28 @@
Tristram to AlphaCentauri = 34
Tristram to Snowdin = 100
Tristram to Tambi = 63
Tristram to Faerun = 108
Tristram to Norrath = 111
Tristram to Straylight = 89
Tristram to Arbre = 132
AlphaCentauri to Snowdin = 4
AlphaCentauri to Tambi = 79
AlphaCentauri to Faerun = 44
AlphaCentauri to Norrath = 147
AlphaCentauri to Straylight = 133
AlphaCentauri to Arbre = 74
Snowdin to Tambi = 105
Snowdin to Faerun = 95
Snowdin to Norrath = 48
Snowdin to Straylight = 88
Snowdin to Arbre = 7
Tambi to Faerun = 68
Tambi to Norrath = 134
Tambi to Straylight = 107
Tambi to Arbre = 40
Faerun to Norrath = 11
Faerun to Straylight = 66
Faerun to Arbre = 144
Norrath to Straylight = 115
Norrath to Arbre = 135
Straylight to Arbre = 127

64
2015/day-09/solution.py Normal file
View File

@@ -0,0 +1,64 @@
from __future__ import print_function
import re
import fileinput
dist = {}
visited = set()
def computeMinDistance(startPoint):
visited.add(startPoint)
if len(dist) == len(visited):
maximum = 0
minimum = 0
else:
minimum = None
maximum = 0
for i in dist[startPoint]:
if i in visited:
continue
shortest, longest = computeMinDistance(i)
if shortest is not None:
shortest += dist[startPoint][i]
longest += dist[startPoint][i]
if minimum is None:
minimum = shortest
maximum = longest
else:
minimum = min(minimum, shortest)
maximum = max(maximum, longest)
visited.remove(startPoint)
return minimum, maximum
linePattern = re.compile(r"(\w+) to (\w+) = (\d+)")
for line in fileinput.input():
match = linePattern.match(line)
if match.group(1) not in dist:
dist[match.group(1)] = {}
if match.group(2) not in dist:
dist[match.group(2)] = {}
dist[match.group(1)][match.group(2)] = int(match.group(3))
dist[match.group(2)][match.group(1)] = int(match.group(3))
minimum = None
possible = []
for i in dist:
shortest, longest = computeMinDistance(i)
if shortest is not None:
possible.append(shortest)
possible.append(longest)
print("Shortest path is", min(possible))
print("Longest path is", max(possible))

17
2015/day-10/solution.py Normal file
View File

@@ -0,0 +1,17 @@
from __future__ import print_function
import itertools
def lookandsay(line):
return ''.join([str(len(list(it))) + c for c, it in itertools.groupby(line)])
line = "1321131112"
for x in range(40):
line = lookandsay(line)
print("40:", len(line))
for x in range(10):
line = lookandsay(line)
print("50:", len(line))

1
2015/day-11/input.txt Normal file
View File

@@ -0,0 +1 @@
hxbxwxba

63
2015/day-11/solution.py Normal file
View File

@@ -0,0 +1,63 @@
from __future__ import print_function
import string
letters = [c for c in string.ascii_lowercase]
password = "hxbxwxba"
forbidden = set([letters.index(c) for c in "iol"])
passwordCode = [letters.index(c) for c in password]
def convert(password):
return [letters.index(c) for c in password]
def isOk(password):
hasStreak = False
prev = -2
streak = 1
same = 0
sameChar = None
for x in password:
if x in forbidden:
return False
if x == prev + 1:
streak += 1
if streak >= 3:
hasStreak = True
else:
streak = 1
if x == prev and x is not sameChar:
same += 1
sameChar = x
prev = x
return hasStreak and same >= 2
def incrementForbidden(password):
for idx, x in enumerate(password):
if x in forbidden:
password[idx] = (x + 1) % len(letters)
for i in range(idx + 1, len(password)):
password[i] = 0
return
def increment(password):
carry = True
i = len(password)
while carry and i > 0:
i -= 1
password[i] = (password[i] + 1) % len(letters)
carry = password[i] == 0
incrementForbidden(password)
for x in range(2):
increment(passwordCode)
while not isOk(passwordCode):
increment(passwordCode)
print("Next password is", ''.join([letters[c] for c in passwordCode]))

1
2015/day-12/input.txt Normal file

File diff suppressed because one or more lines are too long

24
2015/day-12/solution.py Normal file
View File

@@ -0,0 +1,24 @@
from __future__ import print_function
import fileinput
import re
import json
def totals(obj):
if isinstance(obj, int):
return obj
if isinstance(obj, list):
return sum(totals(i) for i in obj)
if not isinstance(obj, dict) or "red" in list(obj.values()):
return 0
return sum(totals(i) for i in list(obj.values()))
fileData = ''.join(line for line in fileinput.input())
# Solve the first part by regex, no parsing needed.
pattern = re.compile(r"-?\d+")
total = sum(int(match) for match in pattern.findall(fileData))
data = json.loads(fileData)
print(total, totals(data))

56
2015/day-13/input.txt Normal file
View File

@@ -0,0 +1,56 @@
Alice would lose 2 happiness units by sitting next to Bob.
Alice would lose 62 happiness units by sitting next to Carol.
Alice would gain 65 happiness units by sitting next to David.
Alice would gain 21 happiness units by sitting next to Eric.
Alice would lose 81 happiness units by sitting next to Frank.
Alice would lose 4 happiness units by sitting next to George.
Alice would lose 80 happiness units by sitting next to Mallory.
Bob would gain 93 happiness units by sitting next to Alice.
Bob would gain 19 happiness units by sitting next to Carol.
Bob would gain 5 happiness units by sitting next to David.
Bob would gain 49 happiness units by sitting next to Eric.
Bob would gain 68 happiness units by sitting next to Frank.
Bob would gain 23 happiness units by sitting next to George.
Bob would gain 29 happiness units by sitting next to Mallory.
Carol would lose 54 happiness units by sitting next to Alice.
Carol would lose 70 happiness units by sitting next to Bob.
Carol would lose 37 happiness units by sitting next to David.
Carol would lose 46 happiness units by sitting next to Eric.
Carol would gain 33 happiness units by sitting next to Frank.
Carol would lose 35 happiness units by sitting next to George.
Carol would gain 10 happiness units by sitting next to Mallory.
David would gain 43 happiness units by sitting next to Alice.
David would lose 96 happiness units by sitting next to Bob.
David would lose 53 happiness units by sitting next to Carol.
David would lose 30 happiness units by sitting next to Eric.
David would lose 12 happiness units by sitting next to Frank.
David would gain 75 happiness units by sitting next to George.
David would lose 20 happiness units by sitting next to Mallory.
Eric would gain 8 happiness units by sitting next to Alice.
Eric would lose 89 happiness units by sitting next to Bob.
Eric would lose 69 happiness units by sitting next to Carol.
Eric would lose 34 happiness units by sitting next to David.
Eric would gain 95 happiness units by sitting next to Frank.
Eric would gain 34 happiness units by sitting next to George.
Eric would lose 99 happiness units by sitting next to Mallory.
Frank would lose 97 happiness units by sitting next to Alice.
Frank would gain 6 happiness units by sitting next to Bob.
Frank would lose 9 happiness units by sitting next to Carol.
Frank would gain 56 happiness units by sitting next to David.
Frank would lose 17 happiness units by sitting next to Eric.
Frank would gain 18 happiness units by sitting next to George.
Frank would lose 56 happiness units by sitting next to Mallory.
George would gain 45 happiness units by sitting next to Alice.
George would gain 76 happiness units by sitting next to Bob.
George would gain 63 happiness units by sitting next to Carol.
George would gain 54 happiness units by sitting next to David.
George would gain 54 happiness units by sitting next to Eric.
George would gain 30 happiness units by sitting next to Frank.
George would gain 7 happiness units by sitting next to Mallory.
Mallory would gain 31 happiness units by sitting next to Alice.
Mallory would lose 32 happiness units by sitting next to Bob.
Mallory would gain 95 happiness units by sitting next to Carol.
Mallory would gain 91 happiness units by sitting next to David.
Mallory would lose 66 happiness units by sitting next to Eric.
Mallory would lose 75 happiness units by sitting next to Frank.
Mallory would lose 99 happiness units by sitting next to George.

51
2015/day-13/solution.py Normal file
View File

@@ -0,0 +1,51 @@
from __future__ import print_function
import fileinput
import re
from itertools import permutations
linePattern = re.compile(r"(\w+) would (gain|lose) (\d+) happiness units by sitting next to (\w+)\.")
ratings = {}
# Read the input by regex
for line in fileinput.input():
match = linePattern.match(line)
person = match.group(1)
if person not in ratings:
ratings[person] = {}
value = int(match.group(3))
if match.group(2) == "lose":
value *= -1
target = match.group(4)
ratings[person][target] = value
maxHappiness = 0
maxWithMe = 0
# Compute happiness with everyone present
for permutation in permutations(list(ratings.keys())):
happiness = 0
withMe = 0
for i in range(len(permutation)):
target = permutation[i]
neighbour1 = permutation[(i + 1) % len(permutation)]
neighbour2 = permutation[(i - 1 + len(permutation)) % len(permutation)]
happiness += ratings[target][neighbour1]
if i < len(permutation) - 1:
withMe += ratings[target][neighbour1]
happiness += ratings[target][neighbour2]
if i > 0:
withMe += ratings[target][neighbour2]
maxHappiness = max(maxHappiness, happiness)
maxWithMe = max(maxWithMe, withMe)
print(maxHappiness, maxWithMe)

9
2015/day-14/input.txt Normal file
View File

@@ -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.

34
2015/day-14/solution.py Normal file
View File

@@ -0,0 +1,34 @@
from __future__ import division, print_function
import fileinput
import re
import itertools
from collections import defaultdict
pattern = re.compile("(\w+) can fly (\d+) km\/s for (\d+) seconds, but then must rest for (\d+) seconds.")
runners = defaultdict(lambda: 0)
runnerData = {}
runnerPoints = defaultdict(lambda: 0)
totalTime = 2503
for line in fileinput.input():
match = pattern.search(line)
reindeer, speed, runtime, resttime = match.group(1, 2, 3, 4)
speed = int(speed)
runtime = int(runtime)
resttime = int(resttime)
runnerData[reindeer] = itertools.cycle([speed] * runtime + [0] * resttime)
for _ in range(totalTime):
for i in runnerData:
runners[i] += next(runnerData[i])
best = max(runners.values())
for i in runners:
if runners[i] == best:
runnerPoints[i] += 1
print("Fastest runner covered", max(runners.values()))
print("Highest score is", max(runnerPoints.values()))

4
2015/day-15/input.txt Normal file
View File

@@ -0,0 +1,4 @@
Sugar: capacity 3, durability 0, flavor 0, texture -3, calories 2
Sprinkles: capacity -3, durability 3, flavor 0, texture 0, calories 9
Candy: capacity -1, durability 0, flavor 4, texture 0, calories 1
Chocolate: capacity 0, durability 0, flavor -2, texture 2, calories 8

47
2015/day-15/solution.py Normal file
View File

@@ -0,0 +1,47 @@
from __future__ import print_function
import fileinput
import re
from operator import mul
from functools import reduce
pattern = re.compile(r"(\w+): capacity (-?\d+), durability (-?\d+), flavor (-?\d+), texture (-?\d+), calories (-?\d+)")
ingredients = []
calories = []
def computeScore(amounts):
scores = [sum(ingredients[idx][x] * value for idx, value in enumerate(amounts)) for x in range(4)]
return reduce(mul, [max(x, 0) for x in scores], 1)
def computeCalories(amounts):
return sum(a * b for a, b in zip(calories, amounts))
def computeMax(ingredient, budget, currentAmounts):
budgetLeft = budget - sum(currentAmounts[:ingredient])
if ingredient == len(ingredients) - 1:
currentAmounts[ingredient] = budgetLeft
score = computeScore(currentAmounts)
if computeCalories(currentAmounts) == 500:
return score, score
return score, None
results = []
resultsCorrect = [0]
for n in range(budgetLeft + 1):
currentAmounts[ingredient] = n
general, correct = computeMax(ingredient + 1, budget, currentAmounts)
results.append(general)
resultsCorrect.append(correct)
return max(results), max(x for x in resultsCorrect if x is not None)
for line in fileinput.input():
match = pattern.match(line)
ingredients.append([int(x) for x in match.group(2, 3, 4, 5)])
calories.append(int(match.group(6)))
print(computeMax(0, 100, [0] * len(ingredients)))

500
2015/day-16/input.txt Normal file
View File

@@ -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

46
2015/day-16/solution.py Normal file
View File

@@ -0,0 +1,46 @@
from __future__ import print_function
import re
import fileinput
correctAunt = {
"children": 3,
"cats": 7,
"samoyeds": 2,
"pomeranians": 3,
"akitas": 0,
"vizslas": 0,
"goldfish": 5,
"trees": 3,
"cars": 2,
"perfumes": 1
}
def isOK(auntString):
for thing, value in re.findall(r"([a-z]+): (\d+)", line):
if correctAunt[thing] != int(value):
return False
return True
def isOK2(auntString):
for thing, value in re.findall(r"([a-z]+): (\d+)", line):
if thing == "cats" or thing == "trees":
if int(value) <= correctAunt[thing]:
return False
elif thing == "pomeranians" or thing == "goldfish":
if int(value) >= correctAunt[thing]:
return False
elif correctAunt[thing] != int(value):
return False
return True
for line in fileinput.input():
if isOK(line):
print("Found aunt first:", line)
if isOK2(line):
print("Found aunt second:", line)

26
2015/day-17/README.md Normal file
View File

@@ -0,0 +1,26 @@
# Day 17 efficient solution
Day 17 is an instance of the subset sum problem. This problem asks whether for
a (multi)set of integers *V*, there is a non-empty subset of integers summing up to
exactly *s*. This problem is NP-complete.
The brute force approach of this is trying every possible set in the powerset
of *V* to see if they match. This is inpractical however, because a powerset of
a set of size *n* contains 2<sup>2</sup> sets.
In the exercise, we have 20 buckets, and 2<sup>20</sup> is still
brute-forcable. There is a smarter approach.
We split the list of buckets in two lists of (approximately) the same size. We
then take the powersets of those two lists and compute the sum for each entry.
This leaves us with a total of 2<sup>n / 2 + 1</sup> entries. We then sort both
sublists on the total value of each entry.
Finally, we iterate of the first list, and use binary search to see whether
there is an appropriately sized entry in the second list. This gives us a final
complexity of *n* times 2<sup>*n*/2</sup>, allowing the solution to be computed
instantly.
The algorithm above can be modified to find all combinations, not just one, in
time proportional to the number of solutions. This is implemented in the final
program.

20
2015/day-17/input.txt Normal file
View File

@@ -0,0 +1,20 @@
33
14
18
20
45
35
16
35
1
13
18
13
50
44
48
6
24
41
30
42

62
2015/day-17/solution.py Normal file
View File

@@ -0,0 +1,62 @@
from __future__ import print_function, division
import fileinput
from collections import defaultdict
import bisect
def value(buckets, choice):
total = 0
for value in buckets:
if choice % 2 == 1:
total += value
choice //= 2
return total
def ones(x):
n = 0
while x > 0:
if x % 2:
n += 1
x //= 2
return n
def partition(a_list):
pivot = len(a_list) // 2
return a_list[:pivot], a_list[pivot:]
def partitionList(buckets):
result = [(value(buckets, x), ones(x)) for x in range(1 << len(buckets))]
result.sort()
return result
buckets = []
for line in fileinput.input():
buckets.append(int(line))
partition1, partition2 = partition(buckets)
values1 = partitionList(partition1)
values2 = partitionList(partition2)
possible = defaultdict(lambda: 0)
i = 0
target = 150
for entry in values1:
i = bisect.bisect_left(values2, (target - entry[0], 0))
while i < len(values2) and entry[0] + values2[i][0] == target:
possible[entry[1] + values2[i][1]] += 1
i += 1
print("Total possibilities:", sum(possible.values()))
print("Minimal possibilities:", possible[min(possible.keys())])

100
2015/day-18/input.txt Normal file
View File

@@ -0,0 +1,100 @@
#...##......#......##.##..#...##......##.#.#.###.#.#..#..#......####..#......###.#.#....#..##..###..
####..#.#...#....#.#####.##.##.#..#.......#....#.##...###.###..#.#.#........#..#.#.##...##..#.####.#
...#..##...#.#.###.#.###..#.##.####.###...#...........#.###..##.#.##.#.###...#.#..###....#.###.#..#.
.#...##...####.#..#.....#..#...#.#.##...#...##..#.#.###....#..###.....##..#.###..###.....##..###...#
..##.#####....##..#.#..##.##..######...#..###.######.....#..##...#.#..##..##..#..#..#..##.#.#.#.#...
.###.###.###...##...##..###..##.###.#.....##..##.#.#########...##..##.#..##.#..##..####..#.#.#.#####
#.#####..###.###.##.##.#...#.#.#.#..#.###...#..##.###.#...####.#..#.#.....###..#..####..#.#.#...##..
....#...##.....#....####.##.#.###..#.#.##..#.#...##.###.###..#.##..#.#.##..##..#.##.###..#.#.###.###
##.##...#.##...#.#..#.#..#...###...###.#..#..#.#####..###.#......#.....###.#####.#.#..#.#.#.##..#.#.
#.#..#.....#.....##.#..##...###..##...##...###.#.###.#..#.#.###...##..##..#.###...#.#######.#...#.#.
#.#.....####.#..#.##...#.##....#####.###.#.....#####....###..#........##..####...#...#.###....#..###
##.#.##..#.#.##.#.....##.#.....###.####.#..######.....####.#.#..##.#.##...#..#.#.....#.####.#.......
#..#..#.#..#.######.##..##.####.....##.#.##.#.######..#.#....#.#...#.#..#..#.#.###.#..#.#.#..#...###
####..####.#.#.###.....#.#.#.##..#.##.##.##.#..##..##.#.##.....#.#..#.####.....###.#..#.####.#.#..##
###.##..##.#.##..#..##...#.#####.##.#....##.####.#.##....#..###.#.#.##...#.....#.#.#.#.#..##.#.#..#.
......#..####...##.##...#.##.##...##..#..##.###..#...#..##...#.#....###.####...#.##.###.#.##.####.##
..#...#####.#.#..#.##....#..#...#..####.....###...##.###....#..#.###...#........#.#.##..#..#.#.....#
#######.#.#.###.###..######.##..#####.##.###.###....####.#..##.##...###.#..############.#.##....##.#
#.#...##.###.#.###..#.#.#.#.#.#..##..####.#..##.....#.##..#.##...##.#..##..#.#.#....##....##.#..#.#.
..#.#.####.....###..#######.#.#.#.#...##.#####.....##...##...##.###..######.###..#...####.#..###.###
.#.##....#.#.##..##.#.##.##..######...#.....#..#.#.#.#.....#.#..##.#.#.......#######....#.......#...
..###.##.##..##....#.###...#.....##..##......###...##..###.##...##.###.#.#.#.###.###.#.#...###..#...
.##.#.#...#...##.#.#...#..#..#.#...##.#.##...##..#....#.#..##.#..#.#..#.#.....#..#.#...#######.#.##.
...####....#.###.#..###..##...##..#.#.#.###...#..##.##.##..##.#...#..#.##.....#.#........#..#.#.####
.....##..###...#....#.#.#.#...###.###...#.#...#.#.####....#..####...###..#..######..##.##..###.#####
#####.##..#....###.###....##.....#.#..#....#.#####.##.#.####.#.##...#..###...###..##...#.###.#####..
###.##..........########.######....####.###.#..##...#.##.####.#.....##..#####..###...#####.....#.#.#
##..#####.##.#.#####.#.##.##..#.##....########.#####.#...#.###.##...#.###.#.#..#....##.#..#...#.#.#.
.##.#....#..#...#..#####..#..##.#......#..#....########...#..#...#.....####.#...##...#.###.#.#..##.#
.##.##.#.##.#.##...#.#.#..##.##.###.#..##..#...###.##.###.#####.#.###..#..###.#...#.###.#...#..#.#.#
.#..#..#.#..#..###..#....###.####.##.#.###.#.##.###.#.##.###.###...###...###.#...####...#.##.##.#.#.
###..##...###...#..##.#..#.#...##....###.##.##..#####....###..#..#....#..###.###.#...#.##...#.#.#..#
#....#.......##.....#.##...#..#.###.#.##..##..#.##..#.###..##.##...#####.#..#####..#####..#####....#
.####.####....###..###.#.##.####.##.#...####.#.###.#.....#...####..#####.###..#.#.###.##.##...##..#.
####..##...##.########...##..###..#..###.##.#.#.#........#.#####.#...#.###.####.#..####..#.#.#....##
###.#..#...###.#..#..#.###...##..###.##.#.#...#..#...####..##....#.#..#..##.#.#...#####.###.#..#.#.#
...##....#.###.#.#..##...##.###.#..#..#......#...#.#..####.#.##..######.####.#...#..#..#..##.#.#.##.
##.####.#...#..#.#.##..##.#.#.###..##...####......#..######.#......#.##.#....##...###.#.#..#......##
#.....#...#######.##.#..#.#...###.#..#.####....#.#.##.#.##...###..#...#.###.##..#.###..#.##...#####.
#####.##...#..#.#.#.......#.##..#####..#####...###..##.#.#..###.#.#####.####..#.#..##...#.##...#.###
.##.#..#######.###.#.####.....##...#.##.#.#..#...##....####......######.#..######.....##########.##.
##...#.#..#.##.###.#.#.#.##.###.##..##.##.##...#.#..###.#######..#.....#####..#....######.#..##..###
.#.#.###.....#..##..#.#..##..#.###...###.#..##...#...#.#####.#.#####..###.#..#...##..#.#..#..####...
.#......##..#.....####.###....##.###.....###.##........#.###.##..#..#.#######.#.######..##..###.....
..##.#.#..#.##...#.###.###...######..#..#.#..#....###.#.#....#..........#...##.##.##.#..##..#.#####.
###.###.#..#.##..##.#..#..##.....##.....#..#######.#..#.#.#.####.###..###.#.#..#.##.##.####.###.####
#.#.#..#....########.#..#..#...##..#.##..#.#..##..####...##.....#.##.#.#...########..#.###.#..#.#.##
.##.....#...#.#...##.##....###...##..#.####...#..#.#..#..#.##..#.###.##.####.##..####.....##.#.....#
....####.#.##.#.##.#..##.#.######.##.####..#...####.#..###.#.#..#..##.#.#.....##.#####.#.####...#.#.
#..#####.#####.....##....######..##....#..#.#.###.#####.....##.##.####.#...##...#.##.#.#####.##.#...
##.####..###.#....#...#.#.#.#.###.#####.#.####..####...####......##..#..#..#.#.##...########....#...
.###.#.#.#.#..####.##.#..######..#.#.###.....#.#......#.#.#.#..####.##...##.#####.#.##..##..#..#.#..
.....###...#...#.####.###.#.#.#.#.....#....#.####.###.##.##.##.#######......#.####......#....##.....
##..#..#.#.##..#...#..##.##.##..###.#....##.##....####.#.##.###....#.##.#.#.##...##.###...#..#..####
...#.#..##..##.#...##.##...#.#......#.#.##..###....####.##...#.#.###.#..#..#.####..##..##..#####.###
.##.##..##########.##...#.##.####.#.#######.##.#.##.##..#...##....########.###..##.##.##.#..##.#.#.#
#####.#....#.##..#.....#......##.##..#.##.###..##.......###..##.#.###.##.###....####.#..#.###..#.#.#
.#...#..#.##....##....#...####....#...#..#...####...########.###.#..##.#.#.##..###..#.#.###.....##.#
##..##.....###......#..###.##.####.##.####.#.#....#..#...#..#.#..#.###.#...#...#..##.##...#..#######
.....##..###..##...#####.#.#.....###.#.#..####...#.#.#..#..####..##.#..###.####.#....##..###....#..#
#.#.##.#....#.#####.#....##...#...##...##....#.#.......#....#..#...###.###.#.####..####....#.##.#.#.
..##...##..###.#.#.##.#..#....#.#.....##.###.#.###.###.....#...#.#..#######.#####..#.###...##......#
#......###..#....#.#..#.###.##.#...##..###.####.#.#....#.##..#.###..##.#..#####..##.###.....#..###..
##.#.##..##.###.#..##.....#.##.....###....##.####.######.#...#..###....#.#...#.##.....###....#..#.#.
.##.#.#.#.##..#.#.#..##..#.###.####....#..###.######..####.#.....###.##..#...###.#..######.##.#.##..
...##.####.#..##.#####.##.#...##..#..#...#.#.#.#####...#....#..###...#..#....#.#.##.#.######.#..####
..#.#.#.#...#.######.#.....#..#.#..###....#.#.########...#....#.#.##..#...##...#.#..#.#.###....##...
#####..#..##..#..##..#..#.#.##.#....#####.####.##.#.###..##..##....#.....#.#####.#...#.#####.##.#.#.
#.#..#####...####.###.###.....####.###.....##...##...#..#..#######.#.##....##..####.....##...#..#..#
#.#.###.#.#..##..#....#.#...#.#.##.##..#.##.....##...#.#..##.......##.#.###..#####.#.##....#.##.....
...#.......#....#.#.####.#.###.###..#....#..##.#..####........#.##..#...#.#...###.#..#.#.#...#...#..
...##.#####.##.#.###.##.##.#.##..##.#.#.#.#.#.##.#..##...##.#.#..#..##.##.#####.#.###...#####..#..#.
#######.#..#..#....##.#.#..####.#..#..###...#..#.......###.#.#.####....#.###...#.#.###.#.#.#.#..###.
..##.##.#.##.###....###.##.#.###.#...#....#.####..###..###.#.#..#...##.#.#.#..##.###..###.#.##...###
######..######..##..##.#.#.##.##.#..##..#.#.#.##..#.#...#...#.#.#..######.#..#.#.######..#......##.#
#.#####.....#.......#########..###.##...#...##.#.#..#...#####...#...#..#.###.#..#.#...###.#.#.#...#.
#....##....###...##.##.#...##.........##.#.#..#.#.##.#.######.#####..#..###.###.#...#.#.##.######...
#.#...###.#.###.##.#.######.#######.###.##..#.#.#...######.##.####.##..#.#.#.#......##..##.........#
..###..##....#.....##...#.#.###.#.#.....##.#...###.####.#...#...##..##.#.#.####..###...######....#.#
..###.#.##.####.#..#.##....##..#####....#..##.##.#..#######...#.####...##.#.#.##.........#....#....#
.##.#...#.####..#.#...#.##..######.##..##.#.###.##..###.###....##..#.##.##..##.#...###.##.##.###....
#...###.###.#..#....#.......#..#.....###..#.###.##.##....#.####.#.####.##..##..#..#.....#....##.#.#.
.##.#..#..#.##.......#.####.#######.....#.##.##.#.....#.#..#....######.#..###.##.##.....#.####..##.#
###..#.###.#..####.....##....#..####....#.##.##..#...######.#########...#.#....##...###.#..#.##...#.
#..###..##..#.#.##.###.#.#.##...###.#...##.##..#.###....###..#.#...#.###..######.#..#.###..#..#..#.#
.#........##.#.###..###.#.#.##.....##.##.#.#...##..#.##....###..#.#.#.#.##....#.##..#.#...###...#...
####.####..#....#.#.#..#..##.......##.####...###.##..#.#.##.#..##..######.......##.#.##..#...#.....#
..#..#..###..##.##..######.#..###..###.#.##..##.#..#####.#.#.#.##..#.##..##.##......####.#..........
...##.##..###.#...###....#.#.#.#.....#.##.....##...#...#......####...##.##....##.#..#.####.#..###.#.
..#.....####.#.###.#####..#..###..#..#.#...#####...###.###....#.###..#...#..#..#.#..#.##..##.#.#....
..##.#####...###.###.........#....##.####.##..#.#..#.#...#...##.##.##..#.#.##.########......#####...
...###.#.#..#...#.###.###.......##.###.#..#.##########...#..#.#.#.##.#.###...######..#.#...###.##...
.#.#.#######.#..##.##..##...#...####...#..#####.#..##...###.#.#...#.##...#......#..##.####..#.....##
.##.##.#.#......#######..###.....##.#.##..###......#....####...#.###.#.##.#........#..#....##.....##
#...#.###.#.##...##.####....#...#.###..#.#.....#.#....#.#.#.##...#.#..#####.#.#..#..#..#....#...####
.....##...###......#####..##.##.##...##.#.#####..##...#.#.#.#.###...###.##.####..#.#..#.#..#.####.##
#..#..##.#.##.#.##.#.#.#..###....###.##.#.##.#...#.#..#...#....###.#..#.#.######.#...####..#..##.#.#
#..#.#..#...###.#..##.#...#...##.#......#...#..#..####..##.....#.###...#.#..#.#....#.#####.##.###...
###....#.#..#.#..###..#.##......#...#..#..##.#..###..##..#..#.####..#...########..##.#.##.#.#.#...#.
.#.#.##.##.###..#...#.#....#..#.##..#.#.#.#.##.##.#####...#........####..###..####.#####..#.##.#.##.

6
2015/day-18/sample.txt Normal file
View File

@@ -0,0 +1,6 @@
.#.#.#
...##.
#....#
..#...
#.#..#
####..

54
2015/day-18/solution.py Normal file
View File

@@ -0,0 +1,54 @@
from __future__ import print_function
import fileinput
def neighbours(x, y, field):
alive = 0
for i in range(max(x - 1, 0), min(x + 2, len(field))):
for j in range(max(y - 1, 0), min(y + 2, len(field))):
if i == x and j == y:
continue
if field[i][j]:
alive += 1
return alive
def newState(x, y, field):
alive = neighbours(x, y, field)
if field[x][y]:
return alive == 2 or alive == 3
return alive == 3
def update(field):
newField = []
for x in range(len(field)):
newField.append([newState(x, y, field) for y in range(len(field))])
return newField
def enableCorners(field):
size = len(field) - 1
field[0][0] = field[0][size] = field[size][0] = field[size][size] = True
field = []
for line in fileinput.input():
field.append([c == '#' for c in line.strip()])
original = field
for i_ in range(100):
field = update(field)
print ("Without corners:", sum([sum(int(y) for y in x) for x in field]))
field = original
enableCorners(field)
for i_ in range(100):
field = update(field)
enableCorners(field)
print ("With corners:", sum([sum(int(y) for y in x) for x in field]))

45
2015/day-19/input.txt Normal file
View File

@@ -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
CRnSiRnCaPTiMgYCaPTiRnFArSiThFArCaSiThSiThPBCaCaSiRnSiRnTiTiMgArPBCaPMgYPTiRnFArFArCaSiRnBPMgArPRnCaPTiRnFArCaSiThCaCaFArPBCaCaPTiTiRnFArCaSiRnSiAlYSiThRnFArArCaSiRnBFArCaCaSiRnSiThCaCaCaFYCaPTiBCaSiThCaSiThPMgArSiRnCaPBFYCaCaFArCaCaCaCaSiThCaSiRnPRnFArPBSiThPRnFArSiRnMgArCaFYFArCaSiRnSiAlArTiTiTiTiTiTiTiRnPMgArPTiTiTiBSiRnSiAlArTiTiRnPMgArCaFYBPBPTiRnSiRnMgArSiThCaFArCaSiThFArPRnFArCaSiRnTiBSiThSiRnSiAlYCaFArPRnFArSiThCaFArCaCaSiThCaCaCaSiRnPRnCaFArFYPMgArCaPBCaPBSiRnFYPBCaFArCaSiAl

57
2015/day-19/solution.py Normal file
View File

@@ -0,0 +1,57 @@
from __future__ import print_function
import fileinput
import re
def doReplace(replacement, medicine):
replacements = []
for match in re.finditer(replacement[0], medicine):
pos = match.start()
sub = medicine[:pos] + replacement[1] + medicine[pos + len(replacement[0]):]
replacements.append(sub)
return replacements
def allReplacements(replacements, medicine):
options = set()
# Simply attempt all replacements
for replacement in replacements:
for option in doReplace(replacement, medicine):
options.add(option)
return options
# Exhaustive search trying to work back from the medicine.
#
# This is minimal because we try the larger substitutions first.
def solve(replacements, target, current):
if current == target:
return 0
for org, rep in replacements:
for option in doReplace((rep, org), current):
result = solve(replacements, target, option)
if result is not None:
return result + 1
return None
replacements = []
medicine = None
for line in fileinput.input():
if len(line.strip()) == 0:
continue
match = re.match(r"(\w+) => (\w+)", line)
if match:
replacements.append(match.group(1, 2))
else:
medicine = line.strip()
replacements.sort(key=lambda x: -len(x[1]))
print("Options:", len(allReplacements(replacements, medicine)))
print("Steps:", solve(replacements, 'e', medicine))

23
2015/day-20/solution.py Normal file
View File

@@ -0,0 +1,23 @@
from __future__ import print_function
def findFirst(data, target):
return next(idx for idx, value in enumerate(data) if value >= target)
target = 34000000
# Target is achieved at itself/10, so reasonable upper bound.
upperbound = target // 10
# Use a varation of Erathostenes' sieve to compute the results
sieve1 = [10] * (upperbound + 1)
sieve2 = [10] * (upperbound + 1)
for x in range(1, upperbound):
for y in range(x, upperbound, x):
sieve1[y] += 10 * x
for y in range(x, min(50 * x, upperbound) + 1, x):
sieve2[y] += 11 * x
print("House", findFirst(sieve1, target))
print("House", findFirst(sieve2, target))

50
2015/day-21/solution.py Normal file
View File

@@ -0,0 +1,50 @@
from __future__ import print_function, division
from itertools import product, combinations
import math
def price(c):
return c[0][0] + c[1][0] + c[2][0][0] + c[2][1][0]
def power(c):
return c[0][1] + c[1][1] + c[2][0][1] + c[2][1][1]
def armor(c):
return c[0][2] + c[1][2] + c[2][0][2] + c[2][1][2]
def wins(c, monsterHP, monsterAttack, monsterArmor):
monsterDamage = max(1, monsterAttack - armor(c))
heroDamage = max(1, power(c) - monsterArmor)
return math.ceil(100 / monsterDamage) >= math.ceil(monsterHP / heroDamage)
weapons = [
(8, 4, 0),
(10, 5, 0),
(25, 6, 0),
(40, 7, 0),
(74, 8, 0)
]
armors = [
(0, 0, 0), # Dummy armor
(13, 0, 1),
(31, 0, 2),
(53, 0, 3),
(75, 0, 4),
(102, 0, 5)
]
rings = list(combinations([
(0, 0, 0), # Dummy ring
(0, 0, 0), # Second dummy ring
(25, 1, 0),
(50, 2, 0),
(100, 3, 0),
(20, 0, 1),
(40, 0, 2),
(80, 0, 3),
], 2))
print(min(price(c) for c in product(weapons, armors, rings) if wins(c, 103, 9, 2)))
print(max(price(c) for c in product(weapons, armors, rings) if not wins(c, 103, 9, 2)))

106
2015/day-22/solution.py Normal file
View File

@@ -0,0 +1,106 @@
from __future__ import print_function, division
import heapq
def applyEffects(current):
if current['recharge'] > 0:
current['mana'] += 101
current['recharge'] -= 1
if current['shield'] > 0:
current['shield'] -= 1
if current['poison'] > 0:
current['poison'] -= 1
current['bossHP'] -= 3
def dijkstraMagic(initialState, hard):
todo = [(0, 0, initialState.copy())]
visited = {tuple(initialState.values()): 0}
iteration = 0
while todo:
iteration += 1
top = heapq.heappop(todo)
current = top[2].copy()
manaSpent = top[0]
if hard:
# Hard mode
current['hp'] -= 1
if current['hp'] <= 0:
# Already dead
continue
applyEffects(current)
if current['bossHP'] <= 0:
# We won!
return manaSpent
# Try every available spell
for spell in spells:
if current['mana'] < spell[1]:
# Not enough mana to cast
continue
if spell[4] is not None and current[spell[4]] > 0:
# Effect still active
continue
newState = current.copy()
newState['bossHP'] -= spell[2]
newState['mana'] -= spell[1]
newState['hp'] += spell[3]
if spell[4] is not None:
newState[spell[4]] = spell[5]
newMana = manaSpent + spell[1]
# Start Boss turn
applyEffects(newState)
if newState['bossHP'] > 0:
# Alive to attack?
if newState['shield'] > 0:
damage = 2
else:
damage = 9
newState['hp'] -= damage
else:
# Died during effects
return newMana
if newState['hp'] > 0:
# New state
key = tuple(newState.values())
if key not in visited or visited[key] > newMana:
# Insert the route in to the visited and queue
visited[key] = newMana
heapq.heappush(todo, (newMana, iteration, newState))
return None
spells = [
# Name, Mana, Damage, Heal, Effect, Turns
("Magic Missile", 53, 4, 0, None, 0),
("Drain", 73, 2, 2, None, 0),
("Shield", 113, 0, 0, "shield", 6),
("Poison", 173, 0, 0, "poison", 6),
("Recharge", 229, 0, 0, "recharge", 5),
]
status = {
"bossHP": 51,
"hp": 50,
"mana": 500,
"shield": 0,
"poison": 0,
"recharge": 0
}
print(dijkstraMagic(status, False))
print(dijkstraMagic(status, True))

49
2015/day-23/input.txt Normal file
View File

@@ -0,0 +1,49 @@
jio a, +19
inc a
tpl a
inc a
tpl a
inc a
tpl a
tpl a
inc a
inc a
tpl a
tpl a
inc a
inc a
tpl a
inc a
inc a
tpl a
jmp +23
tpl a
tpl a
inc a
inc a
tpl a
inc a
inc a
tpl a
inc a
tpl a
inc a
tpl a
inc a
tpl a
inc a
inc a
tpl a
inc 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

44
2015/day-23/solution.py Normal file
View File

@@ -0,0 +1,44 @@
from __future__ import division, print_function
import fileinput
import re
def run(instructions, registers):
instrptr = 0
while instrptr < len(instructions):
instruction = instructions[instrptr]
if "j" in instruction[0]:
if instruction[0] == "jie":
doJump = registers[instruction[1]] % 2 == 0
elif instruction[0] == "jio":
doJump = registers[instruction[1]] == 1
else:
doJump = True
if doJump:
instrptr = instrptr + int(instruction[-1])
else:
instrptr += 1
continue
if instruction[0] == "hlf":
registers[instruction[1]] //= 2
elif instruction[0] == "tpl":
registers[instruction[1]] *= 3
else:
registers[instruction[1]] += 1
instrptr += 1
return registers
instructions = []
for line in fileinput.input():
instructions.append(tuple(x.strip() for x in re.match(r"(hlf|tpl|inc|jmp|jie|jio) (a|b)?,? ?(\+?-?[0-9]+)?", line).groups() if x is not None))
print(run(instructions, {'a': 0, 'b': 0})['b'])
print(run(instructions, {'a': 1, 'b': 0})['b'])

28
2015/day-24/input.txt Normal file
View File

@@ -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

20
2015/day-24/solution.py Normal file
View File

@@ -0,0 +1,20 @@
from __future__ import print_function, division
import fileinput
import itertools
import functools
import operator
def qes(packageList):
return functools.reduce(operator.mul, packageList)
def minQES(packages, slots):
targetWeight = sum(packages) // slots
for i in range(1, len(packages)):
solutions = [x for x in itertools.combinations(packages, i) if sum(x) == targetWeight]
if len(solutions) > 0:
return min(qes(x) for x in solutions)
packages = set([int(x) for x in fileinput.input()])
print(minQES(packages, 3))
print(minQES(packages, 4))

18
2015/day-25/solution.py Normal file
View File

@@ -0,0 +1,18 @@
from __future__ import print_function
def findCode(n):
modBase = 33554393
base = 252533
start = 20151125
code = start * pow(base, n - 1, modBase)
return code % modBase
row = 2947
col = 3029
triangleNo = row + col - 1
subTriangleSurface = ((triangleNo - 1) * triangleNo) // 2
n = subTriangleSurface + col
print(findCode(n))

19
2015/runall.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
rundir()
{
input=""
if [ -f $1/input.txt ]; then
input="$1/input.txt"
fi
for i in $1/*.py; do
echo "$i" "$input"
time python "$i" "$input"
echo
done
}
for i in day-*; do
rundir $i
done