lukas_grotz

7985033?s=40&v=4

lukas_grotz
GitHub: Transmitt0r

About me

Nothing here yet. Update your profile at /profiles/lukas_grotz.adoc

Day 00: python

Advent of Code 2019 hello world

Python

Hey, I’m participating for the first time this year. I’ll probably use python a lot, but also want to try go or rust.

Run the solution with python solution.py

print("Hello, world!")

Day 01: python

The Tyranny of the Rocket Equation

The solution for this puzzle is in python. It is the solution for the first day of AoC: The Tyranny of the Rocket Equation

I want to get more into test drive development, so this seems like a good opportunity to get some experience and play around with it!

Answers one and two

You can run the application by typign python3 solution.py. Run the tests with python3 -m unittest test_solution.py.

from typing import List
import math

def format_file(input_file) -> List[int]:
    new_list = []
    for row in input_file:
        new_list.append(int(row))
    return new_list

def calculate_fuel(all_modules: List[int], func) -> int:
    required_fuel = 0
    for module_mass in all_modules:
        fuel_required = func(module_mass)
        required_fuel += fuel_required
    return required_fuel

def solution_one(module_mass: int) -> int:
    return math.floor(module_mass / 3) - 2

def solution_two(module_mass: int) -> int:
    fuel_required = solution_one(module_mass)

    if fuel_required > 0:
        return fuel_required + solution_two(fuel_required)
    return 0

if __name__ == '__main__':
    with open('./puzzle_input.txt') as input_file:
        modules = format_file(input_file)

        fuel_one = calculate_fuel(modules, solution_one)
        print("Solution one with provided input parameters: %d" % fuel_one)

        fuel_two = calculate_fuel(modules, solution_two)
        print("Solution two with provided input parameters: %d" % fuel_two)

Day 02: python

1202 Program Alarm

The solution for this puzzle is in python. It is the solution for the first day of AoC: 1202 Program Alarm

I want to get more into test drive development, so this seems like a good opportunity to get some experience and play around with it!

Answers one and two

You can run the application by typign python3 solution.py. Run the tests with python3 -m unittest test_solution.py.

from typing import List

class StopCode(Exception):
   pass

class IntCode:
    def __init__(self, input_list: List[int] = []):
        self.input_codes = input_list

    @classmethod
    def read_file(cls, file_path: str) -> 'IntCode':
        with open(file_path) as input_file:
            content = input_file.readlines()
            op_codes = []
            for line in content:
                elements = [ int(x) for x in line.split(',')]
                op_codes.extend(elements)
        int_code = IntCode(op_codes)
        return int_code

    def execute_step(self, op_pos: int) -> None:
        code = self.input_codes[op_pos]
        if code not in [1, 2, 99]:
            raise ValueError('Invalid Code!')

        func =self.parse_code(code)
        if code == 99:
            func()

        lhs = self.input_codes[self.input_codes[op_pos+1]]
        rhs = self.input_codes[self.input_codes[op_pos+2]]
        ret_pos = self.input_codes[op_pos+3]
        self.input_codes[ret_pos] = func(lhs, rhs)


    @staticmethod
    def parse_code(op_code: int):
        def add(lhs: int, rhs: int) -> int:
            return lhs + rhs

        def multiply(lhs: int, rhs: int) -> int:
            return lhs * rhs

        def stop(*args) -> None:
            raise StopCode()

        codes = {
            1: add,
            2: multiply,
            99: stop
        }

        return codes[op_code]

    def execute_all(self) -> List[int]:
        try:
            for op in range(0, len(self.input_codes), 4):
                self.execute_step(op)
        except StopCode:
            # hit 99
            pass
        return self.input_codes

if __name__ == '__main__':
    codes = IntCode.read_file('/workspace/aoc-2019/day02/python/lukas_grotz/input.txt')
    codes.input_codes[1] = 12
    codes.input_codes[2] = 2
    codes.execute_all()
    print("Solution for one: %d" % codes.input_codes[0])

    required_output = 19690720
    for first_input in range(100):
        for second_input in range(100):
            codes = IntCode.read_file('/workspace/aoc-2019/day02/python/lukas_grotz/input.txt')
            codes.input_codes[1] = first_input
            codes.input_codes[2] = second_input
            try:
                codes.execute_all()
            except ValueError:
                # invalid code found
                pass
            if required_output == codes.input_codes[0]:
                print("Solution for two: noun=%d verb=%d" % (first_input, second_input))
                print("Solution is: %d" % (100 * first_input + second_input))

Day 03: python

Crossed Wires

The solution for this puzzle is in python. It is the solution for the first day of AoC: Crossed Wires

I want to get more into test drive development, so this seems like a good opportunity to get some experience and play around with it!

Answers one and two

You can run the application by typign python3 solution.py. Run the tests with python3 -m unittest test_solution.py.

from typing import List, Dict


class Vector:
    def __init__(self, x: int, y: int):
        super().__init__()
        self.x = x
        self.y = y

    def __add__(self, other: 'Vector') -> 'Vector':
        x_add = self.x + other.x
        y_add = self.y + other.y
        return Vector(x_add, y_add)

    def __sub__(self, other: 'Vector') -> 'Vecotr':
        x_sub = self.x - other.x
        y_sub = self.y - other.y
        return Vector(x_sub, y_sub)

    def __eq__(self, other: 'Vector') -> bool:
        return self.x == other.x and self.y == other.y

    def __hash__(self):
        return hash((self.x, self.y))

    def __str__(self):
        return str({'x': self.x, 'y': self.y})

    def manhatten_distance_to(self, other: 'Vector') -> int:
        return abs(self.x) + abs(other.x) + abs(self.y) + abs(other.y)


class Operation:
    delta_x = {'L': -1, 'R': 1, 'U': 0, 'D': 0}
    delta_y = {'L': 0, 'R': 0, 'U': 1, 'D': -1}

    def __init__(self, operation: str, distance: int):
        super().__init__()
        self.type = operation
        self.distance = distance

    def to_points(self, start: Vector, start_steps: int):
        points = {}
        additonal_lengt = 0
        for i in range(self.distance+1):
            new_point = Vector(
                start.x+i*self.delta_x[self.type], start.y+i*self.delta_y[self.type])
            points[new_point] = i + start_steps
            additonal_lengt = i
        return additonal_lengt+start_steps, new_point, points


class Wire:
    def __init__(self, operations: List[Operation]):
        super().__init__()
        self.operations = operations
        self.points = {}
        self.compute_path()

    def compute_path(self):
        segments = {}
        start_steps = 0
        start_vector = Vector(0,0)
        for operation in self.operations:
            start_steps, start_vector, points = operation.to_points(start_vector, start_steps)
            segments.update(points)
        self.points = segments

    @classmethod
    def find_intersections(cls, wires: List['Wire']):
        wire_1 = set(wires[0].points.keys())
        wire_1.discard(Vector(0, 0))
        wire_2 = set(wires[1].points.keys())
        intersection_set = wire_1.intersection(wire_2)
        intersections = {}
        for point in intersection_set:
            intersections[point] = wires[0].points[point] + \
                wires[1].points[point]
        return intersections

    @staticmethod
    def get_closest_intersection_distance(intersections) -> int:
        distances = [intersection.manhatten_distance_to(Vector(0,0)) for intersection in intersections]
        return min(distances)

    @classmethod
    def find_intersections_time_sensitive(cls, wires: List['Wire']):
        intersections = cls.find_intersections(wires)
        distances = [wires[0].points[intersection] + wires[1].points[intersection]
                     for intersection in intersections]
        return min(distances)


def parse_file(path: str) -> List[Wire]:
    with open(path) as _file:
        content = _file.readlines()
        wires = []
        for unparsed_wire in content:
            wire = [Operation(op[0], int(op[1:])) for op in unparsed_wire.split(',')]
            wires.append(Wire(wire))
        return wires


if __name__ == '__main__':
    wires = parse_file('input.txt')
    intersections = Wire.find_intersections(wires)
    distance = Wire.get_closest_intersection_distance(intersections)
    print(distance)
    distance_2 = Wire.find_intersections_time_sensitive(wires)
    print(distance_2)

Day 04: python

Secure Container

The solution for this puzzle is in python. It is the solution for the first day of AoC: Secure Container

I want to get more into test drive development, so this seems like a good opportunity to get some experience and play around with it!

Answers one and two

You can run the application by typign python3 solution.py. Run the tests with python3 -m unittest test_solution.py.

lower_bound = '236491'
upper_bound = '713787'


# first formulate password rules
def test_increase(password: str) -> bool:
    return password == ''.join(sorted(password))

def test_length(password: str) -> bool:
    return len(password) == 6

def test_range(password: str) -> bool:
    return int(password) in range(int(lower_bound), int(upper_bound)+1)

def test_adjacency(password: str) -> bool:
    pw_list = list(password)
    last_digit = password[0]
    matches = {}
    digit_counter = 1
    for digit in pw_list[1:len(pw_list)]:
        if digit == last_digit:
            digit_counter += 1
            matches[digit] = digit_counter
        else:
            digit_counter = 1
        last_digit = digit

    if len(matches) == 0:
        return False
    result = any(value == 2 for value in matches.values())
    return result

if __name__ == '__main__':
    possible_combinations = [str(i).zfill(6) for i in range(int(lower_bound), int(upper_bound)+1)]

    solution_sorted = list(filter(test_increase, possible_combinations))
    solution_adjacent = list(filter(test_adjacency, solution_sorted))

    print(len(solution_adjacent))

Day 05: python

Sunny with a Chance of Asteroids

The solution for this puzzle is in python. It is the solution for the fifth day of AoC: Sunny with a Chance of Asteroids

I want to get more into test drive development, so this seems like a good opportunity to get some experience and play around with it!

Answers one and two

You can run the application by typign python3 solution.py.

from typing import List
from int_code import IntCodeMachine, Instruction, StopCode

# Instruction functions need to follow the pattern def func(...) -> result

def add(lhs: int, rhs: int):
    return lhs + rhs

def mul(lhs: int, rhs: int):
    return lhs * rhs

def stop() -> None:
    raise StopCode()

def get_input():
    print('Enter an integer:')
    my_input = int(input())
    return my_input

def output(number: int) -> None:
    print(number)

def jump_if_true(param: int, target: int):
    if param != 0:
        return target, True
    return target, False

def jump_if_false(param: int, target: int):
    if param == 0:
        return target, True
    return target, False

def less_than(lhs: int, rhs: int):
    return int(lhs < rhs)

def equals(lhs: int, rhs: int):
    return int(lhs == rhs)

if __name__ == '__main__':
    op_codes = []
    with open('input.txt') as input_file:
        content = input_file.readlines()
        for line in content:
            elements = [ int(x) for x in line.split(',')]
            op_codes.extend(elements)

    code_machine = IntCodeMachine(op_codes)
    code_machine.instructions[1] = Instruction(add, 3, True)
    code_machine.instructions[2] = Instruction(mul, 3, True)
    code_machine.instructions[3] = Instruction(get_input, 1, True)
    code_machine.instructions[4] = Instruction(output, 1, False)
    code_machine.instructions[5] = Instruction(jump_if_true, 2, False, True)
    code_machine.instructions[6] = Instruction(jump_if_false, 2, False, True)
    code_machine.instructions[7] = Instruction(less_than, 3, True)
    code_machine.instructions[8] = Instruction(equals, 3, True)
    code_machine.instructions[99] = Instruction(stop, 0, False)

    code_machine.execute_all()