Add 2016 day 24 puzzles
This commit is contained in:
99
2016/puzzle-24-01.cc
Normal file
99
2016/puzzle-24-01.cc
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using Int = unsigned;
|
||||
using Coord = std::pair<Int, Int>;
|
||||
using Map = std::vector<std::string>;
|
||||
using PointMap = std::map<char, Coord>;
|
||||
using PointCostMap = std::multimap<char, std::pair<char, Int>>;
|
||||
|
||||
void update_cost_map(PointCostMap& cost_map, Map const& map, std::pair<char, Coord> start)
|
||||
{
|
||||
std::set<Coord> visited;
|
||||
std::set<Coord> to_visit;
|
||||
to_visit.insert(start.second);
|
||||
|
||||
Int cost{0};
|
||||
while (!to_visit.empty()) {
|
||||
visited.insert(to_visit.begin(), to_visit.end());
|
||||
std::set<Coord> next_to_visit;
|
||||
for (auto const& n : to_visit) {
|
||||
char c{map[n.second][n.first]};
|
||||
if (c == '#') {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (c != '.') {
|
||||
cost_map.insert({start.first, {c, cost}});
|
||||
}
|
||||
|
||||
auto add = [&map, &visited, &next_to_visit](Int x, Int y) {
|
||||
if (map[y][x] != '#' && !visited.contains(Coord{x, y})) {
|
||||
next_to_visit.insert(Coord{x, y});
|
||||
}
|
||||
};
|
||||
add(n.first, n.second - 1);
|
||||
add(n.first, n.second + 1);
|
||||
add(n.first - 1, n.second);
|
||||
add(n.first + 1, n.second);
|
||||
}
|
||||
++cost;
|
||||
std::swap(to_visit, next_to_visit);
|
||||
}
|
||||
}
|
||||
|
||||
auto find_lowest_cost(PointCostMap const& cost_map, std::size_t point_count)
|
||||
-> std::pair<std::string, Int>
|
||||
{
|
||||
std::multimap<Int, std::string> nodes;
|
||||
nodes.insert({0, "0"});
|
||||
|
||||
while (!nodes.empty()) {
|
||||
auto it{nodes.begin()};
|
||||
Int cost{it->first};
|
||||
std::string visited{it->second};
|
||||
if (visited.size() == point_count) {
|
||||
return {visited, cost};
|
||||
}
|
||||
nodes.erase(it);
|
||||
|
||||
auto [cm_begin, cm_end] = cost_map.equal_range(visited[visited.size() - 1]);
|
||||
for (auto cm_it{cm_begin}; cm_it != cm_end; ++cm_it) {
|
||||
if (visited.find(cm_it->second.first) == std::string::npos) {
|
||||
nodes.insert({cost + cm_it->second.second, visited + cm_it->second.first});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
auto main() -> int
|
||||
{
|
||||
Map map;
|
||||
PointMap points;
|
||||
std::string line;
|
||||
|
||||
// Read in map and find the locations we want to visit.
|
||||
while (std::getline(std::cin, line) && !line.empty()) {
|
||||
auto y{map.size()};
|
||||
map.push_back(line);
|
||||
std::size_t x{0};
|
||||
for (x = line.find_first_not_of(".#", x); x != std::string::npos;
|
||||
x = line.find_first_not_of(".#", x + 1)) {
|
||||
points.insert({line[x], {x, y}});
|
||||
}
|
||||
}
|
||||
|
||||
PointCostMap cost_map;
|
||||
for (auto const& p : points) {
|
||||
update_cost_map(cost_map, map, p);
|
||||
}
|
||||
|
||||
auto [route, cost] = find_lowest_cost(cost_map, points.size());
|
||||
std::cout << "Route: " << route << " costs " << cost << '\n';
|
||||
return 0;
|
||||
}
|
102
2016/puzzle-24-02.cc
Normal file
102
2016/puzzle-24-02.cc
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using Int = unsigned;
|
||||
using Coord = std::pair<Int, Int>;
|
||||
using Map = std::vector<std::string>;
|
||||
using PointMap = std::map<char, Coord>;
|
||||
using PointCostMap = std::multimap<char, std::pair<char, Int>>;
|
||||
|
||||
void update_cost_map(PointCostMap& cost_map, Map const& map, std::pair<char, Coord> start)
|
||||
{
|
||||
std::set<Coord> visited;
|
||||
std::set<Coord> to_visit;
|
||||
to_visit.insert(start.second);
|
||||
|
||||
Int cost{0};
|
||||
while (!to_visit.empty()) {
|
||||
visited.insert(to_visit.begin(), to_visit.end());
|
||||
std::set<Coord> next_to_visit;
|
||||
for (auto const& n : to_visit) {
|
||||
char c{map[n.second][n.first]};
|
||||
if (c == '#') {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (c != '.') {
|
||||
cost_map.insert({start.first, {c, cost}});
|
||||
}
|
||||
|
||||
auto add = [&map, &visited, &next_to_visit](Int x, Int y) {
|
||||
if (map[y][x] != '#' && !visited.contains(Coord{x, y})) {
|
||||
next_to_visit.insert(Coord{x, y});
|
||||
}
|
||||
};
|
||||
add(n.first, n.second - 1);
|
||||
add(n.first, n.second + 1);
|
||||
add(n.first - 1, n.second);
|
||||
add(n.first + 1, n.second);
|
||||
}
|
||||
++cost;
|
||||
std::swap(to_visit, next_to_visit);
|
||||
}
|
||||
}
|
||||
|
||||
auto find_lowest_cost(PointCostMap const& cost_map, std::size_t point_count)
|
||||
-> std::pair<std::string, Int>
|
||||
{
|
||||
std::multimap<Int, std::string> nodes;
|
||||
nodes.insert({0, "0"});
|
||||
|
||||
while (!nodes.empty()) {
|
||||
auto it{nodes.begin()};
|
||||
Int cost{it->first};
|
||||
std::string visited{it->second};
|
||||
if (visited.size() == point_count + 1) {
|
||||
return {visited, cost};
|
||||
}
|
||||
nodes.erase(it);
|
||||
|
||||
auto [cm_begin, cm_end] = cost_map.equal_range(visited[visited.size() - 1]);
|
||||
for (auto cm_it{cm_begin}; cm_it != cm_end; ++cm_it) {
|
||||
if (visited.find(cm_it->second.first) == std::string::npos) {
|
||||
nodes.insert({cost + cm_it->second.second, visited + cm_it->second.first});
|
||||
}
|
||||
if (cm_it->second.first == '0' && visited.size() == point_count) {
|
||||
nodes.insert({cost + cm_it->second.second, visited + cm_it->second.first});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
auto main() -> int
|
||||
{
|
||||
Map map;
|
||||
PointMap points;
|
||||
std::string line;
|
||||
|
||||
// Read in map and find the locations we want to visit.
|
||||
while (std::getline(std::cin, line) && !line.empty()) {
|
||||
auto y{map.size()};
|
||||
map.push_back(line);
|
||||
std::size_t x{0};
|
||||
for (x = line.find_first_not_of(".#", x); x != std::string::npos;
|
||||
x = line.find_first_not_of(".#", x + 1)) {
|
||||
points.insert({line[x], {x, y}});
|
||||
}
|
||||
}
|
||||
|
||||
PointCostMap cost_map;
|
||||
for (auto const& p : points) {
|
||||
update_cost_map(cost_map, map, p);
|
||||
}
|
||||
|
||||
auto [route, cost] = find_lowest_cost(cost_map, points.size());
|
||||
std::cout << "Route: " << route << " costs " << cost << '\n';
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user