1
+ #include " parser.hpp"
2
+
3
+ namespace aoc ::day_17 {
4
+
5
+ [[nodiscard]] static auto parse_opcode (std::string_view input) -> std::expected<std::vector<opcode>, std::error_code>;
6
+
7
+ [[nodiscard]] static auto parse_registers (std::string_view input)
8
+ -> std::expected<std::array<int64_t, 3>, std::error_code>;
9
+
10
+ [[nodiscard]] auto parse_program (std::string_view input) -> std::expected<program, std::error_code> {
11
+ constexpr auto delimiters = std::array{" \r\n\r\n " , " \n\n " };
12
+ auto split_pos =
13
+ std::ranges::find_if (delimiters, [&](auto delim) { return input.find (delim) != std::string_view::npos; });
14
+
15
+ if (split_pos == delimiters.end ()) {
16
+ return std::unexpected (std::make_error_code (std::errc::invalid_argument));
17
+ }
18
+
19
+ auto const split_at = input.find (*split_pos);
20
+ auto registerInit = input.substr (0 , split_at);
21
+ auto bytecode = input.substr (split_at);
22
+
23
+ auto registers = parse_registers (registerInit);
24
+ if (!registers) {
25
+ return std::unexpected (registers.error ());
26
+ }
27
+
28
+ auto opcodes = parse_opcode (bytecode);
29
+ if (!opcodes) {
30
+ return std::unexpected (opcodes.error ());
31
+ }
32
+
33
+ return program{.m_chunk = opcodes.value (),
34
+ .register_a = registers.value ()[0 ],
35
+ .register_b = registers.value ()[1 ],
36
+ .register_c = registers.value ()[2 ]};
37
+ }
38
+
39
+ [[nodiscard]] static auto parse_opcode (std::string_view input) -> std::expected<std::vector<opcode>, std::error_code> {
40
+ auto opcode = input.substr (0 , input.find (' :' ));
41
+ auto numbers = input.substr (input.find (' :' ) + 1 );
42
+
43
+ return numbers | std::views::split (' ,' ) | std::views::transform ([](auto const & number) {
44
+ auto result = aoc::parser::rules::parse_number<int64_t >(std::string_view{number});
45
+ if (!result) {
46
+ throw std::invalid_argument (" Failed to parse number" );
47
+ }
48
+ return static_cast <aoc::day_17::opcode>(*result);
49
+ }) |
50
+ aoc::ranges::to<std::vector<aoc::day_17::opcode>>;
51
+ }
52
+
53
+ [[nodiscard]] static auto parse_registers (std::string_view input)
54
+ -> std::expected<std::array<int64_t, 3>, std::error_code> {
55
+ std::array<int64_t , 3 > registers;
56
+
57
+ auto lines = input | std::views::split (' \n ' ) | std::views::transform ([](auto && line) {
58
+ auto line_str = std::string_view{line};
59
+ if (line_str.back () == ' \r ' ) {
60
+ line_str = line_str.substr (0 , line_str.size () - 1 );
61
+ }
62
+ return line_str;
63
+ }) |
64
+ aoc::ranges::to<std::vector<std::string_view>>;
65
+
66
+ if (lines.size () != 3 ) {
67
+ return std::unexpected (std::make_error_code (std::errc::invalid_argument));
68
+ }
69
+
70
+ auto parsed_RegisterA = aoc::parser::rules::parse_number<int64_t >(lines[0 ].substr (lines[0 ].find (' :' ) + 1 ));
71
+ if (!parsed_RegisterA) {
72
+ return std::unexpected (parsed_RegisterA.error ());
73
+ }
74
+ auto parsed_RegisterB = aoc::parser::rules::parse_number<int64_t >(lines[1 ].substr (lines[1 ].find (' :' ) + 1 ));
75
+ if (!parsed_RegisterB) {
76
+ return std::unexpected (parsed_RegisterB.error ());
77
+ }
78
+
79
+ auto parsed_RegisterC = aoc::parser::rules::parse_number<int64_t >(lines[2 ].substr (lines[2 ].find (' :' ) + 1 ));
80
+ if (!parsed_RegisterC) {
81
+ return std::unexpected (parsed_RegisterC.error ());
82
+ }
83
+
84
+ registers[0 ] = parsed_RegisterA.value ();
85
+ registers[1 ] = parsed_RegisterB.value ();
86
+ registers[2 ] = parsed_RegisterC.value ();
87
+
88
+ return registers;
89
+ }
90
+
91
+ } // namespace aoc::day_17
0 commit comments