Day 7 optimization

Okay, this optimization was easier than I thought it'd be.

I started by not building a new list every time I wanted to operate on the next value since that seemed like low-hanging fruit. That helped, but not as much as I expected (as is always the case with optimization, I feel).

Next I ran this under a profiler and it showed that string concatenation was the biggest offender, so I found a way to do that without involving strings (it's a bit convoluted, but optimizations tend to do that...) and that cleaned up most of the problem.

After that, getting the next element from the list was a (very minor) next-highest offender, so I cached that locally.

Finally, on a whim I decided that the tuple wasn't helping me anymore, so I removed it and was surprised to see another 100ms or so disappear. I guess constructing those is worse than I thought...gotta file that away for later. I'm a little surprised that it didn't show up in the profiler (or I didn't know how to read it, perhaps).
This commit is contained in:
2024-12-07 10:50:59 -06:00
parent df526c6e3f
commit 57ed9d261e
2 changed files with 52 additions and 18 deletions

View File

@ -1,4 +1,6 @@
namespace aoc2024;
using aoc2024.Util;
namespace aoc2024;
internal class Day07 : Day
{
@ -14,42 +16,45 @@ internal class Day07 : Day
}
}
private static bool CanSolveAddMult((long result, List<long> inputs) eq)
private static bool CanSolveAddMult(long target, long current, List<long> inputs, int idx)
{
if (eq.inputs.Count > 2)
if (idx == inputs.Count)
{
var added = eq.inputs[0] + eq.inputs[1];
var multd = eq.inputs[0] * eq.inputs[1];
return CanSolveAddMult(eq with { inputs = [added, .. eq.inputs.Skip(2)] }) || CanSolveAddMult(eq with { inputs = [multd, .. eq.inputs.Skip(2)] });
return current == target;
}
return eq.inputs[0] + eq.inputs[1] == eq.result || eq.inputs[0] * eq.inputs[1] == eq.result;
var next = inputs[idx];
var added = current + next;
var multd = current * next;
return CanSolveAddMult(target, added, inputs, idx + 1) ||
CanSolveAddMult(target, multd, inputs, idx + 1);
}
internal override string Part1()
{
long total = eqs.Where(CanSolveAddMult).Sum(eq => eq.result);
long total = eqs.Where(eq => CanSolveAddMult(eq.result, eq.inputs[0], eq.inputs, 1)).Sum(eq => eq.result);
return $"Add | Mult calibration result: <+white>{total}";
}
private static bool CanSolveAddMultConcat((long result, List<long> inputs) eq)
private static bool CanSolveAddMultConcat(long target, long current, List<long> inputs, int idx)
{
if (eq.inputs.Count > 2)
if (idx == inputs.Count)
{
var added = eq.inputs[0] + eq.inputs[1];
var multd = eq.inputs[0] * eq.inputs[1];
var cated = long.Parse($"{eq.inputs[0]}{eq.inputs[1]}");
return CanSolveAddMultConcat(eq with { inputs = [added, .. eq.inputs.Skip(2)] })
|| CanSolveAddMultConcat(eq with { inputs = [multd, .. eq.inputs.Skip(2)] })
|| CanSolveAddMultConcat(eq with { inputs = [cated, .. eq.inputs.Skip(2)] });
return current == target;
}
return eq.inputs[0] + eq.inputs[1] == eq.result || eq.inputs[0] * eq.inputs[1] == eq.result || long.Parse($"{eq.inputs[0]}{eq.inputs[1]}") == eq.result;
var next = inputs[idx];
var added = current + next;
var multd = current * next;
var cated = NumConcat.Longs(current, next);
return CanSolveAddMultConcat(target, added, inputs, idx + 1) ||
CanSolveAddMultConcat(target, multd, inputs, idx + 1) ||
CanSolveAddMultConcat(target, cated, inputs, idx + 1);
}
internal override string Part2()
{
long total = eqs.Where(CanSolveAddMultConcat).Sum(eq => eq.result);
long total = eqs.Where(eq => CanSolveAddMultConcat(eq.result, eq.inputs[0], eq.inputs, 1)).Sum(eq => eq.result);
return $"Add | Mult | Concat calibration result: <+white>{total}";
}
}

29
src/Util/NumConcat.cs Normal file
View File

@ -0,0 +1,29 @@
namespace aoc2024.Util;
public static class NumConcat
{
public static long Longs(long a, long b)
{
return b switch
{
< 10 => 10L * a + b,
< 100 => 100L * a + b,
< 1000 => 1000L * a + b,
< 10000 => 10000L * a + b,
< 100000 => 100000L * a + b,
< 1000000 => 1000000L * a + b,
< 10000000 => 10000000L * a + b,
< 100000000 => 100000000L * a + b,
< 1000000000 => 1000000000L * a + b,
< 10000000000 => 10000000000L * a + b,
< 100000000000 => 100000000000L * a + b,
< 1000000000000 => 1000000000000L * a + b,
< 10000000000000 => 10000000000000L * a + b,
< 100000000000000 => 100000000000000L * a + b,
< 1000000000000000 => 1000000000000000L * a + b,
< 10000000000000000 => 10000000000000000L * a + b,
< 100000000000000000 => 100000000000000000L * a + b,
_ => 1000000000000000000L * a + b
};
}
}