-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_24_firstcut.cpp
96 lines (80 loc) · 2.66 KB
/
day_24_firstcut.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Advent of Code 2016
// Day 24 - Air Duct Spelunking
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <queue>
#include <tuple>
#include <algorithm>
#include <numeric>
using namespace std;
// parse input
void parse(vector<pair<int,int>>& parts,int& sum)
{
string row;
ifstream data("day_24.tst");
while (getline(data,row)) {
stringstream line(row);
int p1,p2;
line >> p1; line.get();
line >> p2;
parts.push_back(pair<int,int>(p1,p2));
cout << p1 << " " << p2 << endl;
sum+= (p1+p2);
}
}
// heuristic - return 0 when at goal
// e.g. manhattan distance, points sill left to visit etc., parts still to use
// lower is better
int h(int total, int used)
{
return total-used;
}
// generate moves
vector<int> get_moves(vector<int>& used, int port, vector<pair<int,int>>& parts)
{
vector<int> moves; // find any matching ports we can use
for (auto it=begin(parts);it!=end(parts);++it) {
if (find(begin(used),end(used),it-begin(parts))!=end(used)) continue;
if ((*it).first==port || (*it).second==port) {
moves.push_back(it-begin(parts));
}
}
return moves;
}
int main()
{
vector<pair<int,int>> parts;
int sum = 0;
parse(parts,sum);
// priority port used
priority_queue<tuple<int,int,vector<int>>> frontier; // priority, x,y
map<tuple<int,vector<int>>,tuple<int,vector<int>>> previous;
map<tuple<int,vector<int>>,int> best;
vector<int> emp{};
frontier.push(make_tuple(h(sum,0),0,emp));
while (frontier.size()) {
tuple<int,int,vector<int>> s = frontier.top();
frontier.pop();
auto used = get<2>(s);
auto tot_used = accumulate(begin(used),end(used),0,[&](int a,int idx){return a+parts[idx].first+parts[idx].second;});
if (sum-tot_used==0)
break; // we are done
vector<int> moves = get_moves(used,get<1>(s),parts);
for (auto xy : moves) { // calculate cost and add moves to frontier
auto t = make_tuple(get<1>(s),pair<int,int>(get<2>(s).first,get<2>(s).second));
int new_cost = best[t]+1;
auto s2 = make_tuple(v,pair<int,int>(xy.first,xy.second)); // s2 visited,x,y
if (best.find(s2)==end(best) || new_cost<best[s2]) {
frontier.push(make_tuple(new_cost+h(v),v,pair<int,int>(xy.first,xy.second)));
best[s2] = new_cost;
previous[s2] = make_tuple(get<1>(s),get<2>(s));
}
}
}
// solution on top of heap
return 0;
}