Skarb piratów

18

Znalezienie skarbu ukrytego przez piratów jest naprawdę łatwe. Wszystko, czego potrzebujesz, to mapa. Powszechnie wiadomo, że piraci ręcznie rysują mapy i opisują algorytm, aby znaleźć miejsce w następujący sposób: „Stań w pobliżu samotnej palmy, zrób 30 kroków w kierunku lasu, 15 w kierunku jeziora ...”

Podróż taką trasą jest zwykle świetną okazją do zobaczenia scenerii ... Jednak w dzisiejszych czasach nikt nie ma na to czasu. Dlatego poszukiwacze skarbów poprosili cię o napisanie programu, który określi dokładną lokalizację skarbu na podstawie danej mapy.


Wejście

Dane wejściowe składają się z wielu instrukcji <Direction> <Distance>oddzielonych przecinkami (po których następuje jedna biała spacja).

Kierunek jest jednym z następujących:
N- Północ, S- Południe, E- Wschód, W- Zachód,
NE- Północny wschód, - Północny NWzachód, SE- Południowy wschód, SW- Południowy zachód.

Odległość jest liczbą całkowitą (od 1 do 1000).

Wynik

Rezultatem są współrzędne, w których kończysz po zakończeniu instrukcji, z trzema miejscami po przecinku, oddzielonymi przecinkiem i spacją. Lokalizacja początkowa ma zerowe współrzędne (0, 0).

Pierwsza współrzędna to X (wschód oznacza współrzędne większe niż zero, zachód oznacza mniej niż zero).
Druga współrzędna to Y (północ oznacza więcej niż zero, południe oznacza mniej niż zero).


Przykłady

1. N 3, E 1, N 1, E 3, S 2, W 1

    3.000, 2.000

2) NW 10

    -7.071, 7.071

3) NE 42, NW 42, SE 42, SW 42

    0.000, 0.000


Źródło (w języku ukraińskim). Format wejściowy jest tam inny.

Oleh Prypin
źródło
8
Punkty bonusowe za zrobienie tego w Logo? ;)
Peter Taylor
@Peter Format wyjściowy jest ścisły ... Zobaczymy jednak, czy ludzie polubią obraz: D
Oleh Prypin
1
Pierwszy przykładowy wynik powinien być -3.000, 2.000.
Lowjacker
z logo UCB format wyjściowy można uzyskać jako (print (word (form xcor 4 3) ",) (form ycor 4 3)). Ale nie jestem pewien, jak łatwe byłoby analizowanie danych wejściowych.
Peter Taylor
@Lowjacker Tak, dziękuję. W rzeczywistości dane wejściowe były nieprawidłowe.
Oleh Prypin

Odpowiedzi:

7

Ruby 1.9, 175 171 162 153 130 120 117

l=0
gets.scan(/(\w+) (\d+)/){|d,n|l+=n.to_i*?i.to_c**%w[E NE N NW W SW S SE].index(d).quo(2)}
puts'%.3f, %.3f'%l.rect
Lowjacker
źródło
?i.to_cmożna skrócić do 1.i-4 bajtów.
MegaTom
3

Haskell (291)

import Text.Printf
d=sqrt(0.5)
f"N"n(x,y)=(x,y+n)
f"S"n(x,y)=(x,y-n)
f"E"n(x,y)=(x+n,y)
f"W"n(x,y)=(x-n,y)
f[a,b]n(x,y)=(s,t)where(s,_)=f[b](d*n)(x,y);(_,t)=f[a](d*n)(x,y)
p[]=(0,0)
p(a:b:c)=f a(read b::Float)$p c
s(a,b)=printf"%.3f, %.3f"a b
main=getLine>>=putStrLn.s.p.words.filter(/=',')
marinus
źródło
Co powiesz na zmianę definicji f, aby użyć osłon wzorców? Mają tę fajną właściwość, że nie wymagają łamania linii i w tym przypadku powinny być bardziej breve. Użyj także interakcji.
FUZxxl
3

C99 (319 znaków)

#define B ;break;
#include<math.h>
#include<stdio.h>
float x,y,w,z,j;int
main(void){int
k;char
c[3];while(scanf("%s%d,",c,&k)==2){j=k;w=1;switch(c[1]){case'E':w=3;default:w-=2;j=sqrt(k*k/2)B
case
0:w=z=0;}switch(*c){case'N':z=1
B
case'S':z=-1
B
case'E':w=1
B
default:w=-1;}x+=w*j;y+=z*j;}printf("%5.3f, %5.3f\n",x,y);}

wejście stdin, uruchomienie testowe w ideone :)

pmg
źródło
3

Python, 158 154 150 znaków

p=0j
for s in raw_input().split(','):c,d=s.split();v=sum(dict(N=1j,E=1,S=-1j,W=-1)[x]for x in c);p+=v*int(d)/abs(v)
print'%.3f, %.3f'%(p.real,p.imag)
Keith Randall
źródło
W rzeczywistości masz 157 znaków, a nie 158.
Lowjacker
Chyba nie muszę, ale zwykle liczę końcowy znak nowej linii.
Keith Randall
[157] Wiersz 1: D=dict(N=1j,E=1,S=-1j,W=-1)[153] Wiersz 2: czy jnaprawdę jest potrzebny? [152] Wiersze 3-4: Jeśli przełączysz się na Python 3, raw_inputinputi mimo że później będziesz musiał użyć nawiasów print, zapisujesz 2 znaki [150]
Oleh Prypin
1
@BlaXpirit: Dzięki za optymalizację dict. J jest potrzebne w linii 2, w przypadku gdy wszystkie kierunki to E i W. Wynikowe p musi być złożone .reali .imagdziałać.
Keith Randall
1
klasa int ma oba imagreal
atrybuty
3

JavaScript, 179 164 170 168 158 156 153 znaki

prompt(X=Y=0).replace(/(N|S)?(.)? (\d+)/g,
        function(m,y,x,n){
            n/=x&&y?Math.SQRT2:1
            Y+=y?y<'S'?n:-n:0
            X+=x?x<'W'?n:-n:0
        })
alert(X.toFixed(3)+', '+Y.toFixed(3))
  • 170: naprawiono problem z dokładnością
  • 168: zamieniono (E|W)w wyrażeniu regularnym na(.)
  • 158: zastąpiono powtarzalną logikę w funkcji zmienną d
  • 156: ponownie użyte nzamiast nowej zmiennejd
  • 153: Osobiście uważam, że ta edycja sprawia, że ​​jest dziesięć razy brzydsza, ale jest o trzy znaki krótsza. Opiera się na niestandardowym zachowaniu, które można wywoływać obiektami RegExp jako funkcje: /./g('string')jest takie samo jak /./g.exec('string'):

    for(p=prompt(X=Y=0),R=/(N|S)?(.)? (\d+)/g;[,y,x,n]=R(p)||0;X+=x?x<'W'?n:-n:0)n/=x&&y?Math.SQRT2:1,Y+=y?y<'S'?n:-n:0;alert(X.toFixed(3)+', '+Y.toFixed(3))

Casey Chu
źródło
1
Niestety, q = .707 nie działa na wejściu „NW 10” z powodu błędów zaokrąglania; Myślę, że potrzebujesz „q = Math.SQRT1_2”, który dodaje 8 znaków. Z drugiej strony możesz zastąpić „(E | W)?” z "(.)?" skoro już ustaliłeś północ / południe / none, a dane wejściowe są dobrze uformowane, oszczędzając 2 znaki.
DocMax
Dzięki za bit wyrażenia regularnego. Jeśli chodzi o kwestię dokładności, zamiast tego użyłem SQRT2 i przestawiłem mnożenie na dzielenie.
Casey Chu,
2

Haskell, 199 znaków

import Text.Printf
import Complex
i=0:+(1::Float)
e 'S'= -i
e d=i^mod(fromEnum d-1)4
g p(d:s:t)=g(p+(signum.sum.map e)d*(fst(reads s!!0):+0))t
g(x:+y)[]=printf"%.3f, %.3f"x y
main=interact$g 0.words
hammar
źródło
1

Scala ( 367 , 332)

var (x,y,s)=(.0,.0,.7071);args.mkString(" ").split(",").foreach{m=>val a=m.trim.split(" ");var (n,u,v)=(a(1).toInt,.0,.0);a(0) match{case "N"=>v=1;case "S"=>v= -1;case "E"=>u=1;case "W"=>u= -1;case "NW"=>{u= -s;v=s};case "NE"=>{u=s;v=s};case "SW"=>{u= -s;v= -s};case "SE"=>{u=s;v= -s}};x += n*u;y += n*v};printf("%1.3f %1.3f\n",x,y)
Lalith
źródło
1

Java (459) (445) (402) (382) (363) (352)

import java.util.*;class
M{public
static void main(String[]a){double
x=0,y=0;Scanner
s=new
Scanner(System.in);s.useDelimiter("\\W+");while(s.hasNext()){String
d=s.next();double
z=Math.sqrt(d.length());int
w=s.nextInt();y+=(d.contains("N")?w:d.contains("S")?-w:0)/z;x+=(d.contains("E")?w:d.contains("W")?-w:0)/z;}System.out.format("%1.3f %1.3f",x,y);}}

wejście standardowe

prawdziwość
źródło
1

PowerShell, 178

$input-split','|%{,@{N=0,1
NE=($s=.707106781186548),$s
E=1,0
SE=$s,-$s
S=0,-1
SW=-$s,-$s
W=-1,0
NW=-$s,$s}[($a=-split$_)[0]]*$a[1]}|%{$x+=$_[0]
$y+=$_[1]}
'{0:N3}, {1:N3}'-f$x,$y

Prawdopodobnie może to stracić do 10 znaków, zmniejszając dokładność √2 / 2.

Joey
źródło
1

C (gcc) , 155 152 bajtów

-3 bajty dzięki pułapce cat

float x,y,l;D;main(d){for(;scanf("%s%f,",&d,&l)>0;y+=d^78?d^83?0:-l:l)D=d,l/=D>99?D/=256,d&=255,sqrt(2):1,x+=D^87?D^69?0:l:-l;printf("%.3f, %.3f",x,y);}

Wypróbuj online!

gastropner
źródło
0

Groovy (215)

x=0.0;y=0.0;args.join(' ').split(', ').each{d=it.split(' ');c=d[0]==~/../?Math.sqrt(2):1;s=d[1] as int;a=['N':1,'S':-1,'E':1,'W':-1];m=d[0]=~/N|S/;y+=m?a[m[0]]*(s/c):0;m=d[0]=~/E|W/;x+=m?s/c*a[m[0]]:0};print "$x,$y"

odczytuje dane wejściowe jako argumenty programu. Przykład:

groovy golf.groovy NW 10, SW 10, W 10
TheBigS
źródło
0

Perl 5 -n , 122 bajtów

s,(N|S)?(E|W)? (\d+),$d=$3/($1&$2?2**.5:1);$x+=$2&&$d*(-1)**($2gt F);$y+=$1&&$d*(-1)**($1gt O),ge;printf"%.3f, %.3f",$x,$y

Wypróbuj online!

Xcali
źródło
0

J , 93 bajty

[:0j3&":@+.@(1#.".@>@{:*(0j1^2%~i.8){~<;._1@' E NE N NW W SW S SE'i.{.)@|:[:(<;._1);._1', ',]

Wypróbuj online!

Jonasz
źródło