Pilhas e pilhas de pedras

8

Meu trabalho é empilhar pedras em pilhas triangulares. Eu só faço isso há um século e já é bem chato. A pior parte é que eu rotulo cada pilha. Eu sei como decompor pedras em pilhas de tamanho máximo , mas quero minimizar o número de pilhas. Você pode ajudar?

Tarefa

Dado um número inteiro, decomponha-o no número mínimo de números triangulares e produza esse número mínimo.

Números triangulares

Um número triangular é um número que pode ser expresso como a soma dos primeiros nnúmeros naturais, por algum valor n. Assim, os primeiros números triangulares são

1 3 6 10 15 21 28 36 45 55 66 78 91 105

Exemplo

Como exemplo, digamos que a entrada seja 9. Como não é um número triangular, não pode ser expresso como a soma do 1número triangular. Assim, o número mínimo de números triangulares é 2, que pode ser obtido com [6,3], produzindo a saída correta de 2.

Como outro exemplo, digamos que a entrada seja 12. A solução mais óbvia é usar um algoritmo ganancioso e remover o maior número triangular de cada vez, produzindo [10,1,1]e produzindo 3. No entanto, existe uma solução melhor:, [6,6]produzindo a saída correta de 2.

Casos de teste

in out
1 1
2 2
3 1
4 2
5 3
6 1
7 2
8 3
9 2
10 1
11 2
12 2
13 2
14 3
15 1
16 2
17 3
18 2
19 3
20 2
100 2
101 2
5050 1

Regras

  • O número inteiro de entrada está entre 1 e o número máximo máximo do seu idioma.
  • Posso imitar qualquer idioma com meus seixos e quero que seu código seja o menor possível, porque não tenho nada além de seixos para acompanhá-lo. Portanto, este é o , portanto o código mais curto em cada idioma vence.
fireflame241
fonte
Caixa de areia cheia de pedras.
Fireflame241
OEIS A061336
Martin Ender
Não confunda com OEIS A057945 (a primeira diferença ocorre para n = 12).
Martin Ender

Respostas:

3

Retina , 57 49 bytes

.+
$*
(^1|1\1)+$
1
(^1|1\1)+(1(?(2)\2))+$
2
11+
3

Experimente online! Com base na minha resposta para três números triangulares . Mude a terceira linha para ^(^1|1\1)*$para suportar a entrada zero. Edit: Salvo 8 (mas provavelmente deve haver mais) bytes graças a @MartinEnder.

Neil
fonte
Você não precisa de grupo 1no segundo estágio, nem de grupo 1nem 3no terceiro estágio.
Martin Ender
E então ((?(2)1\2|1))pode ser reduzido para (1(?(2)\2)).
Martin Ender
Na verdade, é uma outra de três bytes mais curto para fazer algo estranho assim: ^((?<2>)(1\2)+){2}$. Ou ^(()(?<2>1\2)+){2}$se você preferir.
Martin Ender
@MartinEnder Essa última versão faz meu cérebro doer, mas pude usar seu segundo comentário para a minha resposta vinculada, o que foi legal.
Neil
Eu acho que o último é realmente mais simples do que a abordagem padrão, porque não tem a referência direta condicional estranha.
Martin Ender
1

Mathematica, 53 bytes

Min[Plus@@@Table[$($+1)/2,{$,#+1}]~FrobeniusSolve~#]&

Este código é muito lento. Se você deseja testar esta função, use a seguinte versão:

Min[Plus@@@Table[$($+1)/2,{$,√#+1}]~FrobeniusSolve~#]&

Experimente na Wolfram Sandbox

Explicação

Min[Plus@@@Table[$($+1)/2,{$,#+1}]~FrobeniusSolve~#]&  (* input: n *)

           Table[$($+1)/2,{$,#+1}]                     (* Generate the first n triangle numbers *)
                                  ~FrobeniusSolve~#    (* Generate a Frobenius equation from the *)
                                                       (* triangle numbers and find all solutions. *)
    Plus@@@                                            (* Sum each solution set *)
Min                                                    (* Fetch the smallest value *)
JungHwan Min
fonte
1

Gelatina ( garfo ), 9 bytes

æFR+\$S€Ṃ

Isso depende de uma bifurcação, na qual implementei um átomo de solução Frobenius ineficiente. Não posso acreditar que já faz um ano desde que eu o toquei pela última vez.

Explicação

æFR+\$S€Ṃ  Input: n
æF         Frobenius solve with
     $     Monadic chain
  R          Range, [1, n]
   +\        Cumulative sum, forms the first n triangle numbers
      S€   Sum each
        Ṃ  Minimum
milhas
fonte
Darn Frobenius resolver átomo bateu minha solução normal de Jelly por 6 bytes inteiros :(
Erik o Outgolfer
@EriktheOutgolfer Preciso terminar e dar um puxão nele.
miles
1

R , 69 58 bytes

function(n)3-n%in%(l=cumsum(1:n))-n%in%outer(c(0,l),l,"+")

Experimente online!

Explicação:

function(n){
 T <- cumsum(1:n)             # first n triangular numbers  [1,3,6]
 S <- outer(c(0,T),T,"+")     # sums of the first n triangular numbers,
                              # AND the first n triangular numbers [1,3,6,2,4,7,4,6,9,7,9,12]
 3 - (n %in% S) - (n %in% T)  # if n is in T, it's also in S, so it's 3-2: return 1
                              # if n is in S but not T, it's 3-1: return 2
                              # if n isn't in S, it's not in T, so 3-0: return 3
}
Giuseppe
fonte
0

JavaScript (ES6), 75 63 61 bytes

f=(n,x=y=0)=>y<n+2?x*x+y*y-8*n-2+!y?f(n,x<n+2?x+1:++y):2-!y:3

Quão?

Usamos as seguintes propriedades:

  • De acordo com teorema do número poligonal de Fermat , qualquer número inteiro positivo pode ser expresso como a soma de no máximo 3 números triangulares.
  • Um número t é triangular se e somente se 8t + 1 for um quadrado perfeito (isso pode ser facilmente comprovado resolvendo t = n (n + 1) / 2 ).

Dado um número inteiro positivo n , basta testar se podemos encontrar:

  • x> 0 tal que 8n + 1 = x² ( n próprio é triangular)
  • ou x> 0 e y> 0, de modo que 8n + 2 = x² + y² ( n é a soma de 2 números triangulares)

Se ambos os testes falharem, n deve ser a soma de 3 números triangulares.

f = (n, x = y = 0) =>                 // given n and starting with x = y = 0
  y < n + 2 ?                         // if y is less than the maximum value:
    x * x + y * y - 8 * n - 2 + !y ?  //   if x² + y² does not equal 8n + 2 - !y:
      f(                              //     do a recursive call with:
        n,                            //       - the original input n
        x < n + 2 ? x + 1 : ++y       //       - either x incremented or
      )                               //         y incremented and x set to y
    :                                 //   else:
      2 - !y                          //     return either 1 or 2
  :                                   // else:
    3                                 //   return 3

Casos de teste

Arnauld
fonte
0

MATL , 15 bytes

`G:Ys@Z^!XsG-}@

Experimente online!

Explicação

`         % Do...while
  G:      %   Push range [1 2 3 ... n], where n is the input
  Ys      %   Cumulative sum: gives [1 3 6 ... n*(n+1)/2]
  @Z^     %   Cartesian power with exponent k, where k is iteration index
          %   This gives a k-column matrix where each row is a Cartesian tuple
  !Xs     %   Sum of each row. Gives a column vector
  G-      %   Subtract input from each entry of that vector. This is the loop 
          %   condition. It is truthy if it only contains non-zeros
}         % Finally (execute before exiting the loop)  
  @       %   Push iteration index, k. This is the output
          % End (implicit). Proceeds with next iteration if the top of the
          % stack is truthy
Luis Mendo
fonte
0

Kotlin , 176 154 bytes

Submissão

{var l=it
var n=0
while(l>0){n++
val r=mutableListOf(1)
var t=3
var i=3
while(t<=l){r.add(t)
t+=i
i++}
l-=r.lastOrNull{l==it|| r.contains(l-it)}?:r[0]}
n}

Embelezado

{
    // Make a mutable copy of the input
    var l=it
    // Keep track of the number of items removed
    var n=0
    // While we still need to remove pebbles
    while (l > 0) {
        // Increase removed count
        n++
        // BEGIN: Create a list of triangle numbers
        val r= mutableListOf(1)
        var t = 3
        var i = 3
        while (t<= l) {
            // Add the number to the list and calculate the next one
            r.add(t)
            t+=i
            i++
        }
        // END: Create a list of triangle numbers
        // Get the fitting pebble, or the biggest one if none fit or make a perfect gap
        l -= r.lastOrNull {l==it|| r.contains(l-it)} ?: r[0]
    }
    //Return the number of pebbles
    n
}

Teste

var r:(Int)->Int =
{var l=it
var n=0
while(l>0){n++
val r=mutableListOf(1)
var t=3
var i=3
while(t<=l){r.add(t)
t+=i
i++}
l-=r.lastOrNull{l==it|| r.contains(l-it)}?:r[0]}
n}

data class TestData(val input:Int, val output:Int)

fun main(args: Array<String>) {
    val tests = listOf(
            TestData(1,1),
            TestData(2,2),
            TestData(3,1),
            TestData(4,2),
            TestData(5,3),
            TestData(6,1),
            TestData(7,2),
            TestData(8,3),
            TestData(9,2),
            TestData(10,1),
            TestData(11,2),
            TestData(12,2),
            TestData(13,2),
            TestData(14,3),
            TestData(15,1),
            TestData(16,2),
            TestData(17,3),
            TestData(18,2),
            TestData(19,3),
            TestData(20,2),
            TestData(100,2),
            TestData(101,2),
            TestData(5050,1)
    )
    tests.map { it to r(it.input) }.filter { it.first.output != it.second }.forEach { println("Failed for ${it.first}, output ${it.second} instead") }
}

TryItOnline

jrtapsell
fonte