1- #include < unordered_map>
1+ #include < array>
2+ #include < numeric>
23#include " ../aocio/aocio.hpp"
34
45/*
56 Problem: https://adventofcode.com/2023/day/15
67
78 Solutions:
89 - Part 1: 512283
9- - Part 2:
10+ - Part 2: 215827
1011 Notes:
11-
12+ - Part 2: Naive solution, but it still runs instantly.
1213*/
1314
1415bool is_ascii (char c)
1516{
1617 return c >= 0 && c <= 127 ;
1718}
1819
19- size_t hash (std::string_view s)
20+ uint8_t hash (std::string_view s)
2021{
21- size_t h = 0 ;
22+ uint8_t h = 0 ;
2223 for (char c : s) {
2324 if (!is_ascii (c)) {
2425 throw " hash: not an ASCII-character" ;
2526 }
26- h += ( uint8_t )c;
27- h *= 17 ;
28- h = h % 256 ;
27+ // (( h + c) * 17) % 256 <=> ((h + c) % 256 * 17 % 256) % 256 <=> ((h + c) % 256 * 17) % 256
28+ h = ( uint8_t )(h + ( uint8_t )c) ;
29+ h = ( uint8_t )(h * 17 );
2930 }
3031 return h;
3132}
3233
33- size_t part_one (const std::vector<std::string>& lines)
34+ int part_one (const std::vector<std::string>& lines)
3435{
35- size_t total_hash = 0 ;
36+ int total_hash = 0 ;
3637 std::string_view line = lines.at (0 );
3738 size_t start_idx = 0 ;
38- do {
39+
40+ while (start_idx < line.size ()) {
3941 size_t end_idx = line.find (" ," , start_idx);
4042 if (end_idx == std::string::npos) {
4143 end_idx = line.size ();
@@ -44,14 +46,97 @@ size_t part_one(const std::vector<std::string>& lines)
4446 std::string_view word = line.substr (start_idx, end_idx - start_idx);
4547 total_hash += hash (word);
4648 start_idx = end_idx + 1 ;
47- } while (start_idx < line. size ());
49+ }
4850
4951 return total_hash;
5052}
5153
52- size_t part_two (const std::vector<std::string>& lines)
54+ struct Lens {
55+ std::string lbl;
56+ int focal_len;
57+ };
58+
59+ inline bool operator ==(const Lens& lens, std::string_view lbl) {
60+ return lens.lbl == lbl;
61+ }
62+
63+ inline bool operator ==(std::string_view lbl, const Lens& lens) {
64+ return lens == lbl;
65+ }
66+
67+ struct Box
68+ {
69+ std::vector<Lens> lenses;
70+ uint8_t idx;
71+
72+ void insert_or_update_lens (const std::string& lbl, int focal_len)
73+ {
74+ if (auto lens = std::find (lenses.begin (), lenses.end (), lbl); lens != lenses.end ()) {
75+ lens->focal_len = focal_len;
76+ } else {
77+ lenses.push_back (Lens{lbl, focal_len});
78+ }
79+ }
80+
81+ void remove_lens (const std::string& lbl)
82+ {
83+ if (auto lens = std::find (lenses.begin (), lenses.end (), lbl); lens != lenses.end ()) {
84+ lenses.erase (lens);
85+ }
86+ }
87+
88+ int calc_focusing_power () const
89+ {
90+ int total = 0 , slot_num = 1 ;
91+ for (const Lens& lens : lenses) {
92+ int focusing_pwr = (idx + 1 ) * slot_num++ * lens.focal_len ;
93+ total += focusing_pwr;
94+ }
95+ return total;
96+ }
97+ };
98+
99+ int part_two (const std::vector<std::string>& lines)
53100{
54- return 0 ;
101+ std::array<Box, 256 > boxes;
102+ for (size_t i = 0 ; i < boxes.size (); ++i) {
103+ boxes.at (i).idx = (uint8_t )i;
104+ }
105+
106+ std::string_view line = lines.at (0 );
107+ size_t start_idx = 0 ;
108+
109+ while (start_idx < line.size ()) {
110+ size_t end_idx = line.find (" ," , start_idx);
111+ if (end_idx == std::string::npos) {
112+ end_idx = line.size ();
113+ }
114+ assert (end_idx >= start_idx);
115+ const std::string_view word = line.substr (start_idx, end_idx - start_idx);
116+
117+ size_t cmd_idx = word.find_first_of (" -=" );
118+ if (cmd_idx == std::string::npos) {
119+ throw " Missing command" ;
120+ }
121+ const char cmd = word.at (cmd_idx);
122+
123+ const std::string lens_lbl = std::string{word.substr (0 , cmd_idx)};
124+ Box &box = boxes.at (hash (lens_lbl));
125+
126+ if (cmd == ' -' ) {
127+ box.remove_lens (lens_lbl);
128+ } else if (cmd == ' =' ) {
129+ const std::string focal_len_str = std::string{word.substr (cmd_idx + 1 , word.size ())};
130+ int focal_len = aocio::parse_num (focal_len_str);
131+ box.insert_or_update_lens (lens_lbl, focal_len);
132+ } else {
133+ throw " Invalid command" ;
134+ }
135+
136+ start_idx = end_idx + 1 ;
137+ }
138+
139+ return std::accumulate (boxes.begin (), boxes.end (), 0 , [](int total, const Box& box) {return total + box.calc_focusing_power ();});
55140}
56141
57142int main ()
@@ -65,9 +150,9 @@ int main()
65150 return EXIT_FAILURE;
66151 }
67152 try {
68- size_t p1 = part_one (lines);
153+ int p1 = part_one (lines);
69154 std::cout << " Part 1: " << p1 << " \n " ;
70- size_t p2 = part_two (lines);
155+ int p2 = part_two (lines);
71156 std::cout << " Part 2: " << p2 << " \n " ;
72157 } catch (const char * err) {
73158 std::cerr << " Error: " << err << " \n " ;
0 commit comments