haro87
: haro87
haro87 |
This solution is written in Python. It is the solution for becoming a team member of the aoc-2019 community.
This solution is written in Python. It is the solution for the first day of AoC: The Tyranny of the Rocket Equation
The solution for the first part is pretty simple.
The function calculate_fuel_requirement
calculates
the required fuel based on the given mass.
The solution for the second part is a bit more complicated.
The function calculate_fuel_requirement_plus
calculates
the required fuel based on the given mass of the required fuel.
Recursion is the hint
you need.
import math
def calculate_fuel_requirement(mass):
"""Calculates the fuel requirement
based on the given mass. (Part 1)
Parameters:
mass (int): mass of the module
Returns:
int:Fuel required
"""
return math.floor(mass / 3) - 2
def calculate_fuel_requirement_plus(fuel):
"""Calculates the fuel requirement
based on the given fuel mass. (Part 2)
Parameters:
fuel (int): mass of the fuel
Returns:
int:Additional fuel required
"""
add = math.floor(fuel / 3) - 2
if add > 0:
return add + calculate_fuel_requirement_plus(add)
else:
return 0
with open("input.txt", "r") as masses:
fuel = 0
fueladd = 0
for mass in masses:
mfuel = calculate_fuel_requirement(int(mass))
fuel = fuel + mfuel
fueladd = fueladd + calculate_fuel_requirement_plus(mfuel)
print('Fuel required: {0}'.format(str(fuel)))
print('Fuel required based on fuel: {0}'.format(str(fueladd)))
print('Fuel required total: {0}'.format(str(fuel + fueladd)))
This solution is written in Python. It is the solution for the second day of AoC: 1202 Program Alarm
The solution for the first part consists of translating the input values and executing them. Attention: you need to operate on the whole data set.
The solution for the second part is basically a brute force approach to find the right noun and verb.
import random
from enterprise import MontgomeryScott as Scotty
scotty = Scotty()
def part_one():
with open('input.txt', "r") as commands:
trans = scotty.translate(commands.read())
res = scotty.execute(trans)
print('Part one, Scotty says: {0}'.format(res[0]))
def part_two():
with open('input.txt', "r") as commands:
orig = scotty.translate(commands.read())
res = 0
while res != 19690720:
noun = random.randint(0, 99)
verb = random.randint(0, 99)
program = orig.copy()
program[1] = noun
program[2] = verb
res = scotty.execute(program)[0]
print('Part two, Scotty says: {0}'.format(100 * noun + verb))
part_one()
part_two()
This solution is written in Python. It is the solution for the third day of AoC: Crossed Wires
This was the hardest puzzle for me up until now. No tests
this time due to some other priorities. :-(
You can run the solution by python solution.py
from enterprise import PavelChekov as Chekov
chekov = Chekov()
with open('input.txt', "r") as commands:
commands1, commands2 = commands.read().splitlines()
instructions1 = chekov.wire_up(commands1)
instructions2 = chekov.wire_up(commands2)
plan1 = chekov.wire_points(instructions1)
plan2 = chekov.wire_points(instructions2)
res1 = chekov.wire_cross(plan1, plan2)
print('Part one, Chekov says: {0}'.format(res1))
res2 = chekov.wire_intersect(plan1, plan2)
print('Part two, Chekov says: {0}'.format(res2))
This solution is written in Python. It is the solution for the fourth day of AoC: Secure Container
The solution for the first part was achieved by iterating over each position in a 6 digit code and subtracting the two adjacent values. If the value is < 0 then we had an decrease which would violate the rules. Furthermore we needed to check whether there is at least one occurance of matching adjacent positions. The calculation is the same as for the first one but having a 0 as result of that calculation indicates matching positions.
The solution for the second part was achieved by counting the occurances of values in the code and checking if there was at least one count of exactly two matching values.
The solution can be run by python solution.py
:
import random
from enterprise import NyotaUhura as Uhura
uhura = Uhura()
START = 240920
END = 789857
codes = uhura.valid_no_decrease(START, END)
codes = uhura.valid_same(codes)
print('Part one, Uhura says: {0}'.format(len(codes)))
codes = uhura.valid_larger_group(codes)
print('Part two, Uhura says: {0}'.format(len(codes)))
The actual methods are in a separate class:
import collections
class NyotaUhura:
def valid_no_decrease(self, start, end):
validcodes = []
for code in range(start, end):
code = str(code)
decrease = False
for pos in range(0, len(code)-1):
value1 = int(code[pos])
value2 = int(code[pos+1])
calc = value2 - value1
if calc < 0:
decrease = True
if not decrease:
validcodes.append(code)
return validcodes
def valid_same(self, codes):
validcodes = []
for code in codes:
same = False
for pos in range(0, len(code)-1):
value1 = int(code[pos])
value2 = int(code[pos+1])
calc = value2 - value1
if calc == 0:
same = True
if same:
validcodes.append(code)
return validcodes
def valid_larger_group(self, codes):
validcodes = []
for code in codes:
c=collections.Counter(code)
large = False
for count in c.values():
count = int(count)
if count == 2:
large = True
if large:
validcodes.append(code)
return validcodes
Test cases are derived from the puzzle description and
can be run by pytest enterprise_test.py
import pytest
from unittest import TestCase
from enterprise import NyotaUhura as Uhura
class Test_Enterprise(TestCase):
def test_no_decrease_one(self):
uhura = Uhura()
res = uhura.valid_no_decrease(111111, 111112)
self.assertEqual(res, ["111111"])
def test_no_decrease_two(self):
uhura = Uhura()
res = uhura.valid_no_decrease(223450, 223451)
self.assertEqual(res, [])
def test_same_one(self):
uhura = Uhura()
res = uhura.valid_same(["123789"])
self.assertEqual(res, [])
def test_large_one(self):
uhura = Uhura()
res = uhura.valid_larger_group(["112233"])
self.assertEqual(res, ["112233"])
def test_large_two(self):
uhura = Uhura()
res = uhura.valid_larger_group(["123444"])
self.assertEqual(res, [])
def test_large_three(self):
uhura = Uhura()
res = uhura.valid_larger_group(["111122"])
self.assertEqual(res, ["111122"])
This solution is written in Python. It is the solution for the fifth day of AoC: Sunny with a Chance of Asteroids
The solution for the fifth day is not that hard but it still took me some time. Structure is key and I learned some new Python features along the way.
The solution can be run by python solution.py
:
import random
import os
from enterprise import MontgomeryScott as Scotty
cwd = os.getcwd()
ifile = cwd + "/input.txt"
with open(ifile, "r") as commands:
#Part one
scotty = Scotty(input=1)
trans = scotty.translate(commands.read())
res = scotty.execute(trans.copy())
print("Scotty says the solution for part one is: {0}".format(res[-1]))
#Part two
scotty = Scotty(input=5)
res = scotty.execute(trans.copy())
print("Scotty says the solution for part two is: {0}".format(res[-1]))
The actual methods are in a separate class:
import logging
from enum import Enum
logging.basicConfig(level=logging.ERROR)
class Instruction(Enum):
ADD = 1
MULTIPLY = 2
STORE = 3
OUTPUT = 4
JUMP_IF_TRUE = 5
JUMP_IF_FALSE = 6
LESS_THAN = 7
EQUALS = 8
class Mode(Enum):
POSITION = 0
IMMEDIATE = 1
class Command:
inst = 0
modes = [].copy()
def __init__(self, opcode):
self.inst = opcode // 10**0 % 10
del self.modes[:]
self.modes.append(opcode // 10**2 % 10)
self.modes.append(opcode // 10**3 % 10)
self.modes.append(opcode // 10**4 % 10)
def instruction(self):
return self.inst
def parameter_modes(self):
return self.modes
class MontgomeryScott:
def __init__(self, input):
self.input = input
def _add(self, one, two):
return one + two
def _multiply(self, one, two):
return one * two
def _store(self, value, add, program):
if add < len(program):
program[add] = value
else:
logging.error("ERROR -> Address: {0} out of bounds".format(add))
def _output(self, add, program):
if add < len(program):
return program[add]
else:
logging.error("ERROR -> Address: {0} out of bounds".format(add))
return None
def _get_parameters(self, count, command, program):
params = []
pos = count + 1
for mode in command.parameter_modes():
if command.instruction() > 4 and command.instruction() < 7 and len(params) == 2:
break
if mode == Mode.IMMEDIATE.value:
if pos < len(program):
params.append(program[pos])
else:
logging.error("ERROR -> Address: {0} out of bounds".format(pos))
if mode == Mode.POSITION.value:
if pos < len(program):
add = program[pos]
if len(params) == 2:
if add < len(program):
params.append(add)
else:
logging.error("ERROR -> Address: {0} out of bounds".format(add))
else:
if add < len(program):
params.append(program[add])
else:
logging.error("ERROR -> Address: {0} out of bounds".format(add))
else:
logging.error("ERROR -> Address: {0} out of bounds".format(pos))
pos = pos + 1
if command.instruction() > 2 and command.instruction() <= 4:
params = [params[0]]
logging.info("INFO -> Collected paramters: {0}".format(params))
return params
def translate(self, code):
trans = str(code).split(',')
trans = list(map(int, trans))
return trans
def execute(self, commands):
output = []
count = 0
while count <= len(commands):
c = commands[count]
if c == 99:
break
command = Command(c)
if command.instruction() < 1 or command.instruction() > 8:
count = count + 1
continue
logging.info("INFO -> Instruction: {0}".format(command.instruction()))
if (command.instruction() > 0 and command.instruction() < 3) or command.instruction() > 4:
params = self._get_parameters(count, command, commands)
logging.info("INFO -> Parameters: {0}".format(params))
if command.instruction() == Instruction.ADD.value:
if len(params) < 3:
logging.error("ERROR -> Not enough paramters for ADD at position {0}".format(count))
continue
self._store(self._add(params[0], params[1]), params[2], commands)
count = count + 4
elif command.instruction() == Instruction.MULTIPLY.value:
if len(params) < 3:
logging.error("ERROR -> Not enough paramters for MULTIPLY at position {0}".format(count))
continue
self._store(self._multiply(params[0], params[1]), params[2], commands)
count = count + 4
elif command.instruction() == Instruction.STORE.value:
self._store(self.input, commands[count + 1], commands)
count = count +2
elif command.instruction() == Instruction.OUTPUT.value:
out = self._output(commands[count + 1], commands)
output.append(out)
print("-->OUTPUT: {0}".format(out))
count = count + 2
elif command.instruction() == Instruction.JUMP_IF_TRUE.value:
if params[0] != 0:
count = params[1]
else:
count = count + 3
elif command.instruction() == Instruction.JUMP_IF_FALSE.value:
if params[0] == 0:
count = params[1]
else:
count = count + 3
elif command.instruction() == Instruction.LESS_THAN.value:
if params[0] < params [1]:
self._store(1, params[2], commands)
else:
self._store(0, params[2], commands)
count = count + 4
elif command.instruction() == Instruction.EQUALS.value:
if params[0] == params[1]:
self._store(1, params[2], commands)
else:
self._store(0, params[2], commands)
count = count + 4
else:
count = count + 1
return output
Test cases are derived from the puzzle description and
can be run by pytest enterprise_test.py
import pytest
from unittest import TestCase
from enterprise import MontgomeryScott as Scotty
class Test_Enterprise(TestCase):
def test_translate(self):
scotty = Scotty(input=1)
res = scotty.translate('3,0,4,0,99')
self.assertEqual(res, [3, 0, 4, 0, 99])
def test_execute_pos_equal_eight(self):
scotty = Scotty(input=8)
trans = scotty.translate('3,9,8,9,10,9,4,9,99,-1,8')
res = scotty.execute(trans)
self.assertEqual(res, [1])
def test_execute_pos_not_equal_eight(self):
scotty = Scotty(input=1)
trans = scotty.translate('3,9,8,9,10,9,4,9,99,-1,8')
res = scotty.execute(trans)
self.assertEqual(res, [0])
def test_execute_pos_less_than_eight(self):
scotty = Scotty(input=1)
trans = scotty.translate('3,9,7,9,10,9,4,9,99,-1,8')
res = scotty.execute(trans)
self.assertEqual(res, [1])
def test_execute_pos_more_than_eight(self):
scotty = Scotty(input=9)
trans = scotty.translate('3,9,7,9,10,9,4,9,99,-1,8')
res = scotty.execute(trans)
self.assertEqual(res, [0])
def test_execute_im_equal_eight(self):
scotty = Scotty(input=8)
trans = scotty.translate('3,3,1108,-1,8,3,4,3,99')
res = scotty.execute(trans)
self.assertEqual(res, [1])
def test_execute_im_not_equal_eight(self):
scotty = Scotty(input=1)
trans = scotty.translate('3,3,1108,-1,8,3,4,3,99')
res = scotty.execute(trans)
self.assertEqual(res, [0])
def test_execute_im_less_than_eight(self):
scotty = Scotty(input=1)
trans = scotty.translate('3,3,1107,-1,8,3,4,3,99')
res = scotty.execute(trans)
self.assertEqual(res, [1])
def test_execute_im_more_than_eight(self):
scotty = Scotty(input=9)
trans = scotty.translate('3,3,1107,-1,8,3,4,3,99')
res = scotty.execute(trans)
self.assertEqual(res, [0])