|
| 1 | +# -------------------------------- Input data -------------------------------- # |
| 2 | +importos |
| 3 | + |
| 4 | +test_data= {} |
| 5 | + |
| 6 | +test=1 |
| 7 | +test_data[test]= {"input":"""set a 1 |
| 8 | +add a 2 |
| 9 | +mul a a |
| 10 | +mod a 5 |
| 11 | +snd a |
| 12 | +set a 0 |
| 13 | +rcv a |
| 14 | +jgz a -1 |
| 15 | +set a 1 |
| 16 | +jgz a -2""", |
| 17 | +"expected": ['4','Unknown'], |
| 18 | + } |
| 19 | +test+=1 |
| 20 | +test_data[test]= {"input":"""snd 1 |
| 21 | +snd 2 |
| 22 | +snd p |
| 23 | +rcv a |
| 24 | +rcv b |
| 25 | +rcv c |
| 26 | +rcv d""", |
| 27 | +"expected": ['4','Unknown'], |
| 28 | + } |
| 29 | + |
| 30 | +test='real' |
| 31 | +input_file=os.path.join(os.path.dirname(__file__),'Inputs',os.path.basename(__file__).replace('.py','.txt')) |
| 32 | +test_data[test]= {"input":open(input_file,"r+").read().strip(), |
| 33 | +"expected": ['7071','Unknown'], |
| 34 | + } |
| 35 | + |
| 36 | +# -------------------------------- Control program execution -------------------------------- # |
| 37 | + |
| 38 | +case_to_test='real' |
| 39 | +part_to_test=2 |
| 40 | +verbose_level=1 |
| 41 | + |
| 42 | +# -------------------------------- Initialize some variables -------------------------------- # |
| 43 | + |
| 44 | +puzzle_input=test_data[case_to_test]['input'] |
| 45 | +puzzle_expected_result=test_data[case_to_test]['expected'][part_to_test-1] |
| 46 | +puzzle_actual_result='Unknown' |
| 47 | + |
| 48 | + |
| 49 | +# -------------------------------- Actual code execution -------------------------------- # |
| 50 | + |
| 51 | +defval_get (registers,value): |
| 52 | +try: |
| 53 | +returnint(value) |
| 54 | +exceptValueError: |
| 55 | +returnregisters[value] |
| 56 | + |
| 57 | + |
| 58 | +defcomputer (instructions,program_id): |
| 59 | +globalverbose_level,puzzle_actual_result |
| 60 | +i=0 |
| 61 | +registers= {'p':program_id} |
| 62 | +whilei<len(instructions): |
| 63 | +instr=instructions[i] |
| 64 | + |
| 65 | +ifverbose_level==3: |
| 66 | +print (program_id,instr) |
| 67 | + |
| 68 | +ifinstr[0]=='snd': |
| 69 | +ifverbose_level==2: |
| 70 | +print (program_id,i,instr,'sending',val_get(registers,instr[1]),registers) |
| 71 | + |
| 72 | +ifprogram_id==1: |
| 73 | +puzzle_actual_result+=1 |
| 74 | +yieldval_get(registers,instr[1]) |
| 75 | +elifinstr[0]=='set': |
| 76 | +registers.update({instr[1]:val_get(registers,instr[2])}) |
| 77 | +elifinstr[0]=='add': |
| 78 | +registers.setdefault(instr[1],0) |
| 79 | +registers[instr[1]]+=val_get(registers,instr[2]) |
| 80 | +elifinstr[0]=='mul': |
| 81 | +registers.setdefault(instr[1],0) |
| 82 | +registers[instr[1]]*=val_get(registers,instr[2]) |
| 83 | +elifinstr[0]=='mod': |
| 84 | +registers.setdefault(instr[1],0) |
| 85 | +registers[instr[1]]%=val_get(registers,instr[2]) |
| 86 | +elifinstr[0]=='rcv': |
| 87 | +registers.setdefault(instr[1],0) |
| 88 | +registers[instr[1]]=yieldNone |
| 89 | +ifverbose_level==2: |
| 90 | +print (program_id,i,instr,'received',registers[instr[1]],registers) |
| 91 | +elifinstr[0]=='jgz': |
| 92 | +ifval_get(registers,instr[1])>0: |
| 93 | +i+=val_get(registers,instr[2])-1 |
| 94 | + |
| 95 | +i+=1 |
| 96 | + |
| 97 | + |
| 98 | + |
| 99 | +ifpart_to_test==1: |
| 100 | +instructions= [(string.split(' '))forstringinpuzzle_input.split('\n')] |
| 101 | + |
| 102 | +i=0 |
| 103 | +registers= {} |
| 104 | +playing=0 |
| 105 | +whilei<len(instructions): |
| 106 | +instr=instructions[i] |
| 107 | + |
| 108 | +ifinstr[0]=='snd': |
| 109 | +playing=val_get(registers,instr[1]) |
| 110 | +elifinstr[0]=='set': |
| 111 | +registers.update({instr[1]:val_get(registers,instr[2])}) |
| 112 | +elifinstr[0]=='add': |
| 113 | +registers.setdefault(instr[1],0) |
| 114 | +registers[instr[1]]+=val_get(registers,instr[2]) |
| 115 | +elifinstr[0]=='mul': |
| 116 | +registers.setdefault(instr[1],0) |
| 117 | +registers[instr[1]]*=val_get(registers,instr[2]) |
| 118 | +elifinstr[0]=='mod': |
| 119 | +registers.setdefault(instr[1],0) |
| 120 | +registers[instr[1]]%=val_get(registers,instr[2]) |
| 121 | +elifinstr[0]=='rcv': |
| 122 | +ifval_get(registers,instr[1]): |
| 123 | +puzzle_actual_result=playing |
| 124 | +break |
| 125 | +elifinstr[0]=='jgz': |
| 126 | +ifval_get(registers,instr[1]): |
| 127 | +i+=val_get(registers,instr[2])-1 |
| 128 | + |
| 129 | +i+=1 |
| 130 | + |
| 131 | + |
| 132 | +else: |
| 133 | +instructions= [(string.split(' '))forstringinpuzzle_input.split('\n')] |
| 134 | + |
| 135 | +i=0 |
| 136 | +registers= {} |
| 137 | +playing=0 |
| 138 | +program= {x:computer(instructions,x)forxinrange(2)} |
| 139 | +reception= {x: []forxinrange(2)} |
| 140 | +start=True |
| 141 | +stalled= {x:Falseforxinrange(2)} |
| 142 | +prog=0 |
| 143 | +puzzle_actual_result=0 |
| 144 | + |
| 145 | +while (len(reception[0])+len(reception[1]))>0orstart: |
| 146 | +start=False |
| 147 | +ifstalled[prog]andlen(reception[prog]): |
| 148 | +result=program[prog].send(reception[prog].pop(0)) |
| 149 | +stalled[prog]=False |
| 150 | +elifnotstalled[prog]: |
| 151 | +result=next(program[prog]) |
| 152 | +else: |
| 153 | +break |
| 154 | + |
| 155 | +ifverbose_level==2: |
| 156 | +print ('main received',result,'from',prog) |
| 157 | + |
| 158 | +whileresultisnotNoneorlen(reception[prog])>0: |
| 159 | +ifresultisNone: |
| 160 | +ifverbose_level==2: |
| 161 | +print ('main sends',reception[prog][0],'to',prog) |
| 162 | +result=program[prog].send(reception[prog].pop(0)) |
| 163 | +else: |
| 164 | +reception[1-prog].append(result) |
| 165 | +result=next(program[prog]) |
| 166 | + |
| 167 | +ifverbose_level==2: |
| 168 | +print ('main received',result,'from',prog) |
| 169 | + |
| 170 | +stalled[prog]=True |
| 171 | + |
| 172 | +ifverbose_level==3: |
| 173 | +print (reception) |
| 174 | +elifverbose_level==2: |
| 175 | +print (len(reception[0]),len(reception[1]),puzzle_actual_result) |
| 176 | + |
| 177 | +prog=1-prog |
| 178 | + |
| 179 | + |
| 180 | + |
| 181 | + |
| 182 | +# -------------------------------- Outputs / results -------------------------------- # |
| 183 | + |
| 184 | +ifverbose_level>=3: |
| 185 | +print ('Input : '+puzzle_input) |
| 186 | +print ('Expected result : '+str(puzzle_expected_result)) |
| 187 | +print ('Actual result : '+str(puzzle_actual_result)) |
| 188 | + |
| 189 | + |
| 190 | + |
| 191 | + |