Montones y montones de guijarros

8

Mi trabajo es apilar piedras en pilas triangulares. Solo he estado haciendo esto durante un siglo y ya es bastante aburrido. La peor parte es que etiqueto cada pila. Sé cómo descomponer los guijarros en pilas de tamaño máximo , pero quiero minimizar el número de pilas. ¿Puede usted ayudar?

Tarea

Dado un número entero, descomponerlo en el número mínimo de números triangulares y generar ese número mínimo.

Números triangulares

Un número triangular es un número que puede expresarse como la suma de los primeros nnúmeros naturales, por algún valor n. Así, los primeros pocos números triangulares son

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

Ejemplo

Como ejemplo, digamos que la entrada es 9. No es un número triangular, por lo que no puede expresarse como la suma del 1número triangular. Por lo tanto, el número mínimo de números triangulares es 2, que se puede obtener con [6,3], dando la salida correcta de 2.

Como otro ejemplo, digamos que la entrada es 12. La solución más obvia es usar un algoritmo codicioso y eliminar el número triangular más grande a la vez, dando [10,1,1]como resultado una salida de 3. Sin embargo, hay una mejor solución: obtener [6,6]el resultado correcto de 2.

Casos de prueba

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

Reglas

  • El entero de entrada está entre 1 y el entero máximo de su idioma.
  • Puedo emular cualquier idioma con mis guijarros , y quiero que su código sea lo más pequeño posible porque no tengo nada más que guijarros para rastrearlo. Por lo tanto, este es el , por lo que gana el código más corto en cada idioma .
fireflame241
fuente
Caja de arena llena de guijarros.
fireflame241
OEIS A061336
Martin Ender
No debe confundirse con OEIS A057945 (se produce la primera diferencia para n = 12).
Martin Ender

Respuestas:

3

Retina , 57 49 bytes

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

Pruébalo en línea! Basado en mi respuesta a Tres números triangulares . Cambie la tercera línea a ^(^1|1\1)*$para admitir entrada cero. Editar: Guardado 8 (pero probablemente debería ser más) bytes gracias a @MartinEnder.

Neil
fuente
No necesita grupo 1en la segunda etapa, ni grupo 1ni 3en la tercera etapa.
Martin Ender
Y luego ((?(2)1\2|1))se puede acortar a (1(?(2)\2)).
Martin Ender
En realidad, se trata de otro de tres bytes más corto para hacer algo raro como esto: ^((?<2>)(1\2)+){2}$. O ^(()(?<2>1\2)+){2}$si lo prefieres.
Martin Ender
@MartinEnder Esa última versión me duele el cerebro, pero pude usar tu segundo comentario para mi respuesta vinculada, lo cual fue agradable.
Neil
Creo que el último es en realidad más simple que incluso el enfoque estándar porque no tiene la referencia directa condicional extraña.
Martin Ender
1

Mathematica, 53 bytes

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

Este código es muy lento. Si desea probar esta función, use la siguiente versión:

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

Pruébalo en Wolfram Sandbox

Explicación

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
fuente
1

Gelatina ( tenedor ), 9 bytes

æFR+\$S€Ṃ

Esto se basa en una bifurcación donde implementé un átomo de resolución de Frobenius ineficiente. No puedo creer que ya haya pasado un año desde la última vez que lo toqué.

Explicación

æ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
millas
fuente
Maldito Frobenius resuelve el átomo, superó mi solución Jelly normal en 6 bytes completos :(
Erik the Outgolfer
@EriktheOutgolfer Necesito terminarlo y tirar de él.
millas
1

R , 69 58 bytes

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

Pruébalo en línea!

Explicación:

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
fuente
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

¿Cómo?

Usamos las siguientes propiedades:

  • Según el teorema del número poligonal de Fermat , cualquier número entero positivo puede expresarse como la suma de, como máximo, 3 números triangulares.
  • Un número t es triangular si y solo si 8t + 1 es un cuadrado perfecto (esto se puede probar fácilmente resolviendo t = n (n + 1) / 2 ).

Dado un número entero positivo n , es suficiente para probar si podemos encontrar:

  • x> 0 tal que 8n + 1 = x² ( n en sí es triangular)
  • o x> 0 e y> 0 de modo que 8n + 2 = x² + y² ( n es la suma de 2 números triangulares)

Si ambas pruebas fallan, n debe ser la suma 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 prueba

Arnauld
fuente
0

MATL , 15 bytes

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

Pruébalo en línea!

Explicación

`         % 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
fuente
0

Kotlin , 176 154 bytes

Sumisión

{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}

Embellecido

{
    // 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
}

Prueba

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
fuente