#include <algorithm>
#include <span>
#include <concepts>
#include <variant>
#include <cmath>

// dane są klasy:

struct Point {
    int x;
    int y;
};
struct Rectangle {
    Point topLeft;
    Point bottomRight;
};
struct Triangle {
    Point vertices[3];
};

using Shape = std::variant<Rectangle, Triangle>;

// oraz funkcja:
std::floating_point auto distance(Point from, Point to);

// Napisz funkcję o sygnaturze:
auto maxPerimeter(std::span<Shape> shapes);

//, która zwraca figurę o największym obwodzie

// przykładowe rozwiązanie:

std::floating_point auto distance(Point from, Point to) {
    const auto dist_x = to.x - from.x;
    const auto dist_y = to.y - from.y;
    return std::sqrt(dist_x*dist_x + dist_y*dist_y);
}

struct Perimeter {
    double operator()(const Rectangle& r) {
        return 2 *
               (r.bottomRight.x - r.topLeft.x + r.bottomRight.y - r.topLeft.y);
    }
    double operator()(const Triangle& t) {
        return distance(t.vertices[0], t.vertices[1]) +
               distance(t.vertices[1], t.vertices[2]) +
               distance(t.vertices[2], t.vertices[0]);
    }
};

auto maxPerimeter(std::span<Shape> shapes) {
    auto elem = std::max_element(
        shapes.begin(), shapes.end(), [](const auto& s1, const auto& s2) {
            return std::visit(Perimeter{}, s1) < std::visit(Perimeter{}, s2);
        });
    return *elem;
}