diff --git a/src/Year_2019/P5.py b/src/Year_2019/P5.py new file mode 100644 index 0000000..12c10e2 --- /dev/null +++ b/src/Year_2019/P5.py @@ -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()