Calcular a raiz quadrada apenas usando ++

13

Sua tarefa é calcular a raiz quadrada de um número inteiro positivo sem usar operadores matemáticos para alterar o número, como:

  • Configurando uma variável (por exemplo, squareRoot = 5)
  • Adição (A + B)
  • Subtração (AB)
  • Multiplicação (A * B)
  • Divisão (A / B)
  • Raízes quadradas, cubas, quarta, etc.
  • Expoentes

Operadores de comparação (como <,>, ==, etc) não são considerados "operadores matemáticos" para os fins desta pergunta e são permitidos desde que não alterem o valor de uma variável.

O único operador que você pode usar é ++. As seguintes exceções estão em vigor:

  • Se desejar, você pode inicializar uma variável configurando-a como 0.
  • Se seu idioma não incluir a sintaxe ++, você poderá usar uma sintaxe equivalente, como foo + = 1 ou foo = foo + 1
  • A raiz quadrada deve ser calculada com pelo menos 6 dígitos além do decimal (a casa das centenas de milhares) e gerar um número inteiro de casas decimais (por exemplo, se eu inserir 2, pode ser 14142135624 ou 1414213, dependendo do arredondamento) . Arredondar para cima ou para baixo não é importante.

Funções definidas pelo usuário não são permitidas. Além disso, a simulação de funções com goto também não é permitida.

Estou interessado em ver o que todos enviam! Feliz codificação!

ESCLARECIMENTO

Esclareça que o número é um número inteiro positivo. Você pode criar um código que faça qualquer número, mas isso não é necessário.

ESCLARECIMENTO # 2

Esclareça que operadores de comparação são permitidos.

ESCLARECIMENTO Nº 3

Adição, subtração, multiplicação, divisão e funções aos números de alteração não são permitidos em tudo , independentemente de se eles são salvos em uma variável ou não. Lamento que isso invalide algumas respostas existentes, mas pretendia definir esse grupo de operadores com "alterar o número" para evitar respostas de trolls (por exemplo, eu apenas usei a função sqrt (), você apenas proibiu a adição, multiplicação, divisão e subtração). Desculpe pela confusão.

ESCLARECIMENTO # 4

Esclareça que precisamos de pelo menos 5 dígitos. 10 dígitos fizeram com que o código fosse executado por um longo tempo.

iggyvolz
fonte
1
Não, - não é permitido, desculpe pela confusão! Inicialmente, planejava ter ++ e - mas decidi sair no último minuto.
iggyvolz
5
"sem usar nenhum operador matemático para alterar o número" - acho que isso pode precisar de esclarecimentos. Quer dizer que esses operadores não podem ser utilizados em tudo , ou, para que possam ser usados, mas somente se o resultado não é salvo em uma variável, por exemplo while r*r<n*10e20:r+=1- bastante trivial. Além disso, você pode considerar reduzir a saída necessária para 10 ^ 8 ou mais. Primeiro, porque 10 ^ 10 é maior que 2 ^ 31, e segundo, porque levará um tempo para incrementar esse valor alto.
primo
1
Por que você nunca quer "mudança" qualquer variável em tudo? Vocês imperativas têm maneiras estranhas de pensar ...
deixou de vez counterclockwis
4
Estou sinalizando para fechar esta pergunta. Para muitas mudanças radicais na questão. Na verdade, você deve validar essa pergunta através do Sandbox ou frustrar as pessoas que investem nos esforços para responder.
Abhijit
3
Reduzir o número de dígitos necessários não faz sentido sem limites de tempo / memória. Meu código pode lidar com 5 dígitos, mas minha máquina não tem RAM suficiente.
Dennis

Respostas:

13

Python 66

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

Resultado

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

Esta solução usa o Spiral of Theodorus em um plano complexo para obter o resultado.

Abhijit
fonte
2
Eu acho que precisará ser envolvido int(...*1e10), caso contrário, muito bom. Embora, assumir absum valor complexo esteja mais ou menos sqrtdisfarçado.
primo
1
@primo Eu não acho que você está autorizado a *1e10...
Cruncher
@primo: Em vez de multiplicar por 1e10, tomei uma rota um pouco diferente. E embora eu concorde que os abdominais possam estar disfarçados, ainda assim sinto que é completamente legal, como afirmado atualmente no problema.
Abhijit
Eu vejo um voto negativo, e é bastante deprimente. Eu tinha uma grande esperança para esta resposta, portanto, qualquer pessoa que tenha votado mal, por favor, deixe um comentário.
Abhijit
9
@iggyvolz: Estou realmente surpreso que você continue expandindo sua pergunta e adicionando mais restrições. As pessoas investem tempo e esforço para escrever uma resposta e você não pode esperar que elas sejam psíquicas.
Abhijit
6

Python, 184 caracteres

A seguinte solução Python usa apenas o operador de incremento e nenhum outro operador aritmético. No entanto, com a precisão necessária (10 dígitos), leva um tempo incrivelmente longo para ser executado. Você pode testá-lo com menor precisão (3 dígitos), reduzindo 1e20para1e6 .

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)

Ungolfed:

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
fonte
Esclarei a pergunta, você pode fazer isso com quantos dígitos quiser (pelo menos 5). Eu não estou familiarizado com python, mas estou assumindo que int () é apenas um tipo de rodízio? Nesse caso, tudo bem, pois não altera o valor do número.
Iggyvolz 6/06/2014
@iggyvolz: Certo, você precisa converter o valor do argumento da string (especificado na linha de comando) em um número inteiro. Uma função simples não precisaria disso.
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

Pode demorar um pouco para realmente determinar uma resposta para certos valores, mas funcionará com certeza. Enquanto eu uso *e -, estes não estão alterando nenhum valor , apenas o s=s+1realmente muda alguma coisa.

Kyle Kanos
fonte
Uau, acho que não pensei em usar operadores para alterar valores estáticos. Isso é perfeitamente bem e +1 (se eu tivesse 15 reputação a upvote)
iggyvolz
Isso usa o *operador, o que claramente não é permitido. Ou estou de alguma forma entendendo mal as restrições dadas?
Greg Hewgill
@GregHewgill: OP afirma, sem usar nenhum operador matemático para alterar o número ; esses operadores não estão alterando nenhum valor.
Kyle Kanos
7
Mas ainda está usando o *operador para alterar um número, você não está salvando o resultado em nenhum lugar. Se o OP quisesse simplesmente não permitir atribuições (exceto s=s+1), por que mencionar todos os operadores aritméticos não permitidos?
Greg Hewgill
1
@iggyvolz: Mudar as regras ~ 20 horas depois é uma má forma. Por favor, não faça isso e use a caixa de areia para resolver os problemas do seu problema.
Kyle Kanos
2

CJam, 26 bytes

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

Experimente online. Cole o código , digite o número inteiro desejado em Entrada e clique em Executar . Antes de fazer isso, sugiro mudar 1e10para1e4 entanto.

O interpretador Java lida 1e6com a entrada "2" em cerca de 15 segundos. 1e20exigirá um enorme quantidade de RAM.

Exemplos

$ 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

fundo

Como não é permitido que operadores matemáticos alterem números, usaremos operadores setwise para alterar matrizes.

O código começa "multiplicando" a entrada ("i") por 1e20, mas sem nenhuma multiplicação real. Em vez disso, empurramos uma matriz contendo números inteiros “i”, uma matriz contendo números inteiros 1e20, pegamos seu produto cartesiano e calculamos seu comprimento.

Em seguida, pressionamos zero e incrementamos até que o produto inteiro inteiro (calculado como acima) não seja mais menor que i * 1e20 . Isso faz com que a raiz quadrada seja arredondada para cima.

Como funciona

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

Cobra - 62

Publicado antes da terceira edição, não é mais válido.

Não é apenas curto, mas deve ser livre de transbordamentos se n < Decimal.maxValue

def f(n)
    r,e=0d,10000000000
    while r/e*r/e<n,r+=1
    print r
Furioso
fonte
Mas você usou r/e*r/e, o que é claramente um não- ++operador de matemática ...
nneonneo
@nneonneo este foi publicado antes da terceira edição, e eu não mudaram ainda
Ο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)

Não termina em um período de tempo razoável, mesmo para 2 como entrada, mas funciona. Você pode perceber que estou fazendo _+_, mas isso apenas adiciona 1, e Scala não tem um ++operador de qualquer maneira. Eu poderia salvar dois caracteres substituindo o Stream interno por List, mas ele ficaria sem memória. Como está escrito, acho que é escalável apenas no tempo de processamento, não no uso de memória.

Joe K
fonte
0

Haskell, 70 bytes

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

ffornece a raiz quadrada inteira encontrando o maior número cujo quadrado é menor ou igual à entrada. A função quadrática é s iincrementada em um para cada elemento de uma (i,i)matriz. (Digitado no telefone, pode haver erros de digitação).

Michael Klein
fonte
0

PHP, 124 bytes

É um algoritmo exaustivo. Ele apenas tenta números até que o quadrado desse número seja maior que o número "objetivo" (que é o tempo de entrada 1E number of decimalsao quadrado (10.000 para um resultado decimal de 2). Em seguida, imprime esse último número.

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;

Execute assim ( -dadicionado apenas por razões estéticas):

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

Não recomende fazer isso com mais de três casas decimais ou um número acima de 10.

aross
fonte