BuildSystem: Rework the whole cmake build system
Now files are installed using the install() command instead of manually copying files to their destinations. This allows automatic recompilation of headers that did not work previously
This commit is contained in:
9
userspace/aoc2023/day22/CMakeLists.txt
Normal file
9
userspace/aoc2023/day22/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(aoc2023_day22 ${SOURCES})
|
||||
banan_include_headers(aoc2023_day22 ban)
|
||||
banan_link_library(aoc2023_day22 libc)
|
||||
|
||||
install(TARGETS aoc2023_day22)
|
||||
191
userspace/aoc2023/day22/main.cpp
Normal file
191
userspace/aoc2023/day22/main.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
#include <BAN/HashSet.h>
|
||||
#include <BAN/Sort.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using i8 = int8_t;
|
||||
using i16 = int16_t;
|
||||
using i32 = int32_t;
|
||||
using i64 = int64_t;
|
||||
|
||||
using u8 = uint8_t;
|
||||
using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
using u64 = uint64_t;
|
||||
|
||||
struct Position
|
||||
{
|
||||
i64 x, y, z;
|
||||
|
||||
bool operator==(const Position& other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr bool rectangle_contains(const Position& c1, const Position& c2, const Position& p)
|
||||
{
|
||||
ASSERT(c1.x <= c2.x);
|
||||
ASSERT(c1.y <= c2.y);
|
||||
return (c1.x <= p.x && p.x <= c2.x) && (c1.y <= p.y && p.y <= c2.y);
|
||||
}
|
||||
|
||||
struct Brick
|
||||
{
|
||||
Position corners[2];
|
||||
BAN::HashSet<Brick*> supporting;
|
||||
BAN::HashSet<Brick*> supported_by;
|
||||
|
||||
bool supports(const Brick& other) const
|
||||
{
|
||||
if (corners[1].z + 1 != other.corners[0].z)
|
||||
return false;
|
||||
|
||||
for (i32 i = 0; i < 4; i++)
|
||||
if (rectangle_contains(corners[0], corners[1], { other.corners[i / 2].x, other.corners[i % 2].y, 0 }))
|
||||
return true;
|
||||
|
||||
for (i32 i = 0; i < 4; i++)
|
||||
if (rectangle_contains(other.corners[0], other.corners[1], { corners[i / 2].x, corners[i % 2].y, 0 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
i64 parse_i64(BAN::StringView str)
|
||||
{
|
||||
i64 result = 0;
|
||||
for (char c : str)
|
||||
{
|
||||
ASSERT(isdigit(c));
|
||||
result = (result * 10) + (c - '0');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BAN::Vector<Brick> parse_bricks(FILE* fp)
|
||||
{
|
||||
BAN::Vector<Brick> bricks;
|
||||
|
||||
char buffer[64];
|
||||
while (fgets(buffer, sizeof(buffer), fp))
|
||||
{
|
||||
BAN::StringView line(buffer);
|
||||
ASSERT(line.back() == '\n');
|
||||
line = line.substring(0, line.size() - 1);
|
||||
if (line.empty())
|
||||
break;
|
||||
|
||||
auto corner_strs = MUST(line.split('~'));
|
||||
ASSERT(corner_strs.size() == 2);
|
||||
|
||||
Brick brick;
|
||||
for (i32 i = 0; i < 2; i++)
|
||||
{
|
||||
auto coords = MUST(corner_strs[i].split(','));
|
||||
ASSERT(coords.size() == 3);
|
||||
brick.corners[i].x = parse_i64(coords[0]);
|
||||
brick.corners[i].y = parse_i64(coords[1]);
|
||||
brick.corners[i].z = parse_i64(coords[2]);
|
||||
}
|
||||
ASSERT(brick.corners[0].x <= brick.corners[1].x);
|
||||
ASSERT(brick.corners[0].y <= brick.corners[1].y);
|
||||
ASSERT(brick.corners[0].z <= brick.corners[1].z);
|
||||
MUST(bricks.push_back(brick));
|
||||
}
|
||||
|
||||
return bricks;
|
||||
}
|
||||
|
||||
i64 puzzle1(FILE* fp)
|
||||
{
|
||||
auto brick_comp = [](const Brick& b1, const Brick& b2) { return b1.corners[0].z < b2.corners[0].z; };
|
||||
|
||||
auto bricks = parse_bricks(fp);
|
||||
BAN::sort::sort(bricks.begin(), bricks.end(), brick_comp);
|
||||
|
||||
// Simulate brick falling
|
||||
for (size_t i = 0; i < bricks.size();)
|
||||
{
|
||||
bool can_fall = bricks[i].corners[0].z > 1;
|
||||
for (size_t j = 0; j < i && can_fall; j++)
|
||||
if (bricks[j].supports(bricks[i]))
|
||||
can_fall = false;
|
||||
|
||||
if (!can_fall)
|
||||
i++;
|
||||
else
|
||||
{
|
||||
bricks[i].corners[0].z--;
|
||||
bricks[i].corners[1].z--;
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
if (brick_comp(bricks[i - 1], bricks[i]))
|
||||
break;
|
||||
BAN::swap(bricks[i - 1], bricks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store brick supporting structures
|
||||
for (size_t i = 0; i < bricks.size(); i++)
|
||||
{
|
||||
for (size_t j = 0; j < bricks.size(); j++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
if (bricks[i].supports(bricks[j]))
|
||||
{
|
||||
MUST(bricks[i].supporting.insert(&bricks[j]));
|
||||
MUST(bricks[j].supported_by.insert(&bricks[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i64 result = 0;
|
||||
for (const auto& brick : bricks)
|
||||
{
|
||||
bool disintegratable = true;
|
||||
for (const auto* support : brick.supporting)
|
||||
if (support->supported_by.size() <= 1)
|
||||
disintegratable = false;
|
||||
result += disintegratable;
|
||||
}
|
||||
|
||||
// OFF BY 7
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
i64 puzzle2(FILE* fp)
|
||||
{
|
||||
(void)fp;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* file_path = "/usr/share/aoc2023/day22_input.txt";
|
||||
|
||||
if (argc >= 2)
|
||||
file_path = argv[1];
|
||||
|
||||
FILE* fp = fopen(file_path, "r");
|
||||
if (fp == nullptr)
|
||||
{
|
||||
perror("fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("puzzle1: %" PRId64 "\n", puzzle1(fp));
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
printf("puzzle2: %" PRId64 "\n", puzzle2(fp));
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
Reference in New Issue
Block a user