Decomponha um número em triângulos

15

Dado um número inteiro n , decompor-se-a em uma soma de números triangulares máxima (onde T m representa o m th número triangular, ou a soma dos números inteiros de 1 a m ) como se segue:

  • enquanto n> 0 ,

    • Encontre o maior número triangular possível T m de modo que T m ≤ n .

    • anexa m à representação de decomposição triangular de n .

    • subtrair T m de n .

Por exemplo, uma entrada de 44 produziria uma saída de 8311 , porque:

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

    • o primeiro dígito é 8 ; subtraia 36 de 44 para sobrar 8 .
  • 1 + 2 + 3 = 6 <8, mas 1 + 2 + 3 + 4 = 10> 8.

    • o segundo dígito é 3 ; subtraia 6 de 8 para sobrar 2 .
  • 1 <2, mas 1 + 2 = 3> 2.

    • o terceiro e o quarto dígitos devem ser 1 e 1 .

Use os dígitos de 1 a 9 para representar os 9 primeiros números triangulares e, em seguida, use as letras de a a z (podem ser maiúsculas ou minúsculas) para representar o 10º a 35º número triangular. Você nunca receberá uma entrada que exigirá o uso de um "dígito" maior.

Os limites na entrada são 1 ≤ n <666 e sempre será um número inteiro.

Todas as entradas e saídas possíveis e alguns casos de teste selecionados (listados como entrada e saída):

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

Uma saída de para uma entrada de -1/12 não é necessária. :)

Maçaneta da porta
fonte
Mas uma entrada de precisa ter uma saída de ∞?
user75200

Respostas:

8

JavaScript (ES6), 52 bytes

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

Quão?

Em vez de computação explicitamente T i  = 1 + 2 + 3 + ... + i , que começam com t = 0 e iterativamente subtraia t + 1 a partir de N , enquanto t <n , incrementando t em cada iteração. Quando a condição não é mais atendida, um total de T t foi subtraído de n e a saída é atualizada de acordo. Repetimos o processo até n = 0 .

Abaixo está um resumo de todas as operações 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 teste

Arnauld
fonte
5

Geléia , 18 17 bytes

Ḥ‘½+.Ḟ©ịØB2®cạµ¹¿

Este é um link monádico que imprime no STDOUT. Seu valor de retorno é 0 e deve ser ignorado.

Experimente online!

Dennis
fonte
4

dc, 74 bytes

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

Isso é horrível.

?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
poi830
fonte
3

JavaScript (ES6), 61 57 bytes

Guardado 4 bytes graças a @Arnauld

f=(n,p=q=0)=>n?p-~q>n?q.toString(36)+f(n-p):f(n,++q+p):''
ETHproductions
fonte
1
Eu tinhaf=(n,t=0)=>n?t+1>n?t.toString(36)+f(n):f(n-++t,t):1
Arnauld
@ Arnauld Oh uau, isso é muito melhor. Você deve publicá-lo você mesmo ...
ETHproductions
1
Bem. Na sua versão, seria seguro fazer f=(n,p=q=0)e f(n,++q+p)?
Arnauld
@ Arnauld Sim, obrigado!
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):"");}

Porta da incrível resposta JavaScript (ES6) do @Arnauld .
Minha própria abordagem tinha quase o dobro do tempo ..

Experimente aqui.

Explicação:

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
Kevin Cruijssen
fonte
2

Retina , 115 108 38 34 bytes

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

[Experimente online!] (Inclui suíte de testes) Usa letras maiúsculas. Edit: Salvo 70 74 bytes, adaptando descaradamente a resposta de @ MartinEnder para Este número é triangular? Explicação: O número é convertido em unário e, em seguida, o maior número triangular possível é correspondido repetidamente até que o número se esgote. Cada partida é então convertida na base 36.

Neil
fonte
1

PHP, 74 bytes

for(;$n=&$argn;$t.=$i>10?chr($i+86):$i-1)for($i=0;$n>=++$i;)$n-=$i;echo$t;

Versão Online

Jörg Hülsermann
fonte
0

R, 87 bytes

Originalmente, tentei predefinir os possíveis números triangulares. Isso levou a esse código com 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})

Isso exigiu mais indexação, então tentei a metodologia do @Arnauld para reduzir os bytes para 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 os códigos usavam as letras predefinidas, pois não era possível encontrar uma maneira curta de converter para a base 36.

Shayne03
fonte