Евклидовы векторы


14

Учитывая искусство двух векторов в ASCII, найдите величину и степень результирующего вектора.


вход

Это может быть получено через STDIN, считано из локального файла или предоставлено посредством вызова функции. Вот пример двух векторного ввода:

^------>
|
|
|
x

Это означает изменение 4 единиц на север и 7 единиц на восток. Начальная точка каждого входа будет представлена x(десятичной 120).

  • Все векторы являются горизонтальными или вертикальными линиями.

  • Каждый вектор имеет одну из этих четырех конечных точек: ^v<>и состоит из тире ( -десятичное 45) или вертикальной черты ( |десятичное 124).

  • Пустые точки на плоскости заполняются пробелами ( , десятичное число 32).

  • Вход может быть одним x.

  • Смежные векторы всегда перпендикулярны друг другу.

  • Все векторы являются кончиками хвоста.


Выход

Это будет смещение результирующей точки (расстояние от начальной точки) и степень ее перемещения относительно начальной точки.

Для указанного выше значения на выходе должны быть 8.06единицы и 60.3градусы. У каждого должно быть ровно 3 значащих цифры. Вот несколько примеров чисел с 3 значащими цифрами:

  • 1,00
  • 60,1
  • 453
  • 7,08
  • 4,50
  • 349

Все единицы измерения будут <= 999.


Эти числа должны быть выведены в следующем формате. Это использует числа сверху.

8.06 units @ 60.3 degrees

Это может сопровождаться одним пробелом или новой строкой.


Если входные данные одиночные x, без смещения и, следовательно, без угла смещения, выходные данные должны быть либо пустой строкой (один символ новой строки), либо в следующем формате:

0 units @ - degrees

Если вы пытаетесь претендовать на бонус, направление должно быть -также.


В случае, когда бонусы 2, 3 или оба завершены, выходные данные должны соответствовать приведенной ниже модели и соблюдать те же ограничения, что и выше.

8.06 units @ 60.3 degrees NE

Градусы должны измеряться в соответствии со стандартной плоскостью.

       90
  135  |  45
      \|/
180 ---x---- 0
      /|\
  225  |  315
      270

0градусы - это восток, 1 - 89градусы - это северо-восток, 90север и т. д.


Бонусы

Следующее стоит в общей сложности -50%.

  1. Возьмите бонус -10% за каждый дополнительный вектор, который можно обработать. Этот бонус может быть применен до 3 раз. Векторы никогда не будут пересекаться или пересекаться.

  2. Возьмите бонус -10%, если ваш вывод включает в себя основное направление угла (север, юг, восток, запад).

  3. Возьмите бонус -10%, если ваши выходные данные включают промежуточные направления угла (северо-восток, северо-запад, юго-восток, юго-запад).


Примеры

В:

x---->
     |
     v

Вне:

5.39 units @ 338 degrees

Необязательно SE


В:

<--------------^
               |
               |
               x

Вне:

15.3 units @ 169 degrees

Необязательно NW


В:

x
|
|<-----^
|      |
v------>

Вне:

2.24 units @ 297 degrees

Необязательно SE


Примеры (несколько векторов)

В:

x--->
    |
    |
    v----------->

Вне:

16.3 units @ 349 degrees

Необязательно SE


В:

<-------^
|       |
|       |
v       |
        |
        |
        x

Вне:

8.54 units @ 159 degrees

Необязательно NW


В:

^-->
|  |
|  v
|
<--------x

Вне:

6.32 units @ 162 degrees

Необязательно NW


Будут ли векторы иметь нулевую составляющую в одном направлении? Если так, то для чего должен быть вывод x? Какая граница между Севером и Северо-Западом?
lirtosiast

Я добавил эту информацию. Спасибо за указание на это! @ThomasKwa
Зак Гейтс

Вы должны добавить тестовый пример, где есть только один вектор, например x-->. Могут ли векторы пересекаться?
lirtosiast

Обычный вход будет двух векторов. Единственное исключение - пустое x. Их может быть больше двух (если вы пытаетесь завершить бонус), но не меньше. Я работаю над примерами для нескольких векторных входов. Ни при каких входах векторы не будут пересекаться. @ThomasKwa
Зак Гейтс

Я добавил их. @ThomasKwa
Зак Гейтс

Ответы:


2

JavaScript (ES6), 305 байт - бонус 50% = 152,5 балла

v=>(l=v.search`
`+1,s=v.search`x`,u=0,d="-",v.replace(/[<>v^]/g,(p,i)=>{c=o=>v[i+o]!=q;with(Math)if(p<"?"?c(l,q="|")&c(-l):c(1,q="-")&c(-1))d=(atan2(x=i%l-s%l,y=(i/l|0)-(s/l|0))*180/PI+270)%360,u=sqrt(x*x+y*y)}),u[p="toPrecision"](3)+` units @ ${d[p](3)} degrees`)

объяснение

Ввод должен быть дополнен пробелами. Использует все бонусы.

v=>(
  l=v.search`
`+1,                                                     // l = line length
  s=v.search`x`,                                         // s = index of start point
  u=0,                                                   // u = units
  d=                                                     // d = degrees
  w="-",                                                 // w = cardinal direction
  v.replace(/[<>v^]/g,(p,i)=>{                           // for each endpoint
    c=o=>v[i+o]!=q;                                      // compares cell at offset to char
    with(Math)                                           // save having to write "Math."
      if(p<"?"?c(l,q="|")&c(-l):c(1,q="-")&c(-1))        // check for line branching off
        d=(atan2(
          x=i%l-s%l,                                     // x = relative x
          y=(i/l|0)-(s/l|0)                              // y = relative y
        )*180/PI+270)%360,                               // convert to degrees
        u=sqrt(x*x+y*y),
        w="N S"[sign(y)+1]+"W E"[sign(x)+1]              // get cardinal direction
  }),
  u[p="toPrecision"](3)+` units @ ${d[p](3)} degrees `+w // format output
)

Тестовое задание


3

Python 2, 238,5 ( 594 562 482 477-50%) байтов

from math import*
def F(x):s='%.3g'%x;return[[s+'.',s]['.'in s].ljust(4,'0'),s][x>99]
I=input()
V=I.split('\n');N=len(V)
l=max(len(x)for x in V)
q=[' '*(l+2)];V=q+[' '+x.ljust(l+1)for x in V]+q
for k in range(N*l):
 i,j=k/l,k%l;c=V[i+1][j+1]
 if c in'<>^v'and['|'not in zip(*V)[j+1][i:i+3],'-'not in V[i+1][j:j+3]][c>'?']:a,b=i,j
 if c=='x':A,B=i,j
Y=A-a;X=b-B;a=atan2(Y,X)/pi*180%360
print[F(hypot(X,Y))+' units @ '+F(a)+' degrees '+' NS'[cmp(Y,0)]+' EW'[cmp(X,0)],''][I=='x']

объяснение

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

Начало это x

Конец можно найти, посмотрев на каждую стрелку ( <>^v) и их соседей. Если соседи продолжают векторы, игнорируйте. Иначе это конец.

Посмотрите на соседей, перпендикулярных направлению стрелки.

Если они содержат перпендикулярную линию, то это непрерывный вектор.

Примеры ( _указывает на пробел):

_#_   
->_   Neighbors marked by #
_#_ 

___   
->_   (end)
___   

_|_   
->_   (not end)
___ 

___   
->|   (end)
___ 

---   
->_   (end)
___ 

Поскольку конечная точка найдена, может быть любое количество векторов ( бонус 30% ).


Вы уверены, что это работает в Python 2? Кроме того, вы можете изменить «из математического импорта » на «из математического импорта » (уберите пробел).
Rɪᴋᴇʀ

@RikerW Это работает для меня. Ideone: ideone.com/9j86yj использует в \nкачестве переносов строк ...
TFeld

Молодцы, с хорошим объяснением "соседей". Я был немного обеспокоен вашим использованием input()и соответствующим переносом ввода с "", но, похоже, не существует правила против этого!
Тим Педерик
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.