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.


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

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

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ść

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

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.


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.


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


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)

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.


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

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


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

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);}}

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)


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


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

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

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


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

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

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

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


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.