Coverage for src\aoc2022\days\day10.py: 100%
44 statements
« prev ^ index » next coverage.py v7.0.0, created at 2022-12-23 05:19 +0000
« prev ^ index » next coverage.py v7.0.0, created at 2022-12-23 05:19 +0000
1from typing import Generator, List, Tuple
3from src.aoc2022 import utils
6def parse_data_to_array(raw_data: str) -> List[List[str]]:
7 """
8 Parse the raw data into a 1D list of instruction sets
10 :param raw_data: Raw data containing numerical data
11 :type raw_data: str
13 :return: parsed matrix of values
14 :rtype: List[List[str]]
15 """
16 parsed_list = []
17 for line in raw_data.split("\n"):
18 instructions = line.split(" ")
19 parsed_list.append(instructions)
21 return parsed_list
24def simulate_cpu_state_machine(
25 instructions: List[List[str]],
26) -> Generator[Tuple[int, int], None, None]:
27 """
28 Creates a generator that simulates the CPU on a per-cycle basis
30 :param instructions: List of instructions to execute
31 :type instructions: List[List[str]]
33 :return: per-cycle CPU simulator
34 :rtype: Generator[Tuple[int, int], None, None]
35 """
36 register_value = 1
37 cycle = 0
39 for instruction_set in instructions:
40 match instruction_set: # noqa
41 case ["noop"]: # noqa: E211
42 cycle += 1
43 yield (cycle, register_value)
44 case ["addx", num]: # noqa: E211
45 value = int(num) # noqa: F821
46 cycle += 1
47 yield (cycle, register_value)
48 cycle += 1
49 yield (cycle, register_value)
50 register_value += value
51 case _: # noqa: E211
52 raise ValueError(f"Invalid CPU instruction {instruction_set}")
55def get_total_signal_strength(instructions: List[List[str]]) -> int:
56 """
57 Computes the total signal strength as sum of cycle * register value for
58 n = 20, 60, 100, 140...
60 :param instructions: List of instructions to execute
61 :type instructions: List[List[str]]
63 :return: total signal strength
64 :rtype: int
65 """
66 running_sum = 0
67 cpu_simulator = simulate_cpu_state_machine(instructions)
69 for cycle_number, register_value in cpu_simulator:
70 if (cycle_number - 20) % 40 == 0:
71 running_sum += cycle_number * register_value
73 return running_sum
76def render_cpu_pixel_values(instructions: List[List[str]]) -> str:
77 """
78 Render the signal to a simulated console
80 :param instructions: List of instructions to execute
81 :type instructions: List[List[str]]
83 :return: rendered console output
84 :rtype: str
85 """
86 cpu_simulator = simulate_cpu_state_machine(instructions)
88 line_width = 40
89 render_chars = []
90 for cycle_number, register_value in cpu_simulator:
91 cursor_pos = (cycle_number - 1) % line_width
93 if cursor_pos == 0:
94 render_chars.append("\n")
96 if abs(register_value - cursor_pos) <= 1:
97 render_chars.append("#")
98 else:
99 render_chars.append(".")
101 return "".join(render_chars[1:]) # remove leading newline
104if __name__ == "__main__": # pragma: no cover
106 raw_data = utils.get_raw_data("./src/aoc2022/data/day10.txt")
108 parsed_data = parse_data_to_array(raw_data)
110 res = get_total_signal_strength(parsed_data)
112 print(f"The total signal strength is {res}")
114 rendered_console = render_cpu_pixel_values(parsed_data)
116 print(f"The rendered console is :\n{rendered_console}")