Add solution for 2016 Day 15
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
Disc #1 has 5 positions; at time=0, it is at position 4.
|
||||||
|
Disc #2 has 2 positions; at time=0, it is at position 1.
|
||||||
|
Disc #2 has 3 positions; at time=0, it is at position 2.
|
||||||
|
|||||||
+35
-8
@@ -2,30 +2,57 @@
|
|||||||
|
|
||||||
namespace y2016::day15
|
namespace y2016::day15
|
||||||
{
|
{
|
||||||
REGISTER_DAY(2016, Day15, std::vector<int>, int);
|
struct Disc
|
||||||
|
{
|
||||||
|
int positions;
|
||||||
|
int position;
|
||||||
|
};
|
||||||
|
|
||||||
REGISTER_TEST_EXAMPLE(2016, Day15, ExampleInput, 1, 0);
|
REGISTER_DAY(2016, Day15, std::vector<Disc>, int64_t);
|
||||||
REGISTER_TEST(2016, Day15, Input, 1, 0);
|
|
||||||
REGISTER_TEST_EXAMPLE(2016, Day15, ExampleInput, 2, 0);
|
REGISTER_TEST_EXAMPLE(2016, Day15, ExampleInput, 1, 25);
|
||||||
REGISTER_TEST(2016, Day15, Input, 2, 0);
|
REGISTER_TEST(2016, Day15, Input, 1, 400589);
|
||||||
|
REGISTER_TEST_EXAMPLE(2016, Day15, ExampleInput, 2, 205);
|
||||||
|
REGISTER_TEST(2016, Day15, Input, 2, 3045959);
|
||||||
|
|
||||||
READ_INPUT(input)
|
READ_INPUT(input)
|
||||||
{
|
{
|
||||||
std::vector<int> vec;
|
std::vector<Disc> vec;
|
||||||
std::string str;
|
std::string str;
|
||||||
while (getline(input, str))
|
while (getline(input, str))
|
||||||
{
|
{
|
||||||
|
std::stringstream ss{str};
|
||||||
|
int i;
|
||||||
|
Disc disc;
|
||||||
|
ss >> "Disc #" >> i >> "has " >> disc.positions >> "positions; at time=" >> i >> ", it is at position " >>
|
||||||
|
disc.position;
|
||||||
|
vec.emplace_back(disc);
|
||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t Solve(const std::vector<Disc>& discs)
|
||||||
|
{
|
||||||
|
std::vector<int64_t> starts;
|
||||||
|
std::vector<int64_t> mods;
|
||||||
|
std::vector<int64_t> remainders(discs.size(), 0);
|
||||||
|
for (int j = 0; j < discs.size(); j++)
|
||||||
|
{
|
||||||
|
starts.emplace_back(discs[j].position + j + 1);
|
||||||
|
mods.emplace_back(discs[j].positions);
|
||||||
|
}
|
||||||
|
return Helper::ChineseRemainderTheorem(mods, remainders, starts);
|
||||||
|
}
|
||||||
|
|
||||||
OUTPUT1(input)
|
OUTPUT1(input)
|
||||||
{
|
{
|
||||||
return 0;
|
return Solve(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
OUTPUT2(input)
|
OUTPUT2(input)
|
||||||
{
|
{
|
||||||
return 0;
|
auto discs = input;
|
||||||
|
discs.emplace_back(Disc{11, 0});
|
||||||
|
return Solve(discs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-8
@@ -600,12 +600,15 @@ struct Helper
|
|||||||
return Index2D{-1, -1};
|
return Index2D{-1, -1};
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t ChineseRemainderTheoremTwo(int64_t mod1, int64_t mod2, int64_t res1, int64_t res2)
|
// Solve for N:
|
||||||
|
// remainder1 = N % mod1
|
||||||
|
// remainder2 = N % mod2
|
||||||
|
static int64_t ChineseRemainderTheoremTwo(int64_t mod1, int64_t mod2, int64_t remainder1, int64_t remainder2)
|
||||||
{
|
{
|
||||||
int64_t i = res1;
|
int64_t i = remainder1;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (i % mod2 == res2)
|
if (i % mod2 == remainder2)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
i += mod1;
|
i += mod1;
|
||||||
@@ -613,17 +616,32 @@ struct Helper
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t ChineseRemainderTheorem(const std::vector<int64_t>& mods, const std::vector<int64_t>& results)
|
// Solve for N:
|
||||||
|
// remainders = N % mods
|
||||||
|
static int64_t ChineseRemainderTheorem(const std::vector<int64_t>& mods, const std::vector<int64_t>& remainders)
|
||||||
{
|
{
|
||||||
int64_t currentMod = mods.front();
|
int64_t currentMod = mods.front();
|
||||||
int64_t currentRes = results.front();
|
int64_t currentRem = remainders.front();
|
||||||
for (int i = 1; i < mods.size(); i++)
|
for (int i = 1; i < mods.size(); i++)
|
||||||
{
|
{
|
||||||
int64_t result = ChineseRemainderTheoremTwo(currentMod, mods[i], currentRes, results[i]);
|
int64_t result = ChineseRemainderTheoremTwo(currentMod, mods[i], currentRem, remainders[i]);
|
||||||
currentRes = result;
|
currentRem = result;
|
||||||
currentMod = currentMod * mods[i];
|
currentMod = currentMod * mods[i];
|
||||||
}
|
}
|
||||||
return currentRes;
|
return currentRem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solve for N:
|
||||||
|
// remainders = (start + N) % mods
|
||||||
|
static int64_t ChineseRemainderTheorem(const std::vector<int64_t>& mods,
|
||||||
|
std::vector<int64_t> remainders,
|
||||||
|
const std::vector<int64_t>& starts)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mods.size(); i++)
|
||||||
|
{
|
||||||
|
remainders[i] = ((remainders[i] - starts[i]) % mods[i] + mods[i]) % mods[i];
|
||||||
|
}
|
||||||
|
return ChineseRemainderTheorem(mods, remainders);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t FastExponentiation(uint64_t start, uint64_t multiplication, uint64_t power, uint64_t mod)
|
static uint64_t FastExponentiation(uint64_t start, uint64_t multiplication, uint64_t power, uint64_t mod)
|
||||||
|
|||||||
Reference in New Issue
Block a user