Skip to content

Commit

Permalink
I guess counting cycles may not be it?
Browse files Browse the repository at this point in the history
  • Loading branch information
K20shores committed Dec 23, 2024
1 parent 3c574df commit b9e08c1
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 52 deletions.
1 change: 1 addition & 0 deletions 2024/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ create_standard_test(NAME 2024_day19 SOURCES day19.cpp LIBRARIES aoc2024)
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)

################################################################################
# Copy input data
Expand Down
63 changes: 11 additions & 52 deletions 2024/src/day21.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,22 @@ std::pair<Vertices, Edges> build_graph(const std::vector<std::string> &keypad)
// between each pair of vertices and stored that in a map
using Distances = std::map<Pos, std::map<Pos, int>>;
using Paths = std::map<Pos, std::map<Pos, Pos>>;
using DirectionChanges = Distances;

std::pair<Distances, Paths> floyd_warshall(const std::pair<Vertices, Edges>& graph)
{
const auto& [vertices, edges] = graph;
Distances dist;
Paths prev;
DirectionChanges direction_changes;

for (const auto &u : vertices)
{
for (const auto &v : vertices)
{
dist[u][v] = INT_MAX;
prev[u][v] = Pos{.x = -1, .y = -1};
direction_changes[u][v] = 0;
}
}

Expand All @@ -98,9 +101,11 @@ std::pair<Distances, Paths> floyd_warshall(const std::pair<Vertices, Edges>& gra
{
dist[u][v] = 1;
prev[u][v] = u;
direction_changes[u][v] = 0;
}
dist[u][u] = 0;
prev[u][u] = u;
direction_changes[u][u] = 0;
}

for (const auto &k : vertices)
Expand All @@ -112,6 +117,10 @@ std::pair<Distances, Paths> floyd_warshall(const std::pair<Vertices, Edges>& gra
auto &dik = dist[i][k];
auto &dkj = dist[k][j];
auto &dij = dist[i][j];

auto &dik_dir = direction_changes[i][k];
auto &dkj_dir = direction_changes[k][j];
auto &dij_dir = direction_changes[i][j];
if (dik != INT_MAX && dkj != INT_MAX && dij > dik + dkj)
{
dij = dik + dkj;
Expand All @@ -124,7 +133,7 @@ std::pair<Distances, Paths> floyd_warshall(const std::pair<Vertices, Edges>& gra
return {dist, prev};
}

std::vector<Pos> shortest_path1(const Pos &start, const Pos &end, const Paths &paths, const Distances &distances, std::vector<std::string> keypad)
std::vector<Pos> shortest_path(const Pos &start, const Pos &end, const Paths &paths)
{
std::vector<Pos> path;
Pos current = end;
Expand All @@ -138,63 +147,13 @@ std::vector<Pos> shortest_path1(const Pos &start, const Pos &end, const Paths &p
return path;
}

// std::vector<Pos> shortest_path2(const Pos &start, const Pos &end, const Paths &paths, const Distances &distances, std::vector<std::string> keypad)
// {
// std::vector<Pos> path;
// Pos current = end;

// Pos last_direction = {0, 0};

// while (current != start)
// {
// path.push_back(current);

// Pos next = paths.at(start).at(current);
// if (next != start)
// {
// Pos candidate_direction = current - next;

// // Check if the same-distance alternative exists with the same direction
// Pos alternative = current;
// bool found_alternative = false;

// // Iterate through potential neighbors of `current`
// for(auto& dir : directions)
// {
// Pos candidate_pos = current + dir;
// if (in_bounds(candidate_pos.x, candidate_pos.y, keypad) && keypad.at(candidate_pos.y).at(candidate_pos.x) != ' ' &&
// distances.at(start).at(candidate_pos) == distances.at(start).at(current))
// {
// alternative = candidate_pos;
// found_alternative = true;
// break;
// }
// }

// if (found_alternative)
// {
// next = alternative;
// }

// // Update the last direction
// last_direction = candidate_direction;
// }

// current = next;
// }

// path.push_back(start);
// std::reverse(path.begin(), path.end());
// return path;
// }

std::string get_path(std::string path, const Paths& shortest_paths, const Distances& distances, std::vector<std::string> keypad, std::map<char, Pos> char_to_pos) {
Pos start = char_to_pos['A'];
std::string numeric_path;
Pos current = start;
for (char c : path) {
Pos next = char_to_pos[c];
auto path = shortest_path1(current, next, shortest_paths, distances, keypad);
auto path = shortest_path(current, next, shortest_paths);
for(size_t i = 0; i < path.size() - 1; ++i) {
Pos dir = path[i + 1] - path[i];
if (dir == up) {
Expand Down
227 changes: 227 additions & 0 deletions 2024/src/day23.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string>
#include <vector>
#include <benchmark/benchmark.h>
#include <format>
#include <aoc/2024/split.h>
#include <stack>
#include <tuple>

struct Node {
std::string name;
bool name_has_t;
std::vector<Node *> neighbors;
int id;
};

struct Data {
std::map<std::string, Node*> nodes;
std::map<int, Node*> nodes_by_id;

~Data() {
for (auto node : nodes) {
delete node.second;
}
}
};

using AdjacencyMatrix = std::vector<std::vector<int>>;

// int DFS(const Data& data, const AdjacencyMatrix& graph, std::vector<int>& visited, int n_cycles, int start) {
// int count = 0;
// // vertex, cycles, vertex with t in its name
// std::stack<std::tuple<int, int, bool>> stack;

// stack.push({start, n_cycles, data.nodes_by_id.at(start)->name_has_t});

// while(!stack.empty()) {
// auto& [node, cycles, has_t] = stack.top();
// visited[node] = 1;
// stack.pop();
// if (cycles == 0) {
// visited[node] = 0;
// if(graph[node][start] == graph[start][node] && has_t) {
// ++count;
// }
// }

// for(int i = 0; i < graph.size(); ++i) {
// if (graph[node][i] == 1 && visited[i] == 0) {
// stack.push({i, cycles - 1, has_t | data.nodes_by_id.at(i)->name_has_t});
// }
// }
// }

// return count;
// }

struct Args {
int start;
int vert;
int n;
bool has_t;
};

void DFS(const Data& data, const AdjacencyMatrix& graph, std::vector<int>& marked, int& count, Args args, int depth = 1) {
marked[args.vert] = 1;

if (args.n == 0) {
marked[args.vert] = 0;
if(graph[args.vert][args.start] == graph[args.start][args.vert] && args.has_t) {
++count;
}
return;
}

for(auto& neighbor : data.nodes_by_id.at(args.vert)->neighbors) {
if (marked[neighbor->id] == 0) {
std::string indent(2*depth, ' ');
std::cout << indent << neighbor->name << std::endl;
Args newargs = {
.start = args.start,
.vert = neighbor->id,
.n = args.n - 1,
.has_t = args.has_t || neighbor->name_has_t
};
DFS(data, graph, marked, count, newargs, depth + 1);
}
}
marked[args.vert] = 0;
}

int count_cycles(const Data& data, const AdjacencyMatrix& graph, int n_cycles) {
std::vector<int> visited(graph.size(), 0);
int count = 0;
for(const auto& [id, node] : data.nodes_by_id) {
bool d = node->name == "co";
std::cout << node->name << std::endl;
Args args = {
.vert = id,
.start = id,
.n = n_cycles - 1,
.has_t = node->name_has_t
};
DFS(data, graph, visited, count, args);
visited[id] = 1;
std::cout << std::endl;
}
return count / 2;
}

int part1(const Data &data)
{
AdjacencyMatrix graph(data.nodes.size(), std::vector<int>(data.nodes.size(), 0));
for(const auto& [id, node] : data.nodes_by_id) {
for(auto neighbor : node->neighbors) {
graph[id][neighbor->id] = 1;
}
}

return count_cycles(data, graph, 3);
}

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

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

int id = 0;
while (std::getline(file, line))
{
std::vector<std::string> parts = split(line, "-");
Node* n1 = nullptr;
Node* n2 = nullptr;
if (data.nodes.find(parts[0]) == data.nodes.end()) {
n1 = new Node();
n1->name = parts[0];
n1->id = id++;
n1->name_has_t = n1->name.find('t') != std::string::npos;
data.nodes[parts[0]] = n1;
data.nodes_by_id[n1->id] = n1;
} else {
n1 = data.nodes[parts[0]];
}
if (data.nodes.find(parts[1]) == data.nodes.end()) {
n2 = new Node();
n2->name = parts[1];
n2->id = id++;
n2->name_has_t = n2->name.find('t') != std::string::npos;
data.nodes[parts[1]] = n2;
data.nodes_by_id[n2->id] = n2;
} else {
n2 = data.nodes[parts[1]];
}
n1->neighbors.push_back(n2);
n2->neighbors.push_back(n1);
}

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();

int answer1 = 0;
int 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 b9e08c1

Please sign in to comment.