Розглянемо потенційно самопересічний багатокутник, визначений списком вершин у двовимірному просторі. Напр
{{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 значущих цифр. (Якщо ви даєте раціональні результати, вони, ймовірно, будуть точними, але я цього не можу вимагати, оскільки я не маю точних результатів для довідки.)
Ви повинні мати можливість вирішити кожен із наведених нижче тестових випадків на розумній настільній машині. (У цьому правилі є деяка свобода, тому використовуйте найкраще рішення. Якщо на моєму ноутбуці потрібно 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
оператором. (Це насправді надзвичайно просте перетворення між сеператорами.}, {
Просто стаєlineto
, і кома між x і y видаляється, а дужки відкривання та закриття замінюються статичним заголовком і колонтитулом ...)