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
|
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <tuple>
#include "util.h"
enum Dir { R = 0, D, L, U };
using Cmd = std::tuple<Dir,long>;
using Pos = std::pair<long,long>;
using Polygon = std::vector<Pos>;
std::vector<Cmd> parse(const char* file)
{
std::vector<Cmd> cmds;
if (std::ifstream input{ file }; input.is_open())
{
Dir dir; int steps; std::string color;
std::string line;
while (not std::getline(input,line).eof())
{
std::stringstream in{ line };
in >> util::skip<char> >> util::skip<int> >> color;
steps = std::stoi(color.substr(2, 5), nullptr, 16);
dir = static_cast<Dir>(std::stoi(color.substr(7, 1)));
cmds.push_back({ dir, steps });
}
}
return cmds;
}
std::pair<long,Polygon> compute_border(Pos pos, const std::vector<Cmd>& cmds)
{
Polygon poly;
long border{};
auto [x, y] = pos;
for(const auto& cmd : cmds)
{
auto [dir, steps] = cmd;
switch (dir)
{
case R: y += steps; break;
case D: x += steps; break;
case L: y -= steps; break;
case U: x -= steps;
}
poly.push_back({ x, y });
border += steps;
}
return { border, std::move(poly) };
}
int main(int argc, char* argv[])
{
auto cmds = parse(argv[1]);
auto [border, polygon] = compute_border({ 0, 0 }, cmds);
long area = util::shoelace<long>(polygon.cbegin(), polygon.cend());
std::cout << border + util::pick(area, border) << std::endl;
return 0;
}
|