def save(): print "Saving..." with open(config_file, "w") as file: config.write(file) print "Saved!" save_button.text = "Saved!" def reset_save_button(): save_button.text = "Save" utils.at(2, reset_save_button)
def generate(): print "Generating..." with open(output_file, "w") as file: file.write('xkb_symbols "' + output_name + '"\n{\n') file.write(' name[Group1] = "' + output_desc + ' - 1";\n') file.write(' name[Group2] = "' + output_desc + ' - 2";\n') for row_name, _, _, keys in KEY_ROWS: for index in range(keys): keyname = row_name + "-" + str(index) output_key = get_output_key(row_name, index) file.write(" key " + output_key + " { [ ") file.write(generate_key_range(keyname, 0, 4)) file.write(" ], [], [ ") file.write(generate_key_range(keyname, 4, 8)) file.write(" ] };\n") file.write("};\n") print "Generated!" generate_button.text = "Generated!" def reset_generate_button(): generate_button.text = "Generate" utils.at(2, reset_generate_button)
parse = compose(list, cmap(int), invoker('split', ',')) # runs Intcode several times by piping their input/output with [phase[index], previousOutput] def runSequence(sequence, intcode, endCondition, startSignal=0): runners = [Runner(iter([phase])) for phase in sequence] runnerIterators = [runner.output_iterator(intcode) for runner in runners] # pipe last signal to current runner's input and add its next output signal to signals def step(signals, index): runners[index].feed(signals[-1]) signal = next(runnerIterators[index], None) return signals + [signal], (index + 1) % len(runners) return reduceUntil(endCondition, unpack(step), ([startSignal], 0))[0] oneLoop = unpack(lambda outputs, index: index == 0 and len(outputs) > 1) noMoreValues = unpack(lambda outputs, index: outputs[-1] is None) # -1 to get last in part A; -2 to get last in part B, since B stops on last = None (no more values) one = compose( max, cmap(at(-1)), lambda intcode: [ runSequence(sequence, intcode, oneLoop) for sequence in permutations(range(0, 5)) ], parse) two = compose( max, cmap(at(-2)), lambda intcode: [ runSequence(sequence, intcode, noMoreValues) for sequence in permutations(range(5, 10)) ], parse)
digitize = lambda n: abs(n) % 10 # we can see the second half of the sequence is just accumulating up the second half of the digits, starting from the end phase_second_half = compose(list, reversed, list, cmap(digitize), accumulate, reversed) # calculate phase by doing the regular computation for the first half, and the "optimized" computation for the second def phase_full(sequence): length = len(sequence) value_at = lambda index: sum(sequence[ j] * factor for factor in [-1, 1] for j in takewhile( lambda j: j < length, positions(PATTERN.index(factor), index + 1))) first_half = [digitize(value_at(index)) for index in range(0, length // 2)] second_half = phase_second_half(sequence[length // 2:]) return first_half + second_half toSequence = compose(list, cmap(int), list, str) toString = compose(partial(''.join), cmap(str)) find_subsequence = lambda index_slice, repeat_factor: lambda sequence: ( sequence * repeat_factor)[(int(toString(sequence[index_slice]))):] # for part two, we see that the part of the sequence the problem asks us to show belong to the second half of the sequence. since the second half can be # computed in linear time and does not require knowing the first half, we just trim it at the start and apply phase_second_half instead of phase_full one = compose(toString, at(slice(0, 8)), next, partial(skip, 100), partial(iterate, phase_full), toSequence) two = compose(toString, at(slice(0, 8)), next, partial(skip, 100), partial(iterate, phase_second_half), find_subsequence(slice(0, 7), 10000), toSequence)
from utils import cmap, compose, invoker, at, attr from functools import partial, reduce from itertools import permutations from aoc.intcode import Runner parse = compose(list, cmap(int), invoker('split', ',')) def solve(input, intcode): runner = Runner(iter(input)) runner.run(intcode) return intcode, runner one = compose(at(-1), attr('output'), at(1), partial(solve, [1]), parse) two = compose(attr('output'), at(1), partial(solve, [2]), parse)
# assumes that wire crossing only happens 1 point at a time (i.e. segments in the same line do not intersect, only perpendicular segments do) isWithinRange = lambda n, range: range[0] <= n <= range[1] or range[0] >= n >= range[1] segmentsCross = lambda a, b: isWithinRange(b[0].x, [a[0].x, a[1].x]) and isWithinRange(a[0].y, [b[0].y, b[1].y]) segmentIntersection = lambda s1, s2: next((Point((b[0].x, a[0].y)) for a, b in permutations([s1, s2]) if segmentsCross(a, b)), None) # finds the lines of each wire and checks if any pair of lines from different wires intersect # returns tuples of the form (segment1, segment2, intersection) findIntersections = compose( partial(filter, unpack(lambda a, b, intersection: intersection is not None)), lambda segments: ((a, b, segmentIntersection(a, b)) for a, b in product(segments[0], segments[1])), ) # hydrates Points with their travel cost def addCosts(segments): current = 0 for (a, b) in segments: a.cost = current b.cost = current + a.manhattan(b) current = b.cost return segments # find intersections, sort by specified criteria, skip (0, 0) and return the score of the first intersection solve = lambda criteria: compose(criteria, at(1), partial(sorted, key=criteria), findIntersections) # criteria for parts one and two distanceToOrigin = unpack(lambda a, b, intersection: intersection.manhattan(CENTER)) travelCost = unpack(lambda a, b, intersection: a[0].cost + a[0].manhattan(intersection) + b[0].cost + b[0].manhattan(intersection)) one = compose(solve(distanceToOrigin), list, cmap(trace), parseAll) two = compose(solve(travelCost), list, cmap(addCosts), cmap(trace), parseAll)
from utils import cmap, compose, invoker, at, unpack from functools import partial from itertools import product from aoc.intcode import Runner N = 100 TARGET = 19690720 parse = compose(list, cmap(int), invoker('split', ',')) runner = Runner() run = lambda intcode: runner.run(intcode) alarm = lambda noun, verb: lambda intcode: intcode[:1] + [noun, verb ] + intcode[3:] solve = lambda noun, verb: compose(at(0), run, alarm(noun, verb)) findNounVerb = lambda target, intcode: next( (noun, verb) for noun, verb in product(range(N), range(N)) if solve(noun, verb)(intcode) == target) one = compose(solve(12, 2), parse) two = compose(unpack(lambda a, b: a * 100 + b), partial(findNounVerb, TARGET), parse)
elif turn == Robot.RIGHT: return Point((b, -a)) raise "Invalid turn" parse = compose(list, cmap(int), invoker('split', ',')) def solve(intcode, grid): robot = Robot(Runner()) robot.paint_all(intcode, grid) return grid, robot makeGrid = lambda defaults={}: defaultdict(lambda: BLACK, defaults) def display(grid): xs = sorted([p[0] for p, color in grid.items() if color == WHITE]) ys = sorted([p[1] for p, color in grid.items() if color == WHITE]) paintWhite = lambda color: color if color == WHITE else ' ' # for some reason we need to flip it vertically for it to display properly return '\n'.join(''.join( paintWhite(grid[(i, j)]) for i in range(xs[0], xs[-1] + 1)) for j in range(ys[-1], ys[0] - 1, -1)) one = compose(len, attr('painted'), at(1), unpack(solve), lambda intcode: (intcode, makeGrid()), parse) two = compose(display, at(0), unpack(solve), lambda intcode: (intcode, makeGrid({(0, 0): WHITE})), parse)