Рассмотрим потенциально самопересекающийся многоугольник, определенный списком вершин в двумерном пространстве. Например
{{0, 0}, {5, 0}, {5, 4}, {1, 4}, {1, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 1}, {4, 1}, {4, 5}, {0, 5}}
Есть несколько способов определить площадь такого многоугольника, но наиболее интересным является правило четного нечетного. Взяв любую точку на плоскости, проведите линию от точки до бесконечности (в любом направлении). Если эта линия пересекает многоугольник нечетное число раз, точка является частью области многоугольника, если она пересекает многоугольник четное число раз, точка не является частью многоугольника. Для приведенного выше примера многоугольника здесь представлены как его контур, так и четно-нечетная область:
Многоугольник в общем случае не будет ортогональным. Я выбрал только такой простой пример, чтобы было легче подсчитать площадь.
Область этого примера 17
(нет 24
или 33
как могут дать другие определения или область).
Обратите внимание, что согласно этому определению площадь многоугольника не зависит от порядка его намотки.
Соревнование
Учитывая список вершин с целочисленными координатами, определяющими многоугольник, определите его площадь по четно-нечетному правилу.
Вы можете написать функцию или программу, используя ввод через STDIN или ближайшую альтернативу, аргумент командной строки или аргумент функции, и либо вернуть результат, либо распечатать его в STDOUT или ближайшую альтернативу.
Вы можете принимать ввод в любом удобном формате списка или строки, если он не был предварительно обработан.
Результатом должно быть либо число с плавающей запятой с точностью до 6 значащих (десятичных) цифр, либо рациональный результат, представление которого с плавающей запятой с точностью до 6 значащих цифр. (Если вы дадите рациональные результаты, они, вероятно, будут точными, но я не могу требовать этого, поскольку у меня нет точных результатов для справки.)
Вы должны быть в состоянии решить каждый из приведенных ниже тестовых случаев в течение 10 секунд на подходящем настольном компьютере. (В этом правиле есть некоторая свобода действий, поэтому примите во внимание свое мнение. Если на моем ноутбуке это займет 20 секунд, я извлеку выгоду из сомнений, если это займет минуту, я не буду.) Я думаю, что это ограничение должно быть очень щедрым, но предполагается исключить подходы, в которых вы просто дискретизируете многоугольник на достаточно тонкой сетке и рассчитываете, или используете вероятностные подходы, такие как Монте-Карло. Будьте хорошим спортсменом и не пытайтесь оптимизировать эти подходы так, чтобы вы все равно могли уложиться в сроки. ;)
Вы не должны использовать какие-либо существующие функции, связанные непосредственно с полигонами.
Это код гольф, поэтому выигрывает самое короткое представление (в байтах).
Предположения
- Все координаты являются целыми числами в диапазоне
0 ≤ x ≤ 100
,0 ≤ y ≤ 100
. - Там будет хотя бы
3
и не больше50
вершин. - Повторных вершин не будет. Ни одна из вершин не будет лежать на другом ребре. ( Хотя в списке могут быть коллинеарные точки.)
Тестовые случаи
{{0, 0}, {5, 0}, {5, 4}, {1, 4}, {1, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 1}, {4, 1}, {4, 5}, {0, 5}}
17.0000
{{22, 87}, {6, 3}, {98, 77}, {20, 56}, {96, 52}, {79, 34}, {46, 78}, {52, 73}, {81, 85}, {90, 43}}
2788.39
{{90, 43}, {81, 85}, {52, 73}, {46, 78}, {79, 34}, {96, 52}, {20, 56}, {98, 77}, {6, 3}, {22, 87}}
2788.39
{{70, 33}, {53, 89}, {76, 35}, {14, 56}, {14, 47}, {59, 49}, {12, 32}, {22, 66}, {85, 2}, {2, 81},
{61, 39}, {1, 49}, {91, 62}, {67, 7}, {19, 55}, {47, 44}, {8, 24}, {46, 18}, {63, 64}, {23, 30}}
2037.98
{{42, 65}, {14, 59}, {97, 10}, {13, 1}, {2, 8}, {88, 80}, {24, 36}, {95, 94}, {18, 9}, {66, 64},
{91, 5}, {99, 25}, {6, 66}, {48, 55}, {83, 54}, {15, 65}, {10, 60}, {35, 86}, {44, 19}, {48, 43},
{47, 86}, {29, 5}, {15, 45}, {75, 41}, {9, 9}, {23, 100}, {22, 82}, {34, 21}, {7, 34}, {54, 83}}
3382.46
{{68, 35}, {43, 63}, {66, 98}, {60, 56}, {57, 44}, {90, 52}, {36, 26}, {23, 55}, {66, 1}, {25, 6},
{84, 65}, {38, 16}, {47, 31}, {44, 90}, {2, 30}, {87, 40}, {19, 51}, {75, 5}, {31, 94}, {85, 56},
{95, 81}, {79, 80}, {82, 45}, {95, 10}, {27, 15}, {18, 70}, {24, 6}, {12, 73}, {10, 31}, {4, 29},
{79, 93}, {45, 85}, {12, 10}, {89, 70}, {46, 5}, {56, 67}, {58, 59}, {92, 19}, {83, 49}, {22,77}}
3337.62
{{15, 22}, {71, 65}, {12, 35}, {30, 92}, {12, 92}, {97, 31}, {4, 32}, {39, 43}, {11, 40},
{20, 15}, {71, 100}, {84, 76}, {51, 98}, {35, 94}, {46, 54}, {89, 49}, {28, 35}, {65, 42},
{31, 41}, {48, 34}, {57, 46}, {14, 20}, {45, 28}, {82, 65}, {88, 78}, {55, 30}, {30, 27},
{26, 47}, {51, 93}, {9, 95}, {56, 82}, {86, 56}, {46, 28}, {62, 70}, {98, 10}, {3, 39},
{11, 34}, {17, 64}, {36, 42}, {52, 100}, {38, 11}, {83, 14}, {5, 17}, {72, 70}, {3, 97},
{8, 94}, {64, 60}, {47, 25}, {99, 26}, {99, 69}}
3514.46
upath
и lineto
звучит так, будто вы на самом деле предварительно обрабатываете ввод. Т.е. вы берете не список координат, а фактический многоугольник.
CrossingPolygon
.
upath
оператора. (На самом деле это чрезвычайно простое преобразование 1: 1 между разделителями.}, {
Просто становитсяlineto
, и запятая между x и y удаляется, а открывающие и закрывающие скобки заменяются статическим