Inlägg

Inlägg som Ingetledigtnamn har skrivit i forumet
Av Ingetledigtnamn

Dag: 24
Språk: Python (Numpy igen...)

import numpy as np symbols = ".<>^v#" g = np.array([[symbols.find(c) for c in l.strip()] for l in open("input24").readlines()], dtype = np.uint8) b = np.array(([((g == i).astype(np.uint8) << i)[1:-1,1:-1] for i, _ in enumerate(symbols)]))[1:5] def move_blizzards(g, b): for i, (k, a) in enumerate([(-1, 1), (1, 1), (-1, 0), (1, 0)]): b[i] = np.roll(b[i], k, axis = a) g[1:-1,1:-1] = b.sum(axis = 0) return g steps = np.array([[0, 0], [-1, 0], [ 1, 0], [ 0, -1], [ 0, 1]]) def minute(t, g, b, pos, start): g = move_blizzards(g, b) return t + 1, g, {next for p in pos for s in steps if ((p + s) < g.shape).all() and g[next := tuple(p + s)] == 0} | {start} def traverse(t, g, b, start, goal): pos = {start} while goal not in pos: t, g, pos = minute(t, g, b, pos, start) return t, g start, goal = (0,1), (len(g) - 1, len(g[0]) -2) there, _ = traverse(0, g, b, start, goal) back, _ = traverse(there, g, b, goal, start) again, _ = traverse(back, g, b, start, goal) print(there, again)

Dold text
Av Ingetledigtnamn

Dag: 23
Språk: Python

import numpy as np import copy grid = np.array([[".#".find(c) for c in l.strip()] for l in open("input23").readlines()]) def propose(g, p, props, dir): if g[p[0] - 1 : p[0] + 2, p[1] - 1: p[1] + 2].sum() == 1: return for i in range(dir, dir + 4): if i % 4 == 0 and (g[p[0] - 1, p[1] - 1: p[1] + 2] == 0).all(): # N props[p] = (p[0] - 1, p[1]) return if i % 4 == 1 and (g[p[0] + 1, p[1] - 1: p[1] + 2] == 0).all(): # S props[p] = (p[0] + 1, p[1]) return if i % 4 == 2 and (g[p[0] - 1 : p[0] + 2, p[1] - 1 ] == 0).all(): # W props[p] = (p[0], p[1] - 1) return if i % 4 == 3 and (g[p[0] - 1 : p[0] + 2, p[1] + 1 ] == 0).all(): # E props[p] = (p[0], p[1] + 1) return def round(g, dir): if g[0,:].sum() or g[-1,:].sum() or g[:,0].sum() or g[:,-1].sum(): g = np.pad(g, 1) coords = list(zip(*np.where(g == 1))) props = dict() for p in coords: propose(g, p, props, dir) for p in props.values(): g[p] -= 1 for p1, p2 in props.items(): if g[p2] == -1: g[p2] = 1 g[p1] = 0 g[g < 0] = 0 return g g = grid def one(g): for i in range(10): g = round(g, i) xs, ys = np.where(g == 1) return (xs.max() - xs.min() + 1) * (ys.max() - ys.min() + 1) - g.sum() def two(g): for i in range(9999): lastg = copy.deepcopy(g) g = round(g, i) if g.shape == lastg.shape and (lastg == g).all(): return i + 1 print(one(grid), two(grid))

Dold text
Av Ingetledigtnamn

Dag: 22
Språk: Python (Numpy kan rotera kuber...)

Det blev ganska mycket kod, men att mappa sidorna på kuber var lite knöligt.

import numpy as np import re from math import gcd map_, moves = tuple(open("input22").read().split('\n\n')) map_ = map_.split('\n') sx, sy = max(len(l) for l in map_), len(map_) grid = np.zeros((sy, sx), dtype = np.int_) for y, l in enumerate(map_): grid[y, :len(l)] = [' .#'.find(c) for c in l] def rotL(cube): return np.rot90(cube, axes=(0,2)) def rotR(cube): return np.rot90(cube, k = -1, axes=(0,2)) def rotU(cube): return np.rot90(cube, axes=(0,1)) def turnL(cube, pos = (0, 0, 0)): return np.rot90(cube, axes=(2,1)), (0, pos[2], cube.shape[1] - pos[1] - 1) def turnR(cube, pos): return np.rot90(cube, axes=(1,2)), (0, cube.shape[2] - pos[2] - 1, pos[1]) def corners(cube): return cube[0,0,0], cube[0,-1,0], cube[0,0,-1], cube[0,-1,-1] def find_start_face(cube, first): for _ in range(3): if set(corners(cube)) == set(first): return cube cube = rotL(cube) if set(corners(cube)) == set(first): return cube cube = rotU(cube) def project_grid_onto_cube(grid): fs = gcd(sx, sy) first = None faces = dict() cube = np.zeros([fs + 2] * 3, dtype=np.int_) # Mark corners for navigation for ix,x in enumerate([0, fs + 1]): for iy,y in enumerate([0, fs + 1]): for iz,z in enumerate([0, fs + 1]): cube[x,y,z] = ix << 2 | iy << 1 | iz for iy, y in enumerate(range(0, sy, fs)): # Map face and rotate for ix, x in enumerate(range(0, sx, fs)): if grid[y:y+fs, x:x+fs].sum(): cube[0, 1:-1, 1:-1] = grid[y:y+fs, x:x+fs] c = corners(cube) faces[frozenset(c)] = (c, (y, x)) first = first if first else c cube = rotL(cube) # Rotate back and rotate down if non-zero face on the down side for ix, x in enumerate(range(sx - fs, -1, -fs)): cube = rotR(cube) if y + fs < sy and grid[y:y+fs, x:x+fs].sum() and grid[y+fs: y+2*fs, x:x+fs].sum(): cube = rotU(cube) # cube = find_start_face(cube, first) while corners(cube) != faces[frozenset(first)][0]: cube, _ = turnL(cube) return [cube, faces] def project_grid_onto_plane(grid): faces = dict() cube = np.zeros([1, grid.shape[0] + 2, grid.shape[1] + 2], dtype=np.int_) for iy,y in enumerate([0, grid.shape[0] + 1]): for iz,z in enumerate([0, grid.shape[1] + 1]): cube[0,y,z] = iy << 1 | iz cube[0, 1:-1, 1:-1] = grid c = corners(cube) faces[frozenset(c)] = (c, (0, 0)) return [cube, faces] def flip(cube, pos): return rotL(cube), tuple(pos - np.array((0,0,cube.shape[0] - 2))) def skip(cube, pos): while cube[pos] == 0: pos = tuple((pos + np.array((0,0,1))) % cube.shape) return cube, pos def next_move(moves): while moves: if m := re.match('\d+', moves): moves = moves[len(m[0]):] yield int(m[0]) if moves: m, moves = moves[0], moves[1:] yield m def next_pos(cube, pos, on_zero): pos = tuple(pos + np.array((0,0,1))) return (cube, pos) if cube[pos] else on_zero(cube, pos) def do_moves(cube, faces, on_zero): cube, pos = skip(cube, (0,1,1)) for n in next_move(moves): if n == 'L': cube, pos = turnL(cube, pos) elif n == 'R': cube, pos = turnR(cube, pos) else: for i in range(n): ncube, npos = next_pos(cube, pos, on_zero) if ncube[npos] == 2: break cube, pos = ncube, npos (c, (y,x)) = faces[frozenset(corners(cube))] dir = 0 while corners(cube) != c: cube, pos = turnL(cube, pos) dir += 1 return (pos[1] + y) * 1000 + (pos[2] + x) * 4 + dir print([do_moves(*f1(grid), f2) for f1, f2 in [(project_grid_onto_plane, skip), (project_grid_onto_cube, flip)]])

Dold text
Av Ingetledigtnamn

Dag: 20
Språk: C++ (Det bara skrek dubbellänkad lista och pekarmanipulation. Inget för Python...)

#include <iostream> #include <fstream> #include <vector> #include <cstdint> using namespace std; struct List { int64_t val; List *prev; List *next; List(int64_t v, struct List *&last) : val(v), next(this), prev(this) {} void remove() { next->prev = prev; prev->next = next; next = prev = this; } void precede(List *elem) { prev = elem->prev; next = prev->next; elem->prev = this; prev->next = this; } }; List *forward(List *p, int n) { for (auto i = 0; i < n; ++i) p = p->next; return p; } int64_t solve(int64_t scale, int times) { ifstream file; file.open("input20"); List *first = nullptr; List *last = nullptr; vector<List *> v; int64_t n; while (file >> n) { List *elem(new List(n * scale, last)); v.push_back(elem); if (first) { elem->precede(first); } else { first = elem; } } int64_t count = v.size() - 1; for (int j = 0; j < times; ++j) { for (auto i : v ) { auto steps = i->val % count; if (steps > 0) { List *p = i; for (auto j = 0; j < steps; ++j) { p = p->next; } i->remove(); i->precede(p->next); } if (steps < 0) { List *p = i; for (auto j = 0; j > steps; --j) { p = p->prev; } i->remove(); i->precede(p); } } } auto p = first; while (p->val != 0) { p = p->next; } return forward(p, 1000)->val + forward(p, 2000)->val + forward(p, 3000)->val; } int main() { cout << solve(1, 1) << ", " << solve(811589153, 10) << '\n'; return 0; }

Dold text
Av Ingetledigtnamn

Dag: 19
Språk: Python (Bredden först-lösning. Numpy givetvis )

Måste säga att detta var den bökigaste uppgiften att lösa. Kanske till viss del beroende på att jag envisades med att köra BFS. Den blev dock hyfsat effektiv till slut, körtiden mäts i sekunder, inte minuter.

Varje blueprint blir en matris med de state-förändringar som sker om man bygger en robot av typ X. Blueprint-matrisen adderas till matrisen med alla nuvarande state och ut kommer en 5 gånger så stor matris. Det blir snabbt en ohållbart stor sökrymd. Följande fyra regler håller ner antalet states så det faktiskt funkar att köra BFS.

Bort med alla states

  • som inte hade tillräckligt med resurser för att bygga den roboten,

  • som has byggt fler robotar av en viss typ än vad vi kan använda varje minut,

  • där man kunde ha byggt en gorde robot men inte gjorde det,

  • där man byggt en robot som kunde ha byggts minuten innan (detta state kommer alltid vara ett sämre allternative än det state där roboten byggdes den förra minuten).

Den sista regeln är det som gör det möjligt att köra BFS. Det skulle gå att klippa mer i sökrymden, men det funkar OK nu. Minnesåtgången håller sig under 5GB.

import re import numpy as np from collections import defaultdict from math import prod adm, res, cost, robots, br = 0, 1, 1, 2, 3 # adm, resources, cost, robots, built robot ore, cly, obs, geo = 0, 1, 2, 3 bm, cbm, lbm, lcbm = 0, 1, 2, 3 # Built Mask, Can Build Mask, Last Build Mask, Last Can Build Mask bp = [] for l in open("input19").readlines(): _, or0, cl0, ob0, ob1, ge0, ge2 = tuple(map(int, re.findall(r'\d+', l))) bp.append( np.array( # Adm, Cost Owned robots Built Robot [[[1, 0, 0, 0], [-or0, 0, 0, 0], [0, 0, 0, 0], [1, 0, 0, 0]], [[2, 0, 0, 0], [-cl0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 0, 0]], [[4, 0, 0, 0], [-ob0, -ob1, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0]], [[8, 0, 0, 0], [-ge0, 0, -ge2, 0], [0, 0, 0, 0], [0, 0, 0, 1]], [[0, 0, 0, 0], [ 0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]], dtype=np.int_)) def tick(states, bp, limit): s = (states.reshape((-1, 16)) + bp.reshape((-1, 1, 16))).reshape(-1, 4, 4) # Did we have enough resources to build? s = s[s[:,res,:].min(axis = 1) >= 0,:] # No need to have more robots than the resource use each minute s = s[(s[:,robots,:geo] <= limit).all(axis = 1),:] # Can we build geode robot? s = s[((s[:, adm, cbm] & 8) != 0) == s[:, br, geo],:] # Should have built earlier? s = s[ ~np.logical_and( np.logical_and(s[:, adm, bm] != 0, s[:, adm, lbm] == 0), (s[:, adm, bm] & s[:, adm, lcbm]) != 0),:] # Each robot collects one resource s[:, res, :] += s[:,robots,:] # Built any new robots? s[:, robots, :] += s[:, br,:] # Bookkeeping s[:, adm, lbm] = s[:, adm, bm] s[:, adm, lcbm] = s[:, adm, cbm] s[:, adm, bm] = 0 s[:, adm, cbm] = ( (s[:, res, :] + bp[geo, cost, :] >= 0).all(axis = 1) << 3 | (s[:, res, :] + bp[obs, cost, :] >= 0).all(axis = 1) << 2 | (s[:, res, :] + bp[cly, cost, :] >= 0).all(axis = 1) << 1 | (s[:, res, :] + bp[ore, cost, :] >= 0).all(axis = 1)) s[:, br: ,:] = 0 return s def bfs(bp, minutes): l = [] for i,b in enumerate(bp): limit = -b[:, cost, :geo].min(axis=0) s = np.array([[0,0,0,0], [0,0,0,0], [1,0,0,0], [0,0,0,0]]) for j in range(minutes): s = tick(s, b, limit) l.append((i + 1, s[:, res, geo].max())) return l print(sum(map(prod, bfs(bp, 24))), prod(map(lambda x: x[1], bfs(bp[:3], 32))))

Dold text
Av Ingetledigtnamn

Dag: 21
Språk: Python

@Yoshman Det finns andra sätt att lösa uppgiften där men inte behöver befatta sig med flyttal.

Python tillhandahåller både evaluering, parser och traversering av uttryck...

import ast def evaluate(monkey): s = expressions[monkey] op = s.split() if len(op) == 3: s = "(" + evaluate(op[0]) + op[1] + evaluate(op[2]) + ")" try: s = str(int(eval(s))) except: pass expressions[monkey] = s return s class Visitor(ast.NodeVisitor): def __init__(self, v): self.v = v super().__init__() def visit_BinOp(self, node): left = right = None if isinstance(node.left, ast.Constant): left = node.left.value if isinstance(node.right, ast.Constant): right = node.right.value if isinstance(node.op, ast.Add): self.v -= left or right if isinstance(node.op, ast.Mult): self.v //= left or right if isinstance(node.op, ast.Sub): self.v = left - self.v if left else self.v + right if isinstance(node.op, ast.Div): self.v = left // self.v if left else self.v * right ast.NodeVisitor.generic_visit(self, node) expressions = dict([l.strip().split(": ") for l in open("input21").readlines()]) one = evaluate("root") expressions = dict([l.strip().split(": ") for l in open("input21").readlines()]) expressions["humn"] = "humn" e = expressions["root"].split() v = Visitor(eval(evaluate(e[2]))) v.visit(ast.parse(evaluate(e[0]))) two = v.v print(one, two)

Dold text
Av Ingetledigtnamn

Dag: 18
Språk: Python (Trix med numpy igen )

import numpy as np offset = np.array([[ 1, 0, 0], [-1, 0, 0], [ 0, 1, 0], [ 0,-1, 0], [ 0, 0, 1], [ 0, 0,-1]]) def neighbors(point): return a[tuple((point + offset).T)] input = np.loadtxt("input18", dtype=np.int_, delimiter=',') input += (np.min(input) == 0) a = np.zeros([np.max(input) + 2] * 3, dtype=np.int_) a[tuple(input.T)] = 1 one = sum([6 - sum(neighbors(i)) for i in input]) a[0,:,:] = a[:,0,:] = a[:,:,0] = a[-1,:,:] = a[:,-1,:] = a[:,:,-1] = 2 loop = True while loop: loop = False for p in zip(*np.where(a == 0)): if np.any(neighbors(p) == 2): a[p] = 2 loop = True a //= 2 two = sum([sum(neighbors(i)) for i in input]) print(one, two)

Dold text
Av Ingetledigtnamn

Dag: 17
Språk: Python (Numpy)

import numpy as np import itertools as it shapes = [ np.where(np.array([[1,1,1,1]]) == 1), np.where(np.array([[0,1,0], [1,1,1], [0,1,0]]) == 1), np.where(np.array([[1,1,1], [0,0,1], [0,0,1]]) == 1), np.where(np.array([[1], [1], [1], [1]]) == 1), np.where(np.array([[1,1], [1,1]]) == 1) ] input = open("input17").read().strip() def direction(): for d in it.cycle(input): yield [-1, 1][d="='>'"] def drop(n): tunnel = np.zeros((200000, 9), dtype=np.int_) tunnel[0,:] = tunnel[:,0] = tunnel[:,8] = 1 shape = it.cycle(shapes) dirs = direction() for i in range(1, n + 1): height = max(np.where(tunnel[:,1:8] != 0)[0]) x, y, s = 3, height + 4, next(shape) while True: if not any(tunnel[s[0] + y, s[1] + (x + (d := next(dirs)))]): x += d if any(tunnel[s[0] + (y - 1), s[1] + x]): break y -= 1 tunnel[s[0] + y, s[1] + x] = i return tunnel tunnel = drop(2022) one = max(np.where(tunnel[:,1:8] != 0)[0]) def find_cycle(t): end = max(np.where(tunnel[:,1:8] != 0)[0]) // 2 for i in range(2, end): diff = tunnel[end - i:end + 1, 1:8] - tunnel[end - i - i:end - i + 1, 1:8] rock_diff = np.max(diff) diff[diff != 0] -= rock_diff if np.all(diff == 0): return i, rock_diff def find_start(tunnel, length): start = length while start: diff = (tunnel[start + length: start + length + length + 1, 1:8] - tunnel[start :start + length + 1, 1:8]) diff[diff != 0] -= np.max(diff) if np.any(diff != 0): return start, np.max(tunnel[:start]) start -= 1 tunnel = drop(len(input) * len(shapes)) cycle_height, cycle_rocks = find_cycle(tunnel) start_height, start_rocks = find_start(tunnel, cycle_height) cycles = (1000000000000 - start_rocks) // cycle_rocks remainder = (1000000000000 - start_rocks) % cycle_rocks two = cycles * cycle_height + max(np.where(tunnel == (remainder + start_rocks))[0]) print(one, two)

Dold text
Av Ingetledigtnamn

Dag: 16
Språk: Python

När jag angrep detta som ett besök alla noder-problem, med valet att öppna eller inte äppna en kran var det ganska bökigt. Men efter att byggt en ny komplett graf med distanser på bågarna blev det mycket lättare. Nu handle det bara om i vilken ordning man skulle öppna kranarna.

Lösningen för del två som tar kryssprodukten av alla möjliga 26-stegstraverseringar är inte den snabbaste...

import re import itertools def bfs(l): visited = dict() while l: node, dist = l.pop(0) if node in visited: continue visited[node] = dist l += [(t, dist + 1) for t, _ in to[node]] return visited def flow(path, depth): return sum([rate[n] * (depth - t) for n, t in path if t < depth]) def join_solutions(d1, d2, depth): for d in [d2, {k: min(d1[k],d2[k]) for k in set(d1) & set(d2)}]: d1.update(d) return flow(d1.items(), depth) start, to, rate = 'AA', dict(), dict() for line in open("input16").readlines(): l = line.strip() m = re.match("Valve ([A-Z][A-Z]).*=(\d+).*valves? (.*)", l) rate[m[1]] = int(m[2]) to[m[1]] = [(n, 1) for n in m[3].split(', ')] valves = [n for n,r in rate.items() if r or r == start] kgraph = {node:{n:d for n,d in bfs([(node, 0)]).items() if rate[n] and n != node} for node in to if rate[node] or node == start } def open_valves(node, time, unopened, order, depth): if time >= depth or not unopened: return [order] time += 1 l = [] dists = kgraph[node] for i, u in enumerate(unopened): d = dists[u] if time + d < depth: l += open_valves(u, time + d, unopened[:i] + unopened[i+1:], order + [(u, time + d)], depth) return l if l else [order] print(max([flow(p, 30) for p in open_valves(start, 0, valves, [(start, 0)], 30) ]), max([join_solutions(dict(m), dict(e), 26) for m, e in itertools.combinations_with_replacement( open_valves(start, 0, valves, [(start, 0)], depth), 2)]))

Dold text
Av Ingetledigtnamn

Dag: 15
Språk: Python

import re coords = [tuple(map(int, re.findall('\-?\d+', l.strip()))) for l in open("input15").readlines()] def gen(sx, sy, bx, by, line = 0): dist = abs(sx - bx) + abs(sy - by) for i in range(line, sy - dist): yield [] for l in range(max(line, sy - dist), sy): o = dist - (sy - l) yield [(sx - o, sx + o + 1)] for l in range(max(sy, line), sy + dist + 1): o = dist - (l - sy) yield [(sx - o, sx + o + 1)] while True: yield [] def merge(ranges): a, b = sorted(ranges), [] for begin, end in a: if b and b[-1][1] > begin - 1: b[-1][1] = max(b[-1][1], end) else: b.append([begin, end]) return b def one(line): l = [gen(*coord, line) for coord in coords] r = merge(list(r[0] for r in (map(next, l)) if r)) return r[0][1] - r[0][0] - len(set([bx for _, _ ,bx, by in coords if by == line])) def two(): l = [gen(*coord) for coord in coords] for y in range(4000000): if len(m := merge(r[0] for r in (map(next, l)) if r) ) > 1: return y + dim * m[0][1] print(one(2000000), two())

Dold text
Av Ingetledigtnamn

Dag: 14
Språk: Python

import numpy as np stones = [[eval(p) for p in l.strip().split(" -> ")] for l in open("input14").readlines()] mx, my = (max(map(max,c)) + 1 for c in zip(*[(zip(*s)) for s in stones])) grid = np.full((mx + my, my + 2), '.') for line in [list(zip(stone[:-1], stone[1:])) for stone in stones]: for fr, to in line: if fr[0] == to[0]: for y in range(min(fr[1], to[1]), max(fr[1], to[1]) + 1): grid[fr[0], y] = "#" else: for x in range(min(fr[0], to[0]), max(fr[0], to[0]) + 1): grid[x, fr[1]] = "#" grid[:,my + 1] = '#' def fall(x, y, terminate): if terminate(x, y): return False for o in [0, -1, +1]: if grid[x + o, y + 1] == '.': return fall(x + o, y + 1, terminate) grid[x, y] = 'o' return True c1 = c2 = 0 while (fall(500, 0, lambda x, y: y + 1 == my)): c1 = c1 + 1 while (fall(500, 0, lambda x, y: grid[500, 0] == 'o')): c2 = c2 + 1 print(c1, c1 + c2)

Dold text
Av Ingetledigtnamn

Dag: 13
Språk: Python

Dagens fultrick: Returnera bool (true/false) eller None, där None betyder att man ska kolla nästa element.

from itertools import chain from functools import cmp_to_key def compare(left, right): if isinstance(left, int): if isinstance(right, int): return None if left == right else left < right return compare([left], right) if isinstance(right, int): return compare(left, [right]) if not left: return True if right else None if not right: return False if (res := compare(left[0], right[0])) is None: res = compare(left[1:], right[1:]) return res ps = [tuple(eval(l) for l in ll.split('\n')) for ll in open("input13").read().split('\n\n')] s = sorted(chain(*[[l,r] for l, r in ps + [([[2]],[[6]])]]), key=cmp_to_key(lambda x, y: [1, -1][compare(x, y)])) print(sum([i + 1 for i, (l, r) in enumerate(ps) if compare(l, r)]), (s.index([[2]]) + 1) * (s.index([[6]]) + 1))

Dold text
Av Ingetledigtnamn

Dag: 12
Språk: Python

import numpy as np g = np.array([[c for c in l.strip()] for l in open(name).readlines()]) s, e = tuple(zip(*np.where(g == 'S')))[0], tuple(zip(*np.where(g == 'E')))[0] g[s] = 'a' g[e] = 'z' def bfs(s, e, g0, allowed, success, sentinel): g = np.full(np.array(g0.shape) + 2, sentinel) g[1:-1,1:-1] = g0 bf, e, visited = [[(s[0] + 1, s[1] + 1)]], (e[0] + 1, e[1] + 1), set() while bf: path = bf.pop(0) p = path[0] if success(p, g, e): return path if p in visited: continue visited.add(p) bf += [[q] + path for q in [(p[0]+1,p[1]),(p[0]-1,p[1]),(p[0],p[1]+1),(p[0],p[1]-1)] if allowed(p, q, g) ] print(len(bfs(s, e, g, lambda p, q, g: ord(g[p]) + 2 > ord(g[q]), lambda p, g, e: p == e, '~')) -1, len(bfs(e, s, g, lambda p, q, g: ord(g[q]) >= ord(g[p]) - 1, lambda p, g, e: g[p] == 'a', ' ')) - 1)

Dold text
Av Ingetledigtnamn

Dag: 11
Språk: Python

Dagens lärdom: det var inte samma primfaktorer i exemplet och i min personliga input...

from math import prod input = [[l.split(": ")[1] for l in m.split('\n')[1:]] for m in open("input11").read().split('\n\n')] monkeys = [[int(l.split()[-1]) if i else eval(f"lambda old:{l[6:]}") for i, l in enumerate(m[1:])] for m in input] for n, f in [(20, lambda x: x // 3), (10000, lambda x: x % prod([m[1] for m in monkeys]))]: state = [[0, list(map(int, m[0].split(", ")))] for m in input] for _ in range(n): for i, m in enumerate(monkeys): while state[i][1]: state[i][0] += 1 nw = f(m[0](state[i][1].pop(0))) state[m[2 + (nw % m[1] != 0)]][1].append(nw) print(prod(sorted([s[0] for s in state])[-2:]))

Dold text
Av Ingetledigtnamn
Skrivet av Ingetledigtnamn:

Dag: 10
Språk: Python

Det gick att knöka ihop denna lösning som en oneliner i Python, men det krävdes en del trixande.

for s in (lambda d, fs: [f(d) for f in fs])( reduce(lambda x, f: f(x), map(lambda x: [lambda y: lambda z: (z[0], z[1] + [z[0]]), lambda y: lambda z: (z[0] + int(y[5:]), z[1] + [z[0], z[0] + int(y[5:])])] [x[0] == 'a'](x), open("input10").read().splitlines()), (1, [1]))[1], [lambda during: sum([i * during[i] for i in range(20, len(during), 40)]), lambda during: (lambda s: "\n".join([s[i: i + 39] for i in range(0, len(s), 40)])) ("".join([".#"[during[i] in [(i - 1) % 40, i % 40, (i + 1) % 40]] for i in range(240)])) ]): print(s)

Dold text
Av Ingetledigtnamn

Dag: 10
Språk: Python

Verkar som aktiviteten i denna tråd har klingat av ganska ordenligt. Vi får se om den får ett uppsving under helgen.

X, during = 1, [1] for i in open("input10").readlines(): during.append(X) if i[0] == "a": X += int(i[5:]) during.append(X) print(sum([i * during[i] for i in range(20, len(during), 40)])) s = "".join([".#"[during[i] in [(i - 1) % 40, i % 40, (i + 1) % 40]] for i in range(240)]) for i in range(0,240,40): print(s[i:i + 40])

Dold text
Av Ingetledigtnamn

Dag: 9
Språk: Python

Komplexa tal förenklar matematik i tvådimensionella system...

dir = {"U": complex(0,1), "D": complex(0,-1), "L": complex(-1,0), "R": complex(1,0)} parts = [complex(0,0)] * 10 visited = [set(), set(), set(), set(), set(), set(), set(), set(), set(), set(), set()] for move in open("input09").readlines(): m = move.strip().split() for _ in range(int(m[1])): parts[0] += dir[m[0]] for i in range(1, len(parts)): if abs(diff := parts[i - 1] - parts[i]) > 1.5: parts[i] += complex(diff.real / abs(diff.real) if diff.real else 0, diff.imag / abs(diff.imag) if diff.imag else 0) visited[i].add(parts[i]) print([len(visited[i]) for i in [1,9]])

Dold text
Av Ingetledigtnamn

Min favorit där är My Science Project som i de nordiska länderna fick heta Time Busters!?!

Av Ingetledigtnamn

Dag: 8
Språk: Python

Detta är nog det hemskaste jag skrivit på länge. Det blev nästan en oneliner.

import numpy as np from functools import reduce def get_shorter(l, level): for i in l: yield i if i >= level: return print((lambda a, fs: [(lambda a, f1, f2, f3: f1(reduce(f2, [np.rot90(f3(np.rot90(a, k = i)), k = -i) for i in range(4)]))) (a, *f) for f in fs])( np.array([[int(c) for c in l.strip()] for l in open("input08").readlines()]), [(np.sum, np.logical_or, lambda a: (a > np.insert(np.maximum.accumulate(a, axis = 0)[:-1,:], 0, -1, axis = 0))), (np.max, np.multiply, lambda a: np.array([[len(list(get_shorter(l[i+1:], l[i]))) for i in range(len(l))] for l in a]))]))

Dold text

Det intressanta lambdat är en funktion som roterar matrisen så f3 appliceras från alla fyra håll. Resultat-matriserna ORas eller multipliceras och sedan appliceras sum eller max. Fick inte ihop tvåan i numpy, så det fick bli en liten hjälpgenerator för det testet.

Av Ingetledigtnamn

Dag: 7 (version 2)
Språk: Python

Man kan strunta helt i alla namnen. Det enda intressanta är att addera alla storlekar. Stoppa dem i en stack, pusha 0 när man gör cd till nytt directory. Vid "cd ..", poppa av den ackumulerade storleken och addera till föräldern i stacken. Spara den poppade storleken i listan av alla storlekar.

Krävs dock att man städar stacken på slutet eftersom de inte avslutar input med att gå upp till "/" igen.

En traversering och allt är klart. Inga strängar att bråka med.

import itertools def read_sizes(current_size = [], all_sizes = []): for l in open("input07").readlines(): match l.strip().split(): case ['$', 'cd', d]: if d == "..": s = current_size.pop() all_sizes.append(s) current_size[-1] += s else: current_size.append(0) case ['$', 'ls']: pass case ['dir', d]: pass case [size, _]: current_size[-1] += int(size) return all_sizes + list(itertools.accumulate(current_size[::-1])) sizes = read_sizes() print(sum([s for s in sizes if s < 100000]), min([s for s in sizes if 70000000 - max(sizes) + s >= 30000000]))

Dold text