Oblicz pierwiastek kwadratowy tylko przy użyciu ++

13

Twoim zadaniem jest obliczenie pierwiastka kwadratowego dodatniej liczby całkowitej bez użycia żadnych operatorów matematycznych do zmiany liczby, takich jak:

  • Ustawianie zmiennej (np. SquareRoot = 5)
  • Dodawanie (A + B)
  • Odejmowanie (AB)
  • Mnożenie (A * B)
  • Division (A / B)
  • Pierwiastki kwadratowe, sześcianowe, czwarte itd
  • Wykładniki

Operatory porównania (takie jak <,>, == itp.) Nie są uważane za „operatory matematyczne” na potrzeby tego pytania i są dozwolone, o ile nie zmieniają wartości zmiennej.

Jedynym operatorem, którego możesz używać, jest ++. Obowiązują następujące wyjątki:

  • Jeśli chcesz, możesz zainicjować zmienną, ustawiając ją na 0.
  • Jeśli twój język nie zawiera składni ++, możesz użyć równoważnej składni, takiej jak foo + = 1 lub foo = foo + 1
  • Pierwiastek kwadratowy należy obliczyć co najmniej 6 cyfr po przecinku (miejsce stu tysięcy) i wyprowadzić jako liczbę całkowitą po przecinku (np. Jeśli wprowadzę 2, może wynieść 14142135624 lub 1414213 w zależności od zaokrąglenia) . Zaokrąglanie w górę lub w dół nie jest ważne.

Funkcje zdefiniowane przez użytkownika są niedozwolone. Ponadto niedozwolone jest także symulowanie funkcji za pomocą goto.

Chcę zobaczyć, co wszyscy przesyłają! Miłego kodowania!

WYJAŚNIENIE

Wyjaśnij, że liczba jest dodatnią liczbą całkowitą. Możesz stworzyć kod, który będzie zawierał dowolną liczbę, ale nie jest to konieczne.

WYJAŚNIENIE # 2

Wyjaśnij, że operatory porównania są dozwolone.

WYJAŚNIENIE # 3

Dodawanie, odejmowanie, mnożenie, dzielenie, oraz funkcje do numerów zmian są niedozwolone w ogóle , niezależnie od tego, czy są one zapisywane do zmiennej lub nie. Przykro mi, że to unieważnia kilka istniejących odpowiedzi, ale chciałem zdefiniować tę grupę operatorów za pomocą „zmień numer”, aby zapobiec odpowiedziom troll (np. Właśnie użyłem funkcji sqrt (), zabroniłeś tylko dodawania, mnożenie, dzielenie i odejmowanie). Przepraszam za zamieszanie.

WYJAŚNIENIE # 4

Wyjaśnij, że potrzebujemy co najmniej 5 cyfr. 10 cyfr spowodowało, że kod działał przez długi czas.

iggyvolz
źródło
1
Nie, - nie jest dozwolone, przepraszam za zamieszanie! Początkowo planowałem mieć ++ i - ale zdecydowałem się wziąć na wynos w ostatniej chwili.
iggyvolz
5
„bez użycia operatorów matematycznych do zmiany liczby” - myślę, że może to wymagać wyjaśnienia. Czy masz na myśli, że tych operatorów nie można w ogóle używać , lub że można ich używać, ale tylko wtedy, gdy wynik nie jest zapisany w zmiennej, np. while r*r<n*10e20:r+=1- dość trywialny. Możesz także rozważyć zmniejszenie wymaganej wydajności do około 10 ^ 8. Po pierwsze, ponieważ 10 ^ 10 jest większe niż 2 ^ 31, a po drugie, ponieważ zwiększenie tej wartości zajmuje trochę czasu.
primo
1
Dlaczego miałbyś kiedykolwiek w ogóle „zmieniać” dowolną zmienną? Wasze rozkazy macie dziwne sposoby myślenia ...
przestaliście obracać się przeciwnie do zegara
4
Zgłaszam się, by zamknąć to pytanie. Zbyt radykalne zmiany w pytaniu. Powinieneś zweryfikować to pytanie za pomocą piaskownicy, inaczej frustrowałbyś ludzi inwestujących wysiłek, aby na nie odpowiedzieć.
Abhijit
3
Zmniejszenie liczby wymaganych cyfr jest bez znaczenia bez ograniczeń czasowych / pamięci. Mój kod obsługuje 5 cyfr, ale moja maszyna nie ma wystarczającej ilości pamięci RAM.
Dennis

Odpowiedzi:

13

Python 66

print'%.0f'%reduce(lambda a,b:abs(a)+1e10j,range(-2,input())).real

Wynik

>>> print'%.0f'%reduce(lambda a,b:abs(a)+1e10j,range(-2,input())).real
121
110000000000
>>> print'%.0f'%reduce(lambda a,b:abs(a)+1e10j,range(-2,input())).real
1000
316227766017

To rozwiązanie wykorzystuje Spiralę Teodora na złożonej płaszczyźnie, aby osiągnąć wynik.

Abhijit
źródło
2
Myślę, że będzie trzeba to owinąć, w int(...*1e10)przeciwnym razie bardzo miłe. Chociaż przyjmowanie abszłożonej wartości jest mniej więcej sqrtw przebraniu.
primo
1
@primo Nie sądzę, że wolno ci *1e10...
Cruncher
@primo: Zamiast pomnożyć przez 1e10, wybrałem nieco inną trasę. I chociaż zgadzam się, że abs może być sqrt w przebraniu, ale uważam, że jest to całkowicie legalne, jak to obecnie stwierdzono w problemie.
Abhijit
Widzę opinię negatywną, która jest dość przygnębiająca. Miałem wielką nadzieję na tę odpowiedź, więc każdy, kto głosował, proszę zostawić komentarz.
Abhijit
9
@iggyvolz: Jestem naprawdę zaskoczony, że wciąż poszerzasz swoje pytanie i dodajesz więcej ograniczeń. Ludzie poświęcają czas i wysiłek, aby napisać odpowiedź, a ty nie możesz; nie oczekuj, że będą psychiczne.
Abhijit
6

Python, 184 znaki

Poniższe rozwiązanie Python używa tylko operatora inkrementacji i żadnych innych operatorów arytmetycznych. Jednak przy wymaganej precyzji (10 cyfr) uruchomienie zajmuje niemożliwie długo. Możesz to przetestować z mniejszą precyzją (3 cyfry), zmniejszając 1e20do 1e6.

import sys;t=0
for _ in range(int(sys.argv[1])):
 for _ in range(int(1e20)):t+=1
q=0
while 1:
 z=0
 for _ in range(q):
  for _ in range(q):z+=1
 if z>=t:break
 q+=1
print(q)

Nie golfowany:

import sys

# t = N * 100000000000000000000 (magnitude of twice the precision)
t = 0
for _ in range(int(sys.argv[1])):
    for _ in range(int(1e20)):
        t += 1
q = 0
while True:
    # z = q * q
    z = 0
    for _ in range(q):
        for _ in range(q):
            z += 1
    if z >= t:
        break
    q += 1
print(q)
Greg Hewgill
źródło
Wyjaśniłem pytanie, możesz zrobić tyle cyfr, ile chcesz (co najmniej 5). Nie znam Pythona, ale zakładam, że int () jest po prostu rzutnikiem typów? Jeśli tak, to w porządku, ponieważ nie zmienia wartości liczby.
iggyvolz
@iggyvolz: Racja, musisz przekonwertować wartość argumentu ciągu (określoną w wierszu poleceń) na liczbę całkowitą. Zwykła funkcja nie potrzebowałaby tego.
Greg Hewgill
2

Fortran 73

read*,t;s=0;do while(abs(s*s/1e10-t)>1e-10);s=s+1;enddo;print*,s/1e5;end

Może zająć dużo czasu, aby rzeczywiście znaleźć odpowiedź na określone wartości, ale na pewno zadziała. Podczas gdy używam *i -, nie zmieniają one żadnych wartości , tylko s=s+1faktycznie coś zmienia.

Kyle Kanos
źródło
Wow, chyba nie myślałem o użyciu operatorów do zmiany wartości statycznych. To jest w porządku i daje +1 (gdybym miał 15 punktów do oceny)
iggyvolz
Korzysta z tego *operatora, co jest dość wyraźnie niedozwolone. A może w jakiś sposób nie rozumiem podanych ograniczeń?
Greg Hewgill
@GregHewgill: OP określa, bez użycia operatorów matematycznych do zmiany liczby ; operatorzy ci nie zmieniają żadnych wartości.
Kyle Kanos
7
Ale to wciąż używa *operatora do zmiany numeru, po prostu nigdzie nie zapisujesz wyniku. Jeśli PO chciał po prostu zabronić przydziałów (innych niż s=s+1), to po co wspominać o wszystkich niedozwolonych operatorach arytmetycznych?
Greg Hewgill
1
@iggyvolz: Zmiana zasad ~ 20 godzin później jest złą formą. Nie rób tego i używaj piaskownicy do rozwiązania załamań w swoim problemie.
Kyle Kanos
2

CJam, 26 bajtów

q~,1e20,m*,:N!{)_,_m*,N<}g

Wypróbuj online. Wklej kod , wpisz żądaną liczbę całkowitą w polu Input i kliknij Uruchom . Zanim to zrobisz, sugeruję zmianę 1e10na 1e4chociaż.

W interpreter Java uchwyty 1e6z wejściem „2” w około 15 sekund. 1e20będzie wymagał ogromnej ilości pamięci RAM.

Przykłady

$ cjam <(echo 'q~,1e2,m*,:N!{)_,_m*,N<}g') <<< 4; echo
20
$ cjam <(echo 'q~,1e2,m*,:N!{)_,_m*,N<}g') <<< 2; echo
15
$ cjam <(echo 'q~,1e4,m*,:N!{)_,_m*,N<}g') <<< 4; echo
200
$ cjam <(echo 'q~,1e4,m*,:N!{)_,_m*,N<}g') <<< 2; echo
142
$ cjam <(echo 'q~,1e6,m*,:N!{)_,_m*,N<}g') <<< 4; echo
2000
$ cjam <(echo 'q~,1e6,m*,:N!{)_,_m*,N<}g') <<< 2; echo
1415

tło

Ponieważ nie zezwalamy operatorom matematycznym na zmianę liczb, użyjemy operatorów setwise do zmiany tablic.

Kod zaczyna się od „pomnożenia” danych wejściowych („i”) przez 1e20, ale bez faktycznego pomnożenia. Zamiast tego wypychamy tablicę zawierającą liczby całkowite „i”, tablicę zawierającą liczby całkowite 1e20, bierzemy ich kartezjański produkt i obliczamy jego długość.

Następnie naciskamy zero i inkrementujemy, aż iloczyn liczby całkowitej (obliczony jak powyżej) nie będzie już mniejszy niż i * 1e20. Powoduje to zaokrąglenie pierwiastka kwadratowego w górę.

Jak to działa

q~     " Read for STDIN and interpret. ";
,      " Push an array containing that many integers. ";
1e20,  " Push the array [ 0   …   1e20 - 1]. ";
m*,:N  " Get the length of the cartesian product and save it in “N”. ";
!      " Logical NOT. Since the input is a positive integer, this pushes 0. " ;
{      " ";
  )    " Increment the integer on the stack.";
  _,   " Push an array containing that many integers. ";
  _m*, " Get the length of the cartesian product of the array by itself. ";
  N<   " If the product is smaller than the target value, push 1; otherwise push 0. ";
}g     " Repeat the loop if the result was 1. ";
Dennis
źródło
1

Kobra - 62

Wysłany przed trzecią edycją, już nieważny.

Jest nie tylko krótki, ale powinien być wolny od przepełnienia n < Decimal.maxValue

def f(n)
    r,e=0d,10000000000
    while r/e*r/e<n,r+=1
    print r
Obrzydliwe
źródło
Ale r/e*r/e++
używałeś
@nneonneo został opublikowany przed trzecią edycją, a ja go jeszcze nie zmieniłem
Οurous
0

Scala, 117

val z=BigInt(readLine+"0000000000")
print(Stream.from(1)find(x=>(BigInt(0)/:Stream.fill(x,x)(1).flatten){_+_}>=z)get)

Nie kończy się w rozsądnym czasie, nawet dla 2 jako danych wejściowych, ale działa. Możesz zauważyć, że robię _+_, ale to tylko dodaje 1, a Scala i tak nie ma ++operatora. Mógłbym zapisać dwa znaki, zastępując wewnętrzny Strumień Listą, ale wtedy zabrakłoby mu pamięci. Jak napisano, myślę, że skaluje się tylko w czasie przetwarzania, a nie zużycia pamięci.

Joe K
źródło
0

Haskell, 70 bajtów

s i|r<-[1..i]=foldl1(.)[(+1)|j<-r,k<-r]
f i=[j-1|j<-[0..],s j 0>=i]!!1

fpodaje liczbę całkowitą pierwiastek kwadratowy przez znalezienie największej liczby, której kwadrat jest mniejszy lub równy wartości wejściowej. Funkcja kwadratu s izwiększa się o jeden dla każdego elementu (i,i)macierzy. (Wpisany na telefonie, więc może mieć literówki).

Michael Klein
źródło
0

PHP, 124 bajty

To wyczerpujący algorytm. Próbuje liczb, dopóki kwadrat tej liczby nie będzie większy niż liczba „bramkowa” (czyli razy 1E do number of decimalskwadratu (10.000 dla wyniku dziesiętnego). Następnie wypisze ostatnią liczbę.

for(;$a++<$z=$argv[1];)for(;$$a++<1e6;)$g++;for(;$b++<$g;$i=$x=0)for(;$i++<$b;)for($j=0;$j++<$b;)if(++$x>=$g)break 3;echo$b;

Działaj w ten sposób ( -ddodany tylko ze względów estetycznych):

php -d error_reporting=32757 -r 'for(;$a++<$z=$argv[1];)for(;$$a++<1e6;)$g++;for(;$b++<$g;$i=$x=0)for(;$i++<$b;)for($j=0;$j++<$b;)if(++$x>=$g)break 3;echo"$b\n";' 2

Nie zaleca się wypróbowywania tego, używając czegoś więcej niż 3 miejsca po przecinku lub liczby powyżej 10.

aross
źródło