Vérifier si un nombre est un produit de nombres entiers consécutifs

18

Certains nombres tels que: 6, 12, 20, 30, 42, 56, 60, 90, 120 et ainsi de suite peuvent être exprimés comme un produit de nombres entiers consécutifs comme indiqué ci-dessous.

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

Écrivez un programme ou une fonction qui génère une liste d'entiers consécutifs dont le produit est égal au nombre spécifié.

Voici des exemples de nombres qui ne conviennent pas à cette logique:

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)

Veuillez noter que dans le cas de 2 = 2 * 1 , nous ne le considérons pas comme un résultat valide, car un entier multiplié par 1 donne le même résultat. Pour cette question, nous considérons uniquement les entiers> = 2 dans le produit.

Contribution

Un entier positif 32 bits valide. Peut provenir d'une entrée standard, d'un argument de fonction, etc.

Production

Une liste de nombres entiers consécutifs> = 2 (dans l'ordre croissant ou décroissant). S'il y a plusieurs combinaisons d'entiers consécutifs, il suffit d'en fournir un instance. Si vous fournissez plus, c'est bien.

Restrictions

Le code doit prendre un temps raisonnable (<5 minutes) pour s'exécuter sur un ordinateur standard pour toutes les entrées valides (entiers 32 bits positifs). S'il existe un produit entier consécutif, le code doit en afficher un ou plusieurs dans le délai imparti. Sinon, le code doit se terminer sans sortie dans le délai imparti.

Il s'agit du code golf, donc le code le plus court en octets l'emporte.

Suraz
la source
1
Ce puzzle, comme indiqué, ne convient pas au format de ce site. Ce site est destiné aux concours où il existe un bon moyen de choisir un gagnant (par exemple, le code le plus court, le code le plus rapide, la plupart des votes positifs, etc.). Vous n'avez pas fourni de telle manière.
Chris Jester-Young
2
Je vous recommande d'en faire un code-golf (code le plus court.) Vous devez cependant y mettre des limites. Par exemple, les numéros 0 à 1000000, le temps d'exécution maximal 10 secondes, etc.
Level River St
J'ai essayé de le modifier pour récupérer cette question. Mais je n'ai pas posé de questions auparavant, donc si vous voyez quelque chose, veuillez modifier.
vectorisé
@bitpwner Mis à part quelques fautes de frappe, me semble bien. A voté pour rouvrir.
seequ
5
Je pense que tu veux dire 30=5*6.
Kyle Kanos du

Réponses:

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

À partir de 2, cela boucle jusqu'à ce que le numéro de départ soit> la racine carrée de la cible (ou que la cible soit atteinte exactement). Si le produit est faible, il multiplie par le nombre élevé et l'incrémente. S'il est élevé, il divise par le nombre de départ et l'incrémente.

Par exemple, pour 30, il vérifierait:

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!)

Génère une chaîne de facteurs séparés par des espaces dans l'ordre croissant.

Avec des sauts de ligne:

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;
}
Géobits
la source
7

Python - 104 97 95 92 l' essayer

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

S'il nest, par exemple, réglé à 120 au préalable, le programme génère les deux solutions:

[2, 3, 4, 5]
[4, 5, 6]
Falko
la source
Désolé, j'ai oublié de définir une entrée.
Falko
1
remplacer c = c + 1, i = i + 1 par c + = 1, i + = 1
Gerrat
1
Oh ouais, je n'y ai pas pensé +=. Mais je manque ++en Python ...
Falko
1
if s>=net if s/nsont équivalents, vous pouvez donc fournir toutes les solutions dans le même nombre de caractères.
isaacg
1
Vous pouvez enregistrer trois caractères en changeant s=s*(i+c)pour s*=i+c.
El'endia Starman
4

Clojure - 127109 octets

(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)))

Exemple:

(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)

Explication:

Il s'agit d'une approche fonctionnelle de base, peu optimisée. Je crée une liste paresseuse de toutes les possibilités en utilisant une simple boucle sur elles (cela saute toutes les combinaisons qui donneraient des nombres trop grands, empêchant le débordement) et prends la première d'entre elles. Si aucune possibilité n'existe, elle renvoie zéro.

Le plus facile à tester sur http://tryclj.com/ .


J'ai également remarqué que je peux retourner toutes les possibilités: 120 octets 102 octets , mais donne des résultats dans une liste imbriquée.

(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))

Exemple:

(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
la source
3

CJam, 31 octets

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

C'est une approche par force brute, mais le temps d'exécution n'est que de quelques secondes en utilisant le interpréteur Java officiel .

Si vous souhaitez tester le code à l'aide de l' interpréteur en ligne , vous devez garder l'entrée assez faible. Tout ce qui est inférieur à 2 26 fonctionne toujours sur ma machine.

Exemples

$ 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

Comment ça fonctionne

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
la source
2

Java, 162

renvoie un tableau d'entiers, ou nulls'il n'existe aucun nombre consécutif.

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

non 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
la source
2

C 105 110 essayer

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 avec bonus: celui-ci parcourt chaque numéro et trouve les produits correspondants

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);}}
être
la source
Agréable, très simple et élégant! Certainement travaillé pour certains des plus petits nombres que je lui ai jetés. Ensuite, je lui ai donné 50815512 (7128 x 7129) et il est entré dans une boucle infinie. Déborde-t-il lorsqu'il essaie de calculer 7128 x 7129 x 7130 = 362314600560?
Todd Lehman
Merci! apparemment, la condition k < ndevient trop élevée à cause de k *= l++. je pourrais ajouter longtemps non signé au début mais ... cela ruinerait des vies
bebe
2

PHP 258 caractères, 201 sans compter la fonction factorielle.

La façon la plus simple d'exprimer mathématiquement "des facteurs consécutifs qui égalent un nombre" est X!/Y!Xest le nombre le plus élevé et Yle plus petit moins. Malheureusement, j'ai arrêté de prendre le calcul avant d'apprendre à résoudre Z = X!/Y!, j'ai donc dû le forcer un peu.

Version désordonnée et non golfée:

<?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);}

Exemple de sortie:

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

Golfé:

<? 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';}

Production:

[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

Je ne m'attendais pas à ce que le temps d'exécution soit aussi rapide!

Sammitch
la source
cette idée m'est venue aussi à l'esprit et elle a l'air très efficace mais je doute qu'elle puisse être assez raccourcie "pour être qualifiée".
bebe
1
@bebe c'est 258 caractères, pas trop mal pour PHP. Si je n'étais pas aussi paresseux et obstiné, je le ferais dans une vraie langue. : P
Sammitch
X! / Y! est le produit d'entiers N tels que Y <N <= X. Est-ce que cela vous aide?
trichoplax
2

Pyth , 35

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

Remarque: Mon code trouve en fait la représentation la plus courte de l'entrée en tant que représentation d'entiers consécutifs> = 2, donc sur une entrée non valide, il imprimera une liste de 1 élément, éventuellement après un très long temps. Étant donné que l'énoncé du problème indique que l'entrée sera valide, je suppose que cela est OK.

Brève explication:

Essentiellement, le programme stocke les limites supérieure et inférieure d'une plage, calcule le produit des nombres dans la plage à l'aide d'une réduction, ajuste les points de terminaison selon les besoins et répète jusqu'à ce que le produit soit égal à l'entrée.

Explication longue:

Pour chaque extrait de code, je donnerai un python équivalent, ainsi qu'une explication et un raisonnement plus détaillés.

Jvw => J=eval(input())

Manière standard de saisir des données en Pyth.

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

Voici la première partie bizarre: au lieu de stocker les points de terminaison en tant que variables distinctes, je les stocke en tant qu'éléments d'une liste. La raison sera bientôt claire. De plus, au lieu de faire une simple affectation, qui en Pyth seraitK[2 3) , j'utilise une plage pour enregistrer un caractère.

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

À ce stade, vous pourriez demander: "Qu'est-ce que Z? Vous ne l'avez pas défini." En Pyth, toutes les variables sont prédéfinies. Il se trouve que Z commence par 0. Cependant, Z sera défini sur la valeur du produit plus tard, donc cette vérification servira à mettre fin à la boucle while une fois que la liste est à la valeur correcte.

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

Voici pourquoi je stocke les valeurs dans une liste, pas dans des variables distinctes: je veux incrémenter l'un des deux points de terminaison, selon que le produit est actuellement trop élevé ou trop bas. Ce serait une condition assez longue si les points de terminaison étaient des variables distinctes, mais avec la magie de l'indexation de liste, cela devient court. De plus, le fait que cette vérification précède le produit et le fait que Z soit initialisé à 0 garantissent que K le sera [2,4]au moment où nous prenons le produit pour la première fois, qui sont les points finaux appropriés.

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

Maintenant, j'ai besoin de la liste réelle que le produit sera repris, et qui sera imprimée si nous réussissons. De toute évidence, nous utiliserons une fonction de plage. L'astuce réside dans l'obtention des entrées de la fonction range. La façon évidente de le faire, en indexant la liste, serait =Yr'K@K1. Cependant, en utilisant une fonction de réduction sur cette liste de deux éléments, nous pouvons raccourcir celle-ci par un caractère.

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

Et maintenant, pour tout le point de cette affaire, l'opération de réduction pour trouver le produit de la liste.

) => Fin pendant

Y => print(Y)

En cas de succès, imprimez la liste.

Exemple d'exécution:

$ 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
la source
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);}

Un peu moins golfé:

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
la source
Eh, vous avez créé une fonction et imprimé la valeur de retour. Je n'ai jamais vu ça faire ici auparavant.
seequ
Je n'arrive pas à faire imprimer quoi que ce soit ... Mais si cela me donne une sortie, vous pouvez jouer System.out.printlnau golf System.out.printet le point-virgule à la fin for(int k=1,x=j;(x*=j+k)<i;k++)n'est pas seulement inutile, mais provoque également des erreurs.
Qwix
Ça ne marche pas pour moi. x, j, kSont hors de portée dans les derniers if/forblocs en raison d'un ;. Si je supprime le ;, il n'imprime rien.
Geobits
1
@Qwix Changer pour printsignifierait qu'il doit ajouter un caractère blanc pour éviter que les nombres ne fonctionnent ensemble.
Geobits
1
@Geobits Bon point! J'aurais probablement vu cela si cela m'avait donné une sortie.
Qwix
1

Matlab (88)

Le code s'attend à ce que le nombre soit stocké xet sorti 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

Étant donné que 13! > 2^32ce code recherche uniquement les produits de longueur 2 jusqu'à 12. Ce code a un temps d'exécution constant d'environ 0,001 s.

flawr
la source
1

Scala - 86

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

Ce code est très inefficace mais l'optimiser ne ferait qu'ajouter quelques caractères supplémentaires. Il utilise une approche fonctionnelle pour vérifier les produits de toutes les séquences consécutives possibles. (une séquence consécutive d'entiers est représentée comme un objet Range dans Scala)

non 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
}
SpiderPig
la source
1

CJam ne fonctionne pas actuellement pour les grands nombres en raison du temps de calcul long

Ceci est mon code CJam le plus court. Testez à http://cjam.aditsu.net/ . Il fonctionne en: définissant l'entrée comme A; créer un tableau de tous les nombres de 0 à A-1; Coup de pied 0; botter les plus petits nombres jusqu'à ce que la multiplication de tous les nombres du tableau ne soit pas supérieur à A; vérifier s'il est supérieur à A; sinon, créer un tableau de 0 à A-2; et répéter jusqu'à ce que la réponse soit trouvée. Si aucun n'est trouvé, une exception est levée. Je ne considérais pas que des espaces entre les nombres étaient nécessaires, ils sont donc inclus dans le deuxième code de 32 caractères.

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

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g" "*
kaine
la source
Je pense que votre réponse est trop lente pour être valable. N'oubliez pas qu'il doit se terminer en moins de 5 minutes sur tout entier 32 bits valide. Combien de temps cela prend-il sur 3600060000 == 60000 * 60001?
isaacg
bon point, je vais le retravailler et poster s'il est court
kaine
Si vous prévoyez de la retravailler, veuillez supprimer cette réponse jusque-là, sinon, indiquez d'une manière ou d'une autre qu'elle n'est pas valide actuellement.
isaacg
1

Fléchette - 102 caractères

Il s'agit d'une implémentation lente. Cela peut être fait plus rapidement mais cela nécessite plus de caractères (comme faire la boucle seulement jusqu'à i*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]);
}

(Les 102 caractères sont sans les sauts de ligne et les espaces de début).

Pour l'utiliser, faites quelque chose comme:

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

Javascript, 88

Code 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)}}

Code plus facile à lire (bien espacé):

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);
    }
}

Pour chaque nombre de 2 au numéro d'entrée, il trouve le produit d'entiers consécutifs du nombre actuel jusqu'à 2. Si ce produit est égal au numéro d'entrée, la série de nombres consécutifs, ainsi que le numéro d'entrée d'origine, est sortie .

Il sort le numéro d'entrée suivi des entiers consécutifs dont le produit est le numéro d'entrée.

Par exemple, f (120) produit une alerte avec le texte "120,5,4,3,2" puis une deuxième alerte avec le texte "120,6,5,4".

Crème pâtissière à la rhubarbe
la source