Wektory euklidesowe

14

Biorąc pod uwagę sztukę ASCII dwóch wektorów, znajdź wielkość i stopień uzyskanego wektora.


Wejście

Można to odebrać przez STDIN, odczytać z lokalnego pliku lub dostarczyć poprzez wywołanie funkcji. Oto przykład wejścia dwóch wektorów:

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

Oznacza to zmianę o 4 jednostki na północ i 7 jednostek na wschód. Punkt początkowy każdego wejścia będzie reprezentowany przez x(dziesiętny 120).

  • Wszystkie wektory są liniami poziomymi lub pionowymi.

  • Każdy wektor ma jeden z tych czterech punktów końcowych: ^v<>i składa się z myślnika ( -dziesiętnie 45) lub pionowego paska ( |dziesiętnie 124).

  • Puste punkty na płaszczyźnie są wypełnione spacjami ( dziesiętnie 32).

  • Dane wejściowe mogą być pojedyncze x.

  • Sąsiadujące wektory są zawsze prostopadłe do siebie.

  • Wszystkie wektory są od końca do końca.


Wynik

Będzie to przemieszczenie wynikowego punktu (odległość od punktu początkowego) i stopień, w jakim się przesunął, względem punktu początkowego.

Dla powyższego wejścia dane wyjściowe powinny być 8.06jednostkami i 60.3stopniami. Każda powinna mieć dokładnie 3 znaczące liczby. Oto kilka przykładów liczb z 3 cyframi znaczącymi:

  • 1,00
  • 60,1
  • 453
  • 7,08
  • 4.50
  • 349

Wszystkie pomiary jednostkowe będą <= 999.


Liczby te powinny być wyprowadzane w poniższym formacie. To używa liczb z góry.

8.06 units @ 60.3 degrees

Po tym może następować pojedyncza spacja lub znak nowej linii.


Jeśli dane wejściowe są pojedyncze x, bez przesunięcia, a tym samym bez kąta przesunięcia, dane wyjściowe powinny być pustą linią (pojedynczy znak nowej linii) lub mieć następujący format:

0 units @ - degrees

Jeśli próbujesz zakwalifikować się do premii, kierunek powinien również być -.


W przypadku, gdy bonusy 2, 3 lub oba zostaną zrealizowane, wynik powinien być zgodny z poniższym modelem i podlegać takim samym ograniczeniom jak powyżej.

8.06 units @ 60.3 degrees NE

Stopnie należy mierzyć zgodnie ze standardową płaszczyzną.

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

0stopnie to wschód, 1 - 89stopnie to północny wschód, 90to północ, itd.


Bonusy

Poniższe są warte łącznie -50%.

  1. Odbierz premię -10% za każdy dodatkowy wektor, który można obsłużyć. Premię tę można zastosować maksymalnie 3 razy. Wektory nigdy się nie nakładają ani nie krzyżują.

  2. Weź bonus -10%, jeśli twój wynik zawiera główny kierunek kąta (północ, południe, wschód, zachód).

  3. Odbierz premię -10%, jeśli twój wynik zawiera pośrednie kierunki kąta (północny wschód, północny zachód, południowy wschód, południowy zachód).


Przykłady

W:

x---->
     |
     v

Na zewnątrz:

5.39 units @ 338 degrees

Opcjonalnie SE


W:

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

Na zewnątrz:

15.3 units @ 169 degrees

Opcjonalnie NW


W:

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

Na zewnątrz:

2.24 units @ 297 degrees

Opcjonalnie SE


Przykłady (wiele wektorów)

W:

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

Na zewnątrz:

16.3 units @ 349 degrees

Opcjonalnie SE


W:

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

Na zewnątrz:

8.54 units @ 159 degrees

Opcjonalnie NW


W:

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

Na zewnątrz:

6.32 units @ 162 degrees

Opcjonalnie NW

Zach Gates
źródło
Czy wektory kiedykolwiek będą miały składową zerową w jednym kierunku? Jeśli tak, to po co x? Jaka jest granica między północą a północnym zachodem?
lirtosiast
Dodałem tę informację. Dzięki za wskazanie tego! @ThomasKwa
Zach Gates
Należy dodać przypadek testowy, w którym jest tylko jeden wektor, np x-->. Czy wektory mogą się krzyżować?
lirtosiast
Regularne wejście będzie składać się z dwóch wektorów. Jedynym wyjątkiem jest pusty x. Może być ich więcej niż dwa (przy próbie uzupełnienia bonusu), ale nie mniej. Pracuję nad przykładami dla wielu wektorów. W żadnym wejściu wektory się nie krzyżują. @ThomasKwa
Zach Gates
Dodałem je. @ThomasKwa
Zach Gates

Odpowiedzi:

2

JavaScript (ES6), 305 bajtów - 50% bonus = 152,5 wyniku

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

Wyjaśnienie

Wejście musi być wypełnione spacjami. Wykorzystuje wszystkie bonusy.

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
)

Test

użytkownik 81655
źródło
3

Python 2, 238,5 ( 594 562 482 477-50%) bajtów

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']

Wyjaśnienie

Znajduje pozycję początkową i końcową, patrząc na każdy znak na wejściu.

Start jest x

Koniec można znaleźć, patrząc na każdą strzałkę (<>^v ) i ich sąsiadów. Jeśli sąsiedzi kontynuują wektory, zignoruj. W przeciwnym razie to koniec.

Spójrz na sąsiadów prostopadłych do kierunku strzałki.

Jeśli zawierają linię prostopadłą, jest to wektor ciągły.

Przykłady ( _wskazuje spację):

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

___   
->_   (end)
___   

_|_   
->_   (not end)
___ 

___   
->|   (end)
___ 

---   
->_   (end)
___ 

Ponieważ znaleziono punkt końcowy, może być dowolna liczba wektorów ( premia 30% ).

TFeld
źródło
Czy na pewno działa to w Pythonie 2? Dodatkowo możesz zmienić „z importu matematycznego ” na „z importu matematycznego ” (usuń spację).
R
@RikerW Działa dla mnie. Ideone: ideone.com/9j86yj używa \njako przełomów ...
TFeld,
Dobra robota, z przyjemnym wyjaśnieniem „sąsiadów”. Byłem trochę zaniepokojony twoim użyciem input()i odpowiednim opakowaniem danych wejściowych za pomocą „”, ale wydaje się, że nie ma żadnych zasad!
Tim Pederick