Calcule la raíz cuadrada solo con ++

13

Su tarea es calcular la raíz cuadrada de un entero positivo sin utilizar ningún operador matemático para cambiar el número, como:

  • Establecer una variable (ej. SquareRoot = 5)
  • Suma (A + B)
  • Resta (AB)
  • Multiplicación (A * B)
  • División (A / B)
  • Raíces cuadradas, cúbicas, cuarta, etc.
  • Exponentes

Los operadores de comparación (como <,>, ==, etc.) no se consideran "operadores matemáticos" a los fines de esta pregunta y se permiten siempre que no cambien el valor de una variable.

El único operador que puede usar es ++. Se establecen las siguientes excepciones:

  • Si lo desea, puede inicializar una variable estableciéndola en 0.
  • Si su idioma no incluye la sintaxis ++, puede usar una sintaxis equivalente, como foo + = 1 o foo = foo + 1
  • La raíz cuadrada se debe calcular al menos a 6 dígitos más allá del decimal (el lugar de los cientos de miles) y se debe emitir como un número entero de los decimales (por ejemplo, si ingreso 2 podría salir como 14142135624 o 1414213 dependiendo del redondeo) . Redondear hacia arriba o hacia abajo no es importante.

Las funciones definidas por el usuario no están permitidas. Además, la simulación de funciones con goto tampoco está permitida.

¡Estoy interesado en ver lo que todos envían! ¡Feliz codificación!

ACLARACIÓN

Aclare que el número es un entero positivo. Puede hacer un código que haga cualquier número, pero no es necesario.

ACLARACIÓN # 2

Aclare que los operadores de comparación están permitidos.

ACLARACIÓN # 3

La suma, resta, multiplicación, división y funciones a los números de cambio no se permiten en absoluto , independientemente de que se guardan en una variable o no. Lamento que esto invalide un par de respuestas existentes, pero tenía la intención de definir este grupo de operadores con "cambiar el número" para evitar respuestas troll (por ejemplo, acabo de usar la función sqrt (), solo prohibió la suma, multiplicación, división y resta). Perdón por la confusion.

ACLARACIÓN # 4

Aclare que necesitamos al menos 5 dígitos. 10 dígitos hicieron que el código se ejecutara durante mucho tiempo.

iggyvolz
fuente
1
No, no está permitido, perdón por la confusión! Originalmente planeé tener ++ y, pero decidí sacarlo, en el último minuto.
iggyvolz
55
"sin usar ningún operador matemático para cambiar el número" - Creo que esto podría necesitar aclaración. ¿Quiere decir que estos operadores pueden no usarse en absoluto o que pueden usarse, pero solo si el resultado no se guarda en una variable, por ejemplo while r*r<n*10e20:r+=1, bastante trivial? Además, puede considerar reducir la salida requerida a 10 ^ 8 más o menos. Primero, porque 10 ^ 10 es mayor que 2 ^ 31, y segundo, porque tomará un tiempo incrementar ese valor.
primo
1
¿Por qué usted nunca querrá "cambio" cualquier variable en absoluto? Ustedes imperativos tienen formas extrañas de pensar ...
dejaron de girar en contra del reloj el
44
Estoy marcando para cerrar esta pregunta. A muchos cambios radicales a la pregunta. En realidad, debería validar esta pregunta a través de Sandbox o de lo contrario frustraría a las personas que invierten esfuerzos para responder.
Abhijit
3
Reducir el número de dígitos requeridos no tiene sentido sin límites de tiempo / memoria. Mi código puede manejar 5 dígitos, pero mi máquina no tiene suficiente RAM.
Dennis

Respuestas:

13

Python 66

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

Salida

>>> 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 solución utiliza la espiral de Theodorus en un plano complejo para lograr el resultado.

Abhijit
fuente
2
Creo que tendrá que ser envuelto int(...*1e10), de lo contrario, muy agradable. Aunque, tomar absun valor complejo está más o menos sqrtdisfrazado.
primo
1
@primo No creo que se te permita *1e10...
Cruncher
@primo: en lugar de multiplicar por 1e10, tomé una ruta un poco diferente. Y aunque estoy de acuerdo en que los abdominales pueden estar disfrazados de sqrt, sigo sintiendo que es completamente legal como se indica actualmente en el problema.
Abhijit
Veo un voto negativo, y es bastante deprimente. Tenía muchas esperanzas en esta respuesta, por lo que cualquiera que haya votado en contra, deje un comentario.
Abhijit
99
@iggyvolz: Estoy realmente sorprendido de que sigas ampliando tu pregunta y agregando más restricciones. La gente invierte tiempo y esfuerzo para escribir una respuesta y usted no puede esperar que sean psíquicos.
Abhijit
6

Python, 184 caracteres

La siguiente solución de Python usa solo el operador de incremento y ningún otro operador aritmético. Sin embargo, con la precisión requerida (10 dígitos), se tarda un tiempo increíblemente largo en ejecutarse. Puede probarlo con menor precisión (3 dígitos) reduciéndolo 1e20a 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)

Sin golf:

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
fuente
Aclaré la pregunta, puedes hacerlo con tantos dígitos como quieras (al menos 5). No estoy familiarizado con Python, pero supongo que int () es solo un lanzador de tipos. Si es así, está bien porque no cambia el valor del número.
iggyvolz
@iggyvolz: Correcto, lo necesita para convertir el valor del argumento de cadena (especificado en la línea de comando) en un entero. Una función simple no necesitaría eso.
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

Podría tomar mucho tiempo para determinar realmente una respuesta para ciertos valores, pero funcionará con seguridad. Mientras uso *y -, estos no están cambiando ningún valor , solo el s=s+1realmente cambia cualquier cosa.

Kyle Kanos
fuente
Wow, supongo que no pensé en usar operadores para cambiar los valores estáticos. Eso está perfectamente bien y +1 (si tuviera 15 reputación para votar)
iggyvolz
Esto utiliza el *operador, que claramente no está permitido. ¿O de alguna manera estoy malentendido las restricciones dadas?
Greg Hewgill
@GregHewgill: estados OP, sin usar ningún operador matemático para cambiar el número ; Estos operadores no están cambiando ningún valor.
Kyle Kanos
77
Pero eso sigue usando al *operador para cambiar un número, simplemente no está guardando el resultado en ningún lado. Si el OP quería simplemente no permitir asignaciones (que no sean s=s+1), entonces ¿por qué mencionar todos los operadores aritméticos no permitidos?
Greg Hewgill
1
@iggyvolz: Cambiar las reglas ~ 20 horas después es una mala forma. No hagas eso y utiliza el sandbox para resolver los problemas en tu problema.
Kyle Kanos
2

CJam, 26 bytes

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

Pruébalo en línea. Pegue el Código , escriba el número entero deseado en Entrada y haga clic en Ejecutar . Antes de hacerlo, sugiero cambiar 1e10a 1e4aunque.

El intérprete de Java maneja 1e6con la entrada "2" en aproximadamente 15 segundos. 1e20requerirá una gran cantidad de RAM.

Ejemplos

$ 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

Antecedentes

Dado que no se nos permite a los operadores matemáticos cambiar los números, vamos a usar operadores setwise para cambiar las matrices.

El código comienza "multiplicando" la entrada ("i") por 1e20, pero sin ninguna multiplicación real. En cambio, empujamos una matriz que contiene enteros "i", una matriz que contiene enteros 1e20, tomamos su producto cartesiano y calculamos su longitud.

Luego, presionamos cero e incrementamos hasta que el producto del entero por sí mismo (calculado como arriba) ya no es menor que i * 1e20. Esto hace que la raíz cuadrada se redondee hacia arriba.

Cómo 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
fuente
1

Cobra - 62

Publicado antes de la tercera edición, ya no es válido.

No solo es corto, sino que debe estar libre de desbordamiento si n < Decimal.maxValue

def f(n)
    r,e=0d,10000000000
    while r/e*r/e<n,r+=1
    print r
Οurous
fuente
Pero usted solía r/e*r/e, que es claramente un ++operador no matemático ...
nneonneo
@nneonneo este fue publicada antes de la tercera edición, y no he cambiado todavía
Ο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)

No termina en un período de tiempo razonable, incluso para 2 como entrada, pero funciona. Puede notar que lo estoy haciendo _+_, pero eso solo agrega 1, y Scala no tiene un ++operador de todos modos. Podría guardar dos caracteres reemplazando el Stream interno con List, pero luego se quedaría sin memoria. Tal como está escrito, creo que se escala solo en tiempo de procesamiento, no en uso de memoria.

Joe K
fuente
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

fda la raíz cuadrada entera al encontrar el número más grande cuyo cuadrado es menor o igual que la entrada. La función de cuadratura se s iincrementa en uno por cada elemento de una (i,i)matriz. (Escrito en el teléfono, por lo que podría tener errores tipográficos).

Michael Klein
fuente
0

PHP, 124 bytes

Es un algoritmo exhaustivo. Simplemente intenta números hasta que el cuadrado de ese número sea mayor que el número de "meta" (que es la entrada multiplicada por 1E al number of decimalscuadrado (10.000 para un resultado de 2 decimales). Luego imprime ese ú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;

Ejecutar así ( -dagregado solo por razones 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

No recomiendo probar esto con más de 3 decimales o un número superior a 10.

aross
fuente