Verifique se um número é um produto de números inteiros consecutivos


18

Alguns números como: 6, 12, 20, 30, 42, 56, 60, 90, 120 e assim por diante, podem ser expressos como um produto de números inteiros consecutivos, como mostrado abaixo.

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

Escreva um programa ou função que produza uma lista de números inteiros consecutivos cujo produto seja igual ao número especificado.

Exemplos de números que não são adequados para essa lógica são:

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)

Observe que, para o caso de 2 = 2 * 1, não o consideramos um resultado válido, pois um número inteiro multiplicado por 1 fornece o mesmo resultado. Para esta pergunta, consideraríamos apenas números inteiros> = 2 no produto.

Entrada

Um número inteiro positivo válido de 32 bits. Pode ser de entrada padrão, argumento de função etc.

Resultado

Uma lista de números inteiros consecutivos> = 2 (em ordem crescente ou decrescente). Se houver várias combinações de números inteiros consecutivos, forneça apenas uma instância. Se você fornecer mais, tudo bem.

Restrições

O código deve levar um tempo razoável (<5 minutos) para ser executado em um computador padrão para todas as entradas válidas (números inteiros positivos de 32 bits). Se houver um produto inteiro consecutivo, o código deve gerar um ou mais dentro do prazo. Senão, o código deve terminar sem saída dentro do prazo.

Este é o código golf, portanto o código mais curto em bytes vence.


1
Esse quebra-cabeça, como afirmado, não é adequado para o formato deste site. Este site é para concursos em que há uma boa maneira de decidir um vencedor (por exemplo, código mais curto, código mais rápido, mais votos, etc.). Você não forneceu essa maneira.
Chris Jester-Young

2
Eu recomendo que você faça deste um código-golfe (código mais curto.), Você precisa colocar alguns limites nele. Por exemplo, números 0 a 1000000, tempo máximo de execução 10 s, etc.
Level River St

Tentei editá-lo para salvar esta pergunta. Mas eu não fiz perguntas antes, então se você vir alguma coisa, edite.
Vetorizado

@bitpwner Além de alguns erros de digitação, parece bom para mim. Votou para reabrir.
seequ

5
Eu acho que você quer dizer 30=5*6.
Kyle Kanos

Respostas:


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

Começando em 2, isso faz um loop até que o número inicial seja> a raiz quadrada do alvo (ou o alvo seja atingido exatamente). Se o produto estiver baixo, ele multiplica pelo número alto e o incrementa. Se alto, ele divide pelo número inicial e o incrementa.

Por exemplo, para 30, ele verificaria:

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

Gera uma sequência de fatores separados por espaço em ordem crescente.

Com quebras de linha:

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 experimentá-lo

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 nfor, por exemplo, definido como 120 anteriormente, o programa gera as duas soluções:

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

Desculpe, esqueci de definir alguma entrada.
Falko

1
substitua c = c + 1, i = i + 1 por c + = 1, i + = 1
Gerrat

1
Ah, sim, não pensei nisso +=. Mas eu sinto falta ++em Python ...
Falko

1
if s>=ne if s/nsão equivalentes, para que você possa fornecer todas as soluções no mesmo número de caracteres.
Isaacg

1
Você pode salvar três caracteres mudando s=s*(i+c)para s*=i+c.
El'endia Starman 9/08/14

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

Exemplo:

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

Explicação:

Essa é uma abordagem funcional básica e não otimizada. Eu crio uma lista lenta de todas as possibilidades usando um loop simples sobre elas (pula todas as combinações que dariam números muito grandes, impedindo o estouro) e pego a primeira delas. Se não houver possibilidades, ele retornará nulo.

Mais fácil de testar em http://tryclj.com/ .


Também notei agora que posso retornar todas as possibilidades: 120 bytes 102 bytes , mas fornece resultados em uma lista aninhada.

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

Exemplo:

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

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

É uma abordagem de força bruta, mas o tempo de execução é de apenas alguns segundos usando o intérprete oficial do Java .

Se você quiser testar o código usando o intérprete on - line , mantenha a entrada razoavelmente baixa. Qualquer coisa abaixo de 2 26 ainda funciona na minha máquina.

Exemplos

$ 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

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

2

Java, 162

retorna uma matriz de números inteiros ou nullse não houver números consecutivos.

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 experimente

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 com bônus: este percorre todos os números e encontra produtos correspondentes

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

Bom, muito simples e elegante! Definitivamente funcionou para alguns dos números menores que joguei nele. Então eu dei 50815512 (7128 x 7129) e ele entrou em um loop infinito. Está transbordando quando tenta calcular 7128 x 7129 x 7130 = 362314600560?
Todd Lehman

obrigado! aparentemente a condição k < nvai muito alta por causa de k *= l++. i poderia poderia adicionar unsigned long long ao início mas ... isso iria arruinar vidas
bebe

2

PHP 258 caracteres, 201 sem contar a função fatorial.

A maneira mais simples de expressar matematicamente "fatores consecutivos iguais a um número" é X!/Y!Onde Xé o número mais alto e Yo menor menos um. Infelizmente, parei de fazer o cálculo antes de aprender a resolvê- Z = X!/Y!lo, então tive que forçá-lo um pouco.

Versão desarrumada e não destruída:

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

Exemplo de saída:

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

Golfe:

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

Resultado:

[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

Eu não esperava que o tempo de execução fosse tão rápido!


essa idéia também veio à minha mente e parece muito eficaz, mas duvido que possa ser encurtada o suficiente "para ser qualificada".
bebe

1
@ebe é 258 caracteres, não é tão ruim para o PHP. Se eu não fosse tão preguiçoso e obstinado, faria isso em um idioma real . : P
Sammitch

X! / Y! é o produto de números inteiros N tal que Y <N <= X. Isso ajuda em tudo?
Trichoplax

2

Pyth , 35

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

Nota: Meu código, na verdade, encontra a representação mais curta da entrada como uma representação de números inteiros consecutivos> = 2, portanto, na entrada inválida, ele imprimirá uma lista de 1 elemento, possivelmente após um longo período de tempo. Como a declaração do problema diz que a entrada será válida, presumo que isso esteja correto.

Breve explicação:

Essencialmente, o programa armazena os limites superior e inferior de um intervalo, calcula o produto dos números no intervalo usando uma redução, ajusta os pontos de extremidade conforme necessário e se repete até que o produto seja igual à entrada.

Explicação longa:

Para cada trecho de código, darei python equivalente, bem como uma explicação e raciocínio mais detalhados.

Jvw => J=eval(input())

Maneira padrão de obter informações em Pyth.

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

Aqui está a primeira parte estranha: em vez de armazenar os pontos de extremidade como variáveis ​​separadas, estou armazenando-os como elementos de uma lista. O motivo será em breve claro. Além disso, em vez de fazer uma tarefa simples, como seria em Pyth K[2 3), estou usando um intervalo para salvar um personagem.

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

Nesse ponto, você pode perguntar: "O que é Z? Você não o definiu". No Pyth, todas as variáveis ​​são predefinidas. Z começa como 0. No entanto, Z será definido como o valor do produto posteriormente, portanto, essa verificação servirá para encerrar o loop while quando a lista estiver no valor correto.

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

Eis por que estou armazenando os valores em uma lista, e não em variáveis ​​separadas: desejo incrementar um dos dois pontos de extremidade, dependendo se o produto está alto ou baixo demais no momento. Essa seria uma condicional bastante longa se os pontos de extremidade fossem variáveis ​​separadas, mas com a mágica da indexação de lista, ele se tornará curto. Além disso, o fato de essa verificação ocorrer antes do produto e o fato de Z ser inicializado como 0 garantem que K será [2,4]quando chegarmos o produto pela primeira vez, que são os pontos de extremidade adequados.

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

Agora, preciso da lista real de que o produto será adquirido e que será impresso se tivermos sucesso. Claramente, usaremos uma função range. A dificuldade está em obter as entradas para a função de faixa. A maneira óbvia de fazer isso, indexando a lista, seria =Yr'K@K1. No entanto, usando uma função de redução nessa lista de dois elementos, podemos reduzi-la com um caractere.

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

E agora, em todo o caso, a operação de redução para encontrar o produto da lista.

) => Terminar enquanto

Y => print(Y)

Com sucesso, imprima a lista.

Exemplo de execução:

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

Um pouco menos golfe:

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, você criou uma função e imprime o valor de retorno. Não vi isso feito aqui antes.
seequ

Eu não posso obtê-lo para imprimir qualquer coisa ... Mas se ele iria me dar alguma saída, você pode golf System.out.printlnaté System.out.printeo ponto e vírgula no final for(int k=1,x=j;(x*=j+k)<i;k++)não é apenas desnecessário, mas também faz com que os erros.
Qwix

Isso não funciona para mim. x, j, kEstão fora do escopo nos últimos if/forblocos por causa de uma ;. Se eu remover o ;, ele não imprime nada.
Geobits 08/08/19

1
@Qwix Alterar para printsignifica que ele precisa adicionar um caractere de espaço em branco para evitar que os números sejam executados juntos.
Geobits 8/08/14

1
@Geobits Good point! Eu provavelmente teria visto isso se tivesse me dado alguma saída.
Qwix

1

Matlab (88)

O código espera que o número seja armazenado xe produzido 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

Como 13! > 2^32esse código pesquisa apenas produtos de tamanho 2 a 12. Esse código tem um tempo de execução constante de cerca de 0,001s.


1

Scala - 86

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

Esse código é muito ineficiente, mas a otimização adicionaria apenas mais alguns caracteres. Ele usa uma abordagem funcional para verificar os produtos de todas as sequências consecutivas possíveis. (uma sequência consecutiva de números inteiros é representada como um objeto Range no 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 atualmente não funciona para grandes números devido ao longo tempo de computação

Este é o meu código CJam mais curto. Teste em http://cjam.aditsu.net/ . Ele funciona: definindo entrada como A; criando uma matriz de todos os números de 0 a A-1; Chutando 0; chutar os números menores até multiplicar todos os números na matriz não é maior que A; verificando se é maior que A; caso contrário, crie uma matriz de 0 a A-2; e repetindo até que a resposta seja encontrada. Se nenhum for encontrado, uma exceção será lançada. Não considerei que eram necessários espaços entre os números, para que sejam incluídos no segundo código, com 32 caracteres.

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

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

Eu acho que sua resposta é muito lenta para ser válida. Lembre-se, ele deve ser concluído em não mais de 5 minutos em qualquer número inteiro válido de 32 bits. Quanto tempo leva em 3600060000 == 60000 * 60001?
Isaacg

ponto justo, eu vou refazê-la e pós se for curta
kaine

Se você deseja refazê-la, exclua esta resposta até então ou, de alguma forma, indique que não é válida no momento.
Isaacg

1

Dardo - 102 caracteres

Esta é uma implementação lenta. Pode ser feito mais rápido, mas isso requer mais caracteres (como fazer o loop apenas até 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]);
}

(Os 102 caracteres estão sem quebras de linha e espaços à esquerda).

Para usá-lo, faça algo como:

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

0

Javascript, 88

Código de golfe:

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 mais fácil de ler (espaçado):

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 de 2 ao número de entrada, ele encontra o produto de números inteiros consecutivos do número atual de volta para 2. Se este produto for igual ao número de entrada, será emitida a série de números consecutivos, juntamente com o número de entrada original. .

Ele gera o número de entrada seguido pelos números inteiros consecutivos cujo produto é o número de entrada.

Por exemplo, f (120) produz um alerta com o texto "120,5,4,3,2" e, em seguida, um segundo alerta com o texto "120,6,5,4".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.