Вычислить число обмоток


15

Число обмоток - это целое число чистых оборотов против часовой стрелки, которое наблюдатель должен совершить, чтобы следовать заданному замкнутому пути. Обратите внимание, что любые обороты по часовой стрелке считаются отрицательными по отношению к числу обмоток. Путь разрешен самопересекающимся.

Некоторые примеры (бессовестно взятые из Википедии) приведены ниже:

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

Ваша цель - вычислить число обмоток для заданного пути.

вход

Предполагается, что наблюдатель находится в начале координат (0,0).

Входные данные представляют собой конечную последовательность точек (в виде пары целых чисел) из любого желаемого входного источника, который описывает кусочно-линейный путь. При желании вы можете сгладить это в одномерную последовательность целых чисел, а также быстро изменить ввод, чтобы получить все координаты x перед всеми координатами y / наоборот. Вы также можете принять ввод как комплексное число a+b i. Путь может сам пересекаться и может содержать сегменты нулевой длины. Первая точка - это начало пути, и предполагается, что она лежит где-то на положительной оси x.

Никакая часть пути не будет пересекать источник. Путь всегда будет закрыт (т.е. первая и потерянная точки совпадают). Ваш код может подразумевать последний пункт или требовать его включения.

Например, в зависимости от ваших предпочтений оба входа указывают один и тот же квадрат:

подразумеваемая конечная точка

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

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

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

Выход

Вывод представляет собой одно целое число для номера обмотки. Это может быть любой источник (возвращаемое значение, стандартный вывод, файл и т. Д.).

Примеры

Все примеры имеют явно определенную конечную точку и задаются как пары 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"?)
Level River St

да, любой тип пары разрешен.
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, а ваша проблема выдаст 2.
Wojowu

@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)))

Ввод дан в виде списка комплексных чисел.

Ideone.

Я думаю, что подход похож на ответ ES6.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.