#include "aoc.h" #include namespace aoc2022 { static line_view moves; static size_t index = 0; static bool at(uint8_t r, int p) { // p 0..7 uint8_t m = 0x01; while (p-- > 0) m <<= 1; return m & r; } char next() { int x = index++ % (moves.length - 1); const char* p = moves.line; // printf("%c at %d\n", *(p + x), x); return *(p + x); } void print(std::vector& rs) { for (size_t i = rs.size(); i > 0; i--) { uint8_t x = rs[i - 1]; printf("%05ld| ", i - 1); int c{6}; while (c >= 0) { printf("%c", at(x, c) ? '#' : '.'); c--; } printf("\n"); } } rock17 make_rock(size_t i) { rock17 r; r.type = (rock_type)(i % 5); switch (r.type) { case r1: r.rs = {0x1E}; break; case r2: r.rs = {0x08, 0x1C, 0x08}; break; case r3: r.rs = {0x1C, 0x04, 0x04}; break; case r4: r.rs = {0x10, 0x10, 0x10, 0x10}; break; case r5: r.rs = {0x18, 0x18}; break; default: break; } /* case chamber: r.rs = {0x7F}; break; case three: r.rs = {0x00, 0x00, 0x00}; break; */ return r; } rock17 right(rock17 r) { for (auto& rx : r.rs) { rx >>= 1; } return r; } rock17 left(rock17 r) { for (auto& rx : r.rs) { rx <<= 1; } return r; } bool collide(uint8_t r1, uint8_t r2) { return r1 & r2; } bool collide_left(std::vector& rs1, std::vector& rs2) { for (size_t j = 0; j < rs1.size(); j++) { for (int i = 6; i >= 0; i--) { if (at(rs1[j], i)) { if (i == 6) return true; if (at(rs2[j + 1], i + 1)) { return true; } else { break; } } } } return false; } bool collide_right(std::vector& rs1, std::vector& rs2) { for (size_t j = 0; j < rs1.size(); j++) { for (int i = 0; i <= 6; i++) { if (at(rs1[j], i)) { if (i == 0) return true; if (at(rs2[j + 1], i - 1)) { return true; } else { break; } } } } return false; } bool collide_down(std::vector& rs1, std::vector& rs2) { for (size_t i = 0; i < rs1.size(); i++) { if (collide(rs1[i], rs2[i])) return true; } return false; } void merge(rock17& floor, rock17 r, int n) { std::vector room; for (size_t i = floor.rs.size() - n - 1; room.size() < r.rs.size() + 1 && i < floor.rs.size(); i++) { room.push_back(floor.rs[i]); } while (room.size() < r.rs.size() + 1) { room.push_back(0x00); } auto m = next(); if (m == '>' && !collide_right(r.rs, room)) { // printf("%c %d\n", m, r.type); r = right(r); } if (m == '<' && !collide_left(r.rs, room)) { // printf("%c %d\n", m, r.type); r = left(r); } if (!collide_down(r.rs, room)) { merge(floor, r, n + 1); } else { // merge from n to last with r size_t m{0}; // 1. merge for (size_t i = floor.rs.size() - n; m < r.rs.size() && i < floor.rs.size(); i++) { floor.rs[i] |= r.rs[m]; m++; } // 2. push if necessary while (m < r.rs.size()) { floor.rs.push_back(r.rs[m++]); } } } int merge(std::vector& rs1, std::vector& rs2, int n) { if (collide(rs1[rs1.size() - 1 - n], rs2[0])) return n; else return merge(rs1, rs2, n + 1); } int check_three(std::vector& rs) { auto n = 0; while (rs[rs.size() - n - 1] == 0x00) { n++; } auto needed = 3 - n; while (needed-- > 0) { rs.push_back(0x00); } return n; } std::vector get_pattern(rock17& r) { auto n = 0; while (r.rs[r.rs.size() - n - 1] == 0x00) { n++; } return {r.rs.begin() + 1, r.rs.end() - n}; } std::pair day17(line_view file) { moves = file; rock17 floor{chamber, {0x7F}}; // size_t p = (file.length - 1) * 5; // size_t n = 8602 + 8576; size_t n = 2022; // sample 17(29) 35(53)/35/35 // input 8602 8575/8575/8575 for (size_t i = 0; i < n; i++) { rock17 r = make_rock(i); check_three(floor.rs); // auto x = check_three(floor.rs); // if (x == 0) { // printf("%ld, %ld\n", i, index % p); // } merge(floor, r, 0); // printf("%ld, %ld %ld\n", i, index % p, floor.rs.size() - 1); // 8601, 6 13526 // 8602, 11 13529 // 8603, 17 13531 // 15450, 40309 24274 // 15451, 40313 24275 // 15452, 40318 24278 // 17177, 11 26979 // 8602 + 116618074 * 8575 + 6848 // 13526 + 116618074 * 13450 + (24274 - 13529) } return {floor.rs.size() - 1, 1568513119571}; } } // namespace aoc2022