Skip to content

Commit

Permalink
day 24 part 1 in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
K20shores committed Dec 24, 2024
1 parent fb4db3d commit ab54306
Show file tree
Hide file tree
Showing 2 changed files with 247 additions and 0 deletions.
1 change: 1 addition & 0 deletions 2024/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ create_standard_test(NAME 2024_day20 SOURCES day20.cpp LIBRARIES aoc2024)
create_standard_test(NAME 2024_day21 SOURCES day21.cpp LIBRARIES aoc2024)
create_standard_test(NAME 2024_day22 SOURCES day22.cpp LIBRARIES aoc2024)
create_standard_test(NAME 2024_day23 SOURCES day23.cpp LIBRARIES aoc2024)
create_standard_test(NAME 2024_day24 SOURCES day24.cpp LIBRARIES aoc2024)

################################################################################
# Copy input data
Expand Down
246 changes: 246 additions & 0 deletions 2024/src/day24.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string>
#include <vector>
#include <benchmark/benchmark.h>
#include <format>
#include <aoc/2024/split.h>

enum Gate {
AND,
OR,
XOR
};

std::string gate_to_string(Gate gate) {
switch(gate) {
case Gate::AND:
return "AND";
case Gate::OR:
return "OR";
case Gate::XOR:
return "XOR";
default:
break;
}
return "unknown";
}

struct Operation {
Gate gate;
std::string arg1;
std::string arg2;
std::string target;
};

struct Data {
std::map<std::string, int> gates;
std::vector<Operation> operations;
};

bool has_both_inputs(const Operation& op, const std::map<std::string, int>& gates) {
return gates.at(op.arg1) != -1 && gates.at(op.arg2) != -1;
}

void put_valid_gates_first(std::vector<Operation>& operations, const std::map<std::string, int>& gates, size_t offset = 0) {
std::sort(operations.begin() + offset, operations.end(), [&](const Operation& a, const Operation& b) {
int valid_args_a = 0;
valid_args_a += gates.at(a.arg1) != -1;
valid_args_a += gates.at(a.arg2) != -1;
int valid_args_b = 0;
valid_args_b += gates.at(b.arg1) != -1;
valid_args_b += gates.at(b.arg2) != -1;
return valid_args_a > valid_args_b;
});
}

int64_t form_number(const std::map<std::string, int>& gates) {
int idx = 0;
int64_t result = 0;
for(auto& [gate, value] : gates) {
if (gate[0] == 'z') {
std::cout << std::format(" {} {}\n", gate, value);
result |= value << idx;
++idx;
}
}
return result;
}

int64_t part1(const Data &data)
{
auto operations = data.operations;
auto gates = data.gates;

for(auto& [gate, value] : gates) {
std::cout << gate << " " << value << std::endl;
}

for(auto& op : operations) {
std::cout << std::format("{} {} {} -> {}\n", op.arg1, gate_to_string(op.gate), op.arg2, op.target);
}
std::cout << std::endl;

put_valid_gates_first(operations, gates);

for(auto& op : operations) {
std::cout << std::format("{} {} {} -> {}\n", op.arg1, gate_to_string(op.gate), op.arg2, op.target);
}
std::cout << std::endl;

for(size_t i = 0; i < operations.size(); ++i) {
auto& op = operations[i];
if (has_both_inputs(op, gates)) {
int arg1 = data.gates.at(op.arg1);
int arg2 = data.gates.at(op.arg2);
int result = 0;
switch(op.gate) {
case Gate::AND:
result = arg1 & arg2;
break;
case Gate::OR:
result = arg1 | arg2;
break;
case Gate::XOR:
result = arg1 ^ arg2;
break;
default:
break;
}
gates[op.target] = result;
}
else {
put_valid_gates_first(operations, gates, i);
// --i;
}
}
for(auto& [gate, value] : gates) {
std::cout << gate << " " << value << std::endl;
}
std::cout << std::endl;
return form_number(gates);
}

int part2(const Data &data)
{
return 0;
}

Data parse()
{
std::ifstream file(std::filesystem::path("inputs/day24.txt"));
if (!file.is_open())
{
throw std::runtime_error("file not found");
}
std::string line;
Data data;

bool gates = false;
while (std::getline(file, line))
{
if (line.empty())
{
gates = true;
continue;
}
if (!gates)
{
auto parts = split(line, ": ");
data.gates[parts[0]] = std::stoi(parts[1]);
}
else
{
auto parts = split(line, " ");
Operation op;
op.arg1 = parts[0];
op.arg2 = parts[2];
op.target = parts[4];
if (parts[1] == "AND")
{
op.gate = Gate::AND;
}
else if (parts[1] == "OR")
{
op.gate = Gate::OR;
}
else if (parts[1] == "XOR")
{
op.gate = Gate::XOR;
}
else
{
throw std::runtime_error("invalid gate");
}
if(data.gates.find(op.arg1) == data.gates.end()) {
data.gates[op.arg1] = -1;
}
if(data.gates.find(op.arg2) == data.gates.end()) {
data.gates[op.arg2] = -1;
}
if(data.gates.find(op.target) == data.gates.end()) {
data.gates[op.target] = -1;
}
data.operations.push_back(op);
}
}

return data;
}

class BenchmarkFixture : public benchmark::Fixture
{
public:
static Data data;
};

Data BenchmarkFixture::data = parse();

BENCHMARK_DEFINE_F(BenchmarkFixture, Part1Benchmark)
(benchmark::State &state)
{
for (auto _ : state)
{
auto s = part1(data);
benchmark::DoNotOptimize(s);
}
}

BENCHMARK_DEFINE_F(BenchmarkFixture, Part2Benchmark)
(benchmark::State &state)
{
for (auto _ : state)
{
auto s = part2(data);
benchmark::DoNotOptimize(s);
}
}

BENCHMARK_REGISTER_F(BenchmarkFixture, Part1Benchmark)->Unit(benchmark::kMillisecond);
BENCHMARK_REGISTER_F(BenchmarkFixture, Part2Benchmark)->Unit(benchmark::kMillisecond);

int main(int argc, char **argv)
{
Data data = parse();

int64_t answer1 = 0;
int64_t answer2 = 0;

auto first = part1(data);
std::cout << "Part 1: " << first << std::endl;

auto second = part2(data);
std::cout << "Part 2: " << second << std::endl;

first != answer1 ? throw std::runtime_error("Part 1 incorrect") : nullptr;
second != answer2 ? throw std::runtime_error("Part 2 incorrect") : nullptr;

for (int i = 1; i < argc; ++i) {
if (std::string(argv[i]) == "--benchmark") {
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
return 0;
}
}
}

0 comments on commit ab54306

Please sign in to comment.