11#include " advent_of_code/day_3.hxx"
2- #include " spdlog/spdlog.h"
3- #include < regex>
4- #include < stdexcept>
2+ #include < algorithm>
3+ #include < iterator>
54#include < string>
65
76namespace AdventOfCode24 ::Day3 {
8- std::vector<std::pair<int , int >> parse_line (std::istringstream& line) {
9- std::vector<std::pair<int , int >> operations;
7+ bool use_calculation (int operation_index, logic_set logic_indexes, const bool & current_state) {
8+ auto last_do_before_val = std::find_if (
9+ logic_indexes.first .rbegin (),
10+ logic_indexes.first .rend (),
11+ [operation_index](int value){return value < operation_index;}
12+ );
13+
14+ auto last_dont_before_val = std::find_if (
15+ logic_indexes.second .rbegin (),
16+ logic_indexes.second .rend (),
17+ [operation_index](int value){return value < operation_index;}
18+ );
1019
11- const std::string line_str{line.str ()};
20+ // If we have not yet encountered any logic statements enable by default
21+ if (last_do_before_val == logic_indexes.first .rend () && last_dont_before_val == logic_indexes.second .rend ()) return current_state;
22+
23+ return (*last_do_before_val) > (*last_dont_before_val);
24+ }
25+ logic_set get_logic_indexes (const std::string& line) {
26+ const std::regex find_dos (" do\\ (\\ )" );
27+ const std::regex find_donts (" don't\\ (\\ )" );
28+
29+ logic_set logic_indexes;
30+
31+ auto dos_begin{std::sregex_iterator (line.begin (), line.end (), find_dos)};
32+ auto dos_end {std::sregex_iterator ()};
33+ auto donts_begin{std::sregex_iterator (line.begin (), line.end (), find_donts)};
34+ auto donts_end {std::sregex_iterator ()};
35+
36+ for (std::sregex_iterator iter{dos_begin}; iter != dos_end; ++iter) {
37+ const std::smatch do_match{*iter};
38+ const size_t index = std::distance (line.begin (), line.begin () + do_match.position ());
39+ logic_indexes.first .push_back (static_cast <int >(index));
40+ }
41+
42+ for (std::sregex_iterator iter{donts_begin}; iter != donts_end; ++iter) {
43+ const std::smatch dont_match{*iter};
44+ const size_t index = std::distance (line.begin (), line.begin () + dont_match.position ());
45+ logic_indexes.second .push_back (static_cast <int >(index));
46+ }
47+
48+ return logic_indexes;
49+ }
50+
51+ std::vector<std::pair<int , int >> parse_line (const std::string& line, bool logic_enabled, bool & do_state) {
52+ std::vector<std::pair<int , int >> operations;
1253
1354 const std::regex find_valid_mul_statements{" mul\\ (-?\\ d+,-?\\ d+\\ )" };
1455 const std::regex find_numbers{" -?\\ d+" };
1556
16- auto results_begin{std::sregex_iterator (line_str .begin (), line_str .end (), find_valid_mul_statements)};
57+ auto results_begin{std::sregex_iterator (line .begin (), line .end (), find_valid_mul_statements)};
1758 auto results_end {std::sregex_iterator ()};
1859
60+ std::optional<std::pair<std::vector<int >, std::vector<int >>> logic_indexes = {};
61+
62+ if (logic_enabled) logic_indexes = get_logic_indexes (line);
63+
1964 for (std::sregex_iterator iter{results_begin}; iter != results_end; ++iter) {
2065 const std::smatch match{*iter};
2166 const std::string match_str{match.str ()};
67+ bool calculation_active{true };
2268
2369 auto numbers_begin{std::sregex_iterator (match_str.begin (), match_str.end (), find_numbers)};
2470 auto numbers_end {std::sregex_iterator ()};
2571
2672 std::pair<int , int > arguments{-1000 , -1000 };
73+ const size_t match_position = std::distance (line.begin (), line.begin () + match.position ());
2774
2875 for (std::sregex_iterator n_iter{numbers_begin}; n_iter != numbers_end; ++n_iter) {
2976 const std::smatch n_match{*n_iter};
3077 int n_match_int{0 };
3178
3279 try {
33- n_match_int = std::stoi (match .str ());
80+ n_match_int = std::stoi (n_match .str ());
3481 } catch (std::invalid_argument& e) {
3582 spdlog::error (" Could not parse " + n_match.str ());
3683 return operations;
@@ -40,8 +87,40 @@ namespace AdventOfCode24::Day3 {
4087 else arguments.second = n_match_int;
4188 }
4289
43- operations.push_back (arguments);
90+ bool state_result{do_state};
91+
92+ if (logic_enabled) state_result = use_calculation (match_position, logic_indexes.value (), do_state);
93+
94+ if (!logic_enabled || state_result) operations.push_back (arguments);
95+
96+ // Update global state with latest state result
97+ do_state = state_result;
4498 }
4599 return operations;
46100 }
101+
102+ std::vector<int > calculate_file_lines (const std::filesystem::path& input_file, bool logic_enabled) {
103+ std::vector<int > calculation_results;
104+
105+ std::ifstream read_in (input_file, std::ios::in);
106+ std::string line;
107+ bool do_state{true };
108+
109+ while (std::getline (read_in, line)) {
110+ const std::vector<std::pair<int , int >> line_calculations{parse_line (line, logic_enabled, do_state)};
111+
112+ const int line_total = std::accumulate (
113+ line_calculations.begin (),
114+ line_calculations.end (),
115+ 0 ,
116+ [](int total, std::pair<int , int > couplet){
117+ spdlog::debug (" \t " + std::to_string (couplet.first ) + " * " + std::to_string (couplet.second ));
118+ return total + (couplet.first * couplet.second );
119+ }
120+ );
121+ calculation_results.push_back (line_total);
122+ }
123+
124+ return calculation_results;
125+ }
47126};
0 commit comments