Compruebe si un número es producto de números enteros consecutivos

18

Algunos números como: 6, 12, 20, 30, 42, 56, 60, 90, 120, etc., se pueden expresar como un producto de números enteros consecutivos como se muestra a continuación.

6   = 2 * 3  
12  = 3 * 4  
30  = 5 * 6
60  = 3 * 4 * 5  
90  = 9 * 10  
120 = 4 * 5 * 6  

Escriba un programa o función que genere una lista de enteros consecutivos cuyo producto sea igual al número especificado.

Ejemplos de números que no son adecuados para esta lógica son:

99  = 9 * 11  (Product of non-consecutive numbers)
121 = 11 * 11 (Same numbers)
2   = 1 * 2   (Product of itself and 1)
13  = 13      (Product of only one number)

Tenga en cuenta que para el caso de 2 = 2 * 1, no lo consideramos como un resultado válido, ya que un número entero multiplicado por 1 da el mismo resultado. Para esta pregunta, consideraríamos solo enteros> = 2 en el producto.

Entrada

Un entero positivo válido de 32 bits. Puede ser de entrada estándar, un argumento de función, etc.

Salida

Una lista de números enteros consecutivos> = 2 (en orden ascendente o descendente). Si hay varias combinaciones de enteros consecutivos, solo proporcione una instancia. Si proporciona más, está bien.

Restricciones

El código debe tomar un tiempo razonable (<5 minutos) para ejecutarse en una computadora estándar para todas las entradas válidas (enteros positivos de 32 bits). Si hay un producto entero consecutivo, el código debe generar uno o más dentro del límite de tiempo. De lo contrario, el código debe terminar sin salida dentro del límite de tiempo.

Este es el código de golf, por lo que gana el código más corto en bytes.

Suraz
fuente
1
Este rompecabezas, como se dijo, no es adecuado para el formato de este sitio. Este sitio es para concursos donde hay una buena manera de decidir un ganador (por ejemplo, el código más corto, el código más rápido, la mayoría de los votos, etc.). No has proporcionado tal manera.
Chris Jester-Young
2
Sin embargo, le recomiendo que convierta esto en un código de golf (el código más corto). Sin embargo, debe ponerle algunos límites. Por ejemplo, números del 0 al 1000000, tiempo de ejecución máximo de 10 segundos, etc.
Level River St
Intenté editarlo para salvar esta pregunta. Pero no he hecho ninguna pregunta antes, así que si ves algo, edítalo.
Vectorizado el
@bitpwner Aparte de algunos errores tipográficos, me parece bien. Votado para volver a abrir.
seequ
55
Creo que te refieres 30=5*6.
Kyle Kanos

Respuestas:

8

Java - 124

String f(int t){int s=2,h=3,p=s,i;String o="";for(;p!=t&&s*s<t;p=p<t?p*h++:p/s++);if(p==t)for(i=s;i<h;o+++=i+" ");return o;}

Comenzando en 2, esto se repite hasta que el número de inicio es> la raíz cuadrada del objetivo (o el objetivo se alcanza exactamente). Si el producto es bajo, se multiplica por el número alto y lo incrementa. Si es alto, se divide por el número inicial y lo incrementa.

Por ejemplo, para 30, comprobaría:

2*3     = 6 (too low, multiply)
2*3*4   = 24 (too low, multiply)
2*3*4*5 = 120 (too high, divide)
3*4*5   = 60 (too high, divide)
4*5     = 20 (too low, multiply)
4*5*6   = 120 (too high, divide)
5*6     = 30 (bingo!)

Emite una cadena de factores separados por espacios en orden ascendente.

Con saltos de línea:

String p(int t){
    int s=2,h=3,p=s,i;
    String o="";
    for(;p!=t&&s*s<t;p=p<t?p*h++:p/s++);
    if(p==t)
        for(i=s;i<h;o+=i+" ");
    return o;
}
Geobits
fuente
7

Python - 104 97 95 92 pruébalo

n=input()
s=i=2
c=1
while s<n:
 s*=i+c;c+=1
 if s==n:print range(i,i+c)
 if s/n:i+=1;s,c=i,1

Si n, por ejemplo, se establece en 120 de antemano, el programa genera las dos soluciones:

[2, 3, 4, 5]
[4, 5, 6]
Falko
fuente
Lo siento, olvidé definir alguna entrada.
Falko
1
reemplace c = c + 1, i = i + 1 con c + = 1, i + = 1
Gerrat
1
Oh sí, no pensé en eso +=. Pero extraño ++en Python ...
Falko
1
if s>=ny if s/nson equivalentes, por lo que puede proporcionar todas las soluciones en el mismo número de caracteres.
isaacg
1
Puede guardar tres caracteres cambiando s=s*(i+c)a s*=i+c.
El'endia Starman el
4

Clojure - 127 109 bytes

(defn f[x](first(for[r[range]y(r 2 x)v[(take-while #(<=(apply * %(r y %))x)(r y x))]:when(=(apply * v)x)]v)))

Ejemplo:

(map f [6 12 30 60 90 120 1404816 99 121 2 13])
=> ((2 3) (3 4) (5 6) (3 4 5) (9 10) (2 3 4 5) (111 112 113) nil nil nil nil)

Explicación:

Este es un enfoque funcional básico y poco optimizado. Creo una lista perezosa de todas las posibilidades usando un bucle simple sobre ellas (omite todas las combinaciones que darían números demasiado grandes, evitando el desbordamiento) y tomo la primera de ellas. Si no existen posibilidades, devuelve nulo.

Más fácil de probar en http://tryclj.com/ .


También noté que puedo devolver todas las posibilidades: 120 bytes 102 bytes , pero da resultados en una lista anidada.

(defn f[x](for[r[range]y(r 2 x)v[(take-while #(<=(apply * %(r y %))x)(r y x))]:when(=(apply * v)x)]v))

Ejemplo:

(map f [6 12 30 60 90 120 1404816 99 121 2 13])
=> (((2 3)) ((3 4)) ((5 6)) ((3 4 5)) ((9 10)) ((2 3 4 5) (4 5 6)) ((111 112 113)) () () () ())
seequ
fuente
3

CJam, 31 bytes

q~:Qmq,A,m*{2f+~,f+_:*Q={p}*}%;

Es un enfoque de fuerza bruta, pero el tiempo de ejecución es de solo un par de segundos usando el intérprete oficial de Java .

Si desea probar el código utilizando el intérprete en línea , debe mantener la entrada razonablemente baja. Cualquier cosa menos que 2 26 todavía funciona en mi máquina.

Ejemplos

$ TIME="%e s"
$ time cjam product.cjam <<< 2
0.12 s
$ time cjam product.cjam <<< 6
[2 3]
0.10 s
$ time cjam product.cjam <<< 120
[2 3 4 5]
[4 5 6]
0.12 s
$ time cjam product.cjam <<< 479001600
[2 3 4 5 6 7 8 9 10 11 12]
0.68 s
$ time cjam product.cjam <<< 4294901760
[65535 65536]
1.48 s
$ time cjam product.cjam <<< 4294967295
1.40 s

Cómo funciona

q~:Q      " Read from STDIN, interpret the input and save the result in variable “Q”.     ";
mq,       " Push the array [ 0 1 2 … (Q ** 0.5 - 1) ].                                    ";
A,m*      " Push the array [ 0 1 2 … 9 ] and take the Cartesian product.                  ";
{         " For each pair in the Cartesian product:                                       ";
  2f+     " Add 2 to each component.                                                      ";
  ~       " Dump the array's elements on the stack.                                       ";
  ,       " Push the array [ 0 1 2 … n ], where “n” is the topmost integer on the stack.  ";
  f+      " Add “m” to each element, where “m” is the integer below the array.            ";
  _:*     " Duplicate the resulting array and push the product of its elements.           ";
  Q={p}*  " If the product is equal to “Q”, print.                                        ";
}%        " Collect the remaining results into an array.                                  ";
;         " Discard the array from the stack.                                             ";
Dennis
fuente
2

Java, 162

devuelve una matriz de enteros, o nullsi no hay números consecutivos que existan.

int[] e(int n){for(int i=1;i<n;i++){int h=i+1,c=1,s=i;while(s<n){c++;s*=h++;}if(s==n){int[] o=new int[c];for(int j=0;j<c;j++){o[j]=h-j-1;}return o;}}return null;}

sin golf:

int[] execute(int input){
    for(int i=1; i<input; i++){
        int highest = i+1, count = 1, sum = i;
        while(sum < input){
            count++;
            sum *= highest++;
        }
        if(sum == input){
            int[] numbers = new int[count];
            for(int j=0; j<count; j++){
                numbers[j] = highest-j-1;
            }
            return numbers;
        }
    }
    return null;
}
Qwix
fuente
2

C 105 110 pruébalo

n,k,l;main(i){for(scanf("%d",&n);++i<n;)for(k=1,l=i;k<n;)if(k*=l++,k==n)for(l=n;l/=i;)printf("%d ",i++);}

144 con bonificación: este itera a través de cada número y encuentra productos coincidentes

main(i,j,k,l,m){for(scanf("%d",&m);++i<13;)for(j=0;++j<46341-i;){for(l=k=1;k<=i;)l*=j+k++;if(l==m)for(puts(""),k=0;k<i;)printf("%d ",j+k+++1);}}
bebe
fuente
Agradable, muy simple y elegante! Definitivamente funcionó para algunos de los números más pequeños que le arrojé. Luego le di 50815512 (7128 x 7129) y entró en un bucle infinito. ¿Se desborda cuando intenta calcular 7128 x 7129 x 7130 = 362314600560?
Todd Lehman
¡Gracias! aparentemente la condición k < nva demasiado alta debido a k *= l++. podría agregar sin firmar mucho tiempo al principio, pero ... eso arruinaría vidas
quizás el
2

PHP 258 caracteres, 201 sin contar la función factorial.

La forma más simple de expresar matemáticamente "factores consecutivos que equivalen a un número" es X!/Y!Where Xes el número más alto y Yes el menos menos uno. Desafortunadamente, dejé de tomar cálculos antes de aprender a resolver Z = X!/Y!, así que tuve que aplicar un poco de fuerza bruta.

Versión desordenada y sin golf:

<?php
// PHP does not define a factorial function, so I've kludged one in.
function fact($n) {
    $r = 1;
    for($i=$n; $i>1; $i--) {
        $r *= $i;
    }
    return $r;
}

$input = intval($argv[1]);

if( $input < 2 ) { die('invalid input'); }

printf("input: %s\n", $input);

$max=min(ceil(sqrt($input)),170); // integer breakdown for > 170!
$grid = array();
for( $x=1;$x<$max;$x++ ) {
    for( $y=$max;$y>=1;$y-- ) {
        if( $y >= $x ) { continue; } // Skip results that would be < 1
        $cur = fact($x)/fact($y);
        if( $cur > $input ) { // too large!
            echo "\n"; continue 2;
        }
        if( $cur == $input ) { //just right
            printf("%7d\n\nFound %s == %s\n", $cur, implode(' * ', range($y+1, $x)), $cur);
            break 2;
        }
        printf("%7d ", $cur);
    }
    echo "\n";
}
if($cur!=$input){printf("No consecutive factors produce %d\n", $input);}

Salida de ejemplo:

input: 518918400

  2
  3       6
  4      12      24
  5      20      60     120
  6      30     120     360     720
  7      42     210     840    2520    5040
  8      56     336    1680    6720   20160   40320
  9      72     504    3024   15120   60480  181440  362880
 10      90     720    5040   30240  151200  604800 1814400 3628800
 11     110     990    7920   55440  332640 1663200 6652800 19958400 39916800
 12     132    1320   11880   95040  665280 3991680 19958400 79833600 239500800 479001600
 13     156    1716   17160  154440 1235520 8648640 51891840 259459200
 14     182    2184   24024  240240 2162160 17297280 121080960
 15     210    2730   32760  360360 3603600 32432400 259459200
 16     240    3360   43680  524160 5765760 57657600 518918400

Found 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 == 518918400

Golfizado:

<? function f($n){$r=1;for($i=$n;$i>1;$i--)$r*=$i;return $r;}$i=$argv[1];$m=min(ceil(sqrt($i)),170);for($x=1;$x<$m;$x++){for($y=$m;$y>0;$y--){if($y>=$x)continue;$c=f($x)/f($y);if($c>$i)continue 2;if($c==$i){$y++;echo "$y $x";break 2;}}}if($c!=$i){echo 'No';}

Salida:

[sammitch@vm ~/golf] time php consecutive_golf.php 518918400
9 16
real 0m0.019s
user 0m0.011s
sys  0m0.009s
[sammitch@vm ~/golf] time php consecutive_golf.php 518918401
No
real 0m0.027s
user 0m0.017s
sys  0m0.011s

¡No esperaba que el tiempo de ejecución fuera tan rápido!

Sammitch
fuente
Esta idea también me vino a la mente y parece muy eficiente, pero dudo que se pueda acortar lo suficiente "para ser calificado".
bebe
1
@bebe son 258 caracteres, no está mal para PHP. Si no fuera tan vago y obstinado, lo haría en un idioma real . : P
Sammitch
X! / Y! es el producto de enteros N tal que Y <N <= X. ¿Eso ayuda en absoluto?
trichoplax
2

Pyth , 35

JvwKr2 4W-ZJ~@KgJZ1=YurGHK=Zu*NTY)Y

Nota: Mi código realmente encuentra la representación más corta de la entrada como una representación de enteros consecutivos> = 2, por lo que en una entrada no válida imprimirá una lista de 1 elemento, posiblemente después de mucho tiempo. Como la declaración del problema dice que la entrada será válida, supongo que esto está bien.

Breve explicación:

Esencialmente, el programa almacena los límites superior e inferior de un rango, calcula el producto de los números en el rango usando una reducción, ajusta los puntos finales según sea necesario y repite hasta que el producto iguale la entrada.

Larga explicación:

Para cada fragmento de código, daré python equivalente, así como una explicación y razonamiento más detallados.

Jvw => J=eval(input())

Manera estándar de tomar entrada en Pyth.

Kr2 4=> K=range(2,4)=>K=[2,3]

Aquí está la primera parte extraña: en lugar de almacenar los puntos finales como variables separadas, los estoy almacenando como elementos de una lista. La razón pronto estará clara. Además, en lugar de hacer una tarea simple, que en Pyth seríaK[2 3) , estoy usando un rango para guardar un personaje.

W-ZJ => while Z-J=>while Z!=J

En este punto, puede preguntar: "¿Qué es Z? No lo ha definido". En Pyth, todas las variables vienen predefinidas. Z comienza a iniciarse como 0. Sin embargo, Z se establecerá en el valor del producto más adelante, por lo que esta verificación servirá para finalizar el ciclo while una vez que la lista esté en el valor correcto.

~@K>JZ1 => K[J>Z] += 1

He aquí por qué estoy almacenando los valores en una lista, no en variables separadas: deseo incrementar uno de los dos puntos finales, dependiendo de si el producto es actualmente demasiado alto o demasiado bajo. Eso sería un condicional bastante largo si los puntos finales fueran variables separadas, pero con la magia de la indexación de listas, se vuelve corto. Además, el hecho de que esta verificación se realice antes del producto, y el hecho de que Z se inicialice a 0, aseguran que K estará [2,4]en el momento en que tomamos el producto, que son los puntos finales adecuados.

=YurGHK=> Y=reduce(lambda G,H: range(G,H),K)=>Y=range(K[0],K[1])

Ahora, necesito la lista real de que el producto se hará cargo, y que se imprimirá si tenemos éxito. Claramente, utilizaremos una función de rango. El truco radica en obtener las entradas para la función de rango. La forma obvia de hacer esto, indexando la lista, sería =Yr'K@K1. Sin embargo, al usar una función de reducción en esta lista de dos elementos, podemos acortar eso por un carácter.

=Zu*NTY => Z=reduce(lambda N,T: N*T,Y)

Y ahora, para todo el asunto de este asunto, la operación de reducción para encontrar el producto de la lista.

) => Finalizar mientras

Y => print(Y)

En caso de éxito, imprima la lista.

Ejemplo de ejecución:

$ cat seq_prod 
JvwKr2 4W-ZJ~@K>JZ1=YurGHK=Zu*NTY)Y

$ cat seq_prod | python3 pyth.py
<debug stuff>
==================================================
[9, 10, 11, 12, 13, 14, 15, 16]
isaacg
fuente
1

Java - 115

void f(int i){for(int j=2;j<i;j++)for(int k=1,x=j;(x*=j+k)<i;k++);if(x==i)for(i=j;i<j+k;i++)System.out.println(i);}

Ligeramente menos golfizado:

void f(int i) {
 for(int j=2; j<i; j++)
  for(int k=1, x=j; (x*=j+k) < i; k++);
   if(x == i)
    for(i=j; i<j+k; i++)
     System.out.println(i);
}
Ypnypn
fuente
Eh, creaste una función e imprimiste el valor de retorno. No he visto eso hecho aquí antes.
seequ
No puedo reciba para imprimir cualquier cosa ... Pero si me daría una cierta salida, se puede jugar golf System.out.printlnhasta System.out.printy el punto y coma al final de for(int k=1,x=j;(x*=j+k)<i;k++)no sólo es innecesario, sino que también provoca errores.
Qwix
Esto no funciona para mi. x, j, kEstán fuera del alcance de los últimos if/forbloques debido a una ;. Si elimino el ;, no imprime nada.
Geobits
1
@Qwix Cambiar a printsignificaría que necesita agregar un espacio en blanco para evitar que los números se ejecuten juntos.
Geobits
1
@Geobits Buen punto! Probablemente habría visto eso si me hubiera dado algo de salida.
Qwix
1

Matlab (88)

El código espera que el número se almacene xy se envíe l.

for n=2:12
r=ceil(x^(1/n))
for s=-3*n:n
l=r-s+(1:n)
if prod(l)==x
return 
end;end;l=x;end

Dado que 13! > 2^32este código busca solo productos de longitud 2 hasta 12. Este código tiene un tiempo de ejecución constante de alrededor de 0.001s.

falla
fuente
1

Scala - 86

def p(n:Int)=(2 to n).flatMap(i=>(i to n).map(i to _-1).find(_.product==n)).headOption

Este código es muy ineficiente, pero optimizarlo solo agregaría unos pocos caracteres más. Utiliza un enfoque funcional para verificar los productos de todas las secuencias consecutivas posibles. (una secuencia consecutiva de enteros se representa como un objeto Range en Scala)

sin golf:

def product(n: Int): Option[Range] = {
  def productStartingAt(start: Int): Option[Range] =
    (start to n-1).map(start to _).find(_.product == n)

  (2 to n).flatMap(i => productStartingAt(i)).headOption
}
Puerco araña
fuente
1

CJam no funciona actualmente para grandes cantidades debido al largo tiempo de cálculo

Este es mi código CJam más corto. Prueba en http://cjam.aditsu.net/ . Funciona: definiendo la entrada como A; creando una matriz de todos los números del 0 al A-1; Pateando 0; patear los números más pequeños hasta multiplicar todos los números en la matriz no es mayor que A; comprobar si es mayor que A; si no, creando una matriz de 0 a A-2; y repitiendo hasta que se encuentre la respuesta. Si no se encuentra ninguno, se lanza una excepción. No consideré que se necesitaran espacios entre los números, por lo que están incluidos en el segundo código, que tiene 32 caracteres de longitud.

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g" "*
kaine
fuente
Creo que tu respuesta es demasiado lenta para ser válida. Recuerde, debe completarse en no más de 5 minutos en cualquier entero válido de 32 bits. ¿Cuánto tiempo lleva 3600060000 == 60000 * 60001?
isaacg
punto justo, lo reelaboraré y publicaré si es corto
kaine
Si va a volver a trabajarlo, elimine esta respuesta hasta entonces o, de lo contrario, indique que no es válida actualmente.
isaacg
1

Dart - 102 caracteres

Esta es una implementación lenta. Se puede hacer más rápido, pero eso requiere más caracteres (como hacer el ciclo solo hastai*i<n )

f(n,[i=2]){
  t(j,p,a)=>p<n?t(++j,p*j,a..add(j)):p>n?f(n,i+1):a;
  for(;i<n;i++)if(n%i<1)return t(i,i,[i]);
}

(Los 102 caracteres no tienen saltos de línea ni espacios iniciales).

Para usarlo, haga algo como:

main() {
  print(f(123456789*123456790));
}
lrn
fuente
0

Javascript, 88

Código de golf:

function f(a){for(i=2;i<a;i++){b=[1];for(j=i;j>1;j--)if((b[0]*=b[i-j+1]=j)==a)alert(b)}}

Código más fácil de leer (muy bien espaciado):

function f(a){
    for(i=2;i<a;i++){
        b=[1];
        for(j=i;j>1;j--)
            if((b[0]*=b[i-j+1]=j)==a)
                alert(b);
    }
}

Para cada número del 2 al número de entrada, encuentra el producto de enteros consecutivos desde el número actual de nuevo a 2. Si este producto es igual al número de entrada, entonces se emite la serie de números consecutivos, junto con el número de entrada original. .

Produce el número de entrada seguido de los enteros consecutivos cuyo producto es el número de entrada.

Por ejemplo, f (120) produce una alerta con el texto "120,5,4,3,2" y luego una segunda alerta con el texto "120,6,5,4".

Natillas de ruibarbo
fuente