summaryrefslogtreecommitdiff
path: root/2023/18/src/part1.cpp
blob: b7c9e0935150ca64ba0242e0c22e1ed29aba6154 (plain) (blame)
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
#include <iostream>
#include <fstream>
#include <sstream>
#include <deque>
#include <vector>
#include <tuple>

#include "util.h"

using Cmd = std::tuple<char,int>;
using Pos = std::pair<int,int>;
using Polygon = std::vector<Pos>;

std::vector<Cmd> parse(const char* file)
{
    std::vector<Cmd> cmds;
    if (std::ifstream input{ file }; input.is_open())
    {
        char dir; int steps;
        std::string line;
        while (not std::getline(input,line).eof())
        {
            std::stringstream in{ line };
            in >> dir >> steps;
            cmds.push_back({ dir, steps });
        }
    }
    return cmds;
}

std::pair<int,Polygon> compute_border(Pos pos, const std::vector<Cmd>& cmds)
{
    Polygon poly;
    int 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);
    int area = util::shoelace<int>(polygon.cbegin(), polygon.cend());

    std::cout << border + util::pick(area, border) << std::endl;
    return 0;
}