def apply_to(self, num: ThirtySixBitNumber) -> list[ThirtySixBitNumber]:
        if num in self.seen_applications:
            return self.seen_applications[num]

        number_of_copies = int(math.pow(2, self.number_of_xs_in_mask))
        copies = [num.copy()] + ([num.copy()] * (number_of_copies - 1))
        for i, m in enumerate(self.mask):
            if m == "1":
                for copy in copies:
                    copy.set_bit_in_place(i, 1)

        seen_xs = 0
        for index in range(0, 36):
            if self.mask[index] != "X":
                continue

            # now repeat by 2^seen_xs across the list
            # so 2^0 is 1 -> goes 01010101
            # 2^1 is 2    -> goes 001100110011
            # 2^2 is 4    -> goes 0000111100001111
            for _ in range(0, number_of_copies):
                pattern = [0] * pow(2, seen_xs) + [1] * pow(2, seen_xs)
                pattern_generator = itertools.cycle(pattern)
                for copy_index, copy in enumerate(copies):
                    copies[copy_index] = copy.set_bit(index, next(pattern_generator))

            seen_xs += 1

        self.seen_applications[num] = copies
        return copies
    def test_set_bits_in_place(self):
        x = ThirtySixBitNumber(36)
        y = x.set_bit(31, 1)
        self.assertEqual(52, y.value)

        z = x.set_bit_in_place(31, 1)
        self.assertEqual(52, z.value)
        self.assertEqual(52, x.value)
    def process_line(self, line: str):
        if line.startswith('mask'):
            self.bitmask = VersionTwoBitMask(line.split(" = ")[1].strip())
        elif line.startswith("mem"):
            match = re.match(r"mem\[(\d+)] = (\d+)", line)
            address = int(match.group(1))
            num = ThirtySixBitNumber(int(match.group(2)))
            decoded_addresses = self.bitmask.apply_to(ThirtySixBitNumber(address))

            for decoded_address in decoded_addresses:
                self.memory[decoded_address.value] = num.value
    def test_v2_bitmask_x_writes_all_possibilities(self):
        mask = VersionTwoBitMask("000000000000000000000000000000X1001X")
        num = ThirtySixBitNumber(42)
        results = mask.apply_to(num)

        self.assertEqual(len(results), 4)

        self.assertCountEqual(
            results,
            [
                ThirtySixBitNumber(26),
                ThirtySixBitNumber(27),
                ThirtySixBitNumber(58),
                ThirtySixBitNumber(59)
            ]
        )
예제 #5
0
    def test_apply_bitmask(self):
        program = """
mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X
mem[8] = 11
mem[7] = 101
mem[8] = 0
        """
        parsed_program = parse(program)
        masked_program = apply_bitmask(parsed_program)
        self.assertEqual(
            masked_program, {
                'mask':
                BitMask("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"),
                'values': [(8, ThirtySixBitNumber(73)),
                           (7, ThirtySixBitNumber(101)),
                           (8, ThirtySixBitNumber(64))]
            })
예제 #6
0
    def test_parse_program(self):
        program = """
mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X
mem[8] = 11
mem[7] = 101
mem[8] = 0
        """
        parsed_program = parse(program)
        print(parsed_program['values'])
        self.assertEqual(
            parsed_program, {
                'mask':
                BitMask("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"),
                'values': [(8, ThirtySixBitNumber(11)),
                           (7, ThirtySixBitNumber(101)),
                           (8, ThirtySixBitNumber(0))]
            })
예제 #7
0
    def test_example_values(self):
        self.assertEqual(
            ThirtySixBitNumber(73).bits, [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1
            ])

        self.assertEqual(
            ThirtySixBitNumber(101).bits, [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1
            ])

        self.assertEqual(
            ThirtySixBitNumber(64).bits, [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0
            ])
예제 #8
0
 def test_can_create_number_from_bits(self):
     n = ThirtySixBitNumber([
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
     ])
     self.assertEqual(n.bits, [
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
     ])
     self.assertEqual(3, n.value)
    def test_v2_bitmask_zero_does_nothing(self):
        mask = VersionTwoBitMask("000000000000000000000000000000000000")
        bits = [0] * 36
        bits[35] = 1
        bits[34] = 0
        num = ThirtySixBitNumber(bits)

        actual = mask.apply_to(num)

        self.assertEqual(actual[0].bits[35], 1)
        self.assertEqual(actual[0].bits[34], 0)
예제 #10
0
def parse(program: str):
    program_lines = [
        line.strip() for line in program.splitlines() if len(line.strip()) > 0
    ]

    instructions = []
    for line in program_lines[1:]:
        match = re.match(r"mem\[(\d+)] = (\d+)", line)
        instructions.append(
            (int(match.group(1)), ThirtySixBitNumber(int(match.group(2)))))

    return {
        'mask': BitMask(program_lines[0].split(" = ")[1].strip()),
        'values': instructions
    }
    def test_v2_bitmask_one_writes_one(self):
        mask = VersionTwoBitMask("000000000000000000000000000001010101")
        bits = [0] * 36
        num = ThirtySixBitNumber(bits)

        actual = mask.apply_to(num)
        self.assertEqual(len(actual), 1)

        result = actual[0]
        self.assertEqual(result.bits[35], 1)
        self.assertEqual(result.bits[34], 0)
        self.assertEqual(result.bits[33], 1)
        self.assertEqual(result.bits[32], 0)
        self.assertEqual(result.bits[31], 1)
        self.assertEqual(result.bits[30], 0)
        self.assertEqual(result.bits[29], 1)
예제 #12
0
 def test_three(self):
     n = ThirtySixBitNumber(3)
     self.assertEqual(n.bits, [
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
     ])
예제 #13
0
 def test_two(self):
     n = ThirtySixBitNumber(2)
     self.assertEqual(n.bits, [
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
     ])
예제 #14
0
 def test_one(self):
     n = ThirtySixBitNumber(1)
     self.assertEqual(n.bits, [
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
     ])
예제 #15
0
 def test_zero(self):
     zero = ThirtySixBitNumber(0)
     self.assertEqual(zero.bits, [
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     ])
예제 #16
0
 def test_bitmask_can_have_impact(self):
     mask = BitMask("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0X")
     x = mask.apply_to(ThirtySixBitNumber(2))
     self.assertEqual(x, ThirtySixBitNumber(0))