Problem:
W wybranym języku napisz najkrótszą funkcję zwracającą podstawę pierwiastka kwadratowego z niepodpisanej 64-bitowej liczby całkowitej.
Przypadki testowe:
Twoja funkcja musi działać poprawnie dla wszystkich danych wejściowych, ale oto kilka, które pomagają zilustrować ten pomysł:
INPUT ⟶ OUTPUT
0 ⟶ 0
1 ⟶ 1
2 ⟶ 1
3 ⟶ 1
4 ⟶ 2
8 ⟶ 2
9 ⟶ 3
15 ⟶ 3
16 ⟶ 4
65535 ⟶ 255
65536 ⟶ 256
18446744073709551615 ⟶ 4294967295
Zasady:
- Możesz nazwać swoją funkcję dowolnie. (Funkcje bezimienne, anonimowe lub lambda są w porządku, o ile można je wywołać).
- Liczba postaci jest najważniejsza w tym wyzwaniu, ale ważne jest również środowisko wykonawcze. Jestem pewien, że możesz iteracyjnie skanować w górę w poszukiwaniu odpowiedzi w czasie O (√n) przy bardzo małej liczbie znaków, ale czas O (log (n)) naprawdę byłby lepszy (to znaczy przy założeniu wartości wejściowej n, nie długość bitowa n).
- Prawdopodobnie będziesz chciał zaimplementować tę funkcję, używając arytmetyki wyłącznie liczb całkowitych i / lub logicznych. Jeśli jednak naprawdę chcesz korzystać z obliczeń zmiennoprzecinkowych, to jest w porządku, o ile nie wywołujesz żadnych funkcji bibliotecznych. Zatem po prostu powiedzenie
return (n>0)?(uint32_t)sqrtl(n):-1;
w C jest poza limitem, nawet jeśli dałoby to prawidłowy wynik. Jeśli używasz arytmetyki zmiennoprzecinkowej, można użyć*
,/
,+
,-
oraz potęgowanie (np**
lub^
jeśli jest wbudowany operatora w wybranym języku, ale tylko potęgowanie uprawnień nie mniej niż 1 ). To ograniczenie ma na celu zapobieganie „oszukiwaniu” przez sprawdzaniesqrt()
lub wariant lub podnoszenie wartości do ½ potęgi. - Jeśli używasz operacji zmiennoprzecinkowych (patrz # 3), nie jest wymagane, aby typ zwracany był liczbą całkowitą; tylko, że zwracana wartość jest liczbą całkowitą, np. floor (sqrt (n)), i jest w stanie pomieścić dowolną 32-bitową wartość bez znaku.
- Jeśli używasz C / C ++, można zakładać istnienie niepodpisane 64-bitowych i 32-bitowych typów całkowitych, np
uint64_t
iuint32_t
, jak określono wstdint.h
. W przeciwnym razie upewnij się, że Twój typ liczb całkowitych jest w stanie pomieścić dowolną 64-bitową liczbę całkowitą bez znaku. - Jeśli Twój język nie obsługuje 64-bitowych liczb całkowitych (na przykład, Brainfuck najwyraźniej obsługuje tylko 8-bitowe liczby całkowite), zrób to najlepiej i podaj ograniczenie w tytule odpowiedzi. To powiedziawszy, jeśli możesz dowiedzieć się, jak zakodować 64-bitową liczbę całkowitą i poprawnie uzyskać jej pierwiastek kwadratowy za pomocą 8-bitowej prymitywnej arytmetyki, to więcej mocy dla ciebie!
- Baw się i bądź kreatywny!
code-golf
math
arithmetic
Todd Lehman
źródło
źródło
O(log_2 n) === O(log_4 n)
.log_4(n) = log_2(n) / log_2(2) = log_2(n) / 2
Odpowiedzi:
CJam, 17 (lub 10) bajtów
Wypróbuj online , weryfikując przypadki testowe:
Nie przejdzie ostatniego przypadku testowego z powodu problemów z zaokrąglaniem, ale ponieważ
18446744073709551615
nie jest liczbą całkowitą w CJam (jest to duża liczba całkowita ), nadal jesteśmy dobrzy, prawda?Jeśli nie, poniższy (i nieco dłuższy) kod naprawi te błędy:
Nie jest to już najkrótsze rozwiązanie, ale uczciwe .
Jak to działa
źródło
<.@%~^&1.5
. Czy mogę to opublikować jako osobną odpowiedź (ponieważ jest to właściwie twój port)?4294967295
i4294967296
wygląd bardzo podobny ...Haskell,
2826Uważam, że jest to najkrótsza pozycja z dowolnego języka, który nie został zaprojektowany do gry w golfa.
IT nazwy funkcji
s
z parametrema
i zwraca jeden minus pierwszego numeru, który jest większy niż kwadrata
. Działa niesamowicie wolno (może O (sqrt n)?).źródło
[...]!!0
) nie byłby krótszy niż head?Golfscript, 17 znaków
Mógłbym nazwać moją funkcję w dowolny sposób, ale postanowiłem nie nazywać jej wcale. Dodaj dwa znaki, aby go nazwać, dodaj trzy, aby nazwać go i nie pozostawiać go na stosie, odejmij jeden znak, jeśli podanie pełnego programu jest w porządku.
Ta obrzydliwość nie działa w czasie logarytmicznym w wartości wejściowej, a nie w czasie O (sqrt n), a uzyskanie wyniku zajmuje ogromną ilość czasu. Zajmuje również tyle miejsca. Absolutnie przerażające. Ale ... to jest golf golfowy.
Algorytm to:
źródło
Pyth , 14 znaków
Zapewnia nazwaną funkcję s, która oblicza pierwiastek kwadratowy, filtrując listę od 0 do n dla kwadratu większego niż dane wejściowe, a następnie drukuje ostatnią taką liczbę. Nie używa potęgowania ani liczb zmiennoprzecinkowych.
Przykładowe użycie:
źródło
Retina (niekonkurencyjna - język jest nowszy niż wyzwanie), 43
Podczas pracy nad tą odpowiedzią przyszło mi do głowy, że podobną metodę można zastosować do obliczenia całkowitych pierwiastków kwadratowych za pomocą siatkówki:
Opiera się to na tym, że idealne kwadraty mogą być wyrażone jako
1+3+5+7+...
, a następstwem tego jest to, że liczba wyrażeń w tym wyrażeniu jest pierwiastkiem kwadratowym.Wypróbuj online. (Dodano pierwszy wiersz, aby umożliwić uruchomienie wielu przypadków testowych).
Oczywiście ze względu na konwersję dziesiętną na jednostkową będzie to działać tylko w przypadku stosunkowo niewielkich nakładów.
źródło
Perl, 133 znaki
Zdecydowanie nie najkrótszy, ale wykorzystuje algorytm cyfra po cyfrze do obsługi dowolnego rozmiaru wejściowego i działa w czasie O (log n). Swobodnie konwertuje między liczbami jako ciągami znaków i liczbami jako liczbami. Ponieważ największym możliwym produktem jest jak dotąd pierwiastek z kwadratem jednej cyfry, powinien być w stanie przyjąć pierwiastek kwadratowy z około 120-bitowych liczb w systemie 64-bitowym.
Zdekompresowane, to znaczy:
źródło
if length%2
zamiast powiedziećif(length)%2
? Ogoliłoby to 1 postać. Czy to by działało powiedzieć$y=$z,$d=$_ if
zamiast($y,$d)=($z,$_)if
? Myślę, że zgoliłoby to 3 kolejne postacie.for
pętlę jako:$a<($z=$_*(20*$r+$_))or$y=$z,$d=$_ for(1..9);
%2
), ale pozostałe są poprawne. Pracuję nad nimi.for
nie wymaga nawiasów; dodanie tego do twoich sugestii daje mi łącznie 6 znaków. Dzięki!Matlab (56) / Octave (55)
Oblicza pierwiastek kwadratowy za pomocą metody punktu stałego. Zbiega się w maksymalnie 36 krokach (dla 2 ^ 64-1 jako argument), a następnie sprawdza, czy jest to dolny z „możliwych” pierwiastków całkowitych. Ponieważ zawsze używa 36 iteracji, ma czas działania O (1) = P
Przyjmuje się, że argumentem jest uint64.
Matlab:
Oktawa:
źródło
Ruby - 36 znaków
źródło
while
pętla kończy się dokładnie, gdy g zbiega się do podłogi (√n), co jest pożądaną wartością. Czy widzisz przypadek, w którym nie byłoby to prawdą?Python (39)
Naturalne podejście rekurencyjne. Zlicza potencjalne pierwiastki kwadratowe, aż ich kwadrat będzie zbyt wysoki, a następnie spadnie o 1. Użyj Python bez stosu, jeśli martwisz się przekroczeniem głębokości stosu.
Ten
and/or
idiom jest równoważny operatorowi potrójnemu jakoEdit: mogę zamiast dostać 25 znaków wykorzystując regułę „można użyć
*
,/
,+
,-
, i potęgowanie (np**
lub^
jeśli jest wbudowany operatora w wybranym języku, ale tylko potęgowanie uprawnień nie mniej niż 1). „ (Edycja: Najwyraźniej Dennis już znalazł i wykorzystał tę sztuczkę.)Używam operatora dzielenia liczb całkowitych
//
w Pythonie 3 do zaokrąglania w dół. Niestety spędzam dużo znaków, aby skrzynkan=0
nie dzieliła błędu przez 0. Gdyby nie to, mógłbym zrobić 18 znakówReguły również nie mówiły, że funkcja musi zostać nazwana (w zależności od tego, jak interpretujesz „Możesz nazwać swoją funkcję dowolnie.”), Ale jeśli tak, to dwa kolejne znaki.
źródło
C99 (58 znaków)
To przykład odpowiedzi, której nie uważałbym za dobrą, chociaż jest to dla mnie interesujące z punktu widzenia golfa kodowego, ponieważ jest tak przewrotne, i pomyślałem, że fajnie byłoby wrzucić do tego miksu:
Oryginał: 64 znaki
Powodem tego jest to, że działa on w czasie O (√n) zamiast w czasie O (log (n)). (Gdzie n jest wartością wejściową.)
Edycja: 63 znaków
Zmiana
r-1
do--r
i łączące je doreturn
:Edycja: 62 znaki
Przeniesienie przyrostu pętli do wewnątrz warunkowej części pętli (uwaga: zachowanie to nie jest gwarantowane, ponieważ kolejność operacji względem operatora wstępnego przyrostu zależy od kompilatora):
Edycja: 60 znaków
Dodanie
typedef
do ukryciauint64_t
( podziękowania dla technozaura użytkownika za tę sugestię).Edycja: 58 znaków
Teraz wymaga podania drugiego parametru jako 0 w wywołaniu funkcji, np.
r(n,0)
Zamiast po prostur(n)
. Ok, przez całe moje życie, w tym momencie nie widzę, jak to kompresować ... ktoś?źródło
uint64_t s(uint64_t n){for(uint64_t r=n;--n>r/n;);return n;}
.--n
kiedyn==0
byłoby –1, a są to wartości bez znaku, więc –1 byłoby 2⁶⁴ – 1.#define Z uint64_t
... lub typedef uratuje paręn/++r/r
ma niezdefiniowane zachowanie ....Golfscript - 14 znaków
Znajdź najmniejszą liczbę
i
mniejszą niż wartość wejściowa,n
dla którejn < i*i
. Returni - 1
.To znaczy
[0..n-1].first(i => n < i*i) - 1
Wyjaśnienie dla tych, którzy nie znają również Golfscript, dla przykładowego wywołania z wejściem
5
:źródło
1
prawdopodobnie zajmuje dwa znaki.Haskell,
147138134128 128 bajtówNie jest to najkrótszy kod na świecie, ale działa w O (log n) i na liczbach o dowolnej wielkości:
Wykonuje binarne wyszukiwanie zakresu [0..n] w celu znalezienia najlepszego niższego przybliżenia do sqrt (n). Oto wersja bez golfa:
Edycja: Zapisano dwa bajty, zastępując klauzule „w przeciwnym razie” „0 <1” jako krótszą wersją „True”, a kilka innych poprzez wstawienie g * g.
Ponadto, jeśli jesteś zadowolony z O (sqrt (n)), możesz po prostu to zrobić
na 35 znaków, ale co to za zabawa?
Edycja 2: Właśnie zdałem sobie sprawę, że ponieważ pary są sortowane według kolejności słownikowej, zamiast robić min2Cycle. map fst, mogę po prostu zrobić fst. min2Cycle. W kodzie golfowym oznacza to zamianę f $ map fst na fst $ f, co pozwala zaoszczędzić 4 bajty.
Edycja 3: Oszczędź sześć kolejnych bajtów dzięki dumnemu paskudnikowi!
źródło
JavaScript
918886: Zoptymalizowany pod kątem szybkościJavaScript 46: Niezoptymalizowany pod kątem szybkości
Oto JSFiddle: http://jsfiddle.net/rmadhuram/1Lnjuo4k/
źródło
function s(n){for(a=1;++a*a<n;);return a}
C 95
97Edytuj Typedef, sugerowany przez @Michaelangelo
Powinno to być mniej więcej prostą implementacją algorytmu Heron. Jedynym dziwactwem jest obliczenie średniego uniknięcia przepełnienia liczb całkowitych: a = (m + n) / 2 nie działa dla liczb dużych.
źródło
C #
646255Ponieważ jest to gra w golfa kodowego (a ja jestem okropny z matematyki), a środowisko wykonawcze jest jedynie sugestią, zastosowałem naiwne podejście, które działa w czasie liniowym:
( test na dotnetfiddle )
Oczywiście jest to strasznie wolne dla większych nakładów.
źródło
return i-1
nareturn--i
?i*i<=a
ma to być arytmetyka liczb całkowitych zwykłego typu? (Nie znam C #.) Jeśli tak, a jeśli C # pozwala na niejawną konwersję liczb całkowitych na wartość logiczną, podobnie jak C, możesz być w stanie zapisać jeszcze jeden znak, zmieniając go naa/i/i
.Decimal
, wyższa maksymalna wartość i precyzja), aby uniknąć przepełnienia, ponieważ wynik pomnożenia może potencjalnie przejść o krok dalejUInt64.MaxValue
. Ale C # i tak nie ma niejawnych konwersji na Boolean. Dzięki, powinienem być w stanie to zmienićreturn
. Zrobię to, kiedy wrócę do komputera.Clojure - 51 lub 55 bajtów
Sprawdza wszystkie liczby od n do 0, podając pierwszą gdzie
x^2 <= n
. Czas działania jestO(n - sqrt n)
Anonimowy:
O imieniu:
Przykład:
źródło
Befunge 93 - 48 bajtów lub 38 znaków
Wypróbuj tutaj.
źródło
Kobra - 62
Partia - 74
źródło
Haskell,
535049 znaków, O (log n)to rozwiązanie implementuje metodę Newtona-Raphsona, chociaż przeszukuje liczby całkowite zamiast liczb zmiennoprzecinkowych. wiki: http://en.wikipedia.org/wiki/Newton%27s_method
złożoność wydaje się dotyczyć O (log n), ale czy jest na to dowód? proszę odpowiedzieć w komentarzach.
źródło
\g->div(n+g^2)$2*g
oszczędza 7 bajtów.J (10)
Bardzo, bardzo, bardzo zainspirowany odpowiedzią @Dennis :
I nieco dłużej, ale z lepszą wydajnością (podejrzewam):
floor(halve under log)
Aby wykonać, wprowadzane są wcięte części:
źródło
APL - 12 znaków, 19 bajtów
przykład użycia:
zwraca 4
Wektor testowy
zwroty
1 1 1 1 2 2 3 3 4 255 256 4294967296
Wypróbuj online
Ogromne podziękowania dla : użytkownika „ssdecontrol” za algorytm
źródło
0
→1
! Używając APL Dyalog , możesz ustawić⎕DIV←1
(z których wielu korzysta domyślnie), aby uzyskać poprawny wynik.C99 (108 znaków)
Oto moje własne rozwiązanie w C99, które zostało zaadaptowane z algorytmu w artykule na Wikipedii . Jestem pewien, że w innych językach musi być możliwe zrobienie tego znacznie lepiej.
Gra w golfa:
Częściowo grał w golfa:
Nie golfowany:
źródło
a
, użyjn
.n
, że tuż przed powrotem mogłem stwierdzić (nie pokazano), że r ^ 2 <= n <(r + 1) ^ 2. Z pominięciem tego twierdzenia nie trzeba dłużej zachowywaćn
nienaruszonego charakteru.const
wersji bez golfisty.JavaScript
7381 (w celu spełnienia wymagań liczb 64-bitowych)n=prompt();g=n/3;do{G=g,g=(n/g+g)/2}while(1E-9<Math.abs(G-g))alert(Math.floor(g))
Implementacja algorytmu Heron of Alexandria ...
źródło
|0
wpływa na wersję 32-bitową, podczas gdyMath.floor
jest bardziej skuteczny w wersji 64-bitowej ... Zaktualizowałem swój kod, wymagając dodatkowych 8 znaków, aby to zrobić ...Powershell (52) Ograniczony do Int32 (-2 147 483 648 do 2 147 483 647)
W tej chwili krzyczę na Powershell, próbując sprawić, by ostatni przypadek testowy zadziałał, ale bez względu na to, co zrobię, Powershell kończy się przy użyciu zmiennej $ _ jako Int32 i nie mogę teraz znaleźć sposobu na obejście tego.
Więc na razie ograniczę swoją odpowiedź. Jeśli znajdę lepszy sposób obsługi uint64s, dokonam edycji. (Nawiasem mówiąc, ostatni przypadek testowy jest zbyt duży dla normalnego typu Int64 Powershell!)
Oto kilka przypadków testowych (z odrobiną dodatkowej wydajności, której użyłem do śledzenia czasu)
Nie znam moich O (), ale wydaje się to dość dramatycznym skokiem.
źródło
Zastrzeżenie: od 2011 r. R nie miał wbudowanej obsługi 64-bitowych liczb całkowitych, tak jak zakładałem. Te odpowiedzi mogą być niepoprawne pod względem technicznym, ale z drugiej strony R bardzo się zmieniło w ciągu ostatnich 3 lat.
R 85
Za pomocą metody Newtona:
który zbiega się kwadratowo. +2 znaki, aby przypisać funkcję do zmiennej w celu przeprowadzenia testu porównawczego:
R, 37
Brutalna siła:
I ta sama kontrola:
R, 30
Tani / potęgowanie genialna sztuczka :
który również okazuje się być bardzo szybki (choć nie tak szybki jak wbudowany):
źródło
C, 38
Tłumaczenie mojego przedłożenia. Powoli, ale poprawnie. O (√n). Testowany na OS X (64-bitowy).
źródło
dc, 50 bajtów
Rozłożył się i wyjaśnił:
źródło
C,
139137136 bajtówMoja pierwsza próba gry w golfa kodowego. Wygląda na to, że jest najkrótszy w C, który pasuje do „wydajnego” wymagania w miarę działania
O(log n)
czasie, wykorzystując tylko dodawanie i przesuwanie bitów. Chociaż jestem pewien, że może być jeszcze krótszy ...Powinno również działać dobrze w przypadku większych wartości całkowitych, o ile
a=32
część zostanie zmieniona naa=NUMBITS/2
.źródło
(t++)
zamiastt++
samego zadaniar
?a--+1
sposób na unikanie pisaniaa-- != UINT64_C(-1)
. Czy nauczyłeś się gdzieś tej sztuczki, czy sam ją wymyśliłeś?C - 50 (61 bez globalnej)
Wykorzystuje zmienne globalne jako parametry i zwraca wartość, aby zaoszczędzić miejsce.
Brak wersji globalnej:
źródło
C ++ 125
źródło
x+=(d<0)-0.5;
… zapisanie kolejnych 5 znaków?main
jest funkcją, ale nie można jej wywoływać z wnętrza programu tak jakf(y)
by to było.)while((d=x*x-y)>0.5)
zamiastwhile((d=(x*x-y))>0.5)
. Zapisuje 2 kolejne znaki. :)