Descomponer un número en triángulos


15

Dado un número entero n , descomponerlo en una suma de números triangulares máximos (donde T m representa el número triangular número m , o la suma de los números enteros de 1 a m ) de la siguiente manera:

  • mientras n> 0 ,

    • encuentre el número triangular más grande posible T m tal que T m ≤ n .

    • agregue m a la representación de descomposición triangular de n .

    • restar T m de n .

Por ejemplo, una entrada de 44 produciría una salida de 8311 , porque:

  • 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 = 36 <44, pero 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45> 44.

    • el primer dígito es 8 ; reste 36 de 44 para obtener 8 sobrantes.
  • 1 + 2 + 3 = 6 <8, pero 1 + 2 + 3 + 4 = 10> 8.

    • el segundo dígito es 3 ; reste 6 de 8 para obtener 2 sobrantes.
  • 1 <2, pero 1 + 2 = 3> 2.

    • los dígitos tercero y cuarto deben ser 1 y 1 .

Use los dígitos del 1 al 9 para representar los primeros 9 números triangulares, luego use las letras de la a a la z (pueden escribirse en mayúsculas o minúsculas) para representar el número triangular del 10 al 35. Nunca se le dará una entrada que requerirá el uso de un "dígito" más grande.

Los límites en la entrada son 1 ≤ n <666 , y siempre será un número entero.

Todas las entradas y salidas posibles , y algunos casos de prueba seleccionados (listados como entrada, luego salida):

1 1
2 11
3 2
4 21
5 211
6 3
100 d32
230 k5211
435 t
665 z731

No se requiere una salida de para una entrada de -1/12 . :)


¿Pero una entrada de necesita tener una salida de ∞?
user75200

Respuestas:


8

JavaScript (ES6), 52 bytes

f=(n,t=0)=>t<n?f(n-++t,t):t.toString(36)+(n?f(n):'')

¿Cómo?

En lugar de calcular explícitamente T i  = 1 + 2 + 3 + ... + i , comenzamos con t = 0 y restamos iterativamente t + 1 de n mientras t <n , incrementando t en cada iteración. Cuando la condición ya no se cumple, un total de T t se resta de n y la salida se actualiza en consecuencia. Repetimos el proceso hasta n = 0 .

A continuación se muestra un resumen de todas las operaciones para n = 100 .

 n  |  t | t < n | output
----+----+-------+--------
100 |  0 | yes   | ""
 99 |  1 | yes   | ""
 97 |  2 | yes   | ""
 94 |  3 | yes   | ""
 90 |  4 | yes   | ""
 85 |  5 | yes   | ""
 79 |  6 | yes   | ""
 72 |  7 | yes   | ""
 64 |  8 | yes   | ""
 55 |  9 | yes   | ""
 45 | 10 | yes   | ""
 34 | 11 | yes   | ""
 22 | 12 | yes   | ""
  9 | 13 | no    | "d"
----+----+-------+--------
  9 |  0 | yes   | "d"
  8 |  1 | yes   | "d"
  6 |  2 | yes   | "d"
  3 |  3 | no    | "d3"
----+----+-------+--------
  3 |  0 | yes   | "d3"
  2 |  1 | yes   | "d3"
  0 |  2 | no    | "d32"

Casos de prueba



4

cc, 74 bytes

?sa[2k_1K/1 4/la2*+v+0k1/dlardd*+2/-sadd10<t9>ula0<s]ss[87+P]st[48+P]sulsx

Esto es horrible

?sa             stores the input
[2k             sets precision to 2 so dc doesn't truncate 1/4
_1K/1 4/la2*+v+ uses the quadratic formula to find k, the next value to print
0k1/d           truncates k to an integer
lardd*+2/-sa    subtracts kth triangular number from the input 
dd10<t9>u       determines whether to print k as a letter or a digit         
la0<s]ss        loops when a is greater than 0
[87+P]st        prints k as a letter
[48+P]su        prints k as a digit (not p, as that leaves a trailing newline)
lsx             starts the main loop

3

JavaScript (ES6), 61 57 bytes

Guardado 4 bytes gracias a @Arnauld

f=(n,p=q=0)=>n?p-~q>n?q.toString(36)+f(n-p):f(n,++q+p):''

1
Teníaf=(n,t=0)=>n?t+1>n?t.toString(36)+f(n):f(n-++t,t):1
Arnauld

@Arnauld Oh, wow, eso es mucho mejor. Deberías publicarlo tú mismo ...
ETHproductions

1
Bien. En su versión, ¿sería seguro hacerlo f=(n,p=q=0)y f(n,++q+p)?
Arnauld

@Arnauld ¡Sí, gracias!
ETHproductions

2

Java 7, 81 bytes

int i=0;String c(int n){return i<n?c(n-++i):Long.toString(i,36)+(n>(i=0)?c(n):"");}

Puerto de la sorprendente respuesta JavaScript (ES6) de @Arnauld .
Mi propio enfoque fue casi el doble de largo ...

Pruébalo aquí.

Explicación:

int i=0;                  // Temp integer `i` (on class level)
String c(int n){          // Method with integer parameter and String return-type
  return i<n?             //  If `i` is smaller than the input integer
    c(n-++i)              //   Return a recursive call with input minus `i+1` (and raise `i` by 1 in the process)
   :                      //  Else:
    Long.toString(i,36)+  //   Return `i` as Base-36 +
     (n>(i=0)?            //   (If the input integer is larger than 0 (and reset `i` to 0 in the process)
      c(n)                //    Recursive call with the input integer
     :                    //   Else:
      "");                //    an empty String)
}                         // End of method

2

Retina , 115 108 38 34 bytes

.+
$*¶
(\G¶|¶\1)+
0$1
+T`_w¶`w_`.¶

[¡Pruébelo en línea!] (Incluye paquete de prueba) Utiliza letras mayúsculas. Editar: ahorró 70 74 bytes adaptando descaradamente la respuesta de @ MartinEnder a ¿Es este número triangular? Explicación: El número se convierte en unario, luego el número triangular más grande posible se empareja repetidamente hasta que se agota el número. Cada partido se convierte en la base 36.



0

R, 87 bytes

Originalmente, traté de preestablecer los posibles números triangulares. Esto llevó a este código con 105 bytes:

pryr::f(n,{l=cumsum(1:35)
k=''
while(n){y=tail(which(l<=n),1)
n=n-l[y]
k=paste0(k,c(1:9,letters)[y])}
k})

Esto requirió más indexación, así que probé la metodología de @Arnauld para reducir los bytes a 87.

pryr::f(n,{k='';while(n){t=0;while(t<n){t=t+1;n=n-t};k=paste0(k,c(1:9,letters)[t])};k})

Ambos códigos hicieron uso de las letras preestablecidas, ya que no pude encontrar una forma corta de convertir a la base 36.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.