Advent of Code 2019 🤯 (יום 7)

תגיות: ,

בהצלחה :slight_smile:
יום 7

2 לייקים
חלק 1
import operator


def int_input(inputs=None):
    if inputs == None or inputs == []:
        return int(input())
    else:
        return inputs.pop(0)


def intcode_computer(instructions, user_inputs=None, pass_print=False):
    temp = instructions.copy()
    STATES = {
        1: {'func': operator.add, 'inputs': 3, 'index': 4, 'type': 0},
        2: {'func': operator.mul, 'inputs': 3, 'index': 4, 'type': 0},
        3: {'func': int_input, 'inputs': 1, 'index': 2, 'type': 1},
        4: {'func': print, 'inputs': 1, 'index': 2, 'type': 2},
        5: {'func': operator.truth, 'inputs': 2, 'index': 3, 'type': 3},
        6: {'func': operator.not_, 'inputs': 2, 'index': 3, 'type': 3},
        7: {'func': operator.lt, 'inputs': 3, 'index': 4, 'type': 4},
        8: {'func': operator.eq, 'inputs': 3, 'index': 4, 'type': 4},
             }

    outputs = []
    index = 0
    while True:
        opcode = str(temp[index]).zfill(5)
        state = int(opcode[-2:])
        if state != 99:
            inputs = [temp[index + i + 1] for i in range(STATES[state]['inputs'])]
            for pos in range(len(inputs) - 1):
                if int(opcode[-3 - pos]) == 0:
                    inputs[pos] = temp[inputs[pos]]
            if STATES[state]['type'] == 0:
                temp[inputs[-1]] = STATES[state]['func'](*inputs[:-1])
            elif STATES[state]['type'] == 1:
                if user_inputs is not None:
                    inputs = user_inputs + inputs
                temp[inputs[-1]] = STATES[state]['func'](inputs[:-1])
                if user_inputs is not None and user_inputs != []: 
                    user_inputs.pop(0)
            elif STATES[state]['type'] == 2:
                if int(opcode[-3]) == 0:
                    inputs[0] = temp[inputs[0]]
                if not pass_print:
                    STATES[state]['func'](inputs[0])
                outputs.append(inputs[0])
            elif STATES[state]['type'] == 4:
                if STATES[state]['func'](*inputs[:-1]):
                    temp[inputs[-1]] = 1
                else:
                    temp[inputs[-1]] = 0
            index += STATES[state]['index']
            if STATES[state]['type'] == 3:
                if STATES[state]['func'](*inputs[:-1]):
                    if int(opcode[-4]) == 0:
                        index = temp[inputs[-1]]
                    else:
                        index = inputs[-1]
        else:
            if outputs:
                return outputs
            else:
                return temp


def calc_signal(software_input, sequence_list, pass_print=False):
    output = 0
    for digit in sequence_list:
        inputs = [digit, output]
        output = intcode_computer(software_input, inputs, pass_print)[0]
    return output


def find_highest_signal(software_input, range_start, range_end, pass_print=False):
    all_sequences = [[d0, d1, d2, d3, d4]
                     for d0 in range(range_start, range_end)
                     for d1 in range(range_start, range_end)
                     if d1 != d0
                     for d2 in range(range_start, range_end)
                     if d0 != d2 != d1
                     for d3 in range(range_start, range_end)
                     if d0 != d3 != d1 and d3 != d2
                     for d4 in range(range_start, range_end)
                     if d0 != d4 != d1 and d2 != d4 != d3
                    ]

    max_signal = 0
    for sequence in all_sequences:
        signal = calc_signal(software_input, sequence, pass_print)
        if signal > max_signal:
            max_signal = signal

    return max_signal


with open('Day 7.txt', 'r') as file_handler:
    challenge_input = list(map(int, file_handler.read().split(',')))


find_highest_signal(challenge_input, 0, 5, pass_print=True)

הפעם הם ניצחו אותי. אני פשוט לא מבין מה רוצים בחלק 2 וויתרתי לבנתיים.
אחזור לזה בהמשך עם ראש נקי.

לייק 1

:star2:

חלק 1
#day7
#part 1
import itertools
import operator

PRO_CODE = list(range(1, 9))


def get_intcode_program(intcode):
    with open(intcode, "r") as intcode_program:
        intcode_program_read = intcode_program.read()
    intcode_program_read = list(map(int, intcode_program_read.split(",")))
    return intcode_program_read


def opcode_3_4(intcode_pro, code, signal):
    if intcode_pro[code] % 100 == 3:
        intcode_pro[intcode_pro[code + 1]] = signal
        return True
    elif intcode_pro[code] % 1000 == 4:
        return False
    elif intcode_pro[code] % 1000 == 104:
        return False
    return True


def opcode_1_2(int_code_pro, code, a, b):
    if code == 1:
        return operator.add(int_code_pro[a], int_code_pro[b])
    elif code == 2:
        return operator.mul(int_code_pro[a], int_code_pro[b])


def opcode_5_6(int_code_pro, code, a, b):
    if int_code_pro[code] % 100 == 5:
        if int_code_pro[a] != 0:
            return int_code_pro[b]
    elif int_code_pro[code] % 100 == 6:
        if int_code_pro[a] == 0:
            return int_code_pro[b]
    return code + 3


def opcode_7_8(int_code_pro, code, a, b):
    if int_code_pro[code] % 100 == 7:
        if int_code_pro[a] < int_code_pro[b]:
            return 1
    elif int_code_pro[code] % 100 == 8:
        if int_code_pro[a] == int_code_pro[b]:
            return 1
    return 0


def retrieve_parameters_mode_and_run(int_code_pro, pos, number):
    number = str(number).zfill(5)
    if number[2] == "0":
        a = int_code_pro[pos + 1]
    else:
        a = pos + 1
    if number[1] == "0":
        b = int_code_pro[pos + 2]
    else:
        b = pos + 2
    return a, b


def run_code(intcode_pro, signal, signal2):
    code = 0
    counti = 0
    while code < len(intcode_pro):
        if intcode_pro[code] % 100 in PRO_CODE[0:2]:
            a, b = retrieve_parameters_mode_and_run(intcode_pro, code, intcode_pro[code])
            intcode_pro[intcode_pro[code + 3]] = opcode_1_2(intcode_pro, intcode_pro[code] % 100, a, b)
            code += 4
        elif intcode_pro[code] % 100 in PRO_CODE[2:4]:
            if True:
                if counti == 1:
                    signal = signal2
                counti = 1
            if not opcode_3_4(intcode_pro, code, signal):
                if intcode_pro[code + 2] == 99:
                    if intcode_pro[code] == 4:
                        return (intcode_pro[intcode_pro[code + 1]], intcode_pro)
                    return (intcode_pro[code + 1], intcode_pro)
                print("Error")
                return False
            code += 2
        elif intcode_pro[code] % 100 in PRO_CODE[4:6]:
            a, b = retrieve_parameters_mode_and_run(intcode_pro, code, intcode_pro[code])
            code = opcode_5_6(intcode_pro, code, a, b)
        elif intcode_pro[code] % 100 in PRO_CODE[6:8]:
            a, b = retrieve_parameters_mode_and_run(intcode_pro, code, intcode_pro[code])
            value = opcode_7_8(intcode_pro, code, a, b)
            intcode_pro[intcode_pro[code + 3]] = value
            code += 4


intcode_prog = get_intcode_program("resources//day7.txt")
all_possibilites = itertools.permutations("01234", 5)
maximum = 0
for possible in all_possibilites:
    output = 0
    for digit in possible:
        output, intcode_prog = run_code(intcode_prog, int(digit), output)
    if output > maximum:
        maximum = output
print(f"answer part 1 : {maximum}")
לייק 1

חלק 2 יחכה למחר כנראה. בינתיים זה נחמד מאוד :slight_smile:

חלק 1
from itertools import permutations 


# *************************************** IntCode Computer ************************************************
def get_input(path):
    with open(path, 'r') as puzzle_input:
        return puzzle_input.read().split(',')


def run_input(puzzle_input, op_dict, inputs):
    op_code = 0
    i = 0
    while i < len(puzzle_input) and puzzle_input[i] != '99':
        op_code = puzzle_input[i]
        puzzle_input, to_increase, to_set = handle_op_code(op_code, i, puzzle_input, op_dict, inputs)
        
        if to_increase:
            i += int(to_increase)
        else:
            i = int(to_set)
        if puzzle_input == -1:
            return -1
        
    return puzzle_input


def handle_op_code(op_code, op_code_idx, puzzle_input, op_dict, inputs):
    op = get_operation(op_code)
    op_code = op_code.zfill(5)
    mode1 = op_code[2]
    mode2 = op_code[1]
    mode3 = op_code[0]
    
    if op == 99:
        return puzzle_input, _, 0
    elif op == -1:
        return puzzle_input, _, 0
    
    elif op == 3:
        return handle_three(op_code_idx, puzzle_input, inputs), 2, 0
    
    elif op == 4:
        if int(op_code.zfill(5)[2]):
            mode = 1
        else:
            mode = 0
        return handle_four(op_code_idx, puzzle_input, mode), 2, 0
    
    elif op == 5:
        to_set = handle_five(op_code_idx, puzzle_input, mode1, mode2, mode3)
        return puzzle_input, 0, to_set
            
    
    elif op == 6:
        to_set = handle_six(op_code_idx, puzzle_input, mode1, mode2, mode3)
        return puzzle_input, 0, to_set
    
    elif op == 7:
        return handle_seven(op_code_idx, puzzle_input, mode1, mode2, mode3), 4, 0
    
    elif op == 8:
        return handle_eight(op_code_idx, puzzle_input, mode1, mode2, mode3), 4, 0
        
    else:
        return handle_math_ops(op_dict, op, op_code_idx, puzzle_input, mode1, mode2, mode3), 4,0



def get_operation(op_code):
    if op_code[-1] == '1':
        return '+'
    elif op_code[-1] == '2':
        return '*'
    elif op_code[-1] == '3':
        return 3
    elif op_code[-1] == '4':
        return 4
    elif op_code[-1] == '5':
        return 5
    elif op_code[-1] == '6':
        return 6
    elif op_code[-1] == '7':
        return 7
    elif op_code[-1] == '8':
        return 8
    elif op_code[-1] == '9':
        return 99
    else:
        return -1


def get_args(op_code_idx, puzzle_input, modes, num_args):
    args = []
    if num_args == 2:
        for i in range(len(modes)):
            if not int(modes[i]):
                args.append(int(puzzle_input[int(puzzle_input[op_code_idx + i + 1])]))
            else:
                args.append(int(puzzle_input[op_code_idx + i + 1]))
        args.append(-1)

    else:
        for i in range(len(modes) - 1):
            if not int(modes[i]):
                args.append(int(puzzle_input[int(puzzle_input[op_code_idx + i + 1])]))
            else:
                args.append(int(puzzle_input[op_code_idx + i + 1]))
        args.append(op_code_idx + 3)
    
    return args


def handle_three(op_code_idx, puzzle_input, inputs):
    integer = inputs[0]
    inputs.pop(0)
    puzzle_input[int(puzzle_input[op_code_idx + 1])] = integer
    return puzzle_input


def handle_four(op_code_idx, puzzle_input, mode):
    if mode:
        return puzzle_input[op_code_idx + 1]
    else:
        return puzzle_input[int(puzzle_input[op_code_idx + 1])]


def handle_five(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2]
    arg1, arg2, _ = get_args(op_code_idx, puzzle_input, modes, len(modes))    
    if arg1:
        return arg2
    else:
        return op_code_idx + 3


def handle_six(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2]
    arg1, arg2, _ = get_args(op_code_idx, puzzle_input, modes, len(modes))
    if not arg1:
        return arg2
    else:
        return op_code_idx + 3


def handle_seven(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2, mode3]
    arg1, arg2, arg3 = get_args(op_code_idx, puzzle_input, modes, len(modes))    
    if arg1 < arg2:
        puzzle_input[int(puzzle_input[arg3])] = '1'
    else:
        puzzle_input[int(puzzle_input[arg3])] = '0'
    
    return puzzle_input


def handle_eight(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2, mode3]
    arg1, arg2, arg3 = get_args(op_code_idx, puzzle_input, modes, len(modes))
    if arg1 == arg2:
        puzzle_input[int(puzzle_input[arg3])] = '1'
    else:        
        puzzle_input[int(puzzle_input[arg3])] = '0'
        
    return puzzle_input


def handle_math_ops(op_dict, op, op_code_idx, puzzle_input, mode1='0', mode2='0', mode3='0'):
    arg3 = int(puzzle_input[op_code_idx + 3])
    arg2 = set_arg(op_code_idx + 2, puzzle_input, mode2)
    arg1 = set_arg(op_code_idx + 1, puzzle_input, mode1)
    
    
    operation_result = op_dict.get(op)(arg1, arg2)
    puzzle_input[arg3] = str(op_dict.get(op)(arg1, arg2))
    return puzzle_input


def set_arg(idx, puzzle_input, mode):
    if mode == '0':
        first_input_idx = int(puzzle_input[idx])
        arg = int(puzzle_input[first_input_idx])
    else:
        arg = int(puzzle_input[idx])
    return arg


def add(num1, num2):
    return num1 + num2


def multiply(num1, num2):
    return num1 * num2
# *************************************** IntCode Computer ************************************************


def get_permutations(numbers):
    perm = permutations(numbers) 
    for i in list(perm): 
        yield i 


def get_best(puzzle_input, op_dict):
    results = []
    perms = get_permutations(range(0, 5))
    for perm in perms:
        res = '0'
        for i in range(5):
            inputs = [str(perm[i]), res]
            res = run_input(puzzle_input, op_dict, inputs)
        results.append(res)
    
    results = [int(result) for result in results]
    return max(results)
 

def main():
    puzzle_input = get_input('input.txt')
    op_dict = op_dict = {'+': add, '*': multiply}
    first_part_result = get_best(puzzle_input, op_dict)
    print(f'First part result: {first_part_result}')


main()
לייק 1

כבר כמעט השארתי את הסוף של זה למחר ויצאתי לרוץ… ואז בזמן הריצה איכשהו עלה לי רעיון וזה עבד!

חלק 2
from itertools import permutations 


# *************************************** IntCode Computer ************************************************
def get_input(path):
    with open(path, 'r') as puzzle_input:
        return puzzle_input.read().split(',')


def run_input(puzzle_input, op_dict, inputs, idx=0):
    op_code = 0
    i = idx
    while i < len(puzzle_input) and puzzle_input[i] != '99':
        op_code = puzzle_input[i]
        puzzle_input, to_increase, to_set = handle_op_code(op_code, i, puzzle_input, op_dict, inputs)

        if to_increase:
            i += int(to_increase)
        else:
            i = int(to_set)
        if puzzle_input == -1:
            return -1

    if type(puzzle_input) == str:
        return puzzle_input, i
    
    if puzzle_input[i] == '99':
        return 99, i


def handle_op_code(op_code, op_code_idx, puzzle_input, op_dict, inputs):
    op = get_operation(op_code)
    op_code = op_code.zfill(5)
    mode1 = op_code[2]
    mode2 = op_code[1]
    mode3 = op_code[0]

    if op == 99:
        return puzzle_input, _, 0
    elif op == -1:
        return puzzle_input, _, 0

    elif op == 3:
        return handle_three(op_code_idx, puzzle_input, inputs), 2, 0

    elif op == 4:
        if int(op_code.zfill(5)[2]):
            mode = 1
        else:
            mode = 0
        return handle_four(op_code_idx, puzzle_input, mode), 2, 0

    elif op == 5:
        to_set = handle_five(op_code_idx, puzzle_input, mode1, mode2, mode3)
        return puzzle_input, 0, to_set


    elif op == 6:
        to_set = handle_six(op_code_idx, puzzle_input, mode1, mode2, mode3)
        return puzzle_input, 0, to_set

    elif op == 7:
        return handle_seven(op_code_idx, puzzle_input, mode1, mode2, mode3), 4, 0

    elif op == 8:
        return handle_eight(op_code_idx, puzzle_input, mode1, mode2, mode3), 4, 0

    else:
        return handle_math_ops(op_dict, op, op_code_idx, puzzle_input, mode1, mode2, mode3), 4,0



def get_operation(op_code):
    if op_code[-1] == '1':
        return '+'
    elif op_code[-1] == '2':
        return '*'
    elif op_code[-1] == '3':
        return 3
    elif op_code[-1] == '4':
        return 4
    elif op_code[-1] == '5':
        return 5
    elif op_code[-1] == '6':
        return 6
    elif op_code[-1] == '7':
        return 7
    elif op_code[-1] == '8':
        return 8
    elif op_code[-1] == '9':
        return 99
    else:
        return -1


def get_args(op_code_idx, puzzle_input, modes, num_args):
    args = []
    if num_args == 2:
        for i in range(len(modes)):
            if not int(modes[i]):
                args.append(int(puzzle_input[int(puzzle_input[op_code_idx + i + 1])]))
            else:
                args.append(int(puzzle_input[op_code_idx + i + 1]))
        args.append(-1)

    else:
        for i in range(len(modes) - 1):
            if not int(modes[i]):
                args.append(int(puzzle_input[int(puzzle_input[op_code_idx + i + 1])]))
            else:
                args.append(int(puzzle_input[op_code_idx + i + 1]))
        args.append(op_code_idx + 3)

    return args


def handle_three(op_code_idx, puzzle_input, inputs):
    integer = inputs[0]
    inputs.pop(0)
    puzzle_input[int(puzzle_input[op_code_idx + 1])] = integer
    return puzzle_input


def handle_four(op_code_idx, puzzle_input, mode):
    if mode:
        return puzzle_input[op_code_idx + 1]
    else:
        return puzzle_input[int(puzzle_input[op_code_idx + 1])]


def handle_five(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2]
    arg1, arg2, _ = get_args(op_code_idx, puzzle_input, modes, len(modes))    
    if arg1:
        return arg2
    else:
        return op_code_idx + 3


def handle_six(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2]
    arg1, arg2, _ = get_args(op_code_idx, puzzle_input, modes, len(modes))
    if not arg1:
        return arg2
    else:
        return op_code_idx + 3


def handle_seven(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2, mode3]
    arg1, arg2, arg3 = get_args(op_code_idx, puzzle_input, modes, len(modes))    
    if arg1 < arg2:
        puzzle_input[int(puzzle_input[arg3])] = '1'
    else:
        puzzle_input[int(puzzle_input[arg3])] = '0'
    
    return puzzle_input


def handle_eight(op_code_idx, puzzle_input, mode1, mode2, mode3):
    modes = [mode1, mode2, mode3]
    arg1, arg2, arg3 = get_args(op_code_idx, puzzle_input, modes, len(modes))
    if arg1 == arg2:
        puzzle_input[int(puzzle_input[arg3])] = '1'
    else:        
        puzzle_input[int(puzzle_input[arg3])] = '0'
        
    return puzzle_input


def handle_math_ops(op_dict, op, op_code_idx, puzzle_input, mode1='0', mode2='0', mode3='0'):
    arg3 = int(puzzle_input[op_code_idx + 3])
    arg2 = set_arg(op_code_idx + 2, puzzle_input, mode2)
    arg1 = set_arg(op_code_idx + 1, puzzle_input, mode1)
    
    
    operation_result = op_dict.get(op)(arg1, arg2)
    puzzle_input[arg3] = str(op_dict.get(op)(arg1, arg2))
    return puzzle_input


def set_arg(idx, puzzle_input, mode):
    if mode == '0':
        first_input_idx = int(puzzle_input[idx])
        arg = int(puzzle_input[first_input_idx])
    else:
        arg = int(puzzle_input[idx])
    return arg


def add(num1, num2):
    return num1 + num2


def multiply(num1, num2):
    return num1 * num2
# *************************************** IntCode Computer ************************************************


def get_permutations(numbers):
    perm = permutations(numbers) 
    for i in list(perm): 
        yield i 


def part_two(puzzle_input, op_dict):
    results = []
    perms = get_permutations(range(5, 10))
    for perm in perms:
        res = '0'
        i = 0
        j = 0
        flag = False
        amplifiers_pos = [0, 0, 0, 0, 0]
        puzzle_input_copies = []
        for k in range(5):
            puzzle_input_copies.append(puzzle_input.copy())
        
        while res != 99:
            if not flag:
                inputs = [str(perm[i]), res]
            else:
                inputs = [res]
            prev_res = res
            res, j = run_input(puzzle_input_copies[i], op_dict, inputs, amplifiers_pos[i])
            amplifiers_pos[i] = j
            if (i + 1) % 5 == 0:
                flag = True
                
            i = (i + 1) % 5
            
        results.append(prev_res)

    results = [int(result) for result in results]
    return max(results)


def main():
    puzzle_input = get_input('input.txt')
    op_dict = op_dict = {'+': add, '*': multiply}    
    second_part_result = part_two(puzzle_input, op_dict)
    print(second_part_result)


main()
2 לייקים

אסגור ברביעי :slight_smile:

לייק 1

וואי וואי, חלש פה הפעם :slight_smile:
לא מת על הפתרון שלי, אבל עובד.
מסיבות של חוסר זמן לא צנזרתי דברים שאתם לא יודעים, אבל אין פה איזו טכניקה מטורפת שגורמת להכול להיות יותר קל.

import itertools
import operator
from copy import copy
from typing import (
    Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union,
)

from typing_extensions import TypedDict


Command = TypedDict(
    'Command',
    {
        'size': int, 'function': Callable[..., Any],
        'jump': bool, 'void': int, 'method': bool,
    },
    total=False,
)
ParsedCmds = Iterator[int]
vmethod = {'void': 1, 'method': True}


class IntcodeMachine:
    OPCODES: Dict[int, Command] = {
        1: {'size': 4, 'function': operator.add},
        2: {'size': 4, 'function': operator.mul},
        3: {'size': 2, 'function': lambda s: s.get_input(), 'method': True},
        4: {'size': 2, 'function': lambda s, v: s.add_output(v), **vmethod},
        5: {'size': 3, 'function': operator.truth, 'jump': True},
        6: {'size': 3, 'function': operator.not_, 'jump': True},
        7: {'size': 4, 'function': lambda x, y: bool(operator.lt(x, y))},
        8: {'size': 4, 'function': lambda x, y: bool(operator.eq(x, y))},
    }

    def __init__(self, code: List[int], inputs: Iterable[int]) -> None:
        self.eip = 0  # Instructions pointer
        self.code = code
        self._inputs = iter(inputs)
        self._outputs_index = 0
        self._outputs: List[int] = []

    @property
    def opcode(self) -> int:
        return self.code[self.eip] % 100

    @property
    def is_halt(self) -> bool:
        return self.opcode == 99

    @property
    def is_jump(self) -> bool:
        return self.opcode_get('jump', False)

    def add_inputs(self, inputs: Union[int, List[int]]) -> None:
        if not isinstance(inputs, (list, tuple)):
            inputs = [inputs]
        self._inputs = itertools.chain(self._inputs, inputs)

    def get_input(self) -> Optional[int]:
        try:
            return next(self._inputs)
        except StopIteration:
            return None

    def add_output(self, outputs: Union[int, List[int]]) -> None:
        if not isinstance(outputs, (list, tuple)):
            outputs = [outputs]
        self._outputs.extend(outputs)

    def get_outputs(self) -> List[int]:
        outputs = self._outputs[self._outputs_index:]
        self._outputs_index = len(self._outputs)
        return outputs

    @property
    def modes(self) -> Tuple[int, int, int]:
        modes_part = self.code[self.eip] // 100
        return modes_part % 10, modes_part // 10 % 10, modes_part // 100

    def opcode_get(self, prop: str, default: Any = None) -> Any:
        return self.OPCODES[self.opcode].get(prop, default)

    @property
    def argc(self) -> int:
        return self.opcode_get('size', 2) - 2

    @property
    def args(self) -> List[int]:
        offset = self.argc + self.opcode_get('void', 0)
        params = self.code[self.eip + 1:self.eip + 1 + offset]
        out = []
        for param, mode in zip(params, self.modes):
            out.append(param if mode else self.code[param])
        if self.opcode_get('method'):
            out.insert(0, self)
        return out

    @property
    def write_address(self) -> Optional[int]:
        if self.opcode_get('void'):
            return None

        write_to = self.code[self.eip + 1 + self.argc]
        is_relative_jump = self.is_jump and self.modes[self.argc] == 0
        return self.code[write_to] if is_relative_jump else write_to

    def __call__(self) -> List[int]:
        while self.opcode != 99:
            op_size = self.opcode_get('size')
            args, write_to = self.args, self.write_address
            returns = self.opcode_get('function')(*args)
            if returns is None and self.opcode == 3:
                return self.get_outputs()  # Halt until you get input
            if write_to is not None and not self.is_jump:
                self.code[write_to] = returns
            should_jump = self.is_jump and returns
            self.eip = write_to if should_jump else (self.eip + op_size)
        return self.get_outputs()


def get_input() -> List[int]:
    with open('input.txt', 'r') as challenge_input:
        return list(map(int, challenge_input.read().strip().split(',')))


# Part 1
program = get_input()
outputs = []
for phases in itertools.permutations(list(range(5))):
    current_input = 0
    for phase in phases:
        current_machine = IntcodeMachine(program, [phase, current_input])
        current_input = current_machine()[-1]
        program = current_machine.code
    outputs.append(current_input)
print(max(outputs))


# Part 2
program = get_input()
max_output = 0
for phases in itertools.permutations(list(range(5, 10))):
    machines = [IntcodeMachine(copy(get_input()), [phase]) for phase in phases]
    next_input = 0
    i = 0
    while not machines[-1].is_halt:
        machines[i].add_inputs(next_input)
        next_input = machines[i]()[-1]
        i = (i + 1) % len(machines)
    max_output = max(max_output, next_input)
print(max_output)
לייק 1

תאמין או לא - מסתבר שהקטע עם הריצה קרה גם לי!
קצת באיחור, אבל פתרתי. עובר ל-8 :star_struck:

Advent of Code, Day 7
# ADVENT OF CODE, DAY 7
from itertools import permutations

def get_intcode():
    with open('input.txt', 'r') as file:
        intcode = file.read().split(',')
    intcode = intcode_items_to_int(intcode)
    return intcode


def intcode_items_to_int(intcode):
    for i, num in enumerate(intcode):
        intcode[i] = int(intcode[i])
    return intcode


def read_instruction(code):
    opcode = int(code) % 100
    parameters = str(int(code) // 100).zfill(3)
    return opcode, parameters


def run_intcode(amp_memory, phase, intcode):
    i = 0
    j = 0
    is_phase = True
    is_ended = False
    current_output = 0
    while i < len(intcode):
        opcode, parameters = read_instruction(intcode[i])
        if opcode == 1 or opcode == 2:
            if parameters[2] == '0':
                num1 = intcode[intcode[i + 1]]
            elif parameters[2] == '1':
                num1 = intcode[i + 1]
            if parameters[1] == '0':
                num2 = intcode[intcode[i + 2]]
            elif parameters[1] == '1':
                num2 = intcode[i + 2]
            if opcode == 1:
                intcode[intcode[i + 3]] = num1 + num2
            else:
                intcode[intcode[i + 3]] = num1 * num2
            i += 4
        if opcode == 3:
            if is_phase:
                intcode[intcode[i + 1]] = phase
                is_phase = False
            else:
                intcode[intcode[i + 1]] = amp_memory[j]
                j += 1
            i += 2
        if opcode == 4:
            if parameters[2] == '0':
                current_output = intcode[intcode[i + 1]]
            elif parameters[2] == '1':
                current_output = intcode[i + 1]
            if j == len(amp_memory):
                return intcode, current_output, is_ended
            i += 2
        if opcode == 5 or opcode == 6:
            if parameters[2] == '0':
                num1 = intcode[intcode[i + 1]]
            elif parameters[2] == '1':
                num1 = intcode[i + 1]
            if opcode == 5:
                if num1 != 0:
                    if parameters[1] == '0':
                        i = intcode[intcode[i + 2]]
                    if parameters[1] == '1':
                        i = intcode[i + 2]
                else:
                    i += 3
            if opcode == 6:
                if num1 == 0:
                    if parameters[1] == '0':
                        i = intcode[intcode[i + 2]]
                    if parameters[1] == '1':
                        i = intcode[i + 2]
                else:
                    i += 3
        if opcode == 7 or opcode ==8:
            if parameters[2] == '0':
                num1 = intcode[intcode[i + 1]]
            elif parameters[2] == '1':
                num1 = intcode[i + 1]
            if parameters[1] == '0':
                num2 = intcode[intcode[i + 2]]
            elif parameters[1] == '1':
                num2 = intcode[i + 2]
            if opcode == 7:
                if num1 < num2:
                    intcode[intcode[i + 3]] = 1
                else:
                    intcode[intcode[i + 3]] = 0
            if opcode == 8:
                if num1 == num2:
                    intcode[intcode[i + 3]] = 1
                else:
                    intcode[intcode[i + 3]] = 0
            i += 4
        if opcode == 99:
            is_ended = True
            return intcode, current_output, is_ended


def feedback_loop(phases):
    options = list(permutations(phases))
    max_thrusters = 0
    correct_phases = []
    current_amp = 'a'
    for option in options:
        amp_a = [0]
        amp_b = []
        amp_c = []
        amp_d = []
        amp_e = []
        is_complete = False
        j = 0
        while not is_complete:
            for phase in option:
                intcode = get_intcode()
                if current_amp == 'a':
                    intcode, output_value, _ = run_intcode(amp_a, phase, intcode)
                    amp_b.append(output_value)
                    current_amp = 'b'
                elif current_amp == 'b':
                    intcode, output_value, _ = run_intcode(amp_b, phase, intcode)
                    amp_c.append(output_value)
                    current_amp = 'c'
                elif current_amp == 'c':
                    intcode, output_value, _ = run_intcode(amp_c, phase, intcode)
                    amp_d.append(output_value)
                    current_amp = 'd'
                elif current_amp == 'd':
                    intcode, output_value, _ = run_intcode(amp_d, phase, intcode)
                    amp_e.append(output_value)
                    current_amp = 'e'
                elif current_amp == 'e':
                    intcode, output_value, is_complete = run_intcode(amp_e, phase, intcode)
                    amp_a.append(output_value)
                    current_amp = 'a'
        if amp_a[-1] > max_thrusters:
            max_thrusters = amp_a[-1]
            correct_phases = option
    return (max_thrusters, correct_phases) 


# PART 1
print(feedback_loop([0, 1, 2, 3, 4]))
# PART 2
print(feedback_loop([5, 6, 7, 8, 9]))
2 לייקים