any chance it's overheating? did you clean the vents and checked the fans?
hades
That just makes sense -- the top-1k are competitive programmers, and today's puzzle had nothing to do with competitive programming :)
Feels like a really bad way to get the solution, though.
Does that come from an expectation that AoC is a programming challenge, where you typically are expected to come up with an implementation that works for all possible inputs? Because AoC is intentionally not that. Some tasks in AoC can/should be solved by hand, and I don't think you should feel bad about it :)
In my input (and I suppose in everyone else's too) the swaps only occurred within the adder subcircuit for a single bit. In general, however, the way the problem is phrased, any two outputs can be swapped, which can lead to two broken bits per swap (but this just doesn't happen).
Good, although it took some time. Actually, I got my personal best global rank on that problem.
good start to your new collection of abstract art
Could you fix the year in the title? Will get confusing in four years :)
C#
public class Day19 : Solver {
private string[] designs;
private class Node {
public Dictionary<char, Node> Children = [];
public bool Terminal = false;
}
private Node root;
public void Presolve(string input) {
List<string> lines = [.. input.Trim().Split("\n")];
designs = lines[2..].ToArray();
root = new();
foreach (var pattern in lines[0].Split(", ")) {
Node cur = root;
foreach (char ch in pattern) {
cur.Children.TryAdd(ch, new());
cur = cur.Children[ch];
}
cur.Terminal = true;
}
}
private long CountMatches(Node cur, Node root, string d) {
if (d.Length == 0) return cur.Terminal ? 1 : 0;
if (!cur.Children.TryGetValue(d[0], out var child)) return 0;
return CountMatches(child, root, d[1..]) + (child.Terminal ? CountMatches(root, d[1..]) : 0);
}
private readonly Dictionary<string, long> cache = [];
private long CountMatches(Node root, string d) {
if (cache.TryGetValue(d, out var cached_match)) return cached_match;
long match = CountMatches(root, root, d);
cache[d] = match;
return match;
}
public string SolveFirst() => designs.Where(d => CountMatches(root, d) > 0).Count().ToString();
public string SolveSecond() => designs.Select(d => CountMatches(root, d)).Sum().ToString();
}
- A* algorithm
- honestly a lot of other graph algorithms, just be aware of them, and be able to find algorithms you didn't know before
- OEIS
- SMT solvers
- set operations on intervals
C#
using QuickGraph;
using QuickGraph.Algorithms.ShortestPath;
namespace aoc24;
public class Day18 : Solver {
private int width = 71, height = 71, bytes = 1024;
private HashSet<(int, int)> fallen_bytes;
private List<(int, int)> fallen_bytes_in_order;
private record class Edge((int, int) Source, (int, int) Target) : IEdge<(int, int)>;
private DelegateVertexAndEdgeListGraph<(int, int), Edge> MakeGraph() => new(GetAllVertices(), GetOutEdges);
private readonly (int, int)[] directions = [(-1, 0), (0, 1), (1, 0), (0, -1)];
private bool GetOutEdges((int, int) arg, out IEnumerable<Edge> result_enumerable) {
List<Edge> result = [];
foreach (var (dx, dy) in directions) {
var (nx, ny) = (arg.Item1 + dx, arg.Item2 + dy);
if (nx < 0 || ny < 0 || nx >= width || ny >= height) continue;
if (fallen_bytes.Contains((nx, ny))) continue;
result.Add(new(arg, (nx, ny)));
}
result_enumerable = result;
return true;
}
private IEnumerable<(int, int)> GetAllVertices() {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
yield return (i, j);
}
}
}
public void Presolve(string input) {
fallen_bytes_in_order = [..input.Trim().Split("\n")
.Select(line => line.Split(","))
.Select(pair => (int.Parse(pair[0]), int.Parse(pair[1])))];
fallen_bytes = [.. fallen_bytes_in_order.Take(bytes)];
}
private double Solve() {
var graph = MakeGraph();
var search = new AStarShortestPathAlgorithm<(int, int), Edge>(graph, _ => 1, vtx => vtx.Item1 + vtx.Item2);
search.SetRootVertex((0, 0));
search.ExamineVertex += vertex => {
if (vertex.Item1 == width - 1 && vertex.Item2 == width - 1) search.Abort();
};
search.Compute();
return search.Distances[(width - 1, height - 1)];
}
public string SolveFirst() => Solve().ToString();
public string SolveSecond() {
foreach (var b in fallen_bytes_in_order[bytes..]) {
fallen_bytes.Add(b);
if (Solve() > width*height) return $"{b.Item1},{b.Item2}";
}
throw new Exception("solution not found");
}
}
Great find, thanks for sharing!
that's not like JSON at all. JSON is human readable, while this is clearly a binary format