15 part 1
This commit is contained in:
parent
f18d9043a9
commit
c95b0b2daa
102
2022/15.cpp
102
2022/15.cpp
|
@ -1,13 +1,12 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cmath>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/phoenix.hpp>
|
#include <boost/phoenix.hpp>
|
||||||
#include <boost/range/irange.hpp>
|
|
||||||
#include <boost/spirit/include/qi.hpp>
|
#include <boost/spirit/include/qi.hpp>
|
||||||
|
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
|
@ -70,12 +69,15 @@ auto Parse(std::istream & in) -> Input
|
||||||
struct Range {
|
struct Range {
|
||||||
std::int64_t lo, hi;
|
std::int64_t lo, hi;
|
||||||
auto operator<=>(Range const& rhs) const = default;
|
auto operator<=>(Range const& rhs) const = default;
|
||||||
|
auto size() const -> std::size_t {
|
||||||
|
return hi - lo;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
auto subtract(
|
auto subtract_to(
|
||||||
std::array<Range, N> x,
|
std::array<Range, N> x,
|
||||||
std::array<Range, N> y,
|
std::array<Range, N> const& y,
|
||||||
std::vector<std::array<Range, N>> & out
|
std::vector<std::array<Range, N>> & out
|
||||||
) -> void
|
) -> void
|
||||||
{
|
{
|
||||||
|
@ -98,6 +100,17 @@ auto subtract(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
auto subtract(
|
||||||
|
std::array<Range, N> const& x,
|
||||||
|
std::array<Range, N> const& y
|
||||||
|
) -> std::vector<std::array<Range, N>>
|
||||||
|
{
|
||||||
|
std::vector<std::array<Range, N>> result;
|
||||||
|
subtract_to(x, y, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
auto Segment(std::int64_t center, std::int64_t radius) -> Range {
|
auto Segment(std::int64_t center, std::int64_t radius) -> Range {
|
||||||
return { center - radius, center + radius + 1};
|
return { center - radius, center + radius + 1};
|
||||||
}
|
}
|
||||||
|
@ -111,16 +124,59 @@ auto Corner(std::array<Range, 2> const& s) -> aocpp::Coord
|
||||||
return { (s[0].lo + s[1].lo) / 2, (s[0].lo - s[1].lo) / 2};
|
return { (s[0].lo + s[1].lo) / 2, (s[0].lo - s[1].lo) / 2};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Part2(Input const& input) -> void {
|
auto RowSlice(aocpp::Coord sensor, std::int64_t radius, std::int64_t row)
|
||||||
|
-> std::optional<std::array<Range, 1>>
|
||||||
|
{
|
||||||
|
auto dy = std::abs(row - sensor.y);
|
||||||
|
auto dx = radius - dy;
|
||||||
|
if (dx >= 0) {
|
||||||
|
return {{Segment(sensor.x, dx)}};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto region = std::vector<std::array<Range, 2>>{Square({2'000'000, 2'000'000}, 2'000'000)};
|
auto Part1(Input const& input, std::int64_t search) -> std::size_t {
|
||||||
|
auto region = std::vector<std::array<Range, 1>>{};
|
||||||
|
auto region_next = std::vector<std::array<Range, 1>>{};
|
||||||
|
|
||||||
|
for (auto const& entry : input) {
|
||||||
|
auto radius = aocpp::Norm1(entry.beacon - entry.sensor);
|
||||||
|
if (auto s = RowSlice(entry.sensor, radius, search)) {
|
||||||
|
region_next.push_back(*s);
|
||||||
|
for (auto const& x : region) {
|
||||||
|
subtract_to(x, *s, region_next);
|
||||||
|
}
|
||||||
|
std::swap(region, region_next);
|
||||||
|
region_next.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t result {};
|
||||||
|
for (auto const& x : region) {
|
||||||
|
result += x[0].hi - x[0].lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::int64_t> seen;
|
||||||
|
for (auto const& entry : input) {
|
||||||
|
if (entry.beacon.y == search && seen.insert(entry.beacon.x).second) {
|
||||||
|
result--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Part2(Input const& input, std::int64_t search) -> std::int64_t {
|
||||||
|
|
||||||
|
auto region = std::vector<std::array<Range, 2>>{Square({search/2, search/2}, search)};
|
||||||
auto region_next = std::vector<std::array<Range, 2>>{};
|
auto region_next = std::vector<std::array<Range, 2>>{};
|
||||||
|
|
||||||
for (auto const& entry : input) {
|
for (auto const& entry : input) {
|
||||||
auto radius = aocpp::Norm1(entry.beacon - entry.sensor);
|
auto radius = aocpp::Norm1(entry.beacon - entry.sensor);
|
||||||
auto s = Square(entry.sensor, radius);
|
auto s = Square(entry.sensor, radius);
|
||||||
for (auto const& x : region) {
|
for (auto const& x : region) {
|
||||||
subtract(x, s, region_next);
|
subtract_to(x, s, region_next);
|
||||||
}
|
}
|
||||||
std::swap(region, region_next);
|
std::swap(region, region_next);
|
||||||
region_next.clear();
|
region_next.clear();
|
||||||
|
@ -128,19 +184,20 @@ auto Part2(Input const& input) -> void {
|
||||||
|
|
||||||
for (auto const& entry : region) {
|
for (auto const& entry : region) {
|
||||||
auto corner = Corner(entry);
|
auto corner = Corner(entry);
|
||||||
//if (0 <= corner.x && corner.x <= 4000000 &&
|
if (0 <= corner.x && corner.x <= search &&
|
||||||
// 0 <= corner.y && corner.y <= 4000000)
|
0 <= corner.y && corner.y <= search)
|
||||||
//{
|
{
|
||||||
std::cout << corner << " " << 4'000'000 * corner.x + corner.y << std::endl;
|
return 4'000'000 * corner.x + corner.y;
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error{"no solution to part 2"};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_SUITE("2022-15 examples") {
|
TEST_SUITE("2022-15 examples") {
|
||||||
/*
|
TEST_CASE("subtraction") {
|
||||||
TEST_CASE("1D subtraction") {
|
|
||||||
CHECK(subtract<1>({1,3}, {4,5}) == std::vector<std::array<Range, 1>>{{1,3}});
|
CHECK(subtract<1>({1,3}, {4,5}) == std::vector<std::array<Range, 1>>{{1,3}});
|
||||||
CHECK(subtract<1>({4,5}, {1,3}) == std::vector<std::array<Range, 1>>{{4,5}});
|
CHECK(subtract<1>({4,5}, {1,3}) == std::vector<std::array<Range, 1>>{{4,5}});
|
||||||
CHECK(subtract<1>({1,3}, {2,4}) == std::vector<std::array<Range, 1>>{{1,2}});
|
CHECK(subtract<1>({1,3}, {2,4}) == std::vector<std::array<Range, 1>>{{1,2}});
|
||||||
|
@ -149,8 +206,17 @@ TEST_SUITE("2022-15 examples") {
|
||||||
CHECK(subtract<1>({1,4}, {2,3}) == std::vector<std::array<Range, 1>>{{1,2}, {3,4}});
|
CHECK(subtract<1>({1,4}, {2,3}) == std::vector<std::array<Range, 1>>{{1,2}, {3,4}});
|
||||||
CHECK(subtract<1>({1,4}, {2,4}) == std::vector<std::array<Range, 1>>{{1,2}});
|
CHECK(subtract<1>({1,4}, {2,4}) == std::vector<std::array<Range, 1>>{{1,2}});
|
||||||
CHECK(subtract<1>({1,4}, {1,3}) == std::vector<std::array<Range, 1>>{{3,4}});
|
CHECK(subtract<1>({1,4}, {1,3}) == std::vector<std::array<Range, 1>>{{3,4}});
|
||||||
|
|
||||||
|
CHECK(subtract<2>(
|
||||||
|
std::array<Range,2>{Range{0,3}, Range{0,4}}, std::array<Range,2>{Range{1,2},Range{2,3}})
|
||||||
|
==
|
||||||
|
std::vector<std::array<Range, 2>>{
|
||||||
|
std::array<Range, 2>{Range{0,1}, Range{0,4}},
|
||||||
|
std::array<Range, 2>{Range{2,3}, Range{0,4}},
|
||||||
|
std::array<Range, 2>{Range{1,2}, Range{0,2}},
|
||||||
|
std::array<Range, 2>{Range{1,2}, Range{3,4}}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
TEST_CASE("documented example") {
|
TEST_CASE("documented example") {
|
||||||
auto in = std::istringstream{
|
auto in = std::istringstream{
|
||||||
|
@ -170,12 +236,14 @@ TEST_SUITE("2022-15 examples") {
|
||||||
"Sensor at x=20, y=1: closest beacon is at x=15, y=3\n"
|
"Sensor at x=20, y=1: closest beacon is at x=15, y=3\n"
|
||||||
};
|
};
|
||||||
auto const input = Parse(in);
|
auto const input = Parse(in);
|
||||||
|
CHECK(26 == Part1(input, 10));
|
||||||
|
CHECK(56000011 == Part2(input, 20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Main(std::istream & in, std::ostream & out) -> void
|
auto Main(std::istream & in, std::ostream & out) -> void
|
||||||
{
|
{
|
||||||
auto const input = Parse(in);
|
auto const input = Parse(in);
|
||||||
//out << "Part 1: " << Part1(bottom, world) << std::endl;
|
out << "Part 1: " << Part1(input, 2'000'000) << std::endl;
|
||||||
Part2(input);
|
out << "Part 2: " << Part2(input, 4'000'000) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user