Solution to problem 5 part 1 in Python

This commit is contained in:
David Doblas Jiménez 2022-03-03 16:16:01 +01:00
parent 38ba226a7f
commit b06905b590

157
src/Year_2019/P5.py Normal file
View File

@ -0,0 +1,157 @@
# --- Day 5: Sunny with a Chance of Asteroids ---
# You're starting to sweat as the ship makes its way toward Mercury. The Elves
# suggest that you get the air conditioner working by upgrading your ship
# computer to support the Thermal Environment Supervision Terminal.
# The Thermal Environment Supervision Terminal (TEST) starts by running a
# diagnostic program (your puzzle input). The TEST diagnostic program will run
# on your existing Intcode computer after a few modifications:
# First, you'll need to add two new instructions:
# Opcode 3 takes a single integer as input and saves it to the position
# given by its only parameter. For example, the instruction 3,50 would take an
# input value and store it at address 50.
# Opcode 4 outputs the value of its only parameter. For example, the
# instruction 4,50 would output the value at address 50.
# Programs that use these instructions will come with documentation that
# explains what should be connected to the input and output. The program
# 3,0,4,0,99 outputs whatever it gets as input, then halts.
# Second, you'll need to add support for parameter modes:
# Each parameter of an instruction is handled based on its parameter mode.
# Right now, your ship computer already understands parameter mode 0, position
# mode, which causes the parameter to be interpreted as a position - if the
# parameter is 50, its value is the value stored at address 50 in memory.
# Until now, all parameters have been in position mode.
# Now, your ship computer will also need to handle parameters in mode 1,
# immediate mode. In immediate mode, a parameter is interpreted as a value -
# if the parameter is 50, its value is simply 50.
# Parameter modes are stored in the same value as the instruction's opcode.
# The opcode is a two-digit number based only on the ones and tens digit of the
# value, that is, the opcode is the rightmost two digits of the first value in
# an instruction. Parameter modes are single digits, one per parameter, read
# right-to-left from the opcode: the first parameter's mode is in the hundreds
# digit, the second parameter's mode is in the thousands digit, the third
# parameter's mode is in the ten-thousands digit, and so on. Any missing modes
# are 0.
# For example, consider the program 1002,4,3,4,33.
# The first instruction, 1002,4,3,4, is a multiply instruction - the rightmost
# two digits of the first value, 02, indicate opcode 2, multiplication. Then,
# going right to left, the parameter modes are 0 (hundreds digit), 1 (thousands
# digit), and 0 (ten-thousands digit, not present and therefore zero):
# ABCDE
# 1002
# DE - two-digit opcode, 02 == opcode 2
# C - mode of 1st parameter, 0 == position mode
# B - mode of 2nd parameter, 1 == immediate mode
# A - mode of 3rd parameter, 0 == position mode,
# omitted due to being a leading zero
# This instruction multiplies its first two parameters. The first parameter, 4
# in position mode, works like it did before - its value is the value stored at
# address 4 (33). The second parameter, 3 in immediate mode, simply has value
# 3. The result of this operation, 33 * 3 = 99, is written according to the
# third parameter, 4 in position mode, which also works like it did before -
# 99 is written to address 4.
# Parameters that an instruction writes to will never be in immediate mode.
# Finally, some notes:
# It is important to remember that the instruction pointer should increase
# by the number of values in the instruction after the instruction finishes.
# Because of the new instructions, this amount is no longer always 4.
# Integers can be negative: 1101,100,-1,4,0 is a valid program (find
# 100 + -1, store the result in position 4).
# The TEST diagnostic program will start by requesting from the user the ID of
# the system to test by running an input instruction - provide it 1, the ID for
# the ship's air conditioner unit.
# It will then perform a series of diagnostic tests confirming that various
# parts of the Intcode computer, like parameter modes, function correctly. For
# each test, it will run an output instruction indicating how far the result
# of the test was from the expected value, where 0 means the test was
# successful. Non-zero outputs mean that a function is not working correctly;
# check the instructions that were run before the output instruction to see
# which one failed.
# Finally, the program will output a diagnostic code and immediately halt. This
# final output isn't an error; an output followed immediately by a halt means
# the program finished. If all outputs were zero except the diagnostic code,
# the diagnostic program ran successfully.
# After providing 1 to the only input instruction and passing all the tests,
# what diagnostic code does the program produce?
with open("files/P5.txt") as f:
code = [int(number) for number in f.read().strip().split(",")]
# function to return a five-element array to represent the intcode
def intcodeArray(num: int) -> list[str]:
intcode: list[str] = list(str(num))
if len(intcode) < 5:
for i in range(5 - len(intcode)):
intcode.insert(0, "0")
for i in range(len(intcode)):
intcode[i] = int(intcode[i])
return intcode
def value(mode: int, position: int) -> int:
if mode == 0:
val = code[code[position]]
else:
val = code[position]
return val
def part_1() -> None:
pos = 0
while code[pos] != 99:
opcode: list[str] = intcodeArray(code[pos])
# add two values
if opcode[4] == 1:
i2 = pos + 1
i3 = pos + 2
o4 = code[pos + 3]
code[o4] = value(opcode[2], i2) + value(opcode[1], i3)
pos += 4
# multiply two values
elif opcode[4] == 2:
i2 = pos + 1
i3 = pos + 2
o4 = code[pos + 3]
code[o4] = value(opcode[2], i2) * value(opcode[1], i3)
pos += 4
# take an input value
elif opcode[4] == 3:
print("What is your input value?")
choice = input()
choice = int(choice)
if opcode[2] == 0:
code[code[pos + 1]] = choice
else:
code[pos + 1] = choice
pos += 2
# print an output value
elif opcode[4] == 4:
_value = value(opcode[2], pos + 1)
if _value != 0:
print(f"The diagnostic code is {_value}")
pos += 2
if __name__ == "__main__":
part_1()