Pseudofatorial


39

Há um número bastante curioso que aparece algumas vezes em problemas de matemática ou enigmas. O pseudo-fatorial (N) é o mínimo múltiplo comum (isto é, o mais baixo) comum dos números 1 a N; em outras palavras, é o número mais baixo que possui todos os números de 1 a N como fatores.

Por exemplo, pseudo-fatorial (7) = 3 * 4 * 5 * 7, que é o mesmo que 7! exceto que 2 e 6 foram removidos porque estão contidos em outros termos.

Escreva um programa para calcular o pseudo-fatorial (N) e, como sempre, o código mais curto vence.

Aqui está uma pequena lista para seu uso. Mais casos de teste podem ser encontrados no OEIS em A003418 .

Fatorial:

  1. 1
  2. 2
  3. 6
  4. 24
  5. 120
  6. 720
  7. 5040

Pseudo-fatorial:

  1. 1
  2. 2
  3. 6
  4. 12
  5. 60
  6. 60
  7. 420

6
Não sei ao certo por que 2e 6foram removidos da lista de múltiplos. Você pode esclarecer as regras?
Maltysen

2
@ Mattysen, psuedofactorial (N) é o menor número que possui os números de 1 a N como fatores (o múltiplo menos comum desses números). Essa é a definição técnica, mas a maneira como escrevi foi um pouco sugestiva de que é semelhante a um fatorial.
Tony Ruth


4
Bem-vindo à programação de quebra-cabeças e código de golfe! Este é um bom primeiro desafio!
Alex A.

1
Seu primeiro desafio chegou ao topo do HNQ. Agradável!
Daniel M.

Respostas:




8

C (com x86), 52 bytes

d(n,k,b,t){for(b=k=1;b;++k)for(t=n,b=0;t;b+=k%t--);}

Verifica números de 1 para cima. Para cada número, divide-o por todos os números de n para 1 e soma os restantes. Para quando a soma é 0.

Uso:

main()
{
    printf("%d\n", d(7)); // outputs 420
}

Não é óbvio como ele retorna um valor (não há returndeclaração).

A convenção de chamada para x86 diz que a função deve retornar seu valor no eaxregistro. Convenientemente, a instrução de divisão idivespera sua entrada eaxe gera o resultado em eax(quociente) e edx(restante). A última iteração divide kpor 1, entãoeax , conterá o valor correto quando a função sair.

Isso funciona apenas com otimizações ativadas (no modo de depuração, ele gera 421).


Como você se safa em não declarar o tipo de n, k, be t?
Tony Ruth

C possui a regra default-int - todos os tipos omitidos são intpor padrão (incluindo o valor de retorno). Ele funciona para argumentos de função se eles forem declarados usando a chamada sintaxe "estilo antigo". A declaração com tipos definidos explicitamente seriaint d(n,k,b,t) int n,k,b,t; {...}
anatolyg

Se você está aproveitando de uma convenção de chamada, então isso realmente deve ser marcado "C (cdecl)" em vez de apenas "C"
Steve Cox

@SteveCox Ambos cdecle stdcallusar o mesmo método para o retorno de valor, então eu acho que x86é o suficiente
anatolyg

7

Haskell, 20 bytes

f x=foldr1 lcm[1..x]

Exemplo de uso: map f [1..7]-> [1,2,6,12,60,60,420].

O lcmtruque em Haskell.


6

Python + SymPy, 45 bytes

import sympy
lambda n:sympy.lcm(range(1,n+1))

Bastante auto-explicativo.


Python 2, 57 54 bytes

i=r=input();exec't=r\nwhile r%i:r+=t\ni-=1;'*r;print r

Teste em Ideone .

Como funciona

A entrada é armazenada em variáveis i e r .

execexecuta o seguinte código r vezes.

t=r
while r%i:r+=t
i-=1

Enquanto i varia de r a 1 , adicionamos o valor inicial de r (armazenado em t ) quantas vezes for necessário para r para criar um múltiplo de i . O resultado é, obviamente, um múltiplo de t .

O valor final de r é, portanto, um múltiplo de todos os números inteiros no intervalo [1, ..., n] , em que n é a entrada.


1
Sem usar bibliotecas ou exectruques de terceiros, há uma solução de 78 bytes: from fractions import*;lambda n:reduce(lambda x,y:x*y/gcd(x,y),range(1,n+1),1) usa o fato disso lcm(x,y) = x*y/gcd(x,y).
Bakuriu 10/06/16

6

Python, 46 bytes

g=lambda n,c=0:n<1or(c%n<1)*c or g(n,c+g(n-1))

Procurando o múltiplo cde g(n-1)diretamente. Antes, eu pensava que esse método encontraria 0 erroneamente como um múltiplo de qualquer coisa, mas o orcurto-circuito ou (c%n<1)*ctambém pulará c==0porque 0 é Falsey.


50 bytes:

g=lambda n,i=1:n<1or(i*n%g(n-1)<1)*i*n or g(n,i+1)

Como a solução de Dennis , mas como uma função recursiva. Tendo calculado g(n-1), procura o menor múltiplo i*nde nque também é múltiplo de g(n-1). Muito devagar.

Graças a Dennis por 4 bytes, olhando para múltiplos em nvez de g(n-1).


5

J, 9 bytes

[:*./1+i.

Abordagem direta. Cria o intervalo de números [0, ..., n-1], adiciona um a cada um e reduz-o usando o LCM.

Uso

   f =: [:*./1+i.
   f 7
420


4

Mathematica, 13 bytes

LCM@@Range@#&

isso não é equivalente a apenas compor LCMe Rangecom @*?
Maltysen

1
LCMopera elemento a elemento em uma lista, que seria passada por Range, o que significa que apenas retornaria o lcm ( x ) para x de 1 a n . Além disso, há uma falta &que fecharia a função anônima. Algo como LCM@@Range@#&13 bytes funcionaria.
milhas



3

Oitava, 27 bytes

@(x)lcm(1,num2cell(1:x){:})

Cria uma função anônima que pode ser chamada como ans(N).

Demo Online

Explicação

Esta solução cria uma lista de todos os números entre 1e x( 1:x), converte-os em uma matriz de células com num2cell. Em seguida, a {:}indexação cria uma lista separada por vírgula que é passada para lcmvários argumentos de entrada para calcular o múltiplo menos comum. Um 1 é sempre passado como o primeiro argumento para, lcmporque lcmsempre precisa de pelo menos dois argumentos de entrada.


1
Assim, lcmno Octave aceita mais de 2 entradas! Interessante
Luis Mendo

@LuisMendo Yup 2+
Suever

3

MATLAB, 49 bytes

@(x)find(~any(bsxfun(@rem,1:prod(1:x),(1:x)')),1)

+1 parabsxfun
flawr

3

Perl 6 , 13 bytes

{[lcm] 1..$_}

Bloco de código anônimo que cria um intervalo de 1 até a entrada (inclusive) e reduz isso com &infix:<lcm>.

Exemplo:

#! /usr/bin/env perl6
use v6.c;

my &postfix:<p!> = {[lcm] 1..$_}

say 1p!; # 1
say 2p!; # 2
say 3p!; # 6
say 4p!; # 12
say 5p!; # 60
say 6p!; # 60
say 7p!; # 420

say 10000p!; # 5793339670287642968692270879...
# the result from this is 4349 digits long


2

JavaScript (ES6), 92 88 80 74 69 bytes:

Obrigado @ConorOBrien e @Neil

y=>(g=(a,b)=>b?g(b,a%b):a,[...Array(y)].map((_,i)=>y=y*++i/g(y,i)),y)

b?g(b,a%b):asalva um byte.
Neil

y*++i/g(y,i)economiza mais alguns bytes.
Neil

1

05AB1E, 20 bytes

Lpvyi¹LÒN>¢àN>*ˆ}}¯P

Explicação

Lpv                    # for each item in isprime(range(1,N)): N=7 -> [0,1,1,0,1,0,1]
   yi                  # if prime
     ¹LÒN>¢            # count occurrences of the prime 
                         in the prime-factorization of range(1,N):
                         p=2 -> [0,1,0,2,0,1,0]
           àN>*ˆ       # add max occurrence of that prime multiplied by the prime 
                         to global array: N=7 -> [4,3,5,7]
                }}     # end if/loop
                  ¯P   # get product of global array

Experimente online


1

Minkolang 0.15 , 12 bytes

Eu tenho duas soluções de 12 bytes e incluí as duas.

1n[i1+4$M]N.

Experimente aqui!

Explicação

1               Push 1
 n              Take number from input
  [             For loop that repeats n times
   i1+          Push loop counter + 1
      4$M       Pop b, a and push lcm(a,b)
         ]      Close for loop
          N.    Output as number and stop.

Tão simples quanto possível.


11nLd[4$M]N.

Experimente aqui!

Explicação

11              Push two 1s
  n             Take number from input
   L            Pop b, a and push range from a to b, inclusive
    d           Duplicate top of stack (n)
     [4$M]      Pop b, a and push lcm(a,b), n times
          N.    Output as number and stop.

Uma terceira solução pode ser derivada disso: remova a 1e adicione a dapós a corrente d. Nos dois casos, o número extra é necessário porque o loop for é executado muitas vezes, e fazê-lo menos uma vez leva dois bytes (um 1-pouco antes do [).


1

Ruby, 25 bytes

g=->n{(1..n).reduce :lcm}

Ruby, 25 bytes

g=->n{n<1?1:a[n-1].lcm n}

1
Olá, e bem-vindo ao PPCG! Ótimo primeiro post! Você não precisa nomear sua função para poder removê-lo g=.
NoOneIsHere

Funções anônimas são permitidas.
Erik the Outgolfer

1

Idioma do GameMaker, 60 bytes

for(b=k=1;b;++k){b=0for(t=argument0;t;b+=k mod t--)}return k

Baseado na lógica da resposta de anatolyg.


1

PHP, 61 52 48 bytes

economizou 9 bytes graças a @ user59178, 4 bytes mesclando os loops.

A recursão no PHP é volumosa devido à functionpalavra-chave; então eu uso a iteração.
E com alguns "truques" pequenos, agora até venci o JS de Arnauld .

while(++$k%++$i?$i>$argv[1]?0:$i=1:$k--);echo$k;

recebe entrada do argumento da linha de comando. Corra com -r.

demolir

while(++$k%++$i?    # loop $i up; if it does not divide $k
    $i>$argv[1]?0       # break if $i (smallest non-divisor of $k) is larger than input
    :$i=1               # while not, reset $i and continue loop with incremented $k
    :$k--);         # undo increment while $i divides $k
echo$k;         # print $k

destroçado

Na verdade, são dois loops em um:

while($i<=$argv[1]) # loop while $i (smallest non-divisor of $k) is not larger than input
    for($k++,       # loop $k up from 1
        $i=0;$k%++$i<1;);   # loop $i up from 1 while it divides $k
echo$k;             # print $k

Nota: copiado da minha resposta na duplicata




0

Hoon , 67 bytes

|*
*
(roll (gulf 1 +<) |=({a/@ b/_1} (div (mul a b) d:(egcd a b))))

Crie a lista [1..n], dobre a lista com lcm. Infelizmente, o Hoon stdlib não possui um pré-criado que eu possa usar: /



0

AWK, 42 bytes

{for(x=n=1;n<=$1;)if(x%n++){x++;n=1}$0=x}1

Uso da linha de comando:

awk '{for(x=n=2;n<=$1;)if(x%n++){x++;n=2}$0=x}1' <<< NUM

Eu não vi uma AWKsolução e uma duplicata da pergunta acabou de ser postada ontem, então pensei em juntar isso. É uma solução bastante lenta para 19ou maior na minha caixa, mas funciona.


0

QBIC , 35 32 bytes

Isso me trouxe aqui.

:{p=0[a|~q%b|p=1]]~p=0|_Xq\q=q+1

Explicação:

:        Get cmd line param as number 'a'
{        Start an infinite DO loop
p=0      Sets a flag that shows if divisions failed
[a|      FOR (b=1; b<=a; b++)
~q%b     IF 'q' (which starts at 1 in QBIC) is not cleanly divisible by 'b'
|p=1     THEN Set the flag
]]   Close the FOR loop and the IF, leave the DO open
~p=0     IF 'q' didn't get flagged
|_Xq     THEN quit, printing 'q'
\q=q+1   ELSE raise 'q', redo
         [DO Loop implicitly closed by QBIC]

Aqui está uma versão que para de testar qquando bnão a divide de maneira limpa. Além disso, a fim de testar b's contra qé revertida na suposição de que mais elevados b' s será mais difícil de dividir por (take 2, 3, 4por exemplo: se %2=0, %4poderia ser !0. E vice-versa, não tanto ...).

:{p=0[a,2,-1|~q%b|p=1┘b=2]]~p=0|_Xq\q=q+1



0

, 23 bytes

Código

1 ' lcm rot 2 swap loop

Esse código deixa o pseudo-fatorial resultante no TOS

Uso e exemplo

ok> 7 1 ' lcm rot 2 swap loop .
420

Ou mais claramente

ok> : pseudofact 1 ' n:lcm rot 2 swap loop ;

ok> 7 pseudofact .
420
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.