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


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
Zach Gates

Вам слід додати тестовий випадок, коли є лише один вектор, наприклад x-->. Чи можуть перетинатися вектори?
lirtosiast

Регулярним входом буде два вектори. Єдиним винятком є ​​порожній x. Їх може бути більше двох (якщо намагаються заповнити бонус), але не менше. Я працюю над прикладами для декількох векторних входів. У жодних входах не будуть перетинатися вектори. @ThomasKwa
Zach Gates

Я їх додав. @ThomasKwa
Zach Gates

Відповіді:


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.