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!
Rough one today. Don't know if I was tired or what, but I had to resort to Python to get it done in time.
"""Day 14: Docking Data
Interface with a docking computer doing bit masking to store values
in memory.
"""fromitertoolsimportproductfromtypingimportGenerator,Union,ListclassMaskCommand:"""A command that parses and sets the mask for subsequent memory
setting commands to be filtered through.
Properties:
bits (list(int)): The original bit-string of 1's, 0's, and X's.
and_ (int): A value to be `&`-ed with memory values to set some
bits to 0 no matter what
or_ (int): A value to be `|`-ed with memory values to set some
bits to 1 no matter what
floating (list(int)): Indices where X's live, to help with
generating floating bits.
"""def__init__(self,s:str):self.bits=sself.and_=0self.or_=0self.floating:list(int)=[]fori,cinenumerate(s):ifc=='0':self.and_|=(1<<(35-i))elifc=='1':self.or_|=(1<<(35-i))elifc=='X':self.floating.append(i)self.and_=(~self.and_)&0xFFFFFFFFF@staticmethoddefgenerate_binary(digits:int)->Generator[str,None,None]:"""Generates strings of binary digits for all values between
0 and 2**(digits)-1 (i.e. all possible sequences of 1's and 0's.)
"""foriinrange(1<<digits):yieldf"{i:0{digits}b}"defv2_addresses(self,command:Union['MaskCommand','SetCommand'])->Generator[List[str],None,None]:"""Generates addresses following V2 guidelines.
Performs an OR between the command's address and the mask, and
then generates every possible string made up of 1's and 0's in
place of all the floating bits (X's).
The OR assumes X's take precedence.
e.g. 110X0X (after the OR) would yield 110000, 110001, 110100,
and 110101.
"""merged=[c_bitifm_bit=='0'elsem_bitfor(m_bit,c_bit)inzip(self.bits,command.bits)]forcombinMaskCommand.generate_binary(len(self.floating)):forindex,bitinzip(self.floating,comb):merged[index]=bityieldmergedclassSetCommand:"""A command to set memory to some value. Stores the address and
value to be stored there. Used for both V1 and V2, so includes both
and integer version of the address and the bits for compatability.
Properties:
value (int): The value to be stored.
address (int): The location in memory to store the value.
bits (str): A string representation of the 0's and 1's that
make up the binary value for the address. (36 bits wide).
"""def__init__(self,address:str,value:str):self.value=int(value)self.address=int(address)self.bits=f"{self.address:036b}"defparse(filename:str)->List[Union[MaskCommand,SetCommand]]:"""Parse the input file into a list of commands."""commands=[]withopen(filename,"r")asf:forlineinf:ifline.startswith("mask"):commands.append(MaskCommand(line[7:]))else:parts=line.split()commands.append(SetCommand(parts[0][4:-1],parts[-1]))returncommandsdefpart1(commands:List[Union[MaskCommand,SetCommand]])->int:"""Find the sum of all values in memory after running all commands
following the V1 spec.
"""memory=dict()mask=Noneforcommandincommands:ifisinstance(command,MaskCommand):mask=commandelse:new_value=(command.value&mask.and_)|mask.or_memory[command.address]=new_valuereturnsum(memory.values())defpart2(commands:List[Union[MaskCommand,SetCommand]])->int:"""Find the sum of all values in memory after running all commands
following the V2 spec.
"""memory=dict()mask=Noneforcommandincommands:ifisinstance(command,MaskCommand):mask=commandelse:foraddressinmask.v2_addresses(command):memory["".join(address)]=command.valuereturnsum(memory.values())if__name__=="__main__":assert165==part1(parse("data/day14_test.txt"))assert208==part2(parse("data/day14_test2.txt"))print("All tests passed.")commands=parse("data/day14.txt")print(part1(commands))print(part2(commands))
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.
Rough one today. Don't know if I was tired or what, but I had to resort to Python to get it done in time.