Ryan is an engineer in the Sacramento Area with a focus in Python, Ruby, and Rust. Bash/Python Exercism mentor. Coding, physics, calculus, music, woodworking. Looking for work!
I agree with the main sentiment here, that there didn't seem to be a whole lot to this one. Lots of typing, but not too much thinking. I didn't like my initial code very much, though, I so I refactored some. I'm leaving all of the operations out addr, addi, etc. because they take up a lot of space and are all basically the same. Check them out in the git repo.
"""Day 16: Chronal Classification
Identify and classify time machine opcodes
"""fromcollectionsimportdefaultdict,namedtuplefromitertoolsimportchainfromday16_opsimportOPERATIONSExample=namedtuple("Example",["before","opcode","after"])defparse_examples(text):"""Parses text to build 'before, command, after' examples.
Input text has the pattern:
Before: [0, 0, 0, 0]
12 4 2 1
After: [1, 2, 3, 4]
"""examples=[]fortripletintext.split("\n\n"):before,command,after=triplet.splitlines()before_registers=[int(c)forcinbeforeifc.isdigit()]opcode=[int(num)fornumincommand.split()]after_registers=[int(c)forcinafterifc.isdigit()]examples.append(Example(before=before_registers,opcode=opcode,after=after_registers,))returnexamplesdefat_least_n_possible_opcodes(examples,n,operations):"""Returns the number of cases that could have applied at least n operations"""result=0forexampleinexamples:_,a,b,c=example.opcodepossible_ops=sum(1foropinoperationsifop(example.before,a,b,c)==example.after)ifpossible_ops>=n:result+=1returnresultdefpotential_op_ids(examples,operations):"""Figure out which op_ids *could* match which operations"""potential_ids=defaultdict(set)forexampleinexamples:op_id,a,b,c=example.opcodeforopinoperations:ifop(example.before,a,b,c)==example.after:potential_ids[op].add(op_id)returnpotential_idsdefidentify_opcodes(examples,operations):"""Given a set of operation input/outputs, identifies which opcodes
go with which operations.
"""potential_ids=potential_op_ids(examples,operations)available_op_ids=set(chain.from_iterable(potential_ids.values()))# Whittle down the possibilities by finding each op id that is guaranteed
# to match to a particular operation function. Then, remove that op id
# from the running for every other op function. This will cause more
# op functions to only have one possible op id. Lather, rinse, repeat.
result={}whilepotential_ids:forop,codesinpotential_ids.items():iflen(codes)==1:code=list(codes)[0]result[code]=opavailable_op_ids.remove(code)# Remove any op_ids that are "spoken for" by another operation
# Thank God for set mathematics
potential_ids[op]=codes&available_op_ids# Filter out any operation functions that don't need figured out anymore
potential_ids={op:codesforop,codesinpotential_ids.items()iflen(codes)>0}returnresultdefprocess_instructions(instructions,optable):"""Given a starting bank of registers with value 0, what are the contents
of the registers after all instructions are processed"""registers=[0]*4forinstructionininstructions:op_id,a,b,c=instructionregisters=optable[op_id](registers,a,b,c)returnregistersif__name__=="__main__":withopen("python/data/day16.txt","r")asf:text=f.read()# Part 1
examples=parse_examples(text)print(at_least_n_possible_opcodes(examples,3,OPERATIONS))# Part 2
optable=identify_opcodes(examples,OPERATIONS)withopen("python/data/day16_ops.txt","r")asf:instruction_text=f.read()instructions=[[int(value)forvalueininstruction.split()]forinstructionininstruction_text.splitlines()]print(process_instructions(instructions,optable))
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I agree with the main sentiment here, that there didn't seem to be a whole lot to this one. Lots of typing, but not too much thinking. I didn't like my initial code very much, though, I so I refactored some. I'm leaving all of the operations out
addr, addi, etc.
because they take up a lot of space and are all basically the same. Check them out in the git repo.