Cppconf piter
От: ioni Россия  
Дата: 03.09.19 17:00
Оценка:
Собирается кто нибудь
Re: Cppconf piter
От: Stanislav V. Zudin Россия  
Дата: 03.09.19 17:06
Оценка: 7 (1)
Здравствуйте, ioni, Вы писали:

I>Собирается кто нибудь


А как же!
_____________________
С уважением,
Stanislav V. Zudin
Re: Cppconf piter
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 30.10.19 10:35
Оценка:
Здравствуйте, ioni, Вы писали:

I>Собирается кто нибудь


Up! Начинается завтра. Буду рад личной встрече с кем-нибудь.
Re[2]: Cppconf piter
От: Stanislav V. Zudin Россия  
Дата: 30.10.19 10:45
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Up! Начинается завтра.


Да, доклады обещают быть интересными — хоть разорвись на три зала

N>Буду рад личной встрече с кем-нибудь.


Меня найти легко — я под своей фамилией
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: Cppconf piter
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 30.10.19 10:52
Оценка: 9 (1)
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Меня найти легко — я под своей фамилией


Я тоже под своей, думаю, не потеряемся.
Re[4]: Cppconf piter
От: rg45 СССР  
Дата: 30.10.19 20:41
Оценка:
Здравствуйте, Nuzhny, Вы писали:

SVZ>>Меня найти легко — я под своей фамилией

N>Я тоже под своей, думаю, не потеряемся.

Я тоже сначала собирался, потом лень победила, как обычно.

Удачи вам! И ждем известий.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Cppconf piter
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 15.11.19 09:19
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

Вспомнил про задачу о треугольниках. Забыл, как называется алгоритм, с помощью которого ты её решил. Не подскажешь?
Re[4]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 10:18
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Вспомнил про задачу о треугольниках. Забыл, как называется алгоритм, с помощью которого ты её решил. Не подскажешь?


А что за задача? Не о симплекс методе речь часом?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Cppconf piter
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 15.11.19 10:58
Оценка: 9 (1) :)
Здравствуйте, rg45, Вы писали:

R>А что за задача? Не о симплекс методе речь часом?


  Картинка

Мне пришла идея про топологическую сортировку, но уснул, укладывая детей спать. Вроде как есть что-то намного проще и быстрее.
Re[6]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 11:07
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Мне пришла идея про топологическую сортировку, но уснул, укладывая детей спать. Вроде как есть что-то намного проще и быстрее.


Классная обучающая задачка. Но условие на грани фола, по правилам форума
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 15.11.2019 11:08 rg45 . Предыдущая версия .
Re[4]: Cppconf piter
От: Stanislav V. Zudin Россия  
Дата: 15.11.19 12:37
Оценка: 27 (2) +1
Привет, Сергей

N>Вспомнил про задачу о треугольниках. Забыл, как называется алгоритм, с помощью которого ты её решил. Не подскажешь?


Там какого-то классического алгоритма нет. Моя вольная импровизация:

1. Выбрали ребра, имеющие два инцидентных треугольника
2. Упорядочили их по оси Y
3. Для каждого ребра определили какой треугольник выше, а какой ниже, вывели сперва верхний, потом нижний.
Всё!

Если ребро направлено слева направо, то верхним получается треугольник слева от ребра, а если справа налево, то треугольник, который справа.
Ну и для треугольников нужен признак, что его уже "посчитали", чтобы не было дублей.

Способ описания треугольников похож на tristrip, применяемый в графике. Но какую-то пользу из него я не извлёк, сделал в лоб.

Собсно, вот код этого безобразия
  котт
#include <iostream>
#include <vector>
#include <algorithm>

typedef int VERTEX;
typedef int TRIANGLE;
typedef int EDGE;

struct TriEdge
{
    VERTEX v1, v2;      // Vertexes of the edge
    TRIANGLE t1, t2;    // The triangles sharing the edge
    TriEdge(VERTEX _v1, VERTEX _v2, TRIANGLE _t1)
        : v1(_v1), v2(_v2), t1(_t1), t2(-1) {}
};

struct DOT
{
    int x, y;
    explicit DOT(int x_, int y_) noexcept
        : x(x_), y(y_)
    {
    }
};

static inline bool operator<(const DOT& d1, const DOT& d2)
{
    return (d1.x < d2.x) || (d1.x == d2.x && d1.y < d2.y);
}

static inline bool operator==(const DOT& d1, const DOT& d2)
{
    return d1.x == d2.x && d1.y == d2.y;
}

std::vector<VERTEX> triangles;
std::vector<TriEdge> edges;
std::vector<DOT> vertexes;

// ==========================================================================
static inline TRIANGLE getTriangleCount()
{
    return static_cast<TRIANGLE>(triangles.size() / 3);
}

static inline DOT getDotOfVertex(VERTEX v)
{
    return vertexes[v];
}

static inline EDGE getEdgeCount()
{
    return static_cast<EDGE>(edges.size());
}

// ==========================================================================
static inline VERTEX getVert1FromTriangle(TRIANGLE t)
{
    return triangles[(t * 3) + 0];
}
static inline VERTEX getVert2FromTriangle(TRIANGLE t)
{
    return triangles[(t * 3) + 1];
}
static inline VERTEX getVert3FromTriangle(TRIANGLE t)
{
    return triangles[(t * 3) + 2];
}

// ==========================================================================
static void buildEdges()
{
    edges.reserve(triangles.size() * 3);
    for (TRIANGLE t = 0, tE = getTriangleCount(); t < tE; ++t)
    {
        VERTEX v[3] = {
            getVert1FromTriangle(t),
            getVert2FromTriangle(t),
            getVert3FromTriangle(t)
        };

                                        // ARRANGE THE VERTEXES IN ASCENDING ORDER
        std::sort(std::begin(v), std::end(v));

                                        // CREATE THREE EDGES
        edges.emplace_back(v[0], v[1], t);
        edges.emplace_back(v[0], v[2], t);
        edges.emplace_back(v[1], v[2], t);
    }

    if (edges.empty())
        return;
                                        // REMOVE DUPLICATES AND MERGE SHARED EDGES
    std::sort(
        edges.begin(), 
        edges.end(), 
        [](const TriEdge& e1, const TriEdge& e2) 
        {
        return (e1.v1 < e2.v1) || (e1.v1 == e2.v1 && e1.v2 < e2.v2);
        }
    );

    for (size_t i = 0, iE = edges.size()-1; i < iE;)
    {
        TriEdge& e1 = edges[i];         // FOR EACH PAIR OF EDGES
        TriEdge& e2 = edges[i + 1];
        if (e1.v1 < 0)                  // SKIP DEAD EDGE
        {
            // Unreachable!
            ++i;
            continue;
        }

                                        // IF A DUPLICATE FOUND
        if (e1.v1 == e2.v1 && e1.v2 == e2.v2)
        {
            e1.t2 = e2.t1;              // SHARE THE EDGE BETWEEN TWO ADJACENT TRINGLES
            e2.v1 = -1;                 // MARK EDGE DEAD
            i += 2;                     // GET THE NEXT PAIR
        }
        else                            // OTHERWISE
        {
            ++i;                        // GET THE NEXT EDGE
        }
    }

                                        // REMOVE DEAD EDGES AND THE ONES HAVING ONLY ONE TRIANGLE
    auto it = std::remove_if(edges.begin(), edges.end(), 
        [](const TriEdge& e) 
    {
        return e.v1 < 0 || e.t2 < 0;
    });

    edges.erase(it, edges.end());
}

static inline bool upAndLeft(const DOT& d1, const DOT& d2)
{
    return (d1.y > d2.y) || (d1.y == d2.y && d1.x < d2.x);
}

static bool orderEdgesByY(const TriEdge& e1, const TriEdge& e2)
{
    DOT d1s = getDotOfVertex(e1.v1),
        d1e = getDotOfVertex(e1.v2),
        d2s = getDotOfVertex(e2.v1),
        d2e = getDotOfVertex(e2.v2);
    // ENSURE THE 1st VERTEX IS HIGHER
    if (d1e.y > d1s.y)
        std::swap(d1s, d1e);
    if (d2e.y > d2s.y)
        std::swap(d2s, d2e);

    return upAndLeft(d1s, d2s) || (d1s == d2s && upAndLeft(d1e, d2e));
}

static bool isEdgeLeftToRight(const TriEdge& e)
{
    DOT d1 = getDotOfVertex(e.v1),
        d2 = getDotOfVertex(e.v2);
    return d1 < d2;
}

static inline bool equalEdge(VERTEX v1, VERTEX v2, VERTEX vt1, VERTEX vt2)
{
    if (vt1 > vt2)
        std::swap(vt1, vt2);
    return v1 == vt1 && v2 == vt2;
}

static VERTEX getTheOppositeVertex(TRIANGLE t, VERTEX v1, VERTEX v2)
{
    VERTEX v[3] = 
    {
        getVert1FromTriangle(t),
        getVert2FromTriangle(t),
        getVert3FromTriangle(t)
    };

    if (equalEdge(v1, v2, v[0], v[1]))
        return v[2];
    if (equalEdge(v1, v2, v[0], v[2]))
        return v[1];
    if (equalEdge(v1, v2, v[1], v[2]))
        return v[0];

    // Unreachable
    return v[0]; // return something
}

//! \brief Get doubled area of triangle ABC
//! CCW direction is considered positive
template<typename D> inline double square2(const D& A, const D& B, const D& C)
{
    /* A cross product of two vectors AB x AC */
    return  double(A.y - B.y) * double(C.x - A.x)
        - double(A.x - B.x) * double(C.y - A.y);
}

//! Whether the dot <d> is on the right side of the segment <se>
static bool isOnTheRight(const DOT& d, const DOT& s, const DOT& e)
{
    bool retval = square2(s, e, d) < 0.0;
    return retval;
}

static TRIANGLE getRightTriangle(const TriEdge& e)
{
    VERTEX opp_vert = getTheOppositeVertex(e.t1, e.v1, e.v2);

    DOT opp_dot = getDotOfVertex(opp_vert);
    DOT d1 = getDotOfVertex(e.v1),
        d2 = getDotOfVertex(e.v2);

    if (isOnTheRight(opp_dot, d1, d2))
        return e.t1;
    else
        return e.t2;
}

static TRIANGLE getLeftTriangle(const TriEdge& e)
{
    TRIANGLE t = getRightTriangle(e);
    return (t == e.t1)  ? e.t2 
                        : e.t1;
}

static bool loadData()
{
    /* 
     * The first line contains two integers:
     * Number of vertexes N (3 <= N <= 10M) and
     * number of triangles M (1 <= M <= 10M)
     * The following N lines contain vertexes' coordinates (a pairs of integers)
     * The following M lines contain triples of vertexes (starting from 1)
    */

    int N = 0, M = 0;
    std::cin >> N >> M;
    if (N < 3 || 10000000 < N)
    {
        std::cerr << "The number of vertexes is invalid. Got " 
            << N << ", expected [3, 10M]\n";
        return false;
    }
    if (M < 1 || 10000000 < M)
    {
        std::cerr << "The number of triangles is invalid. Got "
            << M << ", expected [1, 10M]\n";
        return false;
    }

    vertexes.reserve(N);

    for (int i = 0; i < N; ++i)
    {
        if (!std::cin)
        {
            std::cerr << "Inconsistent data. Failed to read vertexes\n";
            return false;
        }

        int x = 0, y = 0;
        std::cin >> x >> y;
        vertexes.emplace_back(x, y);
    }

    triangles.reserve(M * 3);
    for (int i = 0; i < M; ++i)
    {
        if (!std::cin)
        {
            std::cerr << "Inconsistent data. Failed to read triangles\n";
            return false;
        }

        int v1 = -1, v2 = -1, v3 = -1;
        std::cin >> v1 >> v2 >> v3;
        triangles.push_back(v1 - 1);
        triangles.push_back(v2 - 1);
        triangles.push_back(v3 - 1);
    }

    return true;
}

int main(int argc, char *argv[])
{
    // READ INPUT DATA
    if (!loadData())
        return 1;

    // BUILD EDGES
    buildEdges();

    // ORDER EDGES BY Y
    std::sort(edges.begin(), edges.end(), orderEdgesByY);

    std::vector<bool> visited_tri(getTriangleCount(), false);
    const char* pszDelimiter = "";
    // FOR EACH EDGE
    for (const TriEdge& e : edges)
    {
        // CHOOSE THE UPPER TRIANGLE
        TRIANGLE tt[2] = { getRightTriangle(e),
                           getLeftTriangle(e) };
        if (isEdgeLeftToRight(e))
            std::swap(tt[0], tt[1]);

        // OUTPUT
        for(TRIANGLE t : tt)
        {
            if (!visited_tri[t])
            {
                std::cout << pszDelimiter << t + 1;
                pszDelimiter = " ";
                visited_tri[t] = true;  /* Do not print the triangle twice */
            }
        }
    }

    return 0;
}
_____________________
С уважением,
Stanislav V. Zudin
Re[5]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 14:47
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>1. Выбрали ребра, имеющие два инцидентных треугольника

SVZ>2. Упорядочили их по оси Y
SVZ>3. Для каждого ребра определили какой треугольник выше, а какой ниже, вывели сперва верхний, потом нижний.
SVZ>Всё!

Единственное, что можно заметить, что ребра могу разделяться частично, как на рисунке. Но это всего лишь незначительное усложнение. В целом идея рабочая

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 14:57
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>1. Выбрали ребра, имеющие два инцидентных треугольника

SVZ>2. Упорядочили их по оси Y
SVZ>3. Для каждого ребра определили какой треугольник выше, а какой ниже, вывели сперва верхний, потом нижний.
SVZ>Всё!

С другой стороны, вот случай, когда это решение не работает. Или подобный случай невозможен по условиям задачи?

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Cppconf piter
От: Stanislav V. Zudin Россия  
Дата: 15.11.19 14:58
Оценка:
Здравствуйте, rg45, Вы писали:

R>Единственное, что можно заметить, что ребра могу разделяться частично, как на рисунке. Но это всего лишь незначительное усложнение. В целом идея рабочая


R>Image: incident_edges.jpg


Не, такая конфигурация запрещена условием задачи. "Углы стёкол не касаются граней...". Т.е. на входе честная триангуляция.

Но код есть куда оптимизировать. Сейчас в глаза бросаются неоптимальные куски, где вызовы дублируются — можно сходу соптимиздить пару-тройку тактов, даже не меняя алгоритма.
На обдумывание времени было мало, да и стимула не было — Самсунг пожмотился подарить телевизор
_____________________
С уважением,
Stanislav V. Zudin
Re[7]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 15:00
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:


SVZ>Не, такая конфигурация запрещена условием задачи. "Углы стёкол не касаются граней...". Т.е. на входе честная триангуляция.


Не, ну так это ж просто недорисованная картинка. Можно дорисовать так, что все будет касаться.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 15:04
Оценка:
R>Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>>1. Выбрали ребра, имеющие два инцидентных треугольника

SVZ>>2. Упорядочили их по оси Y
SVZ>>3. Для каждого ребра определили какой треугольник выше, а какой ниже, вывели сперва верхний, потом нижний.
SVZ>>Всё!

R>С другой стороны, вот случай, когда это решение не работает. Или подобный случай невозможен по условиям задачи?


R>Image: incident_edges(2).jpg


А все, прочитал еще раз условие, вопрос снимается, как дурацкий
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[8]: Cppconf piter
От: Stanislav V. Zudin Россия  
Дата: 15.11.19 15:05
Оценка: :)
Здравствуйте, rg45, Вы писали:

SVZ>>Не, такая конфигурация запрещена условием задачи. "Углы стёкол не касаются граней...". Т.е. на входе честная триангуляция.


R>Не, ну так это ж просто недорисованная картинка. Можно дорисовать так, что все будет касаться.


На эту задачу и так со всей конференции набралось лишь два десятка дураков желающих решать.
А если усложнить условие, то вообще никто не стал бы дергаться.
_____________________
С уважением,
Stanislav V. Zudin
Re[9]: Cppconf piter
От: rg45 СССР  
Дата: 15.11.19 15:06
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>На эту задачу и так со всей конференции набралось лишь два десятка дураков желающих решать.

SVZ>А если усложнить условие, то вообще никто не стал бы дергаться.

Я своей малой обязательно подкину, когда у нее появится немного свободного времени. Если появится, конечно. Препод у них просто маньяк.
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.