Chodzę po Manhattanie, jak daleko jestem od hotelu?

27

Niepotrzebna i skomplikowana historia

Chodzę po Manhattanie, blok po bloku, a moje stopy są zmęczone i chcę wracać do domu.

Ruch uliczny jest dość duży, ale na szczęście jestem bardzo bogaty i mam w hotelu helikopter w gotowości. Ale potrzebuję, aby wiedzieli, ile paliwa trzeba spakować na lot, i dlatego muszą znać moją bezpośrednią odległość od hotelu. Pamiętałem, które bloki przeszedłem i mogę im powiedzieć, jaką trasę wybrałem. Odległość ta musi być jednak precyzyjna, jeśli są zbyt krótkie, nie wrócimy zbyt długo i kupiłem paliwo, którego nie mogę użyć.

Czy możesz napisać mi program, który przeliczy to na odległość, którą będą musieli pokonać podczas lotu, aby mnie zabrać?

Specyfikacja:

Napisz mi funkcję, która:

  1. Akceptuje listę lub ciąg bloków kroczonych względem dowolnej siatki:
    • U p, D own, L eft i R ight.
    • Może być wielką lub małą literą - np. jeśli jest krótszy w użyciu uzamiast Uiść do przodu.
    • Nieprawidłowy kierunek ma niezdefiniowane zachowanie - np. kierunek X może spowodować awarię.
  2. Zwraca liczbę zmiennoprzecinkową / dziesiętną / podwójną, która jest dwukrotnością odległości linii prostej od punktu początkowego.

Dla ilustracji i wyjaśnień:

Moja wycieczka

Moja podróż mogła być równie łatwo nagrana jak "luluu..."lub, ['l','u','l'...]ale musi być zapisana jako góra, dół, lewo, prawo.


źródło
15
Jesteś wystarczająco bogaty, aby mieć helikopter, ale zależy ci na zakupie dodatkowego paliwa? : O
Fez Vrasta
8
@fezvrasta, bo jestem skąpy.
7
Sposób, aby zepsuć mi głowę, nie robiąc tego na odległość Manhattanu.
Kendall Frey
25
Prawidłowa odpowiedź brzmi: „To nie ma znaczenia. Jesteś bogatym facetem, więc sięgasz do kieszeni, wyciągasz zwitek 20 dolarów i machasz nim w powietrzu, aby przyciągnąć uwagę taksówkarza; jesteś następnie grupa łobuzów z przedszkola, którzy cię okradają i biją w krwawą miazgę. Jesteś aresztowany za śmiecenie i publiczne włóczęgostwo, oskarżony o terroryzm za próbę wywołania masowej paniki i pandemii poprzez rozprzestrzenianie się wydzieliny z ciała na społeczeństwo chodnik, skazany, w więzieniu, i zamknął się z towarzysz z celi pseudonimie Brutus, który bierze się prawdziwą silną sympatię do Ciebie. Witamy w Nowym Jorku!”
Bob Jarvis - Przywróć Monikę
2
@McKay i tak interpretuję to jako wskazówki na mapie (w przeciwnym razie prawdopodobnie byłoby to „do przodu” i „do tyłu”), a miara odległości jest raczej jednoznaczna „dwa razy większa odległość linii prostej od punktu początkowego”, więc nie odległość manhattan).
FireFly,

Odpowiedzi:

32

J, 17 znaków

2*|+/0j1^'urdl'i.

Wykorzystuje fakt, że moce jreprezentują właściwe kierunki.

  • 'urdl'i. weź ciąg i oblicz wskaźniki (0 dla „u”, 1 dla „r”, ...)
  • 0j1^przekształca się w kierunku w płaszczyźnie złożonej przy użyciu odpowiedniej mocy j.
  • +/ podsumowuje pojedyncze kroki
  • 2*| dwa razy moduł

Przykład:

> 2*|+/0j1^'urdl'i.'uuuudrrrl'
7.2111
Howard
źródło
5
Dobra robota. Wiedza matematyczna na zwycięstwo. :-)
Gareth
Zrób ten „nie rozszerzony” ASCII, a wtedy będzie to tylko 15 bajtów (ponieważ nie używasz ósmego bitu).
Timtech
11

Python 2,7 56 58 56 51 48

Dzięki skradzionej dziesiątce grosza od Scrooge McDuck zarobiłem fortunę i mam teraz więcej bogactwa niż Scrooge.

y=lambda s:2*abs(sum(1j**(ord(i)%15)for i in s))

Python 2.7 - 61 53 50 (bez rozróżniania wielkości liter)

y=lambda s:2*abs(sum(1j**(ord(i)%16%9)for i in s))

Realizacja

>>> from random import sample
>>> y=lambda s:2*abs(sum((-1j)**(ord(i)%15)for i in s))
>>> path=sample('RLUD'*1000, 100)
>>> y(path)
20.0
>>> path=sample('RLUD'*1000, 100)
>>> y(path)
34.058772731852805
Abhijit
źródło
Dostaję IndexError: list index out of range. Jaką formę powinien mieć wkład?
plannapus
@plannapus: Dodałem sekcję dotyczącą implementacji
Abhijit
Ach i to %5nie %8. Ok, teraz ma to większy sens :)
plannapus
5

APL (29)

{|+/2 0j2×-⌿2 2⍴+/'URDL'∘.=⍵}

na przykład

     {|+/2 0j2×-⌿2 2⍴+/'URDL'∘.=⍵} 'UUUUDRRRL'
7.211102551

Wyjaśnienie:

  • +/'URDL'∘.=⍵: zobacz, jak często URDLwystępują znaki w argumencie
  • -⌿2 2⍴: odejmij Uwartość od Dwartości, a Rwartość od Lwartości
  • 2 0j2×: pomnóż wartość pionową przez 2i wartość poziomą przez2i
  • +/: suma
  • |: wielkość
marinus
źródło
4

Rubinowy 1.9+ (67)

f=->s{2*(((g=s.method :count)[?U]-g[?D])**2+(g[?R]-g[?L])**2)**0.5}

Przykład

f["DRUULULLULL"] => 10.0
f["UUUUDRRRL"] => 7.211102550927978
daniero
źródło
3

perl6: 44 znaków

2*abs [+] i <<**>>%(<U R D L>Z ^4){get.comb}
  • get.comb pobiera jeden wiersz danych wejściowych i dzieli się na znaki
  • <U R L D> to lista słów, w tym przypadku znaków
  • (1,2,3) Z (4,5,6)== (1,2), (2,5), (3,6), więc zamyka między sobą 2 listy, tworząc listę paczek, która %()zamienia się w skrót
  • <<**>>robi parami **, przedłużając krótszą listę, aby pasowała do dłuższej. Krótsza lista zdarza się tylkoi
  • [+]sumuje wszystkie elementy listy, absprzyjmuje moduł dla liczb zespolonych

Tak, usunąłem wszystkie możliwe spacje.

Ayiko
źródło
2

Python 2.7 - 65

Przyjemna i krótka, do przejścia przez płaszczyznę używa liczb zespolonych:

x=lambda s:2*abs(sum([[1,-1,1j,-1j]['RLUD'.index(i)]for i in s]))

Rekwizyty dla DSM i Abhijita w innych pytaniach, które pokazały mi, jak to wykorzystać 1jdo obliczenia tego.


źródło
Można 1jzapisać jako j, -1jas -j? Ponadto, czy obsługuje to górne i dolne wejście, czy tylko górne?
DavidC
1
Wujku Scrooze , nienawidzę cię. Powinieneś przynajmniej zostawić trochę pieniędzy swoim siostrzeńcom.
Abhijit
1
@DavidCarraher: Nie, nie możesz. Nie byłoby możliwe rozróżnienie między zmienną ja jednostką urojonąj
Abhijit
Czy nie mówiłeś, że ma on generować dwukrotność odległości? kiedy próbuję z UUUUDRRRL, dostaję 3.606 z tą funkcją zamiast 7.21.
plannapus
4
Możesz zapisać 2 kolejne znaki, mnożąc stałe 2zamiast mnożąc wynik końcowy.
Abhijit
2

Mathematica 92 49

Calle zasługuje na pełne uznanie za usprawnienie kodu.

f@l_:=2 N@Norm[Tr[l/.{"r"→1,"l"→-1,"u"→I,"d"→-I}]]

Przykład

f[{"u", "u", "u", "u", "d", "r", "r", "r", "l"}]

7,2111

DavidC
źródło
1
Wykonujesz dużo pracy, która nie jest wymagana przez OP, f@l_ := 2 N@Norm[Tr[l /. {"r" -> 1, "l" -> -1, "u" -> I, "d" -> -I}]]wystarczy.
Dostaję 2 Norm[(2. + 2. I) + "U" + "X"]jako wyjście dla twojego kodu.
DavidC
1
Tak, ale OP twierdzi, że takie wejście może zakończyć się niepowodzeniem. Tak ja i wszyscy inni to interpretujemy. Nie potrafię czytać tych innych języków, ale zobaczysz, że często kodują one na stałe u, r, lid.
Dobrze. Rozumiem. Dzięki za zwrócenie na to uwagi.
DavidC
Jeśli zamienisz dwie pozostałe pary nawiasów na @s, otrzymasz kolejne dwa znaki mniej.
shrx
2

PHP, 67

function f($a){foreach($a as$d)@$$d++;return 2*hypot($U-$D,$L-$R);}

Przykład:

<?php
var_dump(f(array('U', 'U', 'U', 'U', 'D', 'R', 'R', 'R', 'L')));

>float(7.211102550928)
Boann
źródło
2

Julia, 45 lat

f(l)=2*abs(sum([im^(c=='d'?3:c) for c in l]))

Ukradł isztuczkę do władzy. Również wszystkie znaki oprócz d mają wartości, które działają jako dopuszczalne moce dla i.

gggg
źródło
1

J, 29 znaków

+:+&.*:/-/_2[\#/.~/:~'ruld'i.

Działa tylko z niższych kierunkach przypadków i innych niż znaki r, u, l, i dspowoduje jej dać złą odpowiedź.

Stosowanie:

   +:+&.*:/-/_2[\#/.~/:~'ruld'i.'uuuudrrrl'
7.2111

Wyjaśnienie:

'ruld'i.'uuuudrrrl'Diadadowa forma i.znajduje indeks przedmiotów z prawego argumentu w lewym argumencie. W tym przypadku:

   'ruld'i.'uuuudrrrl'
1 1 1 1 3 0 0 0 2

/:~ sortuje tę listę w porządku rosnącym:

   /:~'ruld'i.'uuuudrrrl'
0 0 0 1 1 1 1 2 3

#/.~ zlicza liczbę wystąpień każdej liczby:

   #/.~/:~'ruld'i.'uuuudrrrl'
3 4 1 1

_2[\ dzieli na 2 rzędy:

   _2[\#/.~/:~'ruld'i.'uuuudrrrl'
3 4
1 1

-/ odejmuje dół od góry

   -/_2[\#/.~/:~'ruld'i.'uuuudrrrl'
2 3

+&.*:zapożycza lewę z innej odpowiedzi J, którą widziałem dziś rano , i podnosi do kwadratu elementy, następnie sumuje je, a następnie wykonuje pierwiastek kwadratowy. Zobacz w&. dokumentacji:

   +&.*:/-/_2[\#/.~/:~'ruld'i.'uuuudrrrl'
3.60555

+: podwaja wynik:

   +:+&.*:/-/_2[\#/.~/:~'ruld'i.'uuuudrrrl'
7.2111
Gareth
źródło
1

R, 86 74 56 znaków

Ok, w rzeczywistości jest o wiele krótszy z wyimaginowanymi liczbami:

2*Mod(sum(sapply(scan(,""),switch,u=1i,d=-1i,l=-1,r=1)))

Stosowanie:

> 2*Mod(sum(sapply(scan(,""),switch,u=1i,d=-1i,l=-1,r=1)))
1: u u u u d r r r l
10: 
Read 9 items
[1] 7.211103

Stare rozwiązanie o długości 74 znaków z współrzędnymi xy:

2*sqrt(sum(rowSums(sapply(scan(,""),switch,u=0:1,d=0:-1,l=-1:0,r=1:0))^2))

Stosowanie:

> 2*sqrt(sum(rowSums(sapply(scan(,""),switch,u=0:1,d=0:-1,l=-1:0,r=1:0))^2))
1: u u u u d r r r l
10: 
Read 9 items
[1] 7.211103

Pobiera dane wejściowe jako standardowe, muszą być małe i oddzielone spacjami. Użyj współrzędnych xy, zaczynając od (0,0).

plannapus
źródło
1

k ( 50 49)

{2*sqrt x$x:0 0f+/("udlr"!(1 0;-1 0;0 -1;0 1))@x}

Przykład

{2*sqrt x$x:0 0f+/("udlr"!(1 0;-1 0;0 -1;0 1))@x}"uuuudrrrl"
7.211103
skeevey
źródło
1

Java, 185, 203 , 204 , 217 , 226

class A{public static void main(String[] a){int x=0,y=0;for(int i=0;i<a[0].length();i++) switch(a[0].charAt(i)){case'U':y++;break;case'D':y--;break;case'L':x++;break;case'R':x--;}System.out.print(Math.hypot(x,y)*2);}}

Zakładałem, że każde „U” to „1 up”, więc dwie jednostki w górę to „UU”

Edycja: zamieniono przełącznik ifs

class A{public static void main(String[]a){int x=0,y=0;for(int i=0;i<a[0].length();i++){int c=a[0].charAt(i);if(c=='U')y++;if(c=='D')y--;if(c=='L')x++;if(c=='R')x--;}System.out.print(Math.hypot(x,y)*2);}}

Przeniesiony do iteratora

class A{public static void main(String[]a){int x=0,y=0;for(int i=0;i<a[0].length();){int c=a[0].charAt(i++);if(c=='U')y++;if(c=='D')y--;if(c=='L')x++;if(c=='R')x--;}System.out.print(Math.hypot(x,y)*2);}}

Nie przyjmuje już danych wejściowych jako ciągu, a raczej tablicy kierunków

class A{public static void main(String[]a){int x=0,y=0;for(String s:a){char c=s.charAt(0);if(c=='U')y++;if(c=='D')y--;if(c=='L')x++;if(c=='R')x--;}System.out.print(Math.hypot(x,y)*2);}}
James Webster
źródło
Rozumiem to, że potrzebujesz tylko funkcji, a nie całego programu.
Boann
1

T-SQL, 158

IF PATINDEX('%[^UDLR]%', @s)=0 select 2*sqrt(power(LEN(REPLACE(@s,'U',''))-LEN(REPLACE(@s,'D','')),2)+power(LEN(REPLACE(@s,'L',''))-LEN(REPLACE(@s,'R','')),2))

@S jest łańcuchem wejściowym typu varchar (max)

duanxn
źródło
1

ES6, 77 69

Definicja:

f=s=>{u=d=l=r=0;for(c of s)eval(c+'++');return 2*Math.hypot(u-d,l-r)}

Stosowanie:

>>> f('uuuudrrrl')
7.211102550927979
>>> f( 'uuuudrrrl'.split('') )
7.211102550927979
  • Akceptuje ciąg LUB tablicę (małe litery)
  • Nie używa wyimaginowanych liczb
  • Nie byłoby to możliwe zaledwie 3 dni przed opublikowaniem przez OP pytania ; to znaczy, działa tylko w przeglądarce Firefox 27+ (a może także w Chrome z włączonymi eksperymentami, nie testowałem :) !!

(Zainspirowany częściowo odpowiedzią Boanna.)

Noyo
źródło
Naprawdę chcę zrobić coś trudnego, aby pozbyć się zwrotu, na przykład zmienić całość w wyrażenie boolowskie, które jest po prostu analizowane i zwracane automatycznie, ale nie jestem pewien, czy istnieje sposób, aby to zrobić, chyba że mogę zastąpić to forstwierdzeniem wyrażenie (treść funkcji strzałki zawierająca instrukcje wymaga nawiasów i jawnego zwrotu, ciała, które są tylko wyrażeniami, nie).
Noyo
1

JavaScript - 142 znaki - bez eval ()

function r(a){return Math.sqrt(Math.pow(a.match(/u/g).length-a.match(/d/g).length,2)+Math.pow(a.match(/l/g).length-a.match(/r/g).length,2))*2}

gdzie a jest ciągiem jak „uudrrl”

użyj tego -

a='uudrrl'
r(a)

Przetestuj w konsoli przeglądarki.

var x = "luluurrrrurd"
r(x)
8.48528137423857
rahulroy9202
źródło
1

C # - 90 znaków

Świeży od LINQPad.

int x=0,y=0;input.Max(i=>i==85?y++:i==82?x++:i==68?y--:x--);(Math.Sqrt(x*x+y*y)*2).Dump();

Gdzie wejście jest poprawnym ciągiem.

>string input = "LULUURRRRURD";

>8.48528137423857
tdink
źródło
0

Befunge-93 (65)

Ma 65 znaków innych niż białe znaki (217 z białymi znakami, choć można to zmniejszyć dzięki bardziej zwartemu układowi (dla znaków 69/176)). Format wyjściowy wymaga pewnej swobody, ale jest niezaprzeczalnie dokładny. Nie wydaje się warte wysiłku, aby wdrożyć / ukraść implementację pierwiastka kwadratowego.

v                  >$:*\:*+88*4*5-2.,.@
               >3-:|
           >6-:|
       >8-:|
>~"D"-:|
       $   $   $   $
           \   \
       1   1   1   1
       -   -   +   +
           \   \
^      <   <   <   <

echo 'UUDLLUU' | ./befungee.py ../man wyjścia 2√13 (w rzeczywistości wydaje się, że problem dotyczy rozszerzonego ASCII).

Joel Bosveld
źródło
0

Matlab, 51 znaków

Moje przesłanie Matlaba działa tylko z listami zastrzeżonymi. To była świetna zabawa! Najtrudniejsze było przekształcenie ciągu znaków na tablicę liczb zespolonych, które należy zsumować.

Funkcjonować:

f=@(s)abs(sum(fix((s-76.5)/8.5)+((s-79)*i/3).^-99))

Stosowanie:

>> f=@(s)abs(sum(fix((s-76.5)/8.5)+((s-79)*i/3).^-99))
>> f('UURDL')
ans =

     1
>>
Hannesh
źródło
0

JavaScript, 136

function z(a){var x=a.split('u').length-a.split('d').length;var y=a.split('r').length-a.split('l').length;return Math.sqrt(x*x+y*y)*2;};
document.write(z('uuuudrrrwl'));
7.211102550927978
Xin
źródło
0

JavaScript, 89

function f(a){U=D=L=R=0;for(d in a)eval(a[d]+'++');return 2*Math.sqrt((U-=D)*U+(L-=R)*L)}

Przykład:

<script>
document.write(f(['U', 'U', 'U', 'U', 'D', 'R', 'R', 'R', 'L']));
</script>

>7.211102550927978
Boann
źródło
0

C 120

float d(char *p){int v=0,h=0;while(*p){v+=*p=='U'?1:*p=='D'?-1:0,h+=*p=='R'?1:*p=='L'?-1:0,++p;}return 2*sqrt(v*v+h*h);}

d("LULUURRRRURD") -> 8.485281

warrenm
źródło
0

JavaScript (bez ES6, bez eval) - 131

f=function(h){for(i=0,a=[0,,0,0,0];i<h.length;++i)++a[(h.charCodeAt(i)>>2)-25];x=a[0]-a[4];y=a[2]-a[3];return Math.sqrt(x*x+y*y)*2}

Test:

console.log(f('uuuudrrrl'));     // 7.211102550927978 
console.log(f('luluurrrrurd'));  // 8.48528137423857
iefserge
źródło