Tres números triangulares [cerrado]

19

Descripción

Ha habido muchos otros desafíos relacionados con estos números antes, y espero que este no esté entre ellos.

El n º número triangular es igual a la suma de todos los números naturales hasta n , cosas simples. Hay una página de wikipedia y una entrada en OEIS , para aquellos que desean informarse más.

Ahora, Gauss descubrió que cada número natural puede expresarse como una suma de tres números triangulares (estos incluyen 0), y está bien tener un número más de una vez, por ejemplo 0 + 1 + 1 = 2.

Desafío

Su tarea es escribir un programa o función, dado un número natural (incluido 0), imprime tres números triangulares que suman el argumento. Puede imprimir los números separados por espacios, como una matriz o por otro método que desee. Sin embargo, está prohibido usar cualquier función integrada para obtener directamente una matriz, un rango o cualquier otra forma de colección que contenga una lista de números triangulares (por ejemplo, un solo átomo que produce el rango).

Casos de prueba

9 -> 6 + 3 + 0 or 3 + 3 + 3
12 -> 6 + 6 + 0 or 6 + 3 + 3 or 10 + 1 + 1
13 -> 6 + 6 + 1
1 -> 1 + 0 + 0
0 -> 0 + 0 + 0

Nota: Si hay más de una combinación posible, puede imprimir una o todas, pero debe imprimir cualquier combinación solo una vez, eliminando todas las combinaciones que son el resultado de reorganizar otras combinaciones. Realmente agradecería un enlace de prueba y una explicación, realmente me encanta ver cómo resuelve el problema;)

Esto es , por lo que se aplican las lagunas estándar. ¡Que gane la respuesta más corta en bytes!

racer290
fuente
1
Para 12 también puedes hacer 1 + 1 + 10.
Erik the Outgolfer
1
@steenbergh ano siempre será un número triangular
Felipe Nardi Batista
3
Puedo analizar " funciones integradas para obtener directamente una matriz, un rango o cualquier otra forma de colección que contenga una lista de números triangulares " de dos maneras, pero ninguna de las dos tiene sentido. El primero prohíbe todas las construcciones que obtienen directamente una matriz, pero parece prohibir todo uso de matrices en todos los idiomas que conozco; el otro prohíbe a los constructores " obtener directamente ... un rango ... que contenga una lista de números triangulares ", pero no sé qué significaría eso.
Peter Taylor
2
Entonces, ¿ están permitidas las funciones integradas que toman un argumento ny devuelven una lista de los primeros nnúmeros de triángulo ? Eso se siente más bien dirigido contra un lenguaje específico, aunque no sé cuál.
Peter Taylor
44
Te insto a que levantes esta restricción. Le prometo que no mejorará la calidad o la imparcialidad de las respuestas entre idiomas en su forma de pensar.
Lynn

Respuestas:

8

05AB1E , 10 bytes

Código:

ÝηO3ãʒOQ}¬

Explicación:

Ý             # Compute the range [0 .. input]
 η            # Get the prefixes
  O           # Sum each prefix to get the triangle numbers
   3ã         # Cartesian repeat 3 times
     ʒ  }     # Keep elements that
      OQ      #   have the same sum as the input
         ¬    # Retrieve the first element

Utiliza la codificación 05AB1E . Pruébalo en línea!

Adnan
fuente
Ahhh ... Sí; Eso lo haría.
Magic Octopus Urn
7

Python 2 , 99 bytes

from random import*
n=input()
while 1:b=sample([a*-~a/2for a in range(n+1)]*3,3);n-sum(b)or exit(b)

Pruébalo en línea!

¡Estoy bastante sorprendido de que esto sea más corto itertoolso una comprensión de triple lista! (Eventualmente) escupe una respuesta aleatoria cada vez que la ejecutas.

Dos 102s:

n=input();r=[a*-~a/2for a in range(n+1)];print[(a,b,c)for a in r for b in r for c in r if a+b+c==n][0]
def f(n):r=[a*-~a/2for a in range(n+1)];return[(a,b,c)for a in r for b in r for c in r if a+b+c==n][0]

itertools parece ser 106:

from itertools import*;lambda n:[x for x in product([a*-~a/2for a in range(n+1)],repeat=3)if sum(x)==n][0]
Lynn
fuente
+1 para salida aleatoria. :) También me sorprende que da la solución más corta (hasta ahora).
Kevin Cruijssen
Muchas gracias por el método. El código Ruby correspondiente tiene 57 bytes.
Eric Duminil
3

Jalea , 12 bytes

0r+\œċ3S=¥Ðf

Pruébalo en línea!

Cómo funciona

0r+\œċ3S=¥Ðf   input: n
0r             [0 1 ... n]
  +\           cumsum
    œċ3        combinations of 3 elements, with repetition
          Ðf   filter on
       S          sum
        =         equals n
Monja permeable
fuente
Considere agregar una explicación .. =)
racer290
2
@ racer290 hecho.
Leaky Nun
3

Brachylog , 13 bytes

⟦⟦ᵐ+ᵐj₃⊇Ṫ.+?∧

Pruébalo en línea!

Cómo funciona

⟦⟦ᵐ+ᵐj₃⊇Ṫ.+?∧  input: n
⟦              [0 1 ... n]
 ⟦ᵐ            [[0] [0 1] [0 1 2] ... [0 1 ... n]]
   +ᵐ          [0 1 3 ... n(n+1)/2]
     j₃        [0 1 3 ... n(n+1)/2 0 1 3 ... n(n+1)/2 0 1 3 ... n(n+1)/2]
       ⊇       is a superset of
        Ṫ      a list of three elements 
         .     which is the output
          +?   which sums up to be the input
Monja permeable
fuente
2

MATL , 18 bytes

Q:qYs3Z^t!sG=fX<Y)

Esto genera el primer resultado en orden lexicográfico.

¡Pruébalo en MATL Online!

Explicación

Q     % Implicitly input n. Add 1
:     % Range (inclusive, 1-based): gives [1 2 ... n+1]
q     % Subtract 1 (element-wise): gives [0 1 ... n]
Ys    % Cumulative sum
3Z^   % Cartesian power with exponent 3. Gives a matrix where each row is a
      % Cartesian tuple
t     % Duplicate
!s    % Sum of each row
G=    % Does each entry equal the input?
f     % Find indices that satisfy that condition
X<    % Minimum
Y)    % Use as row index into the Cartesian power matrix. Implicitly display
Luis Mendo
fuente
2

Haskell, 66 59 bytes

Gracias por permitir la salida de todas las soluciones, ¡fue una distracción fascinante! Estaba tan feliz de no necesitar extraer una solución y poder darles todo lo que no noté el costo que resulta de evitar soluciones permutadas. El comentario de @ Lynn me lo explicó y me permitió guardar 7 bytes.

f n|l<-scanl(+)0[1..n]=[(a,b,c)|c<-l,b<-l,a<-l,a+b+c==n]!!0

Esto une más que suficientes números triangulares ly verifica todas las combinaciones.

Christian Sievers
fuente
¿Acaso no es abandonar las a>=b,b>=ccondiciones y simplemente agregar sufijos !!0a su código? La salida de todas las soluciones realmente no te ayuda aquí.
Lynn
@ Lynn Tienes razón, por supuesto, me distraje. ¡Gracias!
Christian Sievers
2

Retina , 63 59 bytes

.+
$*
^((^1|1\2)*)((1(?(4)\4))*)((1(?(6)\6))*)$
$.1 $.3 $.5

Pruébalo en línea! El enlace incluye casos de prueba. (1(?(1)\1))*es un comparador de números triangulares generalizado, pero para el primer número triangular podemos guardar algunos bytes al usar ^para la coincidencia inicial.

Neil
fuente
1

PHP , 351 bytes

$r=[];function f($a=[],$c=0){global$argn,$t,$r;if($c<3){$n=$argn-array_sum($a);$z=array_filter($t,$f=function($v)use($n,$c){return$v>=$n/(3-$c)&&$v<=$n;});foreach($z as$v){$u=array_merge($a,[$v]);if(($w=$n-$v)<1){if(!$w){$u=array_pad($u,3,0);sort($u);if(!in_array($u,$r)){$r[]=$u;}}}else f($u,$c+1);}}}for($t=[0];$argn>$t[]=$e+=++$i;);f();print_r($r);

Pruébalo en línea!

Jörg Hülsermann
fuente
1

Python 3 , 119 bytes

lambda n:[l for l in combinations_with_replacement([(t**2+t)/2for t in range(n)],3)if sum(l)==n]
from itertools import*

Pruébalo en línea!

¡Gracias a @WheatWizard por guardar 12 bytes!

Chase Vogeli
fuente
Su map(y tal vez su filtro) se puede escribir más corto como una lista de comprensión.
Wheat Wizard
@WheatWizard gracias por la idea, no puedo creer que no haya pensado en una lista de comprensión para elmap
Chase Vogeli
Los objetos de filtro son resultados perfectamente válidos, pero si desea generar una lista, puede usar un splat como este[*filter(...)]
Wheat Wizard
1
Lo que probé fue (x,y,z) for x,y,z in...cuál es más largo que el l for l in...que probablemente explica esa diferencia.
Chase Vogeli
1

C / C ++ - 197 bytes

#include<stdio.h>
#define f(i,l,u) for(int i=l;i<=u;i++)
int t(int n){return n>1?n+t(n-1):n;}
int c(int n){f(a,0,n)f(b,a,n)f(c,b,n)if(t(a)+t(b)+t(c)==n)return printf("%d %d %d\n",t(a),t(b),t(c));}

Golpe a golpe:

#include<stdio.h>

Necesario para imprimirf. Podría ser elidido para ciertas versiones de C

#define f(i,l,u) for(int i=l;i<=u;i++)

Ahorro de espacio para bucle.

int t(int n){return n>1?n+t(n-1):n;}

Triángulo recursivo evaluador.

int c(int n){f(a,0,n)f(b,a,n)f(c,b,n)if(t(a)+t(b)+t(c)==n)return printf("%d %d %d\n",t(a),t(b),t(c));}

Este tipo hace el trabajo pesado. Tres bucles anidados para iterar a, b, c de 0 a n, tenga en cuenta que byc iteran desde el valor anterior hasta n. No es estrictamente necesario recortar la iteración de esa manera, ya que la returnllegada en un minuto resuelve el problema "duplicado".

En el nivel interno, si la suma de los tres triángulos numera ==el valor deseado, imprima los triángulos y regrese.

Puede eliminar legalmente la returnpalabra clave y convertir el tipo de retorno de c a vacío para guardar unos pocos bytes más e imprimir todas las soluciones posibles. Es por esta razón que las iteraciones son limitados, si todos los bucles corrían de 0que nse causaría duplicados.

dgnuff
fuente
1

Mathematica, 63 bytes

(t=#;#&@@Select[Table[i(i+1)/2,{i,0,t}]~Tuples~{3},Tr@#==t&]‌​)&
J42161217
fuente
Con la sintaxis de infijo y esa manera de conseguir Firstque ahorra la friolera de 2 bytes , (t=#;#&@@Select[Table[i(i+1)/2,{i,0,t}]~Tuples~{3},Tr@#==t&])&para 62 bytes.
numbermaniac
Genial,
editaré
0

CJam , 26 bytes

{_),[{\_@+}*]3m*_{:+}%@#=}

Puerto de mi respuesta MATL. Este es un bloque anónimo que espera la entrada en la pila y lo reemplaza por la matriz de salida.

Pruébalo en línea!

Luis Mendo
fuente
0

R , 66 bytes

n=scan();b=expand.grid(rep(list(cumsum(0:n)),3));b[rowSums(b)==n,]

Algoritmo de fuerza bruta; lee nde stdin y devuelve un marco de datos donde cada fila es una combinación de 3 números triangulares que suman n. Si es necesario, puedo devolver solo la primera fila para +4 bytes.

Pruébalo en línea!

Giuseppe
fuente
0

Java 8, 164 bytes

n->{int t[]=new int[n+1],i=0,j=0;for(;i<=n;)if(Math.sqrt(8*i+++1)%1==0)t[j++]=i-1;for(int a:t)for(int b:t)for(int c:t)if(a+b+c==n)return new int[]{c,b,a};return t;}

Explicación:

Pruébalo aquí

n->{                     // Method with int parameter and int-array return-type
  int t[]=new int[n+1],  //  Create an int-array to store triangular numbers
      i=0,j=0;           //  Two index-integers
  for(;i<=n;)            //  Loop (1) from 0 to `n` (inclusive)
    if(Math.sqrt(8*i+++1)%1==0) 
                         //   If `i` is a triangular number
      t[j++]=i-1;        //    Add it to array `t`
                         //  End of for-loop (1) (implicit / single-line body)
  for(int a:t)           //  Loop (2) over the triangular numbers
    for(int b:t)         //   Inner loop (3) over the triangular numbers
      for(int c:t)       //    Inner loop (4) over the triangular numbers
        if(a+b+c==n)     //     If the three triangular numbers sum equal the input
          return new int[]{c,b,a};
                         //      Return these three triangular numbers as int-array
                         //    End of loop (4) (implicit / single-line body)
                         //   End of loop (3) (implicit / single-line body)
                         //  End of loop (2) (implicit / single-line body)
  return t;              //  Return `t` if no sum is found (Java methods always need a
                         //  return-type, and `t` is shorter than `null`;
                         //  since we can assume the test cases will always have an answer,
                         //  this part can be interpret as dead code)
}                        // End of method
Kevin Cruijssen
fuente
0

JavaScript, 108 bytes

r=[],i=a=b=0
while(a<=x)r.push(a=i++*i/2)
for(a=0;a<3;){
b=r[i]
if(b<=x){
x-=b
a++
console.log(b)}
else i--}

Explicación

x representa la entrada

while(a<=x)r.push(a=i++*i/2) Crea una matriz de todos los números triangulares hasta x

El forbucle imprime el número triangular más alto menor que x, luego resta ese número x, por tres iteraciones. (básicamente un algoritmo codicioso)

WaffleCohn
fuente
Tienes el mismo problema que yo: al tomar el número de triángulo más grande <= x en cada paso, no se garantiza que tengas un número de triángulo para tu tercer lugar. Compruebe su salida para x = 103:91 + 10 + 1 = 102
asgallant
0

Pyth, 19 bytes

Estoy tan fuera de práctica con Pyth, no es cierto: /

hfqQsT.C*3+0msSdSQ3

Pruébalo aquí .

hfqQsT.C*3+0msSdSQ3  Implicit: Q=input()

                SQ   Range 1-n
            m        Map the above over d:
              Sd       Range 1-d
             s         Sum the above
                     Yields [1,3,6,10,...]
          +0         Prepend 0 to the above
        *3           Triplicate the above
      .C          3  All combinations of 3 of the above
 f                   Filter the above over T:
    sT                 Where sum of T
  qQ                   Is equal to input
h                    Take the first element of that list
Sok
fuente
Posiblemente podría guardar un byte al omitir el selector para el primer elemento de la lista porque también puede imprimir todas las soluciones posibles.
racer290
@ racer290 Aún mejor, aunque los resultados estarán en la forma [[a, b, c], [d, e, f]] - ¿estaría bien?
Sok
@ racer290 En realidad, no, filtrar los duplicados no estaría libre por el aspecto de las cosas, por lo que no sería más corto: c
Sok
0

Ruby 61 57 55 bytes

Inspirado por la respuesta Python de Lynn . Genera tripletes al azar hasta que se alcanza la suma deseada:

->n{x=Array.new 3{(0..rand(n+1)).sum}until x&.sum==n;x}

Requiere Ruby 2.4. En Ruby 2.3 y versiones anteriores, es un error de sintaxis y Range#sumno está definido. Esta versión más larga (64 bytes) es necesaria para Ruby 2.3:

->n{x=Array.new(3){(a=rand(n+1))*-~a/2}until x&.inject(:+)==n;x}

Aquí hay una pequeña prueba:

f=->n{x=Array.new 3{(0..rand(n+1)).sum}until x&.sum==n;x}
# => #<Proc:0x000000018aa5d8@(pry):6 (lambda)>
f[0]
# => [0, 0, 0]
f[13]
# => [0, 3, 10]
f[5]
# => [3, 1, 1]
f[27]
# => [21, 3, 3]
f[27]
# => [0, 21, 6]
f[300]
# => [3, 21, 276]

¡Pruébelo en línea con Ruby 2.3!

Eric Duminil
fuente
0

Javascript (ES6), 108 bytes - fijo

Toma un entero como entrada, genera una matriz que [a, b, c]contiene una lista ordenada de números de triángulo a + b + c = x, donde ael número de triángulo más grande es menor o igual que la entrada, y bes el número de triángulo más grande menor o igual que la entrada menos a.

x=>{t=[0],t.f=t.forEach,i=j=k=0;for(;j<x;t[i]=j+=i++);t.f(a=>t.f(b=>t.f(c=>a+b+c==x?k=[a,b,c]:0)));return k}

Explicación

x=>{
    t=[0],                               // initialize an array of triangle numbers
    t.f=t.forEach,                       // copy forEach method into t.f,
                                         // saves a net of 4 bytes
    i=j=k=0;
    for(;j<x;t[i]=j+=i++);               // populate t with all triangle numbers that
                                         // we could possibly need
    t.f(                                 // loop over all t
        a=>t.f(                          // loop over all t
            b=>t.f(                      // loop over all t
                c=>a+b+c==x?k=[a,b,c]:0  // if a+b+c = x, set k = [a,b,c], else noop
                                         // using a ternary here saves 1 byte vs
                                         // if statement
                                         // iterating over t like this will find all
                                         // permutations of [a,b,c] that match, but
                                         // we will only return the last one found,
                                         // which happens to be sorted in descending order
            )
        )
    );
    return k
}

asgallant
fuente
No está explicando la parte más interesante: ¿por qué es x-m-nun número triangular, es decir, por qué funciona esto?
Christian Sievers
Bueno dangit, resulta que no está garantizado. Todos los casos de prueba que utilicé produjeron un triplete válido de números triangulares. De vuelta al tablero de dibujo.
asgallant
Corregido ahora, menos contento con esta solución <; o (pero al menos funciona.
asgallant