Обчисліть число обмотки


15

Число обмотки - це ціле число чистих обертів проти годинникової стрілки, які повинен був зробити спостерігач, щоб слідувати заданому замкнутому шляху. Зауважте, що будь-які оберти за годинниковою стрілкою вважаються від’ємними до числа обмотки. Шлях дозволяється самостійно перетинатися.

Деякі приклади (безсоромно взяті з Вікіпедії) наведені нижче:

введіть тут опис зображення

Ваша мета - обчислити число обмотки для заданого шляху.

Вхідні дані

Припускається, що спостерігач знаходиться біля походження (0,0).

Вхід - це кінцева послідовність точок (подібних до пари цілих чисел) від будь-якого потрібного джерела введення, що описує кусковий лінійний шлях. Ви можете вирівняти це в 1D послідовність цілих чисел, якщо це потрібно, а також можете зсунути введення, щоб прийняти всі x координати перед усіма y координатами / навпаки. Ви також можете прийняти введення як комплексне число a+b i. Шлях може самостійно перетинатися і може містити сегменти нульової довжини. Перша точка - це початок шляху і передбачається лежати десь на позитивній осі х.

Жодна частина шляху не перетинатиме початок. Шлях завжди буде закритим (тобто перша і втрачена точка однакові). Ваш код може передбачати або останню точку, або вимагає включення її.

Наприклад, залежно від ваших уподобань обидва входи вказують один і той же квадрат:

мається на увазі кінцева точка

1,0
1,1
-1,1
-1,-1
1,-1

явна кінцева точка

1,0
1,1
-1,1
-1,-1
1,-1
1,0

Вихідні дані

Вихід є єдиним цілим числом для числа обмотки. Це може бути будь-яке джерело (повернене значення, stdout, файл тощо).

Приклади

Всі приклади мають кінцеву точку, чітко визначену і подаються у вигляді x, y пар. Між іншим, ви також можете мати можливість безпосередньо подавати ці приклади до будь-яких кодів, припускаючи неявно визначені кінцеві точки, а виходи повинні бути однаковими.

1. Основний тест

1,0
1,1
-1,1
-1,-1
1,-1
1,0

Вихідні дані

1

2. Повторне бальне тестування

1,0
1,0
1,1
1,1
-1,1
-1,1
-1,-1
-1,-1
1,-1
1,-1
1,0

Вихідні дані

1

3. Тест за годинниковою стрілкою

1,0
1,-1
-1,-1
-1,1
1,1
1,0

Вихідні дані

-1

4. Зовнішній тест

1,0
1,1
2,1
1,0

Вихідні дані

0

5. Змішана обмотка

1,0
1,1
-1,1
-1,-1
1,-1
1,0
1,-1
-1,-1
-1,1
1,1
1,0
1,1
-1,1
-1,-1
1,-1
1,0
1,1
-1,1
-1,-1
1,-1
1,0

Вихідні дані

2

Оцінка балів

Це код гольфу; виграє найкоротший код. Застосовуються стандартні лазівки. Ви можете використовувати будь-які вбудовані функції до тих пір, поки вони не були спеціально розроблені для обчислення числа обмотки.


2
Чи можна вводити дані як складні числа (або рядкове їх зображення, наприклад, "1-i"або "1-1i"?)
рівень Річки Св.

так, дозволяється будь-який тип пар.
helloworld922

Відповіді:


10

ES6, 83 байти

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2

Приймає як вхід масив пар точок, які інтерпретуються як складні числа. Замість того, щоб перетворити кожну точку в кут, точки поділяються на попередню точку, яку Math.atan2 потім перетворює на кут між -π і π, тим самим автоматично визначаючи, яким способом обертається шлях. Сума кутів тоді 2π перевищує число обмотки.

Оскільки Math.atan2 не хвилює масштаб своїх аргументів, я фактично не виконую повний поділ, z / w = (z * w*) / (w * w*)а просто помножую кожну точку на складну сполучену форму попереднього пункту.

Редагувати: збережено 4 байти завдяки @ edc65.


Приємно і швидко. І я не розумію вашої математики. Але reduceмайже завжди це поганий вибір.
edc65

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2використовуючи натомість карту або зменшити. Ви все одно маєте мій голос
edc65

@ edc65 Дякую; Я використовував, reduceтому що я не розумів, що Math.atan2 (0,0) дорівнює 0. (Ну, це залежить від того, чи один з ваших 0 є насправді -0.) Математика базується на складному поділі, який зазвичай розраховується як z / w = z * w* / |w|², але мене не хвилює величина, тому це просто множення на складний кон'югат. Також трохи заплутано Math.atan2 приймає (y, x) аргументи.
Ніл

Я визнаю, що не розумію коду, але якщо ваш опис точний, я вважаю, що ваша відповідь неправильна. Дійсно, якщо ви ввели точки з цього шляху (я даю картину для більшої ясності), то число обмотки - 1, тоді як ваша проблема
виведе

@Wojowu Вибачте, я мав на увазі кут між точками, виміряний від початку, а не зовнішні кути полігона, тому для вашої картини мій код дійсно повинен обчислити відповідь як 1.
Ніл

3

MATL , 11 байт

X/Z/0)2/YP/

Введення - це послідовність складних чисел, включаючи кінцеву точку.

Спробуйте в Інтернеті!

Пояснення

Більшу частину роботи виконує Z/функція ( unwrap), яка розгортає кути в радіанах, змінюючи абсолютні стрибки, більші або рівні пі, на їх 2 * пі доповнення.

X/       % compute angle of each complex number
Z/       % unwrap angles
0)       % pick last value. Total change of angle will be a multiple of 2*pi because 
         % the path is closed. Total change of angle coincides with last unwrapped
         % angle because the first angle is always 0
2/       % divide by 2
YP/      % divide by pi

1
MATL та Jelly останнім часом майже пов язали більшість математичних проблем. Мене вражає, що ви майже вийшли з мета-гольфу на мову Денніса ...
ETHproductions

@ETHproductions Дякуємо за ваші приємні слова! Так, вони були пов'язані в деяких останніх викликах. З іншого боку, я бачив досить багато проблем, коли кількість байтів Jelly приблизно вдвічі менша від MATL :-D
Луїс Мендо

2

Желе, 11 байт

æAI÷ØPæ%1SH

Це сприймає введення як список y-координат і список x-координат.

Спробуйте тут .


1

Пітона, 111

Найдовша відповідь поки що. Мої мотивації: 1) вивчити python і 2) можливо, порт цього pyth.

from cmath import *
q=input()
print reduce(lambda x,y:x+y,map(lambda (x,y):phase(x/y)/pi/2,zip(q[1:]+q[:1],q)))

Введення подається у вигляді списку складних чисел.

Ідеон.

Я думаю, що підхід схожий на відповідь ES6.

Коли множать 2 складних числа, аргумент чи фаза добутку є сумою аргументу чи фази двох чисел. Таким чином, коли складне число ділиться на інше, тоді фаза коефіцієнта - це різниця між фазами чисельника і знаменника. Таким чином, ми можемо обчислити кут, пройдений через кожну та наступну точку. Сума цих кутів і ділення на 2π дає необхідне число обмотки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.