1+ #include  " common_headers.hpp" 
2+ #include  " utils/numeric_algorithm.hpp" 
3+ 
4+ #include  < cmath> 
5+ #include  < sstream> 
6+ 
7+ 
8+ using  HashTable = std::unordered_map<size_t , std::unordered_map<size_t , uint64_t >>;
9+ size_t  calculateStones (size_t  maxBlinks, size_t  blinks, uint64_t  num, HashTable& cache) { 
10+ 
11+     if (cache[num].count (blinks)) {
12+         return  cache[num][blinks];
13+     }
14+     if (blinks == maxBlinks) {
15+         return  1 ;
16+     }
17+     if (num == 0 ) {
18+         const  auto  stones = calculateStones (maxBlinks, blinks + 1 , 1 , cache);
19+         cache[num][blinks] = stones ;
20+     }
21+     else  if (auto  countOfDigits = numOfDigits (num); countOfDigits % 2  == 0 ) {
22+         const  auto  [num1, num2] = splitNum (num, countOfDigits);
23+         
24+         const  auto  stones1 = calculateStones (maxBlinks, blinks + 1 , num1, cache);
25+         const  auto  stones2 = calculateStones (maxBlinks, blinks + 1 , num2, cache);
26+         cache[num][blinks] = stones1 + stones2;
27+     }
28+     else  {
29+         const  auto  stones = calculateStones (maxBlinks, blinks + 1 , num * 2024 , cache);
30+         cache[num][blinks] = stones;
31+     }
32+ 
33+     return  cache[num][blinks];
34+ }
35+ 
36+ size_t  solveFirstPart (const  std::vector<uint64_t >& stones, size_t  maxBlinks) { 
37+     HashTable cache;
38+     size_t  stoneCounter{};
39+     for (auto  it = stones.rbegin (); it != stones.rend (); ++it) {
40+         stoneCounter += calculateStones (maxBlinks, 0 , *it, cache);
41+     }
42+     return  stoneCounter;
43+ }
44+ 
45+ std::vector<uint64_t > lineParser (const  std::string& line) {
46+     std::stringstream ss (line);
47+     uint64_t  num{};
48+     std::vector<uint64_t > nums;
49+     while  ((ss >> num))
50+     {
51+         nums.push_back (num);
52+     }
53+     return  nums;
54+ }
55+ 
56+ void  printHelp ()
57+ {
58+     std::cerr << " \n Usage:\n " 
59+     << " The program requires 2 args: (part1, part2) and the path to the file." 
60+     << " \n For example, ./day7 part1 data/day7.txt"  ;
61+ }
62+ 
63+ int  main (int  argc, char * argv[])
64+ {
65+     if (argc != 3 ) {
66+         printHelp ();
67+         return  1 ;
68+     }
69+ 
70+     std::string_view task{argv[1 ]};
71+     if (task != " part1"   && task != " part2"  ) {
72+         std::cerr << " \n first arg can be either `part1` or `part2`\n "  ;
73+         printHelp ();
74+         return  1 ;
75+     }
76+     
77+     std::vector<std::vector<uint64_t >> inputVec;
78+     readInput (argv[2 ], std::back_inserter (inputVec), lineParser);
79+ 
80+     if (task == " part1"  ) {
81+         const  size_t  maxBlinks{25 };
82+         std::cout << solveFirstPart (inputVec.at (0 ), maxBlinks);
83+     }
84+     else  {
85+         const  size_t  maxBlinks{75 };
86+         std::cout << solveFirstPart (inputVec.at (0 ), maxBlinks);
87+     }
88+ 
89+     return  0 ;
90+ }
0 commit comments