def part1(text, a_mult=16807, b_mult=48271, sample=int(4e7)): a_start, b_start = map(int, re.findall(r"\d+", text)) a_gen = applyfunc(lambda a: (a_mult * a) % DIVISOR, a_start) b_gen = applyfunc(lambda b: (b_mult * b) % DIVISOR, b_start) return count(a_gen, b_gen, sample)
def part2(text, a_mult=16807, b_mult=48271, sample=int(5e6)): a_start, b_start = map(int, re.findall(r"\d+", text)) a_gen = applyfunc(lambda a: (a_mult * a) % DIVISOR, a_start) a_gen = filterfalse(lambda a: a % 4, a_gen) b_gen = applyfunc(lambda b: (b_mult * b) % DIVISOR, b_start) b_gen = filterfalse(lambda b: b % 8, b_gen) return count(a_gen, b_gen, sample)
def process(text, length): def dragon(data, translation=str.maketrans({"0": "1", "1": "0"})): return f"{data}0{data[::-1].translate(translation)}" def valid(data): return length <= len(data) def checksum(data): return "".join("1" if a == b else "0" for a, b in grouper(data, 2)) data = next(filter(valid, applyfunc(dragon, text.strip())))[:length] return next(filter(lambda data: len(data) % 2, applyfunc(checksum, data)))
def part2(text, com="COM", you="YOU", san="SAN"): parents = {} for line in text.splitlines(): a, b = R.match(line).groups() parents[b] = a path = takewhile(partial(ne, com), applyfunc(parents.get, you)) visited = {you: i for i, you in enumerate(path)} path = applyfunc(parents.get, san) count, dest = next( (i, san) for i, san in enumerate(path) if san in visited) return visited[dest] + count
def compute(text, a, b, target): def process(line): instruction, *operands = line.replace(",", "").split() if instruction == "jmp": return instruction, None, int(operands[0]) - 1 elif len(operands) == 1: return instruction, operands[0], None else: return instruction, operands[0], int(operands[1]) - 1 def execute(pointer): instruction, register, offset = program[pointer] if instruction == "hlf": registers[register] //= 2 elif instruction == "tpl": registers[register] *= 3 elif instruction == "inc": registers[register] += 1 elif instruction == "jmp": pointer += offset elif instruction == "jie" and registers[register] % 2 == 0: pointer += offset elif instruction == "jio" and registers[register] == 1: pointer += offset return pointer + 1 registers = {"a": a, "b": b} program = tuple(map(process, text.splitlines())) consume(takewhile(partial(gt, len(program)), applyfunc(execute, 0)), None) return registers[target]
def test_traverse(): """To test the traverse implementation we call gc.collect() while instances of all the C objects are still valid.""" acc = iteration_utilities.accumulate([]) app = iteration_utilities.applyfunc(lambda x: x, 1) cha = iteration_utilities.chained(int, float) cla = iteration_utilities.clamp([], 0, 1) com = iteration_utilities.complement(int) con = iteration_utilities.constant(1) dee = iteration_utilities.deepflatten([]) dup = iteration_utilities.duplicates([]) fli = iteration_utilities.flip(int) gro = iteration_utilities.grouper([], 2) ine = iteration_utilities.intersperse([], 1) iik = iteration_utilities.ItemIdxKey(10, 2) ite = iteration_utilities.iter_except(int, TypeError) mer = iteration_utilities.merge([]) nth = iteration_utilities.nth(1) pac = iteration_utilities.packed(int) par = iteration_utilities.partial(int, 10) rep = iteration_utilities.replicate([], 3) rou = iteration_utilities.roundrobin([]) see = iteration_utilities.Seen() sid = iteration_utilities.sideeffects([], lambda x: x) spl = iteration_utilities.split([], lambda x: True) sta = iteration_utilities.starfilter(lambda x: True, []) suc = iteration_utilities.successive([]) tab = iteration_utilities.tabulate(int) une = iteration_utilities.unique_everseen([]) unj = iteration_utilities.unique_justseen([]) gc.collect()
def part2(text, size=256): lengths = tuple(chain(map(ord, text.strip()), (17, 31, 73, 47, 23))) args = (tuple(range(size)), lengths, 0, 0) array, _, first, _ = nth(63)(applyfunc(process, args)) array = array[first % size:] + array[:first % size] return bytes(reduce(xor, group) for group in grouper(array, 16)).hex()
def part1(text, steps=100): def step(grid): neighbors = convolve2d(grid, np.ones((3, 3)), "same") - grid return (neighbors == 3) | (grid & (neighbors == 2)) grid = np.array(tuple(map(process, text.splitlines()))) return (nth(steps - 1)(applyfunc(step, grid)) if steps else grid).sum()
def part2(text, steps=100): def step(grid): neighbors = convolve2d(grid, np.ones((3, 3)), "same") - grid return (neighbors == 3) | (grid & (neighbors == 2)) | on grid = np.array(tuple(map(process, text.splitlines()))) on = np.zeros_like(grid) on[0, 0] = on[0, -1] = on[-1, 0] = on[-1, -1] = True grid |= on return (nth(steps - 1)(applyfunc(step, grid)) if steps else grid).sum()
def part2(text): def move(c): if 0 == c.real == c.imag: return 1 elif -c.real < c.imag: return c + 1j if c.imag < c.real else c - 1 else: return c - 1j if c.real < c.imag else c + 1 n = int(text) grid = {(c := 0): 1} for c in takewhile(lambda _: grid[c] <= n, applyfunc(move, c)): grid[c] = sum(grid.get(x, 0) for x in map(add, repeat(c), NEIGHBORS)) return grid[c]
def test_applyfunc_normal1(): assert list(getitem(applyfunc(lambda x: x**T(2), T(2)), stop=3)) == [T(4), T(16), T(256)]
def test_applyfunc_normal2(): assert list(getitem(applyfunc(lambda x: x, T(2)), stop=3)) == [T(2), T(2), T(2)]
div, mod = divmod(previous[i], n) chained = chain(islice(previous, i), (0, ), islice(previous, i + 1, n)) if (a := i + mod + 1) == (b := a % n): memory = tuple(map(add, chained, spread(i + 1, a, div + 1, div))) else: memory = tuple(map(add, chained, spread(b, i + 1, div, div + 1))) return visited.setdefault(previous, memory) def duplicated(memory): return memory not in visited visited = {} n = len(memory := tuple(map(int, text.split()))) final = last(takewhile(duplicated, applyfunc(redistribute, memory))) return visited, final def part1(text): return len(process(text)[0]) def part2(text): graph, node = process(text) unique = partial(ne, node) return count_items(takewhile(unique, applyfunc(graph.get, node))) + 1 if __name__ == "__main__": # pragma: no cover
def part2(text): graph, node = process(text) unique = partial(ne, node) return count_items(takewhile(unique, applyfunc(graph.get, node))) + 1
def test_applyfunc_failure1(): with pytest.raises(TypeError): list(getitem(applyfunc(lambda x: x**T(2), T('a')), stop=3))
def test_applyfunc_pickle1(protocol): apf = applyfunc(iteration_utilities.square, T(2)) assert next(apf) == T(4) x = pickle.dumps(apf, protocol=protocol) assert next(pickle.loads(x)) == T(16)
def test_applyfunc_copy1(): iterator_copy(applyfunc(lambda x: x**T(2), T(2)))
def test_applyfunc_failure2(): # Too few arguments with pytest.raises(TypeError): applyfunc(bool)
def test_applyfunc_attributes1(): it = applyfunc(iteration_utilities.square, 2) assert it.func is iteration_utilities.square assert it.current == 2