Last active
April 5, 2021 14:38
-
-
Save shaharz/7fd82b80b6d9db8aa0a6baa552a217ca to your computer and use it in GitHub Desktop.
Advent of Code 2018 solutions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"\n", | |
"def solve(input):\n", | |
" instr = input.split(\", \")\n", | |
" pos = np.array([0, 0])\n", | |
" heading = np.array([0, 1])\n", | |
" R = np.array([[0, -1], [1, 0]])\n", | |
" \n", | |
" visited = {tuple(pos)}\n", | |
"\n", | |
" for ins in instr:\n", | |
" heading = np.dot(heading, R if ins[0] == 'R' else -R)\n", | |
" for i in range(int(ins[1:])):\n", | |
" pos += heading\n", | |
" if tuple(pos) in visited:\n", | |
" return np.sum(np.absolute(pos))\n", | |
" \n", | |
" visited.add(tuple(pos))\n", | |
" \n", | |
" return None" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = \"R5, L2, L1, R1, R3, R3, L3, R3, R4, L2, R4, L4, R4, R3, L2, L1, L1, R2, R4, R4, L4, R3, L2, R1, L4, R1, R3, L5, L4, L5, R3, L3, L1, L1, R4, R2, R2, L1, L4, R191, R5, L2, R46, R3, L1, R74, L2, R2, R187, R3, R4, R1, L4, L4, L2, R4, L5, R4, R3, L2, L1, R3, R3, R3, R1, R1, L4, R4, R1, R5, R2, R1, R3, L4, L2, L2, R1, L3, R1, R3, L5, L3, R5, R3, R4, L1, R3, R2, R1, R2, L4, L1, L1, R3, L3, R4, L2, L4, L5, L5, L4, R2, R5, L4, R4, L2, R3, L4, L3, L5, R5, L4, L2, R3, R5, R5, L1, L4, R3, L1, R2, L5, L1, R4, L1, R5, R1, L4, L4, L4, R4, R3, L5, R1, L3, R4, R3, L2, L1, R1, R2, R2, R2, L1, L1, L2, L5, L3, L1\"\n", | |
"solve(data)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"keypad = [[None, None, 1, None, None],\n", | |
" [None, 2, 3, 4, None],\n", | |
" [5,6,7,8,9],\n", | |
" [None,'A','B','C',None],\n", | |
" [None, None, 'D', None, None]]\n", | |
"ds = {'L': np.array([0,-1]),\n", | |
" 'R': np.array([0,1]),\n", | |
" 'U': np.array([-1,0]),\n", | |
" 'D': np.array([1,0])}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def solve(input):\n", | |
" data = input.split('\\n')\n", | |
" pos = np.array([2,0])\n", | |
" for s in data:\n", | |
" for d in s:\n", | |
" nxt = np.clip(pos + ds[d], 0, 4)\n", | |
" pos = nxt if keypad[nxt[0]][nxt[1]] else pos\n", | |
" yield str(keypad[pos[0]][pos[1]])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"assert \"\".join(solve(\"ULL\\nRRDDD\\nLURDL\\nUUUUD\")) == \"5DB3\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = \"\"\"UULLULLUULLLURDLDUURRDRRLDURDULLRURDUDULLLUULURURLRDRRRRULDRUULLLLUUDURDULDRRDRUDLRRLDLUDLDDRURURUURRRDDDLLRUDURDULUULLRRULLRULDUDRDRLDLURURUDDUDLURUDUDURLURURRURLUDDRURRDLUURLLRURRDUDLULULUDULDLLRRRDLRDLDUDRDDDRRUURRRRRUURRDRRDLURDRRURDLLUULULLRURDLDDDRRLLRRUURULURUUDDLRRUDDRURUUDLRLRDLRURRRDULLDLRUDDUULRDULURUURDULUDLLRRLDDLRDLRUDRLDDRLRRRDURDULLRRRDRRLUURURDRRDRRLDLUDURURLDUURDRUDRDDRLDRRLDLURURULLUURUDUUDLRLL\n", | |
"LLLULLULDDULRLLURLLLRUUDDLRUULRLULLDLLRRDRLRLRLLDRUUURULDRDDLUDLLDUDULLLRLULLLRULDRDRUDLLRLRLLUDULRRRLDRUULDDULLDULULLUDUDLDRDURDLDLLDUDRRRDLUURRUURULLURLDURLRRLLDDUUULDRLUUDUDLURLULUDURRDRLLDDDDDRRULLRLDULULDDRUURRDLUDDDUDURDDRDRULULLLLUURDURUUUULUDLRURRULRDDRURURLLRLUUDUUURDLLDDLUDRLLLUDLLLLULRLURDRRRDUUDLLDLDDDURRDDRURUURDDRURRLDDDURDLLUURUUULRLUURRUDRLLDLURDUDRLULDLRLULULUDDLRDUDRUDLUULUULDURDRRRRLRULLUDRDDRDLDUDRDRRLDLLLLUDDLRULDLLDDUULDDRRULRRUURUDRDURLLLDDUUDRUUDLULLDR\n", | |
"UDUUULLDDDDLUDLDULRLRDLULLDDRULDURRLURRUDLRRUDURRDUDRRRUULRLLRLUDLDRRDUURDDRDRDUUUDUDLDLLRRLUURLUUUDDDUURLULURRLURRRDRDURURUDRLRUURUDRUDDDRDRDLDRDURDLDRRDUUDLLURLDDURRRLULDRDRLLRLLLRURLDURDRLDRUURRLDLDRLDDDRLDLRLDURURLLLLDDRDUDLRULULLRDDLLUDRDRRLUUULDRLDURURDUDURLLDRRDUULDUUDLLDDRUUULRRULDDUDRDRLRULUUDUURULLDLLURLRRLDDDLLDRRDDRLDDLURRUDURULUDLLLDUDDLDLDLRUDUDRDUDDLDDLDULURDDUDRRUUURLDUURULLRLULUURLLLLDUUDURUUDUULULDRULRLRDULDLLURDLRUUUDDURLLLLDUDRLUUDUDRRURURRDRDDRULDLRLURDLLRRDRUUUURLDRURDUUDLDURUDDLRDDDDURRLRLUDRRDDURDDRLDDLLRR\n", | |
"ULDRUDURUDULLUDUDURLDLLRRULRRULRUDLULLLDRULLDURUULDDURDUUDLRDRUDUDDLDRDLUULRRDLRUULULUUUDUUDDRDRLLULLRRDLRRLUDRLULLUUUUURRDURLLRURRULLLRLURRULRDUURRLDDRRDRLULDDRRDRLULLRDLRRURUDURULRLUDRUDLUDDDUDUDDUDLLRDLLDRURULUDRLRRULRDDDDDRLDLRRLUUDLUURRDURRDLDLDUDRLULLULRLDRDUDLRULLULLRLDDRURLLLRLDDDLLLRURDDDLLUDLDLRLUULLLRULDRRDUDLRRDDULRLLDUURLLLLLDRULDRLLLUURDURRULURLDDLRRUDULUURRLULRDRDDLULULRRURLDLRRRUDURURDURDULURULLRLDD\n", | |
"DURLRRRDRULDLULUDULUURURRLULUDLURURDDURULLRRUUDLRURLDLRUDULDLLRRULLLLRRLRUULDLDLLRDUDLLRLULRLLUUULULRDLDLRRURLUDDRRLUUDDRRUDDRRURLRRULLDDULLLURRULUDLRRRURRULRLLLRULLRRURDRLURULLDULRLLLULLRLRLLLDRRRRDDDDDDULUUDUDULRURDRUDRLUULURDURLURRDRRRRDRRLLLLUDLRRDURURLLULUDDLRLRLRRUURLLURLDUULLRRDURRULRULURLLLRLUURRULLLURDDDRURDUDDULLRULUUUDDRURUUDUURURRDRURDUDRLLRRULURUDLDURLDLRRRRLLUURRLULDDDUUUURUULDLDRLDUDULDRRULDRDULURRUURDU\"\"\"\n", | |
"\"\".join(solve(data))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 3" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day3.txt\").read().split('\\n')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import re\n", | |
"def check(tri):\n", | |
" tri = sorted(tri)\n", | |
"# print(tri)\n", | |
" return int(tri[0] + tri[1] > tri[2])\n", | |
"\n", | |
"tris = [list(map(int, re.findall(r'\\d+', x))) for x in data if x]\n", | |
"tris = np.rot90(tris).flatten()\n", | |
"\n", | |
"# sum(check(map(int, re.findall(r'\\d+', x))) for x in data if x)\n", | |
"sum(check(tris[x:x+3]) for x in range(0, len(tris), 3))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 4" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from scipy.stats import itemfreq\n", | |
"from functools import cmp_to_key" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import re\n", | |
"\n", | |
"def cmp(a, b): return (a>b)-(a<b)\n", | |
"\n", | |
"def comp(x, y):\n", | |
" res = cmp(int(x[1]), int(y[1]))\n", | |
" return res if res != 0 else cmp(ord(y[0]), ord(x[0]))\n", | |
"\n", | |
"def solve(input):\n", | |
" last_dash = input.rfind(\"-\")\n", | |
" checksum = re.findall(\"\\[(\\w+)\\]$\", input)[0]\n", | |
" freqs = sorted(itemfreq(list(re.sub(r'-', '', input[:last_dash]))), key=cmp_to_key(comp), reverse=True)[:5]\n", | |
" return checksum == ''.join(map(lambda x: x[0], freqs))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"assert solve(\"a-b-c-d-e-f-g-h-987[abcde]\")\n", | |
"assert solve(\"aaaaa-bbb-z-y-x-123[abxyz]\")\n", | |
"assert solve(\"not-a-real-room-404[oarel]\")\n", | |
"assert solve(\"totally-real-room-200[decoy]\") == False" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day4.txt\").read().split('\\n')[:-1]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def sector(room): return int(re.findall(r'(\\d+)\\[\\w+\\]$', room)[0])\n", | |
"real_rooms = [line for line in data if solve(line)]\n", | |
"sum(sector(room) for room in real_rooms)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def shift(s, by):\n", | |
" return ''.join([chr((ord(c) - ord('a') + by) % (ord('z')-ord('a')+1) + ord('a')) for c in list(s)])\n", | |
"next(filter(lambda room: \"north\" in shift(re.sub(r'-', '', room[:-11]), sector(room)), real_rooms))\n", | |
"# [shift(re.sub(r'-', '', room[:-11]), sector(room)) for room in real_rooms[:15]]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 5" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from hashlib import md5" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"p = [None]*8\n", | |
"i = 0\n", | |
"found = 0\n", | |
"while found < 8 and i < 1e8:\n", | |
" d = md5(b\"ojvtpuvg\" + bytes(str(i).encode('utf-8'))).hexdigest()\n", | |
" if d.startswith('00000'):\n", | |
" try:\n", | |
" idx = int(d[5])\n", | |
" if idx >= 0 and idx < len(p) and p[idx] == None:\n", | |
" p[idx] = d[6]\n", | |
" found = found + 1\n", | |
" except ValueError:\n", | |
" pass\n", | |
" i = i + 1\n", | |
"print(''.join(p), i)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"p" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 6" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day6.txt\").read().split('\\n')[:-1]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"arr2d = np.array([np.array(list(l)) for l in data])\n", | |
"def solve(l):\n", | |
" (values,counts) = np.unique(l,return_counts=True)\n", | |
" ind=np.argmin(counts)\n", | |
" return values[ind]\n", | |
"\n", | |
"''.join(reversed(list(map(solve, np.rot90(arr2d)))))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 7" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import re\n", | |
"regex = re.compile('(\\w+)(?:\\[(\\w+)\\])?')\n", | |
"\n", | |
"def check_abba(s):\n", | |
" for i in range(len(s) - 3):\n", | |
" if s[i] == s[i + 3] and s[i] != s[i+1] and s[i+1] == s[i+2]:\n", | |
" return True\n", | |
" return False\n", | |
"\n", | |
"def solve(input):\n", | |
" parts = regex.findall(input)\n", | |
" if any(check_abba(p[1]) for p in parts):\n", | |
" return False\n", | |
" \n", | |
" return any(check_abba(p[0]) for p in parts)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day7.txt\").read().split('\\n')[:-1]\n", | |
"sum(solve(l) for l in data)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def find_abas(s):\n", | |
" for i in range(len(s) - 2):\n", | |
" if s[i] == s[i + 2] and s[i] != s[i+1]:\n", | |
" yield s[i+1] + s[i] + s[i+1] # ABA->BAB\n", | |
"\n", | |
"def flatten(z): return (x for y in z for x in y)\n", | |
"\n", | |
"def solve2(input):\n", | |
" parts = regex.findall(input)\n", | |
" BABs = flatten(find_abas(p[1]) for p in parts)\n", | |
" return any(BAB in p[0] for BAB in BABs for p in parts)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day7.txt\").read().split('\\n')[:-1]\n", | |
"sum(solve2(l) for l in data)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 8" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"import re" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"screen = np.zeros((6, 50), dtype=np.bool)\n", | |
"parser = re.compile(\"(rect|rotate)\\s(row|column|(?:(\\d+)x(\\d+)))(?:\\s[yx]=(\\d+)\\sby\\s(\\d+))?\")\n", | |
"\n", | |
"def reset(): screen.fill(False)\n", | |
"def rect(w,h): screen[:w,:h] = True\n", | |
"def rotate_row(row, shift): screen[row,:] = np.roll(screen[row,:], shift)\n", | |
"def rotate_col(col, shift): screen[:,col] = np.roll(screen[:,col], shift)\n", | |
"\n", | |
"def parse(s):\n", | |
" g = parser.match(s).groups()\n", | |
" if g[0] == \"rect\":\n", | |
" rect(int(g[3]), int(g[2]))\n", | |
" elif g[1] == \"row\":\n", | |
" rotate_row(int(g[4]), int(g[5]))\n", | |
" elif g[1] == \"column\":\n", | |
" rotate_col(int(g[4]), int(g[5]))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day8.txt\").read().split('\\n')[:-1]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"reset()\n", | |
"for d in data: parse(d)\n", | |
"[''.join(list('#' if x else '.' for x in s)) for s in screen]\n", | |
"# np.count_nonzero(screen)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# ds = [\"rect 4x1\",\n", | |
"# \"rotate row y=2 by 13\",\n", | |
"# \"rotate row y=0 by 5\"]\n", | |
"# import re\n", | |
"# [re.match(\"(rect|rotate)\\s(row|column|(?:(\\d+)x(\\d+)))(?:\\s[yx]=(\\d)\\sby\\s(\\d+))?\", d).groups() for d in ds]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 9" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import re" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"re_comp = re.compile(r'\\((\\d+)x(\\d+)\\)')\n", | |
"\n", | |
"def decompress(data):\n", | |
" pos = 0\n", | |
" while True:\n", | |
" m = re_comp.search(data[pos:])\n", | |
" if not m: break\n", | |
" n, times = [int(n) for n in m.groups()]\n", | |
" yield data[pos:pos+m.start()]\n", | |
" yield decompress(data[pos+m.end():pos+m.end()+n]*times)\n", | |
" pos = pos + m.end() + n\n", | |
" yield data[pos:]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"assert ''.join(decompress(\"X(8x2)(3x3)ABCY\")) == \"X(3x3)ABC(3x3)ABCY\"\n", | |
"assert ''.join(decompress(\"A(1x5)BC\")) == \"ABBBBBC\"\n", | |
"assert ''.join(decompress(\"(3x3)XYZ\")) == \"XYZXYZXYZ\"\n", | |
"assert ''.join(decompress(\"A(2x2)BCD(2x2)EFG\")) == \"ABCBCDEFEFG\"\n", | |
"assert ''.join(decompress(\"(6x1)(1x3)A\")) == \"(1x3)A\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day9.txt\").read()\n", | |
"data = re.sub(r'\\s', '', data)\n", | |
"# inefficient solution (only length needed) ¯\\_(ツ)_/¯\n", | |
"%time sum(len(chunk) for chunk in decompress(data))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 10" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day10.txt\").read().split('\\n')[:-1]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data[40:60]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import re\n", | |
"from collections import defaultdict" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"bots = defaultdict(list)\n", | |
"instr = defaultdict(list)\n", | |
"for line in data:\n", | |
" if line.startswith('value'):\n", | |
" v, b = re.findall(r'\\d+', line)\n", | |
" bots[b].append(int(v))\n", | |
" else:\n", | |
" m = re.match(r'bot (\\d+) gives low to (\\w+) (\\d+) and high to (\\w+) (\\d+)', line).groups()\n", | |
" instr[m[0]].append(m)\n", | |
"\n", | |
"while True:\n", | |
" try:\n", | |
" b = next(b for b in bots if len(bots[b]) == 2)\n", | |
" except StopIteration:\n", | |
" print(\"done?\")\n", | |
" break\n", | |
"\n", | |
" _, dl, nl, dh, nh = instr[b][0]\n", | |
" instr[b] = instr[b][1:]\n", | |
" l, h = sorted(bots[b])\n", | |
"\n", | |
" del bots[b]\n", | |
"# print(dl, nl, dh, nh)\n", | |
" if dl == 'bot':\n", | |
" bots[nl].append(l)\n", | |
" elif dl == 'output':\n", | |
" print('output', nl, l)\n", | |
" if dh == 'bot':\n", | |
" bots[nh].append(h)\n", | |
" elif dh == 'output':\n", | |
" print('output', nh, h)\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true | |
}, | |
"source": [ | |
"# Day 11" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Test\n", | |
"The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.\n", | |
"The second floor contains a hydrogen generator.\n", | |
"The third floor contains a lithium generator.\n", | |
"The fourth floor contains nothing relevant." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Input\n", | |
"The first floor contains a thulium generator, a thulium-compatible microchip, a plutonium generator, and a strontium generator.\n", | |
"\n", | |
"The second floor contains a plutonium-compatible microchip and a strontium-compatible microchip.\n", | |
"The third floor contains a promethium generator, a promethium-compatible microchip, a ruthenium generator, and a ruthenium-compatible microchip.\n", | |
"The fourth floor contains nothing relevant." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"### SLOW\n", | |
"from collections import defaultdict, namedtuple\n", | |
"from copy import deepcopy\n", | |
"from itertools import chain, combinations\n", | |
"from heapq import *\n", | |
"\n", | |
"BaseDist = namedtuple('Dist', ['elev', 'fs', 'dist', 'parent'])\n", | |
"\n", | |
"class Dist(BaseDist):\n", | |
" def __hash__(self):\n", | |
" return hash(str(self.elev) + str(self.fs))\n", | |
" def __lt__(self, other):\n", | |
" return hash(self) < hash(other)\n", | |
" \n", | |
"# Contents = namedtuple('Contents', ['M', 'G'])\n", | |
"initial = Dist(\n", | |
" 0,\n", | |
" [\n", | |
" {'M': frozenset(['H', 'L']), 'G': frozenset()},\n", | |
" {'G': frozenset(['H']), 'M': frozenset()},\n", | |
" {'G': frozenset(['L']), 'M': frozenset()},\n", | |
" {'M': frozenset(), 'G': frozenset()}\n", | |
" ],\n", | |
" 0,\n", | |
" None\n", | |
")\n", | |
"\n", | |
"cat = ''.join\n", | |
" \n", | |
"def prn(dist):\n", | |
" for i, v in enumerate(reversed(dist.fs)):\n", | |
" curfl = dist.elev == 3-i\n", | |
" print(4-i, ' E'[curfl], 'M' + cat(v['M']) , 'G' + cat(v['G']))\n", | |
" if dist.parent:\n", | |
" print(\"##############\")\n", | |
" prn(dist.parent)\n", | |
"\n", | |
"# can't get on elevator empty handed\n", | |
"# elevator capacity = 2\n", | |
"# XG + YM = bad\n", | |
"# XG + XM = protected from other YG\n", | |
"# can pass through floor with XG if holding XM\n", | |
"def valid(ms, gs): return not gs or not (ms - gs)\n", | |
"def valid_move(cur, move, dms, dgs):\n", | |
" return valid(cur.fs[cur.elev]['M']-dms, cur.fs[cur.elev]['G']-dgs) \\\n", | |
" and valid(cur.fs[cur.elev+move]['M']|dms, cur.fs[cur.elev+move]['G']|dgs)\n", | |
" \n", | |
"\n", | |
"def gen_elev(cur, dms, dgs, queue, visited):\n", | |
" # move elevator down\n", | |
" \n", | |
" if cur.elev > 0 and valid_move(cur, -1, dms, dgs):\n", | |
" new_fs = deepcopy(cur.fs)\n", | |
" new_fs[cur.elev]['M'] -= dms\n", | |
" new_fs[cur.elev-1]['M'] |= dms\n", | |
" new_fs[cur.elev]['G'] -= dgs\n", | |
" new_fs[cur.elev-1]['G'] |= dgs\n", | |
" if not hash(str(cur.elev-1) + str(new_fs)) in visited:\n", | |
" res = Dist(\n", | |
" fs=new_fs,\n", | |
" dist=cur.dist+1,\n", | |
" elev=cur.elev-1,\n", | |
" parent=None\n", | |
" )\n", | |
" heappush(queue, (heuristic(res), res))\n", | |
"\n", | |
" # move elevator up\n", | |
" if cur.elev < 3 and valid_move(cur, 1, dms, dgs):\n", | |
" new_fs = deepcopy(cur.fs)\n", | |
" new_fs[cur.elev]['M'] -= dms\n", | |
" new_fs[cur.elev+1]['M'] |= dms\n", | |
" new_fs[cur.elev]['G'] -= dgs\n", | |
" new_fs[cur.elev+1]['G'] |= dgs\n", | |
" if not hash(str(cur.elev-1) + str(new_fs)) in visited:\n", | |
" res = Dist(\n", | |
" fs=new_fs,\n", | |
" dist=cur.dist+1,\n", | |
" elev=cur.elev+1,\n", | |
" parent=None\n", | |
" )\n", | |
" heappush(queue, (heuristic(res), res))\n", | |
"\n", | |
" \n", | |
"def powerset(iterable, mn, mx):\n", | |
" \"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)\"\n", | |
" s = list(iterable)\n", | |
" return chain.from_iterable(combinations(s, r) for r in range(mn, mx+1))\n", | |
"\n", | |
"def heuristic(d):\n", | |
" return d.dist - (len(d.fs[3]['M']) + len(d.fs[3]['G'])) * 5\n", | |
"\n", | |
"def search(initial):\n", | |
" visited = set()\n", | |
" queue = []\n", | |
" heappush(queue, (heuristic(initial), initial))\n", | |
" while queue:\n", | |
" _, cur = heappop(queue)\n", | |
" visited.add(hash(cur))\n", | |
"# print(visited)\n", | |
" if not any(f['G'] or f['M'] for f in cur.fs[:3]):\n", | |
" print(\"match\", cur.dist)\n", | |
" continue\n", | |
" \n", | |
" yield cur\n", | |
" \n", | |
" ms = cur.fs[cur.elev]['M']\n", | |
" gs = cur.fs[cur.elev]['G']\n", | |
" lms = len(ms)\n", | |
" lgs = len(gs)\n", | |
" if lms > 1:\n", | |
" for s in powerset(ms, 1, 2): gen_elev(cur, set(s), set(), queue, visited)\n", | |
" if lgs > 1:\n", | |
" for s in powerset(gs, 1, 2): gen_elev(cur, set(), set(s), queue, visited)\n", | |
" if lms > 0:\n", | |
" for m in ms: gen_elev(cur, {m}, set(), queue, visited)\n", | |
" if lgs > 0:\n", | |
" for g in gs: gen_elev(cur, set(), {g}, queue, visited)\n", | |
" if lms > 0 and lgs > 0:\n", | |
" for m,g in ((m,g) for m in ms for g in gs): gen_elev(cur, {m}, {g}, queue, visited)\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"test = Dist(\n", | |
" 0,\n", | |
" [\n", | |
" {'M': frozenset(['T', 'E', 'D']), 'G': frozenset(['T', 'PL', 'S', 'E', 'D'])},\n", | |
" {'M': frozenset(['PL', 'S']), 'G': frozenset()},\n", | |
" {'M': frozenset(['PR','R']), 'G': frozenset(['PR', 'R'])},\n", | |
" {'M': frozenset(), 'G': frozenset()}\n", | |
" ],\n", | |
" 0,\n", | |
" None\n", | |
")\n", | |
"\n", | |
"s = search(test)\n", | |
"max_d = 0" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": false | |
}, | |
"outputs": [], | |
"source": [ | |
"while True:\n", | |
" c = next(s)\n", | |
" if max_d < c.dist:\n", | |
" if max_d > 70: break\n", | |
" max_d = c.dist\n", | |
" print(max_d)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 12" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day12.txt\").read().split('\\n')\n", | |
"# data = \"\"\"cpy 41 a\n", | |
"# inc a\n", | |
"# inc a\n", | |
"# dec a\n", | |
"# jnz a 2\n", | |
"# dec a\"\"\".split('\\n')\n", | |
"\n", | |
"def r2i(r): return ord(r) - ord('a')\n", | |
"\n", | |
"def parse(d):\n", | |
" regs = [0, 0, 1, 0]\n", | |
" ip = 0\n", | |
" while ip < len(data):\n", | |
" ins = data[ip].split(' ')\n", | |
" yield ins, regs\n", | |
" if ins[0] == 'cpy':\n", | |
" regs[r2i(ins[2])] = int(ins[1]) if ins[1].isdigit() else regs[r2i(ins[1])]\n", | |
" elif ins[0] == 'inc':\n", | |
" regs[r2i(ins[1])] += 1\n", | |
" elif ins[0] == 'dec':\n", | |
" regs[r2i(ins[1])] -= 1\n", | |
" elif ins[0] == 'jnz':\n", | |
" if (ins[1].isdigit() and ins[1] != 0) or regs[r2i(ins[1])]:\n", | |
" ip += int(ins[2])\n", | |
" continue\n", | |
" ip += 1\n", | |
" yield regs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"p = parse(data)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"while True:\n", | |
" try:\n", | |
" r = next(p)\n", | |
" except StopIteration:\n", | |
" print(r)\n", | |
" break" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true | |
}, | |
"source": [ | |
"# Day 13" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"\n", | |
"POPCOUNT_TABLE16 = [0] * 2**16\n", | |
"for index in range(len(POPCOUNT_TABLE16)):\n", | |
" POPCOUNT_TABLE16[index] = (index & 1) + POPCOUNT_TABLE16[index >> 1]\n", | |
"\n", | |
"def popcount32_table16(v):\n", | |
" return (POPCOUNT_TABLE16[ v & 0xffff] +\n", | |
" POPCOUNT_TABLE16[(v >> 16) & 0xffff])\n", | |
"\n", | |
"def wall(v):\n", | |
" return popcount32_table16(v) % 2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from heapq import *\n", | |
"magic = 1350\n", | |
"\n", | |
"x,y = np.indices((2500,2500))\n", | |
"maze = np.rot90(np.fliplr(np.vectorize(wall)(x*x + 3*x + 2*x*y + y + y*y + magic)))\n", | |
"\n", | |
"def heuristic(a, b): return b[0]-a[0]+b[1]-a[1]\n", | |
"\n", | |
"dirs = [np.array([1,0]), np.array([0,1]), np.array([-1,0]), np.array([0, -1])]\n", | |
" \n", | |
"def shortest_path(a, b):\n", | |
" queue = []\n", | |
" heappush(queue, (heuristic(a, b), 0, a))\n", | |
" maze[a] = 2 # visited\n", | |
" while queue:\n", | |
" _, sofar, pt = heappop(queue)\n", | |
" print(pt)\n", | |
" if pt == b:\n", | |
" print(\"done\", sofar)\n", | |
" return\n", | |
" \n", | |
" for offs in dirs:\n", | |
" nextpt = tuple(np.clip(pt + offs, 0, maze.shape[0]-1))\n", | |
" if not maze[nextpt]:\n", | |
" maze[nextpt] = 2 # visited\n", | |
"# print(\"inserting\", sofar + heuristic(nextpt, b), sofar + 1, nextpt)\n", | |
" heappush(queue, (sofar + heuristic(nextpt, b), sofar + 1, nextpt))\n", | |
"# yield queue\n", | |
" \n", | |
"def reachable(a, max_steps):\n", | |
" queue = []\n", | |
" heappush(queue, (0, 0, a))\n", | |
" maze[a] = 2 # visited\n", | |
" while queue:\n", | |
" _, sofar, pt = heappop(queue)\n", | |
" \n", | |
" if sofar == max_steps: return\n", | |
" for offs in dirs:\n", | |
" nextpt = tuple(np.clip(pt + offs, 0, maze.shape[0]-1))\n", | |
" if not maze[nextpt]:\n", | |
" maze[nextpt] = 2 # visited\n", | |
"# print(\"inserting\", sofar + heuristic(nextpt, b), sofar + 1, nextpt)\n", | |
" heappush(queue, (0, sofar + 1, nextpt))\n", | |
"# yield queue\n", | |
"\n", | |
"# [''.join('.#O'[y] for y in x) for x in maze]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"target = (39,31)\n", | |
"start = (1,1)\n", | |
"\n", | |
"# shortest_path(start, target)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"maze[target] = 3\n", | |
"[''.join(('.#OX'[y]) for y in x) for x in maze]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"reachable(start, 50)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"np.count_nonzero(maze == 2)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 14" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from hashlib import md5\n", | |
"from collections import deque" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"hexd = ['{:x}'.format(d) for d in range(0, 16)]\n", | |
"repeats3 = [d*3 for d in hexd]\n", | |
"repeats5 = [d*5 for d in hexd]\n", | |
"\n", | |
"def solve(salt):\n", | |
" last1000 = deque([], 1000)\n", | |
" i = 0\n", | |
" found = set()\n", | |
" while True:\n", | |
" h = md5(salt + bytes(str(i), 'utf-8')).hexdigest()\n", | |
" for _ in range(2016):\n", | |
" h = md5(bytes(h,'utf-8')).hexdigest()\n", | |
" match = [r[0] for r in repeats5 if r in h]\n", | |
" if match:\n", | |
" print(i, h, match)\n", | |
" for i2,h2 in last1000:\n", | |
" match3 = match[0]*3\n", | |
" ma = h2.find(match3)\n", | |
" repeat3 = all(h2.find(r) > ma for r in repeats3 if r != match3 and r in h2)\n", | |
" if i2 == 15578: print(\"ASDFSDFD\", h2, ma, repeat3, (i2 not in found))\n", | |
" if ma > -1 and repeat3 and (i2 not in found):\n", | |
" n = len(found)\n", | |
" print(n, i2,h2)\n", | |
" if n == 80:\n", | |
" return found\n", | |
" found.add(i2)\n", | |
" last1000.append((i,h))\n", | |
"\n", | |
"# yield from ((i2,h2) for (i2,h2) in last1000 if repeat3 in h2)\n", | |
" i += 1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"x = solve(b'qzyelonm')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"sorted(x)[63]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 15" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"input = \"\"\"Disc #1 has 17 positions; at time=0, it is at position 1.\n", | |
"Disc #2 has 7 positions; at time=0, it is at position 0.\n", | |
"Disc #3 has 19 positions; at time=0, it is at position 2.\n", | |
"Disc #4 has 5 positions; at time=0, it is at position 0.\n", | |
"Disc #5 has 3 positions; at time=0, it is at position 0.\n", | |
"Disc #6 has 13 positions; at time=0, it is at position 5.\n", | |
"Disc #7 has 11 positions; at time=0, it is at position 0.\n", | |
"\"\"\"\n", | |
"\n", | |
"import re\n", | |
"lines = input.split('\\n')[:-1]\n", | |
"npo = [[int(n) for n in re.match(r'Disc #(\\d) has (\\d+) positions; at time=0, it is at position (\\d).', line).groups()] for line in lines]\n", | |
"\n", | |
"def l(n,p,o): return lambda t: ((t+n+o) % p)\n", | |
"fs = [l(n,p,o) for i, (n, p, o) in enumerate(npo)]\n", | |
"for t in range(1, 10000000):\n", | |
" if all(f(t) == 0 for f in fs):\n", | |
" print(t)\n", | |
" break" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 16" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def flip(input): return ['01'[c == '0'] for c in reversed(input)]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def checksum(input):\n", | |
" return [str(int(input[i]==input[i+1])) for i in range(0,len(input),2)]\n", | |
"\n", | |
"def go(input, l):\n", | |
" output = input\n", | |
" while len(output) < l:\n", | |
" output = output + ['0'] + flip(output)\n", | |
" cs = checksum(output[:l])\n", | |
" while len(cs) % 2 == 0:\n", | |
" cs = checksum(cs)\n", | |
" return ''.join(cs)\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# l = 20\n", | |
"# initial = list('10000')\n", | |
"\n", | |
"go(list('10011111011011001'), 35651584)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 17" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"from hashlib import md5\n", | |
"from collections import deque" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def hsh(salt, path): return md5(bytes(salt + path, 'utf-8')).hexdigest()\n", | |
"def opendirs(hsh): return [c in 'bcdef' for c in hsh[:4]]\n", | |
"\n", | |
"def solve(passcode):\n", | |
" queue = [((0,0), '')]\n", | |
" maxpath = ''\n", | |
"\n", | |
" while queue:\n", | |
" (x,y), path = queue.pop()\n", | |
" if (x,y) == (3,3):\n", | |
" if len(path) > len(maxpath):\n", | |
" maxpath = path\n", | |
" if len(maxpath) >= 300 or len(maxpath) % 100 == 0: print(len(maxpath))\n", | |
" continue\n", | |
" \n", | |
" uok,dok,lok,rok = opendirs(hsh(passcode, path))\n", | |
" \n", | |
" if x < 3 and rok:\n", | |
" newpath = path + 'R'\n", | |
" queue.append(((x+1,y), newpath))\n", | |
" if x > 0 and lok:\n", | |
" newpath = path + 'L'\n", | |
" queue.append(((x-1,y), newpath))\n", | |
" if y < 3 and dok:\n", | |
" newpath = path + 'D'\n", | |
" queue.append(((x,y+1), newpath))\n", | |
" if y > 0 and uok:\n", | |
" newpath = path + 'U'\n", | |
" queue.append(((x,y-1), newpath))\n", | |
" return maxpath" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"solve('yjjvjgan')" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 18" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"is_trap = ['^^.','.^^','^..','..^']\n", | |
"\n", | |
"def next_row(prev_row):\n", | |
" prev = '.' + prev_row + '.'\n", | |
"# print([prev[i-1:i+2] for i in range(1,len(prev)-1)])\n", | |
" return ''.join('^' if prev[i-1:i+2] in is_trap else '.' for i in range(1,len(prev)-1))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"r = '......^.^^.....^^^^^^^^^...^.^..^^.^^^..^.^..^.^^^.^^^^..^^.^.^.....^^^^^..^..^^^..^^.^.^..^^..^^^..'\n", | |
"safe = 0\n", | |
"for _ in range(400000):\n", | |
"# print(r)\n", | |
" safe += r.count('.')\n", | |
" r = next_row(r)\n", | |
"print(safe)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 19" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def run(elves): \n", | |
" N = len(elves)\n", | |
" eliminated = 0\n", | |
" for i in range(int(math.ceil(N / 3))):\n", | |
" across = i + eliminated + (N // 2) \n", | |
" elves[across] = None\n", | |
" N -= 1\n", | |
" eliminated += 1\n", | |
" return list(filter(None, elves[i+1:] + elves[:i+1]))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def runall(n):\n", | |
" l = list(range(1,n+1))\n", | |
" while len(l) > 1:\n", | |
" l = run(l)\n", | |
" return l\n", | |
"\n", | |
"runall(3005290)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# list(filter(lambda x: x, [n if runall(n) == 0 else None for n in range(4,140)]))\n", | |
"[(n,runall(n)) for n in range(4,40)]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"seed = 3005290\n", | |
"import math\n", | |
"# [(n, 2*(n - 2**math.floor(math.log(n)/math.log(2)))) for n in range(4,20)]\n", | |
"2*(seed - 2**math.floor(math.log(seed)/math.log(2)))+1 # +1 so it's one-based" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 20" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from operator import itemgetter\n", | |
"from itertools import tee\n", | |
"\n", | |
"def pairwise(iterable):\n", | |
" \"s -> (s0,s1), (s1,s2), (s2, s3), ...\"\n", | |
" a, b = tee(iterable)\n", | |
" next(b, None)\n", | |
" return zip(a, b)\n", | |
"\n", | |
"def split(l):\n", | |
" s = l.split('-')\n", | |
" return (int(s[0]), int(s[1]))\n", | |
"\n", | |
"def go(lines):\n", | |
" lastcomp = None\n", | |
" for (sa, sb),(sc, sd) in pairwise(sorted((split(l) for l in lines), key=itemgetter(0))):\n", | |
" if lastcomp:\n", | |
" (sa,sb) = lastcomp\n", | |
" \n", | |
" if sb > sd:\n", | |
" lastcomp = (sa,sb)\n", | |
" else: lastcomp = None\n", | |
" \n", | |
" if sb + 1 < sc:\n", | |
" yield (sc - (sb + 1))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day20.txt\").read().split('\\n')[:-1]\n", | |
"# go(data)\n", | |
"sum(go(data)) + 4294967295 - (sorted((split(l) for l in data), key=itemgetter(1))[-1][1])\n", | |
"# print(list(sorted((split(l) for l in data), key=itemgetter(0))))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 21" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"swap position X with position Y means that the letters at indexes X and Y (counting from 0) should be swapped. \n", | |
"swap letter X with letter Y means that the letters X and Y should be swapped (regardless of where they appear in the string). \n", | |
"rotate left/right X steps means that the whole string should be rotated; for example, one right rotation would turn abcd into dabc. \n", | |
"rotate based on position of letter X means that the whole string should be rotated to the right based on the index of letter X (counting from 0) as determined before this instruction does any rotations. Once the index is determined, rotate the string to the right one time, plus a number of times equal to that index, plus one additional time if the index was at least 4. \n", | |
"reverse positions X through Y means that the span of letters at indexes X through Y (including the letters at X and Y) should be reversed in order. \n", | |
"move position X to position Y means that the letter which is at index X should be removed from the string, then inserted such that it ends up at index Y. " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def go(line, input):\n", | |
" parts = line.split(' ')\n", | |
" if parts[0] == 'swap':\n", | |
" x,y = parts[2], parts[5]\n", | |
" if parts[1] == 'letter':\n", | |
" x,y = input.find(x), input.find(y)\n", | |
" else:\n", | |
" x,y = int(x), int(y)\n", | |
" l = list(input)\n", | |
" l[x], l[y] = l[y], l[x]\n", | |
" input = ''.join(l)\n", | |
" elif parts[0] == 'rotate':\n", | |
" l = len(input)\n", | |
" if parts[1] == 'based':\n", | |
" r = input.find(parts[6])\n", | |
" r = l - (1 + (r + 1 if r >= 4 else r) % l)\n", | |
" else:\n", | |
" r = int(parts[2]) % l\n", | |
" if parts[1] == 'right': r = l - r\n", | |
" input = input[r:] + input[:r]\n", | |
" elif parts[0] == 'reverse':\n", | |
" a,b = int(parts[2]), int(parts[4])\n", | |
" input = input[:a] + ''.join(reversed(input[a:b+1])) + input[b+1:]\n", | |
" elif parts[0] == 'move':\n", | |
" a,b = int(parts[2]), int(parts[5])\n", | |
" if a < b: \n", | |
" input = input[:a] + input[a+1:b+1] + input[a] + input[b+1:]\n", | |
" else:\n", | |
" input = input[:b] + input[a] + input[b:a] + input[a+1:]\n", | |
" return input" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"assert go('swap position 4 with position 0', 'abcde') == 'ebcda'\n", | |
"assert go('swap letter d with letter b', 'ebcda') == 'edcba'\n", | |
"assert go('reverse positions 0 through 4', 'edcba') == 'abcde'\n", | |
"assert go('rotate left 1 step', 'abcde') == 'bcdea'\n", | |
"assert go('move position 1 to position 4', 'bcdea') == 'bdeac'\n", | |
"assert go('move position 3 to position 0', 'bdeac') == 'abdec'\n", | |
"assert go('rotate based on position of letter b', 'abdec') == 'ecabd'\n", | |
"assert go('rotate based on position of letter d', 'ecabd') == 'decab'" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = open(\"day21.txt\").read().split('\\n')[:-1]\n", | |
"def scramble(p):\n", | |
" for l in data:\n", | |
" p = go(l, p)\n", | |
" return pwd\n", | |
"\n", | |
"scramble('abcdefgh')" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 22" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import re\n", | |
"from collections import namedtuple\n", | |
"Node = namedtuple('Node', ['pos', 'size', 'used', 'avail'])\n", | |
"data = open(\"day22.txt\").read().split('\\n')[2:-1]\n", | |
"# data = \"\"\"/dev/grid/node-x0-y0 10T 8T 2T 80%\n", | |
"# /dev/grid/node-x0-y1 11T 6T 5T 54%\n", | |
"# /dev/grid/node-x0-y2 32T 28T 4T 87%\n", | |
"# /dev/grid/node-x1-y0 9T 7T 2T 77%\n", | |
"# /dev/grid/node-x1-y1 8T 0T 8T 0%\n", | |
"# /dev/grid/node-x1-y2 11T 7T 4T 63%\n", | |
"# /dev/grid/node-x2-y0 10T 6T 4T 60%\n", | |
"# /dev/grid/node-x2-y1 9T 8T 1T 88%\n", | |
"# /dev/grid/node-x2-y2 9T 6T 3T 66%\"\"\".split('\\n')\n", | |
"\n", | |
"def parse(line):\n", | |
" name,size,used,avail,_ = re.split(r'\\s+', line)\n", | |
" y,x = re.match(r'/dev/grid/node-x(\\d+)-y(\\d+)', name).groups()\n", | |
" return Node((int(x),int(y)), int(size[:-1]), int(used[:-1]), int(avail[:-1]))\n", | |
"\n", | |
"nodes = [parse(line) for line in data]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from itertools import permutations\n", | |
"sum((ua and ab >= ua) for (_,_,ua,aa),(_,_,ub,ab) in permutations(nodes, 2))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"my, mx = max(nodes, key=lambda x: x[0])[0]\n", | |
"grid = np.zeros((my+1,mx+1), dtype='O')\n", | |
"for node in nodes:\n", | |
" grid[node[0]] = node" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"grid[0,0],grid[0,mx]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"sorted(nodes, key=lambda x: x[2]/x[1])[0]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def draw(x):\n", | |
" if x.pos == (0,mx):\n", | |
" return 'G'\n", | |
" if x.size > 100:\n", | |
" return '#'\n", | |
" if x.used == 0:\n", | |
" return '_'\n", | |
" return '.'\n", | |
"[''.join(draw(x) for x in y) for y in grid]\n", | |
"# grid[mx,0].used, [n for n in nodes if n.avail > grid[mx,0].used]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"from heapq import *\n", | |
"\n", | |
"def heuristic(a, b):\n", | |
" return abs(a.pos[0] - b.pos[0]) + abs(a.pos[1] - b.pos[1])\n", | |
"\n", | |
"def search(start, goal, banned=None):\n", | |
" queue = []\n", | |
" heappush(queue, (heuristic(start, goal), start, [start]))\n", | |
" visited = set()\n", | |
" while queue:\n", | |
" _, n, ns = heappop(queue)\n", | |
" if n.pos == goal.pos:\n", | |
" return ns #, len(ns))\n", | |
" if n == banned: continue\n", | |
"# yield n\n", | |
" for d in [(1,0),(0,1),(-1,0),(0,-1)]:\n", | |
" p = np.array(n.pos)+d\n", | |
" if any(p < (0,0)) or any(p > (my,mx)): continue\n", | |
" nn = grid[tuple(p)]\n", | |
"# if nn.used > n.size: print(n.pos, nn.pos)\n", | |
" if not nn.pos in visited and nn.used <= n.size:\n", | |
" visited.add(nn.pos)\n", | |
"# print(nn.pos, heuristic(nn, goal))\n", | |
" heappush(queue, (heuristic(nn, goal), nn, ns + [nn]))\n", | |
" return visited" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"move1 = search(grid[6,19], grid[0,mx])\n", | |
"free = grid[0,mx]\n", | |
"G = move1[-2]\n", | |
"\n", | |
"total = len(move1)\n", | |
"nextfree = grid[G.pos[0], G.pos[1]-1]\n", | |
"while nextfree.pos != (0,0):\n", | |
" nextfree = grid[G.pos[0], G.pos[1]-1]\n", | |
" print(\"moving {} to {}\".format(free.pos, nextfree.pos))\n", | |
" move = search(free, nextfree, G)\n", | |
" free = G\n", | |
" G = nextfree\n", | |
" total += len(move)\n", | |
"total-1" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 23" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# data = open(\"day12.txt\").read().split('\\n')\n", | |
"data = \"\"\"cpy a b\n", | |
"dec b\n", | |
"cpy a d\n", | |
"cpy 0 a\n", | |
"cpy b c\n", | |
"inc a\n", | |
"dec c\n", | |
"jnz c -2\n", | |
"dec d\n", | |
"jnz d -5\n", | |
"dec b\n", | |
"cpy b c\n", | |
"cpy c d\n", | |
"dec d\n", | |
"inc c\n", | |
"jnz d -2\n", | |
"tgl c\n", | |
"cpy -16 c\n", | |
"jnz 1 c\n", | |
"cpy 74 c\n", | |
"jnz 88 d\n", | |
"inc a\n", | |
"inc d\n", | |
"jnz d -2\n", | |
"inc c\n", | |
"jnz c -5\"\"\".splitlines()\n", | |
"\n", | |
"def r2i(r): return ord(r) - ord('a')\n", | |
"\n", | |
"def parse(d):\n", | |
" d = [[(x if x.isalpha() else int(x)) for x in line.split()] for line in d]\n", | |
" regs = dict(a=12, b=0, c=0, d=0)\n", | |
" ip = 0\n", | |
" def idtoval(x): return (regs[x] if x in regs else x)\n", | |
" total_len = len(d)\n", | |
" while 0 <= ip < total_len:\n", | |
" ins = d[ip]\n", | |
" yield ip, ins, regs\n", | |
" if ins[0] == 'cpy':\n", | |
" if ins[2] in regs:\n", | |
" regs[ins[2]] = idtoval(ins[1])\n", | |
" elif ins[0] == 'inc':\n", | |
" regs[ins[1]] += 1\n", | |
" elif ins[0] == 'dec':\n", | |
" regs[ins[1]] -= 1\n", | |
" elif ins[0] == 'jnz':\n", | |
" if idtoval(ins[1]):\n", | |
" ip += idtoval(ins[2])\n", | |
" continue\n", | |
" elif ins[0] == 'tgl':\n", | |
" offs = ip + idtoval(ins[1])\n", | |
" if 0 <= offs < total_len:\n", | |
" if d[offs][0] in ['dec', 'tgl']:\n", | |
" d[offs][0] = 'inc'\n", | |
" elif d[offs][0] == 'inc':\n", | |
" d[offs][0] = 'dec'\n", | |
" elif d[offs][0] == 'jnz':\n", | |
" d[offs][0] = 'cpy'\n", | |
" else:\n", | |
" d[offs][0] = 'jnz'\n", | |
" ip += 1\n", | |
" yield regs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"p = parse(data)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"while True:\n", | |
" try:\n", | |
" r = next(p)\n", | |
"# print(r[0])\n", | |
" except StopIteration:\n", | |
" print(r)\n", | |
" break" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 24" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from heapq import *\n", | |
"\n", | |
"def heuristic(pos, visited):\n", | |
" return 8 - len(visited) + abs(pos[0] - zero[0]) + abs(pos[1] - zero[1])\n", | |
"\n", | |
"def search(start):\n", | |
" queue = []\n", | |
" heappush(queue, (0, (start, '0'), []))\n", | |
" path_cost = {(start, '0'): 0}\n", | |
" while queue:\n", | |
" _, s0, path = heappop(queue)\n", | |
" ((x0,y0), visited) = s0\n", | |
"\n", | |
" for x1,y1 in [(1,0),(0,1),(-1,0),(0,-1)]:\n", | |
" c = maze[y0+y1][x0+x1]\n", | |
" if c != '#':\n", | |
" new_cost = path_cost[s0] + 1\n", | |
" visited1 = (visited if c == '.' or c in visited else ''.join(sorted(visited + c)))\n", | |
" s1 = ((x0+x1, y0+y1), visited1)\n", | |
" if s1 not in path_cost or new_cost < path_cost[s1]:\n", | |
"# print(path, visited1)\n", | |
" path1 = path + [s1[0]]\n", | |
" h = heuristic(s1[0], visited1)\n", | |
" if h == 0: return path1, len(path1), visited1\n", | |
" path_cost[s1] = new_cost\n", | |
" heappush(queue, (h + path_cost[s1], (s1[0], visited1), path1))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"maze = open(\"day24.txt\").read().splitlines()\n", | |
"# maze = \"\"\"###########\n", | |
"# #0.1.....2#\n", | |
"# #.#######.#\n", | |
"# #4.......3#\n", | |
"# ###########\"\"\".splitlines()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"zero = next((x, y) for y, row in enumerate(maze) for x, c in enumerate(row) if c == '0')\n", | |
"search(zero)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Day 25" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# data = open(\"day12.txt\").read().split('\\n')\n", | |
"data = \"\"\"cpy a d\n", | |
"cpy 11 c\n", | |
"cpy 231 b\n", | |
"inc d\n", | |
"dec b\n", | |
"jnz b -2\n", | |
"dec c\n", | |
"jnz c -5\n", | |
"cpy d a\n", | |
"jnz 0 0\n", | |
"cpy a b\n", | |
"cpy 0 a\n", | |
"cpy 2 c\n", | |
"jnz b 2\n", | |
"jnz 1 6\n", | |
"dec b\n", | |
"dec c\n", | |
"jnz c -4\n", | |
"inc a\n", | |
"jnz 1 -7\n", | |
"cpy 2 b\n", | |
"jnz c 2\n", | |
"jnz 1 4\n", | |
"dec b\n", | |
"dec c\n", | |
"jnz 1 -4\n", | |
"jnz 0 0\n", | |
"out b\n", | |
"jnz a -19\n", | |
"jnz 1 -21\"\"\".splitlines()\n", | |
"\n", | |
"def r2i(r): return ord(r) - ord('a')\n", | |
"\n", | |
"def parse(d, sa):\n", | |
" d = [[(x if x.isalpha() else int(x)) for x in line.split()] for line in d]\n", | |
" regs = dict(a=sa, b=0, c=0, d=0)\n", | |
" ip = 0\n", | |
" def idtoval(x): return (regs[x] if x in regs else x)\n", | |
" total_len = len(d)\n", | |
" while 0 <= ip < total_len:\n", | |
" ins = d[ip]\n", | |
"# yield ip, ins, regs\n", | |
" if ins[0] == 'cpy':\n", | |
" if ins[2] in regs:\n", | |
" regs[ins[2]] = idtoval(ins[1])\n", | |
" elif ins[0] == 'inc':\n", | |
" regs[ins[1]] += 1\n", | |
" elif ins[0] == 'dec':\n", | |
" regs[ins[1]] -= 1\n", | |
" elif ins[0] == 'jnz':\n", | |
" if idtoval(ins[1]):\n", | |
" ip += idtoval(ins[2])\n", | |
" continue\n", | |
" elif ins[0] == 'tgl':\n", | |
" offs = ip + idtoval(ins[1])\n", | |
" if 0 <= offs < total_len:\n", | |
" if d[offs][0] in ['dec', 'tgl']:\n", | |
" d[offs][0] = 'inc'\n", | |
" elif d[offs][0] == 'inc':\n", | |
" d[offs][0] = 'dec'\n", | |
" elif d[offs][0] == 'jnz':\n", | |
" d[offs][0] = 'cpy'\n", | |
" else:\n", | |
" d[offs][0] = 'jnz'\n", | |
" elif ins[0] == 'out':\n", | |
" yield idtoval(ins[1])\n", | |
" ip += 1\n", | |
" yield regs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from itertools import islice\n", | |
"res = [0,1]*5\n", | |
"\n", | |
"for i in range(1000):\n", | |
" if list(islice(parse(data, i), 10)) == res:\n", | |
" print(i)\n", | |
" break\n", | |
" if i % 10 == 0:\n", | |
" print(i)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"list(islice(parse(data, 189), 100))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"anaconda-cloud": {}, | |
"kernelspec": { | |
"display_name": "Python [conda root]", | |
"language": "python", | |
"name": "conda-root-py" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.5.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment