DEV Community

Discussion on: Advent of Code 2019 Solution Megathread - Day 9: Sensor Boost

Collapse
 
devchad profile image
Chad S

Hi, a (very wordy) Python solution using a generator function.

def compute_str(program_str, verbose=False):
    program_str = program_str + ',0' * 1000  # Add additional memory
    program = program_str.split(',')
    program = [int(opcode) for opcode in program]
    return compute(program, verbose=verbose)

# Returns opcode_str; paramter modes; and number to increment instruction_pointer by
def parse_first(int_value):
    map_opcode_to_param_num = {'99': 0, '01': 3, '02': 3, '03': 1, '04': 1, '05': 2, '06': 2, '07': 3, '08': 3, '09': 1}
    max_value_str_len = max(map_opcode_to_param_num.values()) + 2  # Two len opcode

    value_str = str(int_value)
    value_str = value_str.zfill(max_value_str_len)  # Pad with leading zeros

    opcode_str = value_str[-2:]

    parameter_modes = value_str[:-2]

    if opcode_str not in map_opcode_to_param_num.keys():
        print(f'ERROR - invalid opcode: {opcode_str}')

    parameter_mode_map = {'0': 'position', '1': 'immediate', '2': 'relative'}
    parameter_modes = [parameter_mode_map[parameter_mode] for parameter_mode in parameter_modes]
    parameter_modes = [] if opcode_str == '99' else parameter_modes[-map_opcode_to_param_num[opcode_str]:]  # Reduce to correct num of param modes for opcode
    parameter_modes = parameter_modes[::-1]  # Reverse mode order

    instruction_pointer_increment = map_opcode_to_param_num[opcode_str] + 1

    return opcode_str, parameter_modes, instruction_pointer_increment


def compute(program, verbose=False):
    program = list(program)

    instruction_pointer = 0
    relative_base = 0

    while instruction_pointer < len(program):
        int_value = program[instruction_pointer]
        opcode_str, parameter_modes, instruction_pointer_increment = parse_first(int_value)
        if verbose:
            print(f'Processing: {opcode_str}')

        if opcode_str == '99':
            print('Exiting (99 code)...')
            return program

        elif opcode_str == '01':
            # Add
            param_mode_1, param_mode_2, param_mode_3 = parameter_modes

            parameter_1 = program[instruction_pointer + 1]
            if param_mode_1 == 'position':
                operand_1 = program[parameter_1] 
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1] 
            else:
                print(f'ERROR - invalid parameter mode: {parameter_1}')

            parameter_2 = program[instruction_pointer + 2]
            if param_mode_2 == 'position':
                operand_2 = program[parameter_2] 
            elif param_mode_2 == 'immediate':
                operand_2 = parameter_2
            elif param_mode_2 == 'relative':
                operand_2 = program[relative_base + parameter_2] 
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_2}')

            parameter_3 = program[instruction_pointer + 3]
            if param_mode_3 == 'position':  # Note: since writing to memory, cannot be immediate
                output_address = parameter_3
            elif param_mode_3 == 'relative':
                output_address = relative_base + parameter_3
            else:
                print('ERROR - immediate mode for writing to memory')

            # Perform op
            result = operand_1 + operand_2
            program[output_address] = result
            instruction_pointer += instruction_pointer_increment


        elif opcode_str == '02':
            # Multiply
            param_mode_1, param_mode_2, param_mode_3 = parameter_modes

            parameter_1 = program[instruction_pointer + 1]
            if param_mode_1 == 'position':
                operand_1 = program[parameter_1] 
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1] 
            else:
                print(f'ERROR - invalid parameter mode: {parameter_1}')

            parameter_2 = program[instruction_pointer + 2]
            if param_mode_2 == 'position':
                operand_2 = program[parameter_2] 
            elif param_mode_2 == 'immediate':
                operand_2 = parameter_2
            elif param_mode_2 == 'relative':
                operand_2 = program[relative_base + parameter_2] 
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_2}')

            parameter_3 = program[instruction_pointer + 3]
            if param_mode_3 == 'position':  # Note: since writing to memory, cannot be immediate
                output_address = parameter_3
            elif param_mode_3 == 'relative':
                output_address = relative_base + parameter_3
            else:
                print('ERROR - immediate mode while writing to memory')

            # Perform op
            result = operand_1 * operand_2
            program[output_address] = result
            instruction_pointer += instruction_pointer_increment

        elif opcode_str == '03':   
            # Input
            param_mode_1 = parameter_modes[0]

            parameter_1 = program[instruction_pointer + 1]
            if param_mode_1 == 'position':
                output_address = parameter_1
            elif param_mode_1 == 'relative':
                output_address = relative_base + parameter_1
            else:
                print('ERROR - immediate mode while writing to memory')

            user_input = None
            # Keep looping while user_input is None
            while user_input is None:
                user_input = (yield 'input')
            if verbose:
                print(f'Input Received: {user_input}')

            program[output_address] = user_input
            instruction_pointer += instruction_pointer_increment

        elif opcode_str == '04':
            # Output
            param_mode_1 = parameter_modes[0]
            parameter_1 = program[instruction_pointer + 1]
            read_address = parameter_1

            if param_mode_1 == 'position':
                output = program[read_address]
            elif param_mode_1 == 'immediate':
                output = read_address
            elif param_mode_1 == 'relative':
                output = program[relative_base + read_address]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_1}')

            if verbose:
                print(f'Output: {output}')
            yield output
            instruction_pointer += instruction_pointer_increment

        elif opcode_str == '05':
            # Jump if True
            param_mode_1, param_mode_2 = parameter_modes
            parameter_1 = program[instruction_pointer + 1]
            parameter_2 = program[instruction_pointer + 2]

            if param_mode_1 == 'position':
                operand_1 = program[parameter_1]
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_1}')

            if param_mode_2 == 'position':
                operand_2 = program[parameter_2]
            elif param_mode_2 == 'immediate':
                operand_2 = parameter_2
            elif param_mode_2 == 'relative':
                operand_2 = program[relative_base + parameter_2]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_2}')

            if operand_1 != 0:
                instruction_pointer = operand_2
            else:
                instruction_pointer += instruction_pointer_increment

        elif opcode_str == '06':
            # Jump if False
            param_mode_1, param_mode_2 = parameter_modes
            parameter_1 = program[instruction_pointer + 1]
            parameter_2 = program[instruction_pointer + 2]

            if param_mode_1 == 'position':
                operand_1 = program[parameter_1]
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_1}')

            if param_mode_2 == 'position':
                operand_2 = program[parameter_2]
            elif param_mode_2 == 'immediate':
                operand_2 = parameter_2
            elif param_mode_2 == 'relative':
                operand_2 = program[relative_base + parameter_2]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_2}')

            if operand_1 == 0:
                instruction_pointer = operand_2
            else:
                instruction_pointer += instruction_pointer_increment

        elif opcode_str == '07':
            # Less than
            param_mode_1, param_mode_2, param_mode_3 = parameter_modes
            parameter_1 = program[instruction_pointer + 1]
            parameter_2 = program[instruction_pointer + 2]

            if param_mode_1 == 'position':
                operand_1 = program[parameter_1]
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_1}')

            if param_mode_2 == 'position':
                operand_2 = program[parameter_2]
            elif param_mode_2 == 'immediate':
                operand_2 = parameter_2
            elif param_mode_2 == 'relative':
                operand_2 = program[relative_base + parameter_2]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_2}')

            parameter_3 = program[instruction_pointer + 3]
            output_address = parameter_3
            if param_mode_3 == 'position':
                program[output_address] = 1 if operand_1 < operand_2 else 0
            elif param_mode_3 == 'relative':
                program[relative_base + output_address] = 1 if operand_1 < operand_2 else 0
            else:
                print('ERROR - immediate mode while writing to memory')

            instruction_pointer += instruction_pointer_increment

        elif opcode_str == '08':
            # Equals
            param_mode_1, param_mode_2, param_mode_3 = parameter_modes
            parameter_1 = program[instruction_pointer + 1]
            parameter_2 = program[instruction_pointer + 2]

            if param_mode_1 == 'position':
                operand_1 = program[parameter_1]
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_1}')

            if param_mode_2 == 'position':
                operand_2 = program[parameter_2]
            elif param_mode_2 == 'immediate':
                operand_2 = parameter_2
            elif param_mode_2 == 'relative':
                operand_2 = program[relative_base + parameter_2]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_2}')

            parameter_3 = program[instruction_pointer + 3]
            output_address = parameter_3

            if param_mode_3 == 'position':
                program[output_address] = 1 if operand_1 == operand_2 else 0
            elif param_mode_3 == 'relative':
                program[relative_base + output_address] = 1 if operand_1 == operand_2 else 0
            else:
                print('ERROR - immediate mode while writing to memory')

            instruction_pointer += instruction_pointer_increment

        elif opcode_str == '09':
            # Relative base offset instruction
            param_mode_1 = parameter_modes[0]

            parameter_1 = program[instruction_pointer + 1]
            if param_mode_1 == 'position':
                operand_1 = program[parameter_1]
            elif param_mode_1 == 'immediate':
                operand_1 = parameter_1
            elif param_mode_1 == 'relative':
                operand_1 = program[relative_base + parameter_1]
            else:
                print(f'ERROR - invalid parameter mode: {param_mode_1}')

            relative_base = relative_base + operand_1
            instruction_pointer += instruction_pointer_increment

        else:
            print('ERROR - invalid opcode')
            return

    print('End of program without 99 code')
    return

Collapse
 
devchad profile image
Chad S • Edited

Getting output is done by running:

run = compute_str(puzzle_input)
next(run)

then...

Part 1

print(run.send(1))

or Part 2:

print(run.send(2))
Collapse
 
devchad profile image
Chad S

I'll be posting my other attempts to: github.com/devChad/advent_of_code

Collapse
 
jyothi9999 profile image
jyothi9999

"""
Hi,
now i am learning python
i also wrote a program in very basic
but i did not get the answer
can u give me any hint
"""

import numpy as np

f = open("input9","r") # file opening
code = f.read() + ',0' * 1000 # for reading files with commas(,) as list
nList = code.split(',')
f.close() # file closing

print(nList)

for i in range(0, len(nList)): # converting elements of List(strings) into integers
nList[i] = int(nList[i])

print(len(nList))

def get_digit(number, n):
return number // 10**n % 10

def intcode(nList,in1):
List = nList.copy()
for i,each in enumerate(nList):
List[i] = int(each)
i = 0
rb = 0

while i < len(nList):
    n = List[i]
    op = 10 * get_digit(n, 1) + get_digit(n, 0)
    p1_mode = get_digit(n, 2)
    p2_mode = get_digit(n, 3)
    p3_mode = get_digit(n, 1)

    if op == 1 or op == 2 or op == 7 or op == 8:
        int1 = int2 = position = p1 = p2 = 0
        int1 = List[i + 1]
        int2 = List[i + 2]
        int3 = List[i + 3]

        if p1_mode == 1:
            p1 = int1
        elif p1_mode == 0 and int1 >= 0 :
            p1 = List[int1]
        elif p1_mode == 2 and int1 + rb >= 0:
            p1 = List[int1 + rb]
        else:
            print(f'ERROR - invalid parameter mode: {p1_mode}')

        if p2_mode == 1:
            p2 = int2
        elif p2_mode == 0 and int1 >= 0:
            p2 = List[int2]
        elif p2_mode == 2 and int2 + rb >= 0:
            p2 = List[int2 + rb]
        else:
            print(f'ERROR - invalid parameter mode: {p2_mode}')

        if p3_mode == 0 and int1 >= 0:           # p3_mode noi in immediate mode (!= 1)
            position = List[int3]
        elif p3_mode == 2 and int3 + rb >= 0:
            position = List[int3 + rb]
        else:
            print(f'ERROR - invalid parameter mode: {p3_mode}')

        if op == 1:
            add = p1 + p2
            List[position] = add
        elif op == 2:
            multi = p1 * p2
            List[position] = multi
        elif op == 7:
            if p1 < p2:
                List[position] = 1
            else:
                List[position] = 0
        elif op == 8:
            if p1 == p2:
                List[position] = 1
            else:
                List[position] = 0

        i = i + 4
        continue

    elif op == 3 or op == 4 or op == 9:

        int1 = p1 = 0
        int1 = List[i + 1]

        if p1_mode == 1:
            print('ERROR - immediate mode while writing to memory')
        elif p1_mode == 0 and int1 >= 0:
            print(int1)
            p1 = List[int1]
        elif p1_mode == 2 and int1 + rb >= 0:
            print(int1 + rb)
            p1 = List[int1 + rb]
        else:
            print(f'ERROR - invalid parameter mode: {p1_mode}')

        if op == 3:
            if p1_mode == 1:
                List[i+1] = in1
            elif p1_mode == 0 and List[i+1] >= 0:
                List[List[i+1]] = in1
            elif p1_mode == 2 and List[i+1] + rb >= 0:
                List[List[i+1] + rb] = in1
            else:
                print(f'ERROR - invalid parameter mode: {p1_mode}')

        elif op == 4:
            output = p1
            print('output ----------------------------------> ', output)

        elif op == 9:
            rb = rb + p1
            print("rb........................", rb)

        i = i + 2
        continue

    elif op == 5 or op == 6:

        int1 = int2 = p1 = p2 = 0
        int1 = List[i + 1]
        int2 = List[i + 2]

        if p1_mode == 1:
            p1 = int1
        elif p1_mode == 0 and int1 >= 0:
            p1 = List[int1]
        elif p1_mode == 2 and int1 + rb >= 0:
            p1 = List[int1 + rb]
        else:
            print(f'ERROR - invalid parameter mode: {p1_mode}')

        if p2_mode == 1:
            p2 = int2
        elif p2_mode == 0 and int1 >= 0:
            p2 = List[int2]
        elif p2_mode == 2 and int2 + rb >= 0:
            p2 = List[int2 + rb]
        else:
            print(f'ERROR - invalid parameter mode: {p2_mode}')

        if (op == 5 and p1 != 0) or (op == 6 and p1 == 0):
            i = p2
            continue
        i = i + 3
        continue

    elif op == 99:
        print("********* PROGRAM HALTED *********")
        break

    else:
        print(f'ERROR - invalid opcode {op}')
        break

return List

boost_program = intcode(nList,1)
print(boost_program)

print(intcode(boost_program,1))[1]