Raízes fatoriais principais


14

Inspirada nas raízes digitais, a raiz fatorial primária de um número é o número que surge quando você pega os fatores primos de um número, os soma e repete o processo no número resultante, continuando até que você termine com um número primo ( que tem a si próprio como seu único fator primo e, portanto, é sua própria raiz fatorial primordial). A raiz fatorial primária de 4 é 4, como 2 * 2 = 2 + 2, e esta é a única raiz fatorial primária não primária de um número inteiro maior que 1 (que é outro caso especial, pois não possui fatores primos). A sequência OEIS formada por raízes fatoriais primárias é A029908 .

Por exemplo, a raiz fatorial primária de 24 é:

24=2*2*2*3

2+2+2+3=9=3*3

3+3=6=2*3

2+3=5, and the only prime factor of 5 is 5.  Therefore, the prime factoral root of 24 is 5.  

Sua tarefa:

Escreva um programa ou função que encontre a raiz fatorial primária de um número inteiro de entrada.

Entrada:

Um número inteiro, inserido através de qualquer método razoável, entre 2 e o número inteiro maior suportado pelo seu idioma (inclusive). Não é permitido escolher especificamente um idioma que tenha um tamanho inteiro máximo excessivamente baixo (e também viole essa brecha padrão )

Resultado:

Um número inteiro, a raiz fatorial primária da entrada.

Casos de teste:

4   -> 4
24  -> 5
11  -> 11
250 -> 17

Pontuação:

Isso é , a menor pontuação em bytes ganha!


3
Você pode adicionar 4nos casos de teste, já que é uma exceção e é fácil esquecê-la ao testar uma resposta?
Scottinet # 4/17

Temos que produzir 1 para 1?
meu pronome é monicareinstate

@ alguém de acordo com a sequência OEIS vinculada, deve
gerar

2
@someone Os estados desafio que a entrada será pelo menos 2.
Martin Ender

@ alguém Alguém desculpe por estar fora por um tempo. Como Martin disse, o desafio diz especificamente que a entrada será maior que uma e, portanto, o comportamento quando a entrada for 1 é indefinido.
Gryphon #

Respostas:



14

Haskell , 61 bytes

import Data.Numbers.Primes
until=<<((==)=<<)$sum.primeFactors

Experimente online!

Explicação

until=<<((==)=<<)pega uma função fe aplica-a à entrada xaté que um ponto fixo seja alcançado, ou seja, f xigual x. primeFactorsretorna a lista de fatores primos de um número, sumproduz a soma de uma lista de números.

Mas espere, por que until=<<((==)=<<) o trabalho e parece tão estranho?

Se assumirmos f=sum.primeFactors, uma definição mais natural seria until(\x->f x==x)f, porque untilleva um predicado (uma função que retorna um booleano), uma função que tem o mesmo tipo de entrada e retorno (por exemplo Int -> Int) e valor desse tipo e, em seguida, aplica a função ao valor até que o predicado seja cumprido.

until(\x->f x==x)fé o mesmo que until(\x->(==)(f x)x)f, e como ele sustenta, g (h x) xé o mesmo (g=<<h)xque obtemos until(\x->((==)=<<f)x)f. Após a conversão do Eta , isso se torna until((==)=<<f)f. Mas se agora tratamos (==)=<<como uma função aplicada f, podemos ver que ela until(((==)=<<)f)festá novamente na forma g (h x) x, com g=until, h=((==)=<<)e x=f, portanto, pode ser reescrita para (until=<<((==)=<<))f. Usando o $operador para se livrar dos parênteses externos e substituindo fporsum.primeFactors produz a solução de cima.


4
=<<((==)=<<)$Whaaaaaat.
totallyhuman

2
@icrieverytim eu adicionei uma explicação. Sinta-se à vontade para perguntar na sala de bate-papo de Haskell se tiver mais perguntas sobre como essa feitiçaria funciona.
Laikoni

5

Casca , 4 bytes

ω(Σp

Experimente online!

Explicação:

ω(   -- apply the following function until the result no longer changes (fixpoint)
  Σ  -- sum
   p -- the list of primefactors


4

Python 2 , 84 bytes

f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))
i=input()
exec'i=f(i);'*i
print i

Experimente online!


Esta pode ser uma pergunta bem idiota, mas como f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))funciona? Eu nunca programei em Python (principalmente Java e C #), por isso não tenho certeza qual é o resultado dessa função. Essa função modifica a entrada ne a retorna depois, ou é semelhante a um booleano em n>1and(n%d and f(n,d+1)or d+f(n/d))que 0 ou 1, 0 ou 0 nou algo mais? Estou tentando visualizar como uma porta disso seria em Java / C #, mas não consigo porque realmente não entendo lambdas do Python como esta em geral.
21717 Kevin Smithijssen

1
@KevinCruijssen isso é equivalente a n>1 ? (n%d!=0 ? f(n, d+1) : d+f(n/d)) : n>1. Em termos gerais x and yé equivalente a x ? y : x. x and y or zé equivalente a x ? y : zna maioria dos casos.
ovs

1
@KevinCruijssen uma porta Java seria algo parecido f=(n,d=2)->n>1?n%d>0?f(n,d+1):d+f(n/d):0.
ovs 04/10/19

Ah ok. Obrigado pela explicação, agora faz muito mais sentido. E eu lembro também de x and yser x ? y : xdo JavaScript. Obrigado!
Kevin Cruijssen

4

Java 8, 175 144 142 141 bytes

n->{for(int i,t=n,x;;n=t){for(i=2;i<t;t=t%i++<1?0:t);if(t>1|n<5)return n;for(t=0,i=1;i++<n;)for(;n%i<1;n/=i,t+=x)for(x=i;x>9;x/=10)t+=x%10;}}

-1 byte graças a @Nevay .

Ao contrário de bytes únicos em algumas das linguagens do golfe, o Java é bastante detalhado para verificações primárias, fatores primos, somas de dígitos e assim por diante, então acho que menos de 200 não é muito ruim.
É provável que ainda seja possível jogar golfe combinando loops e não usando um método recursivo separado para a soma dos dígitos .

Explicação:

Experimente aqui.

n->{                // Method with integer as both parameter and return-type
  for(int i,        //  Index-integer `i`
          t=n,      //  Temp integer `t`, starting at the input `n`
          x;        //  Temp integer `x`
      ;             //  Loop (1) indefinitely
      n=t){         //    After every iteration, replace `n` with the value `t`
    for(i=2;        //   Reset `i` to 2
        i<t;        //   Inner loop (2) from 2 to `t` (exclusive)
        t=t%i++<1?  //    If `t` is divisible by `i`:
           0        //     Set `t` to 0
          :         //    Else:
           t        //     Leave `t` the same
    );              //   End of inner loop (2)
    if(t>1          //   If `t` is not 0 (it means it's a prime),
       |n<5)        //   or if `n` is below 5 (for edge-cases `4` and 'prime' `1`)
      return n;     //    Return `n` as result
    for(t=0,        //   Reset `t` to 0
        i=1;        //   Reset `i` to 1
        i++<n;)     //   Inner loop (3) from 2 to `n` (inclusive)
      for(;n%i<1;   //    Inner loop (4) as long as `n` is divisible by `i`
          n/=i,     //      After every iteration: Divide `n` by `i`,
          t+=x)     //      and increase `t` by `x`
        for(x=i;    //     Reset `x` to `i`
            x>9;    //     Inner loop (5) as long as `x` contains more than 1 digit
            x/=10)  //       After every iteration, remove the trailing digit
          t+=n%10;  //      Increase `t` with the trailing digit of `n`
                    //     End of inner loop (5) (implicit / single-line body)
                    //    End of inner loop (4) (implicit / single-line body)
                    //   End of inner loop (3) (implicit / single-line body)
  }                 //  End of loop (1)
}                   // End of method

6
+1 por escrever uma explicação detalhada, como se fosse uma linguagem de golfe.
meu pronome é monicareinstate 4/17/17

@ alguém Obrigado! Desde que alguém me perguntou sobre uma explicação de uma resposta minha sobre Java uma vez no passado, eu as adicionei a todas as minhas respostas. :)
Kevin Cruijssen

i,t=n,xparece que pertence em Python, haha
ETHproductions

@ETHproductions Hehe, pena que ainda tenho que adicionar o líder int (ao contrário do Python). ;)
Kevin Cruijssen 4/17/17

Você pode usar em i++<nvez de ++i<=n.
Nevay 04/10/19


3

Retina , 30 bytes

{+`(\1|\b11+?\B)+$
$1;$#1$*
;

Entrada e saída em unário .

Experimente online!(Executa conversão decimal / unária por conveniência.)

Explicação

{+`(\1|\b11+?\B)+$
$1;$#1$*

o { instrui o Retina a executar o programa inteiro em um loop até que uma passagem completa falhe na modificação da string, ou seja, até que um ponto fixo seja alcançado. Consequentemente, o próprio programa calcula uma etapa da soma dos fatores primos do valor atual.

Esse estágio calcula a fatoração principal da entrada. O +é semelhante a, {mas faz um loop apenas neste estágio até que ele pare de alterar a string. O regex tenta corresponder à execução final de 1s correspondendo repetidamente à mesma substring (isto é, o fator). A maneira como isso é feito é um pouco complicada devido à referência direta \1. Na primeira iteração, agrupe ) para garantir que capturamos o divisor real. O benefício de usar essa abordagem um tanto complicada é que o grupo será usado exatamente n / d vezes, ou seja, o que resta depois de dividir o divisor1 ainda não capturou nada, portanto \1falha incondicionalmente. Em vez disso, temos que combinar \b11+?\Bqual é a menor substring possível que começa no início da execução, contém pelo menos dois 1se não cobre a execução inteira. As iterações subseqüentes não poderão usar essa alternativa novamente, devido ao \b. Então, em todas as iterações adicionais, estamos combinando\1, ou seja, a mesma substring repetidamente. Esse processo precisa atingir o final da string exatamente ( d .$1

Substituímos essa correspondência por d ( $1), uma separação ;e n / d ( $#1$*, que insere $#1cópias de 1, onde $#1é o número de capturas feitas por grupo 1).

Esse processo é interrompido quando a execução final da sequência é, por si só, primária, porque a regex não corresponde mais.

;

Tudo o que precisamos fazer para somar os números primos é remover todos os separadores.



2

Na verdade , 7 bytes

⌠w♂πΣ⌡Y

Experimente online!

Explicação:

⌠w♂πΣ⌡Y
⌠    ⌡Y  do this until output stops changing (fixed-point combinator)
 w         factor into [prime, exponent] pairs
  ♂π       product of each pair
    Σ      sum of products

2

R + pracma , 53 bytes

function(n){for(i in 1:n)n=sum(pracma::factors(n))
n}

Experimente online! (r-violino)

R não têm fatores primos embutidas, mas inúmeros pacotes ( pracma, numbers, etc.) fazer, então eu escolhi uma convenientemente curto.


1

Gelatina , 6 bytes

Esta resposta usa um dos muitos principais fatores de fatoração da Jelly, e o mais rápido possível repeat until the results are no longer unique.

ÆfSµÐL

Experimente online!


Eu acho que você foi outgolfed mas, dada a sua abordagem, estou incerto se que as obras resposta
Caird coinheringaahing

@cairdcoinheringaahing Acabei de verificar sua resposta (ou melhor, o equivalente em Python) de 1 a 100000 e funciona. Eu acho que 1é o único caso em que o número de etapas necessárias é igual a n(o que é bom; 1só precisamos executá-lo uma vez), e não parece haver casos em que o número de etapas seja maior que n(ou seja, parece não haver contra-exemplos). Ah, bem, eu tenho outgolfed: D
Sherlock9

Bem, acontece. Embora +1 por ser exatamente o mesmo código que pensei quando vi este desafio
Caird coinheringaahing

A soma dos fatores primos de n é sempre menor ou igual a n, o que facilita bastante provar que n é sempre mais que suficiente.
5197 Chris

1

MATL , 6 bytes

Usa a idéia do escoteiro de fazer um loop mais vezes do que o necessário. Agradeço também a Shaggy por apontar um erro, agora corrigido.

t:"Yfs

Experimente online!

Explicação

t       % Take input (implicit). Duplicate
:"      % Do the following that many times
  Yf    %   Array of prime factors
  s     %   Sum of array
        % End (implicit). Display (implicit)

Isso parece falhar 4.
Shaggy

@ Thanks Shaggy! Trabalhando nisso
Luis Mendo

@Shaggy Resolvido agora
Luis Mendo

1

PowerShell , 124 bytes

function f($a){for($i=2;$a-gt1){if(!($a%$i)){$i;$a/=$i}else{$i++}}}
for($x=$args[0];$l-ne$x){$l=$x;$x=(f($x))-join'+'|iex}$x

Experimente online!

O PowerShell não possui nenhum fator de fatoração principal incorporado, portanto, ele usa o código da minha resposta no Prime Factors Buddies (a linha superior) para executar os cálculos de fatoração.

A segunda linha é a carne deste programa. Tomamos a entrada de $argspara $x, em seguida, forloop até que $lé -not equa a $x. (A primeira iteração $lé $nulle $xé um número inteiro, portanto, repetiremos pelo menos uma vez).

Dentro do loop, definimos nosso $l = $xpara determinar se atingimos o final do loop ou não. Em seguida, obtemos os fatores de $xcom f($x), -joinaqueles com +e com |iexeles (abreviação Invoke-Expressione semelhante a eval). Isso é armazenado de volta $x. Assim, chegamos ao "fim" em que a fatoração primária resumida volta a si mesma. Então, simplesmente colocamos $xno pipeline e a produção está implícita.


0

Mathematica, 35 bytes

#//.x_:>Tr[1##&@@@FactorInteger@x]&

Experimente online!

(O Mathics não suporta Tr. Eu tenho que implementá-lo manualmente)


4
1##&é curto Timese FixedPointquase sempre pode ser reduzido com //.:#//.x_:>Tr[1##&@@@FactorInteger@x]&
Martin Ender

@MartinEnder Thanks! Eu já deveria saber Times, mas não sabia sobre o FixedPointtruque.
user202729

Seu código está escrito no Mathematica. Esta não é uma função matemática. Você deve alterar o nome do idioma para Mathematica ou Tr para Total
J42161217 4/17/17

@ {ninguém} Desculpe, o nome do idioma (Matemática) foi um erro. {i cri evritime} corrigiu isso.
user202729


0

Ruby , 63 bytes

->n{n.times{n=n.prime_division.map{|x|x.reduce:*}.sum};n}

Experimente online!

Usa o -rprimesinalizador para +6 bytes para usar o Prime # prime_division .

prime_divisionretorna pares de [prime, exponent](por exemplo, para 24, temos os fatores [2, 2, 2, 3]que ele fornece [[2, 3], [3, 1]]); portanto, em cada etapa, apenas multiplicamos os membros desses pares e somamos os resultados.


0

Javascript (ES6), 63 bytes

f=n=>(q=(p=(m,x)=>m<x?0:m%x?p(m,x+1):x+p(m/x,x))(n,2))^n?f(q):q
<input id=i type=number min=0 value=0 oninput="o.innerText=f(i.value)">
<p id=o></p>

Ungolfed:

f=n=>(                  // Recursive function `f`
    p=(m,x=2)=>(        //   Recursive function `p`, used to sum prime factors
        m<x?            //     If m (the number to be factored) is less than x (the current
            0           //     iteration), return 0
        :m%x?           //     Else if m doesn't divide x
            p(m,x+1)    //     run the next iteration
        :               //     Else (if m divides x)
            x+p(m/x,x)  //     Divide m by x and repeat the current iteration
    ),
    q=p(n),             //   Set q to the sum of the prime factors of n
    q^n?                //   If q != n then
        f(q)            //     repeat f with q
    :                   //   else
        q               //     return q
)

0

Java 8, 101 bytes

n->{for(int i=n;i-->0;n=f(n,2));return n;}int f(int n,int d){return n>1?n%d>0?f(n,d+1):d+f(n/d,2):0;}

Porto da incrível resposta Python 2 do @ovs .

Explicação:

Experimente aqui.

n->{                  // Method with integer as both parameter and return-type
  for(int i=n;i-->0;  //  Loop the input amount of times
    n=f(n,2)          //   And change `n` that many times with a separate method call
  );                  //  End of loop
  return n;           //  Then return the integer `n` as result
}                     // End of method

int f(int n,int d){   // Separated method with 2 integer parameters and integer return-type
                      // (`d` is 2 when we initially call this recursive-method)
  return n>1?         //  If input `n` is larger than 1:
    n%d>0?            //   And it's not divisible by `d`:
     f(n,d+1)         //    Do a recursive-call with `n, d+1`
    :                 //   Else:
     d                //    Sum `d` with
      +f(n/d,2)       //    a recursive call with `n/d, 2`
   :                  //  Else:
    0;                //   Simply return 0
}                     // End of separated method
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.