Dorado de un entero

21

Un número entero positivo n puede representarse como un rectángulo con lados enteros a , b tal que n = a * b . Es decir, el área representa el número. En general, una y b no son únicos para un determinado n .

Como es bien sabido, un rectángulo es especialmente agradable a la vista (¿o es el cerebro?) Cuando sus lados están en la proporción dorada , φ = (sqrt (5) +1) / 2 ≈ 1.6180339887 ...

Combinando estos dos hechos, el propósito de este desafío es descomponer un número entero n en el producto de dos números enteros a , b cuya relación sea lo más cercana posible a φ (con la métrica usual en ℝ). El hecho de que φ sea ​​irracional implica que hay un par de solución único ( a , b ).

El reto

Dado un número entero positivo n , de salida enteros positivos a , b de tal manera que un * b = n y la diferencia absoluta entre un / b y φ se minimiza.

Como ejemplo, considere n = 12. Los pares ( a , b ) que satisfacen a * b = n son: (1, 12), (2,6), (3,4), (4,3), ( 6,2), (12,1). El par cuya relación es más cercana a φ es (4,3), lo que da 4/3 = 1.333.

Reglas

Las funciones o programas son aceptables.

El numerador ( a ) debe aparecer primero en la salida, y el denominador ( b ) segundo . Aparte de eso, los formatos de entrada y salida son flexibles como de costumbre. Por ejemplo, los dos números se pueden generar como cadenas con cualquier separador razonable o como una matriz.

El código debería funcionar en teoría para números arbitrariamente grandes. En la práctica, puede estar limitado por restricciones de memoria o de tipo de datos.

Es suficiente considerar una versión aproximada de φ , siempre que sea precisa hasta el tercer decimal o mejor. Es decir, la diferencia absoluta entre el verdadero φ y el valor aproximado no debe exceder 0.0005. Por ejemplo, 1.618 es aceptable.

Cuando se utiliza una versión aproximada y racional de φ, existe una pequeña posibilidad de que la solución no sea única. En ese caso, puede generar cualquier par a , b que satisfaga el criterio de minimización.

El código más corto gana.

Casos de prueba

1        ->  1    1
2        ->  2    1 
4        ->  2    2
12       ->  4    3
42       ->  7    6
576      ->  32   18
1234     ->  2    617
10000    ->  125  80
199999   ->  1    199999
9699690  ->  3990 2431
Luis Mendo
fuente
Seguramente la mayoría de las respuestas usarán algún tipo de aproximación racional a φ, a menos que acepte, por ejemplo, la respuesta con el resultado de a / bb / a sea ​​lo más cercana posible a 1.
Neil
@Neil No estoy seguro de entender tu comentario. Su idea de minimizar |a/b-b/a-1|es prometedora, aunque una prueba estaría en orden
Luis Mendo
No estoy seguro de que pueda meter una prueba completa en un comentario, pero el esquema es el siguiente: el rectángulo completo representa a/b. Al quitar el cuadrado de la unidad se deja el pequeño rectángulo a la derecha que representa b/a. Por lo tanto, un rectángulo dorado logra una diferencia de 1.
Neil
Si ayb no son números adyacentes en la secuencia de Fibbonacci, ¿hay algún punto que los incluya en la prueba?
Fresa
Dicho esto, 1618 x 1000 parece un buen candidato (o, por referencia, 809 x 500)
Fresa

Respuestas:

6

Jalea, 16 15 14 bytes

Guardado 1 byte gracias a @miles.

÷/ạØp
ÆDżṚ$ÇÞḢ

Pruébalo en línea!

Explicación

÷/ạØp         Helper link, calculates abs(a/b - phi). Argument: [a, b]
÷/            Reduce by division to calculate a/b.
  ạØp         Calculate abs(a/b - phi).

ÆDżṚ$ÇÞḢ      Main link. Argument: n
ÆD            Get divisors of n.
  żṚ$         Pair the items of the list with those of its reverse. The reversed
              divisors of a number is the same list as the number divided by each
              of the divisors.
     ÇÞ       Sort by the output of the helper link of each pair.
       Ḣ      Get the first element [a, b] and implicitly print.
PurkkaKoodari
fuente
Puede guardar un byte intercalando el reverso de la lista de divisores consigo mismo. Usando ÷/ạØp¶ÆDżṚ$ÇÞḢpara 14 bytes, devuelve una lista [a, b]dada ncomo argumento.
millas
@miles ¡Genial! Aparentemente me perdí por completo /. (Esto es lo que hice en mi solución Pyth). Se editará cuando me conecte a mi computadora portátil.
PurkkaKoodari
7

Pyth - 24 23 bytes

Tiene que haber una mejor manera de encontrar los divisores ...

ho.a-.n3cFNfsIeTm,dcQdS

Test Suite .

Maltysen
fuente
66
No es más corto, pero mucho más rápido: hoa.n3cFNm,d/Qdm*Fdty+1P. Pruebas
TheBikingViking
6

Matlab, 96 81 bytes

Golfed (-15bytes), accesorios para Luis Mendo

function w(n);a=find(~(mod(n,1:n)));[~,c]=min(abs(a./(n./a)-1.618));[a(c) n/a(c)]

Original:

function w(n)
a=find(not(mod(n,1:n)));b=abs(a./(n./a)-1.618);c=find(not(b-min(b)));[a(c) n/a(c)]

Esta no es una gran solución, pero mi primer intento de code-golf. ¡Qué divertido!

ptev
fuente
2
De acuerdo en que es divertido! Bienvenido al sitio!
DJMcMayhem
1
Puede reemplazar notpor ~ para guardar algunos bytes. Además, utilizando la segunda salida de minusted puede deshacerse de find:a=find(~(mod(n,1:n)));[~,c]=min(abs(a./(n./a)-1.618));[a(c) n/a(c)]
Luis Mendo
Bien visto, ¡eso elimina algunos símbolos!
ptev
1
Puede hacerlo más corto usando en n=input('');lugar de function w(n);tener un par adicional ()alrededor mod.
flawr
5

Mathematica, 51 bytes

#&@@SortBy[{x=Divisors@#,#/x},Abs[#/#2-1.618]&]&

El es el operador de postfix de Mathematica para la transposición (se muestra como un superíndice Ten Mathematica).

Mathematica tiene un incorporado GoldenRatio, pero 1.618 es mucho más corto, especialmente porque el primero también lo requiere N@.

Martin Ender
fuente
5

Pyth, 21 20 18 bytes

hoacFN.n3C_Bf!%QTS

Pruébalo en línea. Banco de pruebas.

Explicación

  1. Obtenga el Srango inclusivo de 1 a entrada.
  2. fIndique los números que dividen la entrada !%QT.
  3. Obtener [that list, that list reversed] _B. Los divisores invertidos de un número son la misma lista que el número dividido por cada uno de los divisores.
  4. Transponga la lista para obtener pares de [numerator, denominator].
  5. S ota los pares por la adiferencia bsoluta de la relación del par cFNy la relación de oro .n3.
  6. Obtenga el primer par (el más bajo) he imprima.
PurkkaKoodari
fuente
5

Javascript (ES6), 73 bytes

n=>{for(b=0,k=n/.809;n%++b||k>b*b*2&&(a=b););return[b=k-a*a>b*b?b:a,n/b]}

Buscamos:

  • a = divisor más alto de n para el cual n / φ> a²
  • b = divisor más bajo de n para el cual n / φ <b²

Entonces, la solución es [a, n / a] o [b, n / b] . Comparamos n / φ - a² con b² - n / φ para averiguar qué expresión está más cerca de cero.

La fórmula real utilizado en el código se basa en φ / 2 que se puede escribir de una manera más corta que φ con la misma precisión: .809vs 1.618.

Por lo tanto:

n / φ> a² ⇔ n / (φ / 2)> 2a²

y:

n / φ - a²> b² - n / φ ⇔ 2n / φ - a²> b² ⇔ n / (φ / 2) - a²> b²

Complejidad

El número de iteraciones depende en gran medida del número de factores de n. El peor de los casos ocurre cuando n es primo, porque tenemos que realizar todas las iteraciones de 1 a n para encontrar sus únicos 2 divisores. Esto es lo que sucede con 199999. Por otro lado, 9699690 es 19-suave y rápidamente encontramos dos divisores a ambos lados del punto de ruptura √ (n / φ) ≈ 2448.

Casos de prueba

let f =
n=>{for(b=0,k=n/.809;n%++b||k>b*b*2&&(a=b););return[b=k-a*a>b*b?b:a,n/b]}

console.log(JSON.stringify(f(12)));       // [ 3, 4 ]
console.log(JSON.stringify(f(42)));       // [ 6, 7 ]
console.log(JSON.stringify(f(576)));      // [ 18, 32 ]
console.log(JSON.stringify(f(1234)));     // [ 2, 617 ]
console.log(JSON.stringify(f(10000)));    // [ 80, 125 ]
console.log(JSON.stringify(f(199999)));   // [ 1, 199999 ]
console.log(JSON.stringify(f(9699690)));  // [ 2431, 3990 ]

Arnauld
fuente
4

JavaScript (ES6), 83 bytes

f=
n=>{p=r=>Math.abs(r/n-n/r-1);for(r=i=n;--i;)r=n%i||p(i*i)>p(r*r)?r:i;return[r,n/r]}
;
<input type=number min=1 oninput=[a.value,b.value]=f(+this.value)><input readonly id=a><input readonly id=b>

En realidad, devuelve el par ( a , b ) que minimiza el valor absoluto de a / b - b / a -1, pero esto funciona para todos los casos de prueba al menos, aunque supongo que podría ahorrar 4 bytes usando la prueba 1.618 en su lugar .

Neil
fuente
3

Brachylog , 41 bytes

:1fL:2a:Lzoht
,A:B#>.*?!,.=
:3a/:$A-$|
//

Pruébalo en línea!

Explicación

  • Predicado principal:

    :1fL           L is the list of all couples [A:B] such that A*B = Input (see Pred. 1)
        :2a        Compute the distance between all As/Bs and φ (see Pred. 2)
           :Lz     Zip those distances to L
              o    Sort the zip on the distances
               ht  Take the couple [A:B] of the first element of the sorted list
    
  • Predicado 1: la salida es un par [A:B]tal queA*B = Input

    ,A:B           The list [A:B]
        #>         Both A and B are strictly positive
          .        Output = [A:B]
           *?      A*B = Input
             !,    Discard other choice points
               .=  Assign a value to A and B that satisfy the constraints
    
  • Predicado 2: Calcule la distancia entre A/By φ.

    :3a            Convert A and B to floats
       /           Divide A by B
        :$A-       Subtract φ
            $|     Absolute value
    
  • Predicado 3: Convierta un int en un flotante invirtiendo su inverso

    /              1/Input
     /             Output = 1/(1/Input)
    
Fatalizar
fuente
Por curiosidad: ¿es φun literal predefinido en Brachylog? ¿O dónde se define en el código?
Luis Mendo
1
Oh, acabo de ver:$A
Luis Mendo, el
2
@LuisMendo Afor Au;)
Fatalize
Aaah, muy bien!
Luis Mendo
2

Haskell (Lambdabot), 86 bytes

f(x,y)=abs$(x/y)-1.618
q n=minimumBy((.f).compare.f)[(x,y)|x<-[1..n],y<-[1..n],x*y==n]
Alondra
fuente
2

php, 103 bytes

<?php for($s=$a=$argv[1];++$i<$a;)if($a%$i==0&&$s>$t=abs($i*$i/$a-1.618)){$n=$i;$s=$t;}echo"$n ".$a/$n;

Produce un aviso (esto no interrumpe la ejecución) sobre $ i no asignado, por lo que debe ejecutarse en un entorno que silencia los avisos.

usuario59178
fuente
No es necesario contar la etiqueta abierta de PHP cuando el código se puede ejecutar como php -r '…'(donde -res gratis). Y definitivamente no hay necesidad de la forma larga, como short_open_tagestá activado por defecto.
manatwork
Por lo que sé, $ argv no funciona con -r, por lo que no se puede ejecutar así de todos modos. Dicho esto, cambiarlo a readline () o fgets (STDIN) si está en Windows y ejecuta sin la etiqueta es probablemente más corto de todos modos.
user59178
-ry $argvestán trabajando bien juntos: pastebin.com/vcgb5pT2
manatwork
Huh Bueno, no funciona para mí, solo recibo avisos variables indefinidos, me pregunto si es una configuración o si es solo Windows como de costumbre.
user59178
Todavía puede reemplazar <?phpcon <?para guardar tres bytes.
Paul Schmitz
1

Python 3, 96 bytes

Solución bastante simple. Hace uso de esta respuesta SO .

lambda n:min([((i,n//i),abs(1.618-i/(n//i)))for i in range(1,n+1)if n%i<1],key=lambda x:x[1])[0]

Pruébalo en línea

La misma solución en Python 2 es un byte más largo.

lambda n:min([((i,n/i),abs(1.618-1.*i/(n/i)))for i in range(1,n+1)if n%i<1],key=lambda x:x[1])[0]
mbomb007
fuente