Issue39000
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2019-12-08 20:09 by Sean Moss, last changed 2022-04-11 14:59 by admin. This issue is now closed.
Files | ||||
---|---|---|---|---|
File name | Uploaded | Description | Edit | |
input7.txt | Sean Moss, 2019-12-08 20:09 | Input for IntCode |
Messages (2) | |||
---|---|---|---|
msg358022 - (view) | Author: Sean Moss (Sean Moss) | Date: 2019-12-08 20:09 | |
I was doing this year's Advent of Code and found that the following program produces unstable output when run using the given file as input: """ from itertools import permutations import gc def runProgram(amp_input, program, counter): while program[counter] != 99: # print('*' * 99) instruction = str(program[counter]) opcode = instruction[-2:] value1 = program[counter + 1] # print('2:{}'.format(counter)) try: if opcode in ['01', '02', '1', '2', '5', '05', '6', '06', '7', '07', '8', '08']: value1 = program[counter + 1] value2 = program[counter + 2] param_modes = instruction[::-1][2:] # print('{} {} {} {}'.format(instruction, value1, value2, value3)) param_modes += '0' * (3 - len(param_modes)) # print(param_modes) if param_modes[0] == '0': value1 = program[value1] if param_modes[1] == '0': value2 = program[value2] # print('{} {} {} {}'.format(instruction, value1, value2, value3)) if opcode in ['01', '02', '1', '2', '7', '07', '8', '08']: value3 = program[counter + 3] if opcode.endswith('1'): program[value3] = value1 + value2 elif opcode.endswith('2'): program[value3] = value1 * value2 elif opcode in ['7', '07']: program[value3] = 1 if value1 < value2 else 0 elif opcode in ['8', '08']: program[value3] = 1 if value1 == value2 else 0 counter += 4 elif opcode in ['5', '05']: if value1 != 0: counter = value2 else: counter += 3 elif opcode in ['6', '06']: if value1 == 0: counter = value2 else: counter += 3 elif opcode in ['03', '3']: program[value1] = amp_input.pop(0) counter += 2 elif opcode in ['4', '04']: # print('{} {}'.format(instruction, value1)) if instruction != '104': value1 = program[value1] # print('Output value: {}'.format(value1)) counter += 2 return value1, counter else: print("Something broke at {}".format(counter)) print("program state {}".format(program)) print(instruction) return False except Exception as e: print("Out of bounds at {}".format(counter)) print("program state {}".format(program)) print(instruction) print(e) print(len(program)) return return program, True outputs = [] max_output = 0 # initial_program = list(map(int, open('input7.txt').read().split(','))) amp_ids = ['A', 'B', 'C', 'D', 'E'] permutation = [5, 6, 7, 8, 9] # for permutation in permutations([5, 6, 7, 8, 9]): amp_programs = {amp_id: [list(map(int, open('input7.txt').read().split(',')))[:], 0] for amp_id in ['A', 'B', 'C', 'D', 'E']} loops = 0 prev_output = 0 for x in range(0, 5): gc.collect() new_output, outer_counter = runProgram([permutation[x], prev_output], amp_programs[amp_ids[x]][0], amp_programs[amp_ids[x]][1]) if outer_counter is not True: prev_output = new_output amp_programs[amp_ids[x]][1] = outer_counter # print(new_output) while amp_programs['E'][1] is not True: gc.collect() for amp_id in amp_programs.keys(): amp = amp_programs[amp_id] # print(prev_output) # print('1:{}'.format(amp[1])) new_output, outer_counter = runProgram([prev_output], amp[0], amp[1]) if outer_counter is not True: prev_output = new_output amp[1] = outer_counter # print('{}, {}'.format(amp[1], outer_counter)) # outputs.append(prev_output) # print(prev_output) outputs.append(prev_output) # if prev_output > max_output: # max_output = prev_output print(max(outputs)) # print(outputs) """ However when this program is run on the same input it produces stable input: """ from itertools import permutations def runProgram(amp_input, program, counter): while program[counter] != 99: # print('*' * 99) instruction = str(program[counter]) opcode = instruction[-2:] value1 = program[counter + 1] # print('2:{}'.format(counter)) try: if opcode in ['01', '02', '1', '2', '5', '05', '6', '06', '7', '07', '8', '08']: value1 = program[counter + 1] value2 = program[counter + 2] param_modes = instruction[::-1][2:] # print('{} {} {} {}'.format(instruction, value1, value2, value3)) param_modes += '0' * (3 - len(param_modes)) # print(param_modes) if param_modes[0] == '0': value1 = program[value1] if param_modes[1] == '0': value2 = program[value2] # print('{} {} {} {}'.format(instruction, value1, value2, value3)) if opcode in ['01', '02', '1', '2', '7', '07', '8', '08']: value3 = program[counter + 3] if opcode.endswith('1'): program[value3] = value1 + value2 elif opcode.endswith('2'): program[value3] = value1 * value2 elif opcode in ['7', '07']: program[value3] = 1 if value1 < value2 else 0 elif opcode in ['8', '08']: program[value3] = 1 if value1 == value2 else 0 counter += 4 elif opcode in ['5', '05']: if value1 != 0: counter = value2 else: counter += 3 elif opcode in ['6', '06']: if value1 == 0: counter = value2 else: counter += 3 elif opcode in ['03', '3']: program[value1] = amp_input.pop(0) counter += 2 elif opcode in ['4', '04']: # print('{} {}'.format(instruction, value1)) if instruction != '104': value1 = program[value1] # print('Output value: {}'.format(value1)) counter += 2 return value1, counter else: print("Something broke at {}".format(counter)) print("program state {}".format(program)) print(instruction) return False except Exception as e: print("Out of bounds at {}".format(counter)) print("program state {}".format(program)) print(instruction) print(e) print(len(program)) return return program, True outputs = [] max_output = 0 # initial_program = list(map(int, open('input7.txt').read().split(','))) amp_ids = ['A', 'B', 'C', 'D', 'E'] permutation = [5, 6, 7, 8, 9] # for permutation in permutations([5, 6, 7, 8, 9]): amp_programs = {amp_id: [list(map(int, open('input7.txt').read().split(',')))[:], 0] for amp_id in ['A', 'B', 'C', 'D', 'E']} loops = 0 prev_output = 0 for amp, perm in zip(amp_programs.values(), permutation): new_output, outer_counter = runProgram([perm, prev_output], amp[0], amp[1]) if outer_counter is not True: prev_output = new_output amp[1] = outer_counter # print(new_output) while amp_programs['E'][1] is not True: for amp_id in amp_programs.keys(): amp = amp_programs[amp_id] # print(prev_output) # print('1:{}'.format(amp[1])) new_output, outer_counter = runProgram([prev_output], amp[0], amp[1]) if outer_counter is not True: prev_output = new_output amp[1] = outer_counter # print('{}, {}'.format(amp[1], outer_counter)) # outputs.append(prev_output) # print(prev_output) outputs.append(prev_output) # if prev_output > max_output: # max_output = prev_output print(max(outputs)) # print(outputs) """ The only difference is that the second program uses the zip function to iterate while the first uses the range function to iterate. Again this is not a case of divergent output, it's that the first program doesn't always have the same output, the second program always has the same output. |
|||
msg358027 - (view) | Author: Mark Dickinson (mark.dickinson) * ![]() |
Date: 2019-12-08 20:54 | |
This has nothing to do with range. The source of indeterminacy is this line in your code: for amp_id in amp_programs.keys(): In Python 3.5, the ordering of `amp_programs.keys()` could differ from run to run. (With Python 3.6 and later, that won't happen.) If you want a deterministic result in Python 3.5, you could for example replace that line with: for amp_id in sorted(amp_programs): Closing here; this isn't a Python bug. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:24 | admin | set | github: 83181 |
2019-12-08 20:54:21 | mark.dickinson | set | status: open -> closed nosy: + mark.dickinson messages: + msg358027 resolution: not a bug stage: resolved |
2019-12-08 20:09:03 | Sean Moss | create |