Desafío
Origami (papel plegable) es una forma creativa de arte. Hasta donde yo sé, el maestro de Origami prefiere el papel cuadrado. Comencemos desde el principio: convierta un papel rectangular en uno cuadrado.
Entonces el papel se divide en cuadrados. Eliminamos el cuadrado más grande que comparte un borde más corto con la forma actual, paso a paso (ver la imagen a continuación). Y si la parte restante después de un paso es menor o igual que 0.001 * (area of the original paper)
, el papel no se puede dividir más. Es posible que al final no quede nada.
Su tarea es calcular cuántos cuadrados se forman durante el proceso. El cuadrado en el último paso que hace que el papel no se pueda dividir se cuenta en la salida.
Ejemplo (un papel de 1.350
ancho / alto), la salida es 10:
Entrada y salida
Entrada: relación ancho / alto para el papel rectangular, un decimal (o un entero sin el punto) de 1.002
a 1.999
con un paso mínimo de 0.001
. También puede usar cualquier otro formato razonable que describa la relación. Solo mencionalo en tu respuesta.
Salida: recuento cuadrado, un entero.
Ejemplo de E / S
Se utiliza un formato de mapeo para mantener ordenada la página, mientras que su código no necesita admitir una entrada de lista ni ser una función de mapeo.
1.002 => 251
1.003 => 223
1.004 => 189
1.005 => 161
1.006 => 140
1.007 => 124
1.008 => 111
1.009 => 100
Lista de todas las respuestas.
Gracias a @LuisMendo, aquí está el gráfico de respuestas.
Observaciones
- Este es un código de golf, por lo que el código más corto gana
- Presta atención a las lagunas estándar
- Es su libertad decidir cómo manejar la entrada y salida, pero deben seguir las restricciones estándar.
Por cierto...
- Comenta si tienes algo poco claro sobre el desafío
- Personalmente, sugeriría que su respuesta contenga una explicación si está utilizando un lenguaje de golf
- Gracias a @GregMartin, lea su respuesta para una buena explicación matemática del desafío.
Código de ejemplo
Aquí hay una versión no codificada del código C ++:
#include <iostream>
#include <utility>
int f (double m)
{
double n = 1, k = 0.001;
int cnt = 0;
k *= m; // the target minimum size
while(m*n >= k)
{
m -= n; // extract a square
if(n > m)
std::swap(n, m); // keep m > n
++ cnt;
}
return cnt;
}
int main()
{
double p;
std::cin >> p;
std::cout << f(p);
return 0;
}
Todos los cálculos relacionados en el código de ejemplo necesitan una precisión de 6 dígitos decimales, que está cubierto float
.
Respuestas:
MATL , 19 bytes
La entrada es una matriz con los dos números que definen la relación original, como
[1, 1.009]
. (No es necesario que los números se ordenen o que uno de ellos sea 1.)Pruébalo en línea!
Explicación
fuente
Haskell ,
71 70 65 63 62 61 5856 bytes¡Gracias a @xnor por algunas mejoras ingeniosas!
Pruébalo en línea!
fuente
m==n
al final puede ser1>0
porque es la única posibilidad que queda. O, tal vez los casos podrían reorganizarse para permitir un enlace aquí.n>m
se expanden>=m
y se escribe el primer chequee>m*n*1000
, eso debería dar1
igualdad.(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1;n!m=n#m$n*m
d<-n-m
asotherwise
es realmente genial!JavaScript (ES6),
5958 bytesPrueba
Mostrar fragmento de código
fuente
Mathematica, no competitiva (21 bytes)
¡Esta respuesta no es competitiva porque no responde la pregunta real! Pero sí responde una variante de la pregunta, y proporciona una excusa para resaltar algunas matemáticas interesantes.
Función simbólica que toma un número racional positivo como entrada (cuyo numerador y denominador representan las dimensiones del papel original) y devuelve un entero positivo. Por ejemplo,
Tr@*ContinuedFraction[1350/1000]
vuelve10
. (ContinuedFraction
actúa de manera diferente en los números de coma flotante debido a problemas de precisión, por lo que se necesita un número racional como entrada en este contexto).¡Una interpretación interesante del procedimiento geométrico descrito en el problema (cortar cuadrados de un rectángulo repetidamente) es que es una implementación del algoritmo euclidiano para encontrar los divisores comunes más grandes! Considere el ejemplo en la pregunta misma, con relación
1.35
, que podría modelarse teniendo un trozo de papel con dimensiones (1350,1000). Cada vez que se corta un cuadrado, el número más pequeño se resta del número más grande; entonces los rectángulos resultantes en este ejemplo tienen dimensiones (350,1000), luego (350,650), luego (350,300), luego (50,300), luego (50,250) y (50,200) y (50,150) y (50,100) y (50, 50), y también (50,0) una vez que quitamos el último cuadrado de sí mismo. Así es exactamente como funciona el algoritmo euclidiano (módulo la diferencia entre división y sustracción repetida), y de hecho vemos que 50 es de hecho el MCD de 1350 y 1000.Típicamente en el algoritmo euclidiano, uno realiza un seguimiento de estas dimensiones intermedias y descarta el número de sustracciones; sin embargo, uno puede registrar alternativamente cuántas veces restamos un número del otro antes de que la diferencia sea demasiado pequeña y tengamos que cambiar lo que estamos restando. Ese método de grabación es precisamente la fracción continua de un número racional. (Las fracciones continuas de números irracionales, que nunca terminan, también son súper geniales, pero no relevantes aquí.) Por ejemplo, en el ejemplo 1350/1000, restamos 1000
1
veces, luego 3502
veces, luego 3001
veces, luego 506
veces; por lo tanto, la fracción continua de 1350/1000 es{1,2,1,6}
. Matemáticamente, hemos reescrito 1350/1000 como1
+ 1 / (2
+ 1 / (1
+ 1 /6
)), que puedes verificar.Entonces, para este problema, si no se detiene cuando los cuadrados se hacen más pequeños que un determinado umbral, sino que simplemente cuenta todos los cuadrados finitos antes de que se detenga, entonces el número total de cuadrados es igual al número total de sustracciones, es decir la suma de todos los enteros en la fracción continua, ¡y eso es precisamente lo que
Tr@*ContinuedFraction
calcula la composición de funciones ! (Para el ejemplo dado 1.35, obtiene la respuesta que desea el OP, porque el cuadrado final es lo suficientemente grande como para contar todos los cuadrados. PeroTr@*ContinuedFraction[1001/1000]
, por ejemplo, rinde1001
, ya que cuenta el cuadrado enorme y los 1000 de los cuadrados pequeños 1x1000 .)fuente
Mathematica,
6453 bytesUna solución imperativa (estilo C) tiene exactamente la misma longitud:
fuente
C (CCG / Clang),
6159 bytesLa entrada es dos enteros (ancho y alto) sin punto, como
f(1999,1000)
.Espero que alguien pueda salvar un byte empujando a C al club de 58 bytes. ;)
fuente
m-=n
C, 59 bytes
Pruébalo en línea
La entrada es un número entero que es la relación ancho / alto en milésimas (por ejemplo, 1002 para 1.002: 1).
Versión sin golf
fuente