Controlla se un numero è un prodotto di numeri interi consecutivi


18

Alcuni numeri come: 6, 12, 20, 30, 42, 56, 60, 90, 120 e così via come possono essere espressi come un prodotto di numeri interi consecutivi come mostrato di seguito.

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

Scrivi un programma o una funzione che emetta un elenco di numeri interi consecutivi il cui prodotto è uguale al numero specificato.

Esempi di numeri non adatti a questa logica sono:

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)

Si prega di notare che per il caso di 2 = 2 * 1 , non lo consideriamo come un risultato valido, poiché un numero intero moltiplicato per 1 fornisce lo stesso risultato. Per questa domanda, considereremmo solo numeri interi> = 2 nel prodotto.

Ingresso

Un numero intero positivo a 32 bit valido. Può provenire dall'input standard, da un argomento di funzione, ecc.

Produzione

Un elenco di numeri interi consecutivi> = 2 (in ordine crescente o decrescente). Se ci sono diverse combinazioni di numeri interi consecutivi, basta fornirne uno esempio farà. Se offri di più, va bene.

restrizioni

Il funzionamento del codice dovrebbe richiedere un tempo ragionevole (<5 minuti) su un computer standard per tutti gli input validi (numeri interi positivi a 32 bit). Se esiste un prodotto intero consecutivo, il codice dovrebbe generare uno o più entro il limite di tempo. Altrimenti, il codice dovrebbe terminare senza output entro il limite di tempo.

Questo è il codice golf, quindi vince il codice più breve in byte.


1
Questo puzzle, come detto, non è adatto al formato di questo sito. Questo sito è per concorsi in cui esiste un buon modo per decidere un vincitore (ad es. Codice più breve, codice più veloce, maggior numero di voti, ecc.). Non hai fornito in alcun modo.
Chris Jester-Young,

2
Ti consiglio di renderlo un code-golf (il codice più breve). Tuttavia, devi porre dei limiti. Ad esempio numeri da 0 a 1000000, tempo massimo di esecuzione 10 sec, ecc.
Level River St

Ho provato a modificarlo per salvare questa domanda. Ma non ho fatto domande prima, quindi se vedi qualcosa, per favore modifica.
Vectorized

@bitpwner A parte alcuni errori di battitura, mi sembra perfetto. Votato per riaprire.
Seequ

5
Penso che tu intenda 30=5*6.
Kyle Kanos,

Risposte:


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

A partire da 2, questo scorre fino a quando il numero iniziale è> la radice quadrata del bersaglio (o il bersaglio viene raggiunto esattamente). Se il prodotto è basso, si moltiplica per il numero alto e lo incrementa. Se alto, si divide per il numero iniziale e lo incrementa.

Ad esempio, per 30, verificherebbe:

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

Emette una serie di fattori separati da spazio in ordine crescente.

Con interruzioni di riga:

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

7

Python - 104 97 95 92 provalo

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

Se n, ad esempio, è impostato su 120 in anticipo, il programma genera le due soluzioni:

[2, 3, 4, 5]
[4, 5, 6]

Scusa, ho dimenticato di definire alcuni input.
Falko,

1
sostituisci c = c + 1, i = i + 1 con c + = 1, i + = 1
Gerrat

1
Oh sì, non ci ho pensato +=. Ma mi manca ++in Python ...
Falko,

1
if s>=ne if s/nsono equivalenti, quindi puoi fornire tutte le soluzioni con lo stesso numero di caratteri.
isaacg,

1
Puoi salvare tre personaggi cambiando s=s*(i+c)in s*=i+c.
El'endia Starman,

4

Clojure - 127 109 byte

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

Esempio:

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

Spiegazione:

Questo è un approccio funzionale di base, non ottimizzato. Creo un elenco pigro di tutte le possibilità usando un semplice ciclo su di esse (salta tutte le combinazioni che darebbero numeri troppo grandi, impedendo l'overflow) e ne prendo la prima. Se non esiste alcuna possibilità, restituisce zero.

Più facile da testare su http://tryclj.com/ .


Ora ho anche notato che posso restituire tutte le possibilità: 120 byte 102 byte , ma dà risultati in un elenco nidificato.

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

Esempio:

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

3

CJam, 31 byte

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

È un approccio a forza bruta, ma il tempo di esecuzione è solo un paio di secondi usando l' interprete Java ufficiale .

Se si desidera testare il codice utilizzando l' interprete online , è necessario mantenere l'input ragionevolmente basso. Qualcosa di meno di 2 26 funziona ancora sulla mia macchina.

Esempi

$ 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

Come funziona

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.                                             ";

2

Java, 162

restituisce una matrice di numeri interi o nullse non esistono numeri consecutivi.

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

ungolfed:

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

2

C 105 110 provalo

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 bonus: questo scorre ogni numero e trova prodotti corrispondenti

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

Bello, molto semplice ed elegante! Sicuramente ha funzionato per alcuni dei numeri più piccoli che ho lanciato. Poi gli ho dato 50815512 (7128 x 7129) ed è andato in un ciclo infinito. Trabocca quando tenta di calcolare 7128 x 7129 x 7130 = 362314600560?
Todd Lehman,

Grazie! apparentemente la condizione k < ndiventa troppo alta a causa di k *= l++. potrei aggiungere senza firma a lungo all'inizio ma ... ciò rovinerebbe la vita
bebe

2

PHP 258 caratteri, 201 senza contare la funzione fattoriale.

Il modo più semplice per esprimere matematicamente "fattori consecutivi che equivalgono a un numero" è X!/Y!Where Xè il numero più alto eY è il più basso meno uno. Sfortunatamente ho smesso di fare calcoli prima di aver imparato a risolvereZ = X!/Y! , quindi ho dovuto potenziarlo un po '.

Disordinata, versione non golfata:

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

Esempio di output:

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

golfed:

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

Produzione:

[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

Non mi aspettavo che il tempo di esecuzione fosse così veloce!


anche questa idea mi è venuta in mente e sembra molto efficace ma dubito che possa essere abbreviata abbastanza da "essere qualificata".
Bebe,

1
@bebe sono 258 caratteri, non male per PHP. Se non fossi così pigro e ostinato, lo farei in una lingua vera . : P
Sammitch,

X! / Y! è il prodotto di numeri interi N tale che Y <N <= X. Questo aiuta a tutti?
trichoplax,

2

Pyth , 35

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

Nota: il mio codice in realtà trova la rappresentazione più breve dell'input come rappresentazione di numeri interi consecutivi> = 2, quindi su input non validi stamperà un elenco di 1 elemento, possibilmente dopo un tempo molto lungo. Poiché la dichiarazione del problema dice che l'input sarà valido, suppongo che sia OK.

Breve spiegazione:

In sostanza, il programma memorizza i limiti superiore e inferiore di un intervallo, calcola il prodotto dei numeri nell'intervallo utilizzando una riduzione, regola gli endpoint secondo necessità e si ripete fino a quando il prodotto è uguale all'input.

Spiegazione lunga:

Per ogni frammento di codice, fornirò un pitone equivalente, oltre a una spiegazione e un ragionamento più dettagliati.

Jvw => J=eval(input())

Modo standard per ricevere input in Pyth.

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

Ecco la prima parte strana: invece di archiviare gli endpoint come variabili separate, li sto archiviando come elementi di un elenco. Il motivo sarà presto chiaro. Inoltre, invece di fare un semplice compito, che in Pyth sarebbe K[2 3), sto usando un intervallo per salvare un personaggio.

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

A questo punto, potresti chiedere: "Cos'è Z? Non l'hai definito." In Pyth, tutte le variabili sono predefinite. Z sembra iniziare come 0. Tuttavia, Z verrà impostato sul valore del prodotto in un secondo momento, quindi questo controllo servirà a terminare il ciclo while una volta che l'elenco si trova sul valore corretto.

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

Ecco perché sto memorizzando i valori in un elenco, non in variabili separate: voglio incrementare uno dei due endpoint, a seconda che il prodotto sia attualmente troppo alto o troppo basso. Sarebbe una condizione piuttosto lunga se gli endpoint fossero variabili separate, ma con la magia dell'indicizzazione delle liste, diventa breve. Inoltre, il fatto che questo controllo preceda il prodotto e il fatto che Z sia inizializzato su 0, garantisce che K sarà [2,4]prima del primo utilizzo del prodotto, che sono gli endpoint corretti.

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

Ora, ho bisogno dell'elenco effettivo in cui il prodotto verrà acquisito e che verrà stampato se avremo successo. Chiaramente, useremo una funzione range. La difficoltà sta nell'ottenere gli input per la funzione range. Il modo più ovvio per farlo, indicizzando l'elenco, sarebbe =Yr'K@K1. Tuttavia, utilizzando una funzione di riduzione in questo elenco di due elementi, possiamo accorciarla di un carattere.

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

E ora, per l'intero punto di questa vicenda, ridurre l'operazione per trovare il prodotto della lista.

) => Fine while

Y => print(Y)

In caso di successo, stampare l'elenco.

Esempio di esecuzione:

$ 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]

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

Leggermente meno golfato:

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

Eh, hai creato una funzione e stampa il valore restituito. Non l'ho mai visto prima fatto qui.
Seequ,

Non riesco a farlo stampare nulla ... Ma se mi dà un po 'di output, puoi giocare System.out.printlna golf System.out.printe il punto e virgola alla fine for(int k=1,x=j;(x*=j+k)<i;k++)non è solo non necessario ma causa anche errori.
Qwix,

Questo non funziona per me. x, j, kSono fuori portata negli ultimi if/forblocchi a causa di una ;. Se rimuovo il ;, non stampa nulla.
Geobits

1
@Qwix Modifica in print significherebbe che ha bisogno di aggiungere un carattere spazio bianco per evitare che i numeri corrano insieme.
Geobits

1
@Geobits Un buon punto! Probabilmente l'avrei visto se mi avesse dato un risultato.
Qwix,

1

Matlab (88)

Il codice prevede che il numero venga archiviato xe inviato in uscita 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

Poiché 13! > 2^32questo codice cerca solo prodotti di lunghezza compresa tra 2 e 12. Questo codice ha un tempo di esecuzione costante di circa 0,001 secondi.


1

Scala - 86

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

Questo codice è molto inefficiente ma l'ottimizzazione aggiungerebbe solo pochi caratteri in più. Utilizza un approccio funzionale per verificare i prodotti di tutte le possibili sequenze consecutive. (una sequenza consecutiva di numeri interi è rappresentata come un oggetto Range in Scala)

ungolfed:

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
}

1

CJam attualmente non funziona per grandi numeri a causa del lungo tempo di calcolo

Questo è il mio codice CJam più breve. Test su http://cjam.aditsu.net/ . Funziona: definendo input come A; creando una matrice di tutti i numeri da 0 a A-1; Calci 0; calciare i numeri più piccoli fino a quando moltiplicare tutti i numeri dell'array non è maggiore di A; controllando se è maggiore di A; in caso contrario, creando un array da 0 a A-2; e ripetendo fino a quando non viene trovata la risposta. Se non viene trovato nessuno, viene generata un'eccezione. Non ho considerato che fossero necessari spazi tra i numeri, quindi sono inclusi nel secondo codice che è lungo 32 caratteri.

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

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

Penso che la tua risposta sia troppo lenta per essere valida. Ricorda che deve essere completato in non più di 5 minuti su qualsiasi numero intero a 32 bit valido. Quanto tempo impiega 3600060000 == 60000 * 60001?
isaacg,

punto giusto, lo rielaborerò e
pubblicherò

Se hai intenzione di rielaborarlo, ti preghiamo di eliminare questa risposta fino ad allora, oppure indicare in qualche modo che non è attualmente valido.
isaacg,

1

Dardo - 102 caratteri

Questa è un'implementazione lenta. Può essere reso più veloce ma ciò richiede più caratteri (come fare il ciclo solo fino a quando 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]);
}

(I 102 caratteri sono senza interruzioni di riga e spazi iniziali).

Per usarlo, fai qualcosa del tipo:

main() {
  print(f(123456789*123456790));
}

0

Javascript, 88

Codice golfizzato:

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

Codice più facile da leggere (ben distanziato):

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

Per ogni numero compreso tra 2 e il numero di input, trova il prodotto di numeri interi consecutivi dal numero corrente indietro a 2. Se questo prodotto è uguale al numero di input, viene emessa la serie di numeri consecutivi, insieme al numero di input originale .

Emette il numero di input seguito dagli interi consecutivi il cui prodotto è il numero di input.

Ad esempio f (120) produce un avviso con il testo "120,5,4,3,2" e quindi un secondo avviso con il testo "120,6,5,4".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.