Terrible, awful day 13 solution
This commit is contained in:
2
13input.txt
Normal file
2
13input.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
1000299
|
||||||
|
41,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,971,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,17,13,x,x,x,x,23,x,x,x,x,x,29,x,487,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,19
|
@ -47,6 +47,9 @@
|
|||||||
<None Update="12input.txt">
|
<None Update="12input.txt">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="13input.txt">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
Q10.Go();
|
Q10.Go();
|
||||||
Q11.Go();
|
Q11.Go();
|
||||||
Q12.Go();
|
Q12.Go();
|
||||||
|
Q13.Go();
|
||||||
Util.Log($"Total time={(System.DateTime.Now - start).TotalMilliseconds}ms");
|
Util.Log($"Total time={(System.DateTime.Now - start).TotalMilliseconds}ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
171
Q13.cs
Normal file
171
Q13.cs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace _2020
|
||||||
|
{
|
||||||
|
class Q13
|
||||||
|
{
|
||||||
|
static int leaveTime;
|
||||||
|
static List<int> busses = new List<int>();
|
||||||
|
|
||||||
|
public static void Go()
|
||||||
|
{
|
||||||
|
var start = DateTime.Now;
|
||||||
|
MakeList();
|
||||||
|
Util.Log($"Q13 MakeList took {(DateTime.Now - start).TotalMilliseconds}ms");
|
||||||
|
var p1start = DateTime.Now;
|
||||||
|
Part1();
|
||||||
|
Util.Log($"Q13 part1 took {(DateTime.Now - p1start).TotalMilliseconds}ms");
|
||||||
|
var p2start = DateTime.Now;
|
||||||
|
Part2();
|
||||||
|
Util.Log($"Q13 part2 took {(DateTime.Now - p2start).TotalMilliseconds}ms");
|
||||||
|
|
||||||
|
Util.Log($"Q13 took {(DateTime.Now - start).TotalMilliseconds}ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MakeList()
|
||||||
|
{
|
||||||
|
var lines = File.ReadAllLines("13input.txt");
|
||||||
|
if (lines.Length != 2)
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid input");
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveTime = Convert.ToInt32(lines[0]);
|
||||||
|
foreach (var bus in lines[1].Split(','))
|
||||||
|
{
|
||||||
|
if (bus == "x")
|
||||||
|
{
|
||||||
|
busses.Add(-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
busses.Add(Convert.ToInt32(bus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Part1()
|
||||||
|
{
|
||||||
|
int smallestModulo = int.MaxValue;
|
||||||
|
int smallestBus = -1;
|
||||||
|
foreach (var bus in busses)
|
||||||
|
{
|
||||||
|
if (bus < 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mod = bus - (leaveTime % bus);
|
||||||
|
if (mod < smallestModulo)
|
||||||
|
{
|
||||||
|
smallestModulo = mod;
|
||||||
|
smallestBus = bus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.Log($"Q13Part1: soonest bus={smallestBus}, departs={leaveTime + smallestModulo}, wait time={smallestModulo}m, answer={smallestBus * smallestModulo}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// taken from https://rosettacode.org/wiki/Chinese_remainder_theorem#C.23, modified for int64s. i don't know how this works. who am i, sun-tzu?
|
||||||
|
static long GetChineseRemainderTheorem(IEnumerable<int> n, IEnumerable<int> a)
|
||||||
|
{
|
||||||
|
long prod = n.Aggregate(1L, (i, j) => i * j);
|
||||||
|
long p;
|
||||||
|
long sm = 0;
|
||||||
|
for (int i = 0; i < n.Count(); i++)
|
||||||
|
{
|
||||||
|
p = prod / n.ElementAt(i);
|
||||||
|
sm += a.ElementAt(i) * ModularMultiplicativeInverse(p, n.ElementAt(i)) * p;
|
||||||
|
}
|
||||||
|
return sm % prod;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long ModularMultiplicativeInverse(long a, long mod)
|
||||||
|
{
|
||||||
|
long b = a % mod;
|
||||||
|
for (long x = 1; x < mod; x++)
|
||||||
|
{
|
||||||
|
if ((b * x) % mod == 1)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Part2()
|
||||||
|
{
|
||||||
|
var a = new List<int>();
|
||||||
|
var n = new List<int>();
|
||||||
|
for (int i = 0; i < busses.Count; i++)
|
||||||
|
{
|
||||||
|
if (busses[i] <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Add(busses[i] - i % busses[i]);
|
||||||
|
n.Add(busses[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.Log($"Q13Part2: val={GetChineseRemainderTheorem(n, a)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is how i initially solved it. took ~30mins. i'm not proud of it, but the "real" answer apparently required specialized knowledge i did not have.
|
||||||
|
static void Part2BruteForce()
|
||||||
|
{
|
||||||
|
int root = busses.First(x => x > 0);
|
||||||
|
var sorted = busses.OrderBy(x => x);
|
||||||
|
var largest = sorted.Last();
|
||||||
|
|
||||||
|
long checkVal = 0;
|
||||||
|
|
||||||
|
var idx = busses.IndexOf(largest);
|
||||||
|
int answersFound = 0;
|
||||||
|
int numThreads = 13;
|
||||||
|
Parallel.For(0, numThreads, thread =>
|
||||||
|
{
|
||||||
|
var threadVal = checkVal + (thread * largest);
|
||||||
|
long rootCheckVal = 0;
|
||||||
|
while (answersFound == 0)
|
||||||
|
{
|
||||||
|
threadVal += numThreads * largest;
|
||||||
|
rootCheckVal = threadVal - idx;
|
||||||
|
if (rootCheckVal % root == 0)
|
||||||
|
{
|
||||||
|
var gotit = false;
|
||||||
|
for (int i = 1; i < busses.Count; i++)
|
||||||
|
{
|
||||||
|
if (busses[i] <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rootCheckVal + i) % busses[i] == 0)
|
||||||
|
{
|
||||||
|
gotit = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gotit = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gotit)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref answersFound);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Util.Log($"Q13Part2: val={rootCheckVal}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user