O sapo principal 🐸


44

O "primo sapo" é um animal estranho que salta entre números inteiros, até chegar aos 3 ou 19 anos ...


Seu programa deve aceitar um número inteiro ncomo entrada e gerar o resultado do algoritmo abaixo ( 3ou 19).

Para um dado inteiro n >= 2:

  1. Let fSer a posição do sapo. É inicialmente definido comon
  2. se f = 3ou f = 19: o sapo para de pular - interrompe o programa e a saída f.
  3. se ffor primo: o sapo pula para a posição 2×f-1. Volte para a etapa 2.
  4. se ffor composto: dseja fo maior divisor principal de s. O sapo pula para a posição f-d. Volte para a etapa 2.

Exemplos:

Um exemplo com n = 5:

5 > 9 > 6 > 3 stop

O programa deve sair 3.

Outro exemplo com n = 23:

23 > 45 > 40 > 35 > 28 > 21 > 14 > 7 > 13 > 25 > 20 > 15 > 10 > 5 > 9 > 6 > 3 stop

Novamente, o programa deve sair 3.

Casos de teste:

10 => 3
74 => 19
94 => 3
417 => 3
991 => 19
9983 => 19

Você pode assumir 1 < n < 1000000(verifiquei o programa termina para esses valores).


3
3 loop é [3 5 9 6 3] e 19 loop é [19 37 73 145 116 87 58 29 57 38 19]
Arnaud

8
Variação legal de Collatz.
Arthur

3
Se não pudermos provar que o sapo sempre chega a 3ou 19, poderíamos alterar o item 2. no algoritmo para dizer que, se o sapo entrou em qualquer loop (encontrou uma posição que já havia visto antes), ele interrompe o salto e retorna o menor membro desse loop.
Jeppe Stig Nielsen

4
@ PyRulez Se isso acontecer, você provavelmente deve informar o OP.
mbomb007

3
@KeyuGan Talvez isso seja uma boa coisa para postar no Math.SE.
Mbomb007

Respostas:



12

C (gcc),  87  65 bytes

i,k;f(n){for(i=n;i>1;)for(k=i;k%--i;);n=~16&n-3?f(n-k?:n+n-1):n;}

Experimente online!

Explicação:

i,k;
f(n)
{
    for (i=n; i>1;)              // Loop until `k` is prime (the largest positive
                                 // `i` inequal to `k` that divides `k` is 1).
        for (k=i; k%--i;);       // Find the largest factor `k`

    n =                          // Returning like this is undefined behaviour,
                                 // but happens to work with gcc. This can be
                                 // replaced with `return` at the cost of 4 bytes.

        ~16&n-3                  // If `n` is 3 or 19, this expression equals 0 and
                                 // the algorithm halts. Otherwise the function
                                 // calls itself to perform the next iteration.

        ? f(n-k ?: n+n-1)        // If `n-k` is non-zero, n is not prime.
                                 // In this case call `f` with the value of `n-k`.
                                 // (Omitting the second `n-k` between `?` and `:`
                                 // is a gcc extension)
                                 // Otherwise call `f` with `2*n-1`.

        : n;                     // All done, `n` is returned.
}

Versão portátil (72 bytes):

i,k;f(n){for(i=n;i>1;)for(k=i;k%--i;);return~16&n-3?f(n-k?n-k:n+n-1):n;}

Experimente online!

Com nomes de variáveis ​​mais apropriados:

f,r;o(g){for(f=g;f>1;)for(r=f;r%--f;);g=~16&g-3?o(g-r?:g+g-1):g;}

Experimente online!


5
Ame totalmente o jogo com a palavra sapo e suas variáveis. +1.
rayryeng - Restabelece Monica

10

Retina , 63 62 bytes

Agradecemos a Neil por economizar 1 byte.

{`^(11+)(?<!^\2+(11+))(?=\1+$)

^(?!(11+)\1+$|111$|1{19}$)1
$_

Experimente online!

Entrada e saída em unário (o conjunto de testes usa decimal por conveniência). Essa solução fica incrivelmente lenta para entradas maiores. O 9983caso de teste atinge o tempo limite no TIO.

Explicação

Devido a isso {, os dois estágios do programa são simplesmente executados em um loop até que não afetem mais a string. Alternamos entre um estágio de processamento de compósitos e um estágio de processamento de primos. Isso nos permite evitar uma condicional real (que realmente não existe na Retina). Se o valor atual for do tipo errado para o estágio, o estágio simplesmente não fará nada.

^(11+)(?<!^\2+(11+))(?=\1+$)

Isso processa compostos. Combinamos um divisor em potencial com (11+), mas depois verificamos que ele não é composto (?<!^\2+(11+)), portanto, consideramos apenas os fatores primos. Devido à ganância +, isso prioriza o maior fator. Em seguida, verificamos que esse divisor em potencial é um divisor real , tentando combinar o restante da string com repetições (?=\1+$). Esse divisor é simplesmente removido da string, e é assim que você subtrai algo em unário.

^(?!(11+)\1+$|111$|1{19}$)1
$_

Este processo inicia, exceto 3 e 19 . O lookahead negativo garante que a entrada não seja composta, nem 3 e nem 19 . Em seguida, combinamos um único 1e substituí-lo por toda a cadeia. Esta é uma forma unária de computação n - 1 + n , que obviamente é 2n-1 .

Quando atingimos 3 ou 19 , nenhum estágio pode corresponder à corda e ela não será mais alterada.


1
Não é 1$'o mesmo que $_?
Neil

4
@Neil Yes ......
Martin Ender

8

Casca , 15 bytes

Ω€p57§|o←DṠ-o→p

Experimente online!

Explicação

Ω€p57§|o←DṠ-o→p  Implicit input n.
Ω                Do this to n until
 €p57            you get a prime factor of 57 (which are 3 and 19):
            o→p   Take last element of the prime factors of n
          Ṡ-      and subtract it from n,
     §|           or if this gives 0 (so n is prime),
       o←D        double and decrement n.

8

Gelatina , 12 bytes

_ÆfṂoḤ’$µÐḶṂ

Experimente online!

Como funciona

_ÆfṂoḤ’$µÐḶṂ  Maink link. Argument: n

        µ     Combine the links to the left into a chain.
         ÐḶ   Repeatedly call the chain monadically until the results are no longer
              unique. Yield the loop, i.e., the first occurrence of the first
              repeated integer, up to and excluding the repetition.
              Let's call the argument of the chain k.
_Æf             Subtract all prime factors of k from k.
   Ṃ            Take the minimum of the differences. This yields 0 iff k is prime.
     Ḥ’$        Compute 2k-1.
    o           Take the logical OR of the results.
              The result is now a rotation of either [3, 5, 9, 6] or
              [19, 37, 73, 145, 116, 87, 58, 29, 57, 38].
          Ṃ   Take the minimum, yielding either 3 or 19.

7

Língua Wolfram (Mathematica) , 6566. 68 bytes

#//.i:Except[3|19]:>If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]&
  • -1 bytes, graças a Misha Lavrov!
  • -2 bytes, graças a Martin!

Experimente online!

Inspirado pela dica . Basicamente, apenas recria o algoritmo.

//.é RepeatedReplacee /;é Condition. Portanto, o código substituirá i_(uma única quantidade) por If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i], até ser i!=3&&!=19avaliado True.

Referência:

referência


3
fato do divertimento: este código não funciona para números maiores, como 10000000010porquemaximum number of iterations is 2^16 (= 65536)
J42161217

1
Uma maneira um pouco mais curta de verificar 3 e 19 é#//.i:Except[3|19]:>If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]&
Misha Lavrov

@MishaLavrov mas o resultado está incorreto?
Keyu Gan

@KeyuGan Para mim, as duas funções dar exatamente o mesmo resultado para números inteiros de 1 a 1000.
Misha Lavrov

1
Possivelmente, o problema que você está tendo são caracteres não imprimíveis inseridos quando você copia e cola dos comentários, o que às vezes acontece.
Misha Lavrov #

6

05AB1E , 19 18 17 bytes

[ÐƵηfså#pi·<ëDfθ-

Experimente online!

Explicação

[      #            # loop until
 Ð   så             # a copy of the current value is contained in
  Ƶηf               # the unique prime factors of 171
        pi          # if the current value is prime
          ·<        # double and decrement
            ë   -   # else subtract
             Dfθ    # the largest prime factor of a copy of the current value

4
+1 por ter um sapo real em seu código-fonte
Arnaud

Para 57.991 mais de 1 minuto
RosLuP

@RosLuP: É melhor você executar casos de teste off-line muito longos;)
Emigna 20/17/17

5

JavaScript (ES6), 73 71 69 bytes

f=n=>57%n?f(n-(g=(k,d=1)=>++d<k?k%d?g(k,d):g(k/d):d<n?d:1-n)(n)):n%38

Casos de teste

Formatado e comentado

f = n =>                 // given n
  57 % n ?               // if n is neither 3, 19 or 57 (and assuming that n is > 1):
    f(                   //   do a recursive call to f() with:
      n -                //     n minus
      (g = (k, d = 1) => //     the result of the recursive function g():
        ++d < k ?        //       increment d; if d is less than k:
          k % d ?        //         if d is not a divisor of k:
            g(k, d)      //           recursive call to g() with k and d unchanged
          :              //         else:
            g(k / d)     //           recursive call to g() with k = k / d, d = 1
        :                //       else, d is now the highest prime divisor of n:
          d < n ?        //         if d is less than n:
            d            //           n is composite: return d, which results in f(n - d)
          :              //         else:
            1 - n        //           n is prime: return 1 - n, which results in f(2n - 1)
      )(n)               //     initial call to g()
    )                    //   end of recursive call to f()
  :                      // else:
    n % 38               //   return n % 38 (gives 19 as expected if n = 57)

1
Inteligente, usando 57%ne em n%38vez de n==3|n==19. Salvei 1 byte na minha resposta Java também, então obrigado!
Kevin Cruijssen 19/10/10

Em ideone 57,991 entrada gerar prog.js: 2: 26 InternalError: muito recursão
RosLuP

Em tio f = n => 57% n? F (n- (g = (k, d = 1) => ++ d <k? K% d? G (k, d): g (k / d) ?: d <n d: 1-n) (n)): n% 38 impressão (f (57.991)) geram programa de parada não saída, parece-me
RosLuP

1
@RosLuP Este é um desafio de código-golfe sem qualquer restrição específica. O consenso atual é que as limitações de velocidade ou memória (como o tamanho da pilha de chamadas) podem ser desconsideradas, a menos que seja explicitamente indicado de outra forma na questão. Eu suponho que o limite de 1000000 seja apenas informativo porque a sequência não foi testada além disso. Aliás, sua solução de 70 bytes é perfeita e provavelmente é mais relevante que a versão de 93 bytes para um desafio de código-golfe.
Arnauld #


4

Python 2 , 110 105 103 101 bytes

-2 bytes graças a @Lynn

f=lambda n,i=2,k=0:i/n and(n*(n&~16==3)or f((2*i-1,k-i)[k>0]))or n%i and f(n,i+1,k)or f(n/i,2,k or n)

Experimente online!


Python 2 , 116 112 105 bytes

f=lambda n,i=2:i/n*i or n%i and f(n,i+1)or f(n/i)
n=input()
while~16&n-3:n=[2*n-1,n-f(n)][f(n)<n]
print n

Experimente online!


1
…n*(n&~16==3)or…economiza 2 bytes.
Lynn

Para entrada 57991 sys.setrecursionlimit (20000)
RosLuP 20/17

4

MATL , 22 21 bytes

Obrigado a @ Giuseppe por remover 1 byte!

`tZp?Eq}tYfX>-]tI19h-

Experimente online! Ou verifique todos os casos de teste .

Explicação

`           % Do...while
  t         %   Duplicate. Takes (implicit) input the first time
  Zp        %   Is it prime? 
  ?         %   If so
    Eq      %     Times 2, minus 1
  }         %   Else
    t       %     Duplicate
    YfX>-   %     Prime divisors, maximum, subtract
  ]         %   End
  t         %   Duplicate
  I19h      %   Push array [3 19]
  -         %   Subtract, element-wise. The result is truthy if and only if
            %   it doesn't contain any zero
            % End (implicit). Next iteraton if top of the stack is truthy
            % Display (implicit)

4

Haskell - 154 bytes

f 3=3
f 19=19
f n
 |(c==[1])=f$2*n-1
 |True=f$n-head c
 where c=z n;v b=reverse[x|x<-[1..(b-1)],b`rem`x==0];z j=case v j of[1]->[1];s->filter((==[1]).v)$s

Provavelmente faltando alguns truques de golfe aqui, esta é minha primeira tentativa no haskell golf.


Olá e bem-vindo ao site. Você não precisa de novas linhas e espaços para protetores de padrão. Você também pode usar 1>0na Truemaioria das vezes, mas geralmente pode ser melhor usar uma tarefa, por exemplo c<-z n.
Assistente de Trigo

1
[x|x<-[b-1,b-2..1],rem b x==0]também é curto que reverse[x|x<-[1..(b-1)],brem x==0].
Assistente de trigo

2
E uma última coisa, se você gostaria de discutir golfe haskell, pode se juntar a nós em Of Monads and Men .
Assistente de trigo

3

Neim , 17 16 bytes

ͻY𝐏𝕚÷D𝐌Ξᚫ<#D𝐏𝐠𝕊

Explicação:

ͻ                   Start infinite loop
 D                  Duplicate
  Y                 Push 57
   𝐏                Prime factors: [3 19]
     𝕚              If the second-to-top of stack is in the list
      ÷             Break the loop
       D            Duplicate
        𝐌Ξᚫ<       If prime, double and decrement
            #D𝐏𝐠𝕊   Otherwise, subtract the largest prime factor

Experimente online!


3

Números R + , 102 99 bytes

function(n){while(!n%in%c(3,19))n="if"(isPrime(n),2*n-1,n-max(primeFactors(n)))
n}
library(numbers)

Experimente online!

R não é conhecido por embutidos curtos, e até os pacotes seguem o exemplo!


3

Java 8, 140 135 134 94 bytes

n->{for(int f,t,m=0;57%n>0;n=f>n?2*n-1:n-m)for(t=n,f=1;f++<t;)for(;t%f<1;t/=m=f);return n%38;}

-5 bytes convertendo o método Java 7 recursivo em Java 8 lambda com loop.
-1 byte implícito graças à resposta JavaScript de @Arnauld alterando n!=3&n!=19e return n;para 57%n>0e return n%38;.
Eu acho que deveria ser possível de alguma forma combinar os dois loops e verificar se né um primo e obter o maior fator primo ao mesmo tempo, mas ainda não consigo descobrir (ainda). Portanto, esta será a versão inicial por enquanto.
-40 bytes impressionantes graças ao @Nevay, fazendo o que eu não podia fazer: combinando os loops para verificar se há primos e o maior fator primo de uma só vez.

Explicação:

Experimente aqui (executa mesmo 999999em menos de 1 segundo).

n->{                  // Method with integer as both parameter and return-type
  for(int f,          //  Flag-integer
          t,          //  Temp-integer
          m=1;        //  Max prime factor integer, starting at 0
      57%n>0;         //  Loop (1) as long as `n` is not 3, not 19 and not 57:
      n=f>n?          //    After every iteration: if `f` is larger than `n`:
         2*n-1        //     Change `n` to `2*n-1`
        :             //    Else:
         n-m)         //     Change `n` to `n-m`
    for(t=n,          //   Reset `t` to `n`
        f=1;          //   Reset `f` to 1
        f++<t;)       //   Inner loop (2) from 2 to `t` (inclusive)
      for(;t%f<1;     //    Inner loop (3) as long as `t` is divisible by `f`
        t/=m=f;       //     Set `m` to `f`, and set `t` to `t/f`
      );              //    End of inner loop (3)
                      //   End of inner loop (2) (implicit / single-line body)
                      //  End of loop (1) (implicit / single-line body)
  return n%38;        //  Return `n%38`, which is now either 3 or 19
}                     // End of method

1
1 curto caráter de ser um C # poliglota :(
Ian H.

@IanH. Hehe, sim, geralmente é o caso: em n=>vez de n->. E, às vezes, em letras minúsculas / maiúsculas. ;)
Kevin Cruijssen

1
94 bytes:n->{for(int f,t,m=0;57%n>0;n=f>n?2*n-1:n-m)for(t=n,f=1;f++<t;)for(;t%f<1;)t/=m=f;return n%38;}
Nevay

Obrigado @Nevay! Eu apenas sabia que deveria ser possível combinar os loops, mas não consegui descobrir. Poucos 40 bytes salvos graças a você!
Kevin Cruijssen 20/10

3

Bash, 73 bytes

((57%$1))&&$0 $[(x=$1-`factor $1|sed 's/.* //'`)?x:2*$1-1]||echo $[$1%38]

Experimente online! Modificado ligeiramente para funcionar no TIO.

Recursivamente chama seu próprio arquivo de script usando $0, o que não funciona no TIO porque deve ser executado como./filename.sh . Aceita entrada como argumento da linha de comando.

Usa o mesmo truque de módulo que a resposta JS de @ Arnauld .

Casos de teste

$ for t in 5 23 10 74 94 417 991 9983;{ echo -n "$t -> "; ./prime-frog.sh $t; }
5 -> 3
23 -> 3
10 -> 3
74 -> 19
94 -> 3
417 -> 3
991 -> 19
9983 -> 19


1

Pitão , 19 bytes

.W!/P57H?P_ZtyZ-ZeP

Verifique todos os casos de teste!

A resposta Husk me inspirou a economizar 2 bytes ( ,3 19para P57).

Como isso funciona

.W! / P57H? P_ZtyZ-ZeP - Programa completo.

.W - Enquanto funcional. Enquanto A (valor) é verdadeiro, valor = B (valor). Retorna o último valor.
    P57 - Os fatores primos de 57 ([3, 19]).
   / H - conte as ocorrências do valor atual.
  ! - NÃO lógico. 0 -> Verdade, qualquer outra coisa -> Falsy.
        ? P_Z - Se o valor atual for primo, então:
            tyZ - Dobra o valor atual, diminui.
               -ZeP - Senão, subtrai o fator máximo máximo do valor atual de si mesmo.
                     - Imprima implicitamente.

1

PowerShell , 150 126 bytes

for($n="$args";57%$n){$a=$n;$d=for($i=2;$a-gt1){if(!($a%$i)){$i;$a/=$i}else{$i++}};if($n-in$d){$n+=$n-1}else{$n-=$d[-1]}}$n%38

Experimente online! (aviso: lento para números maiores)

Método iterativo. O PowerShell não possui nenhum fator de fatoração principal incorporado, portanto, isso empresta o código da minha resposta no Prime Factors Buddies .

Primeiro é o nosso forloop. A configuração é definida $ncomo o valor de entrada, e a condicional mantém o loop ativo desde que 57%$nseja diferente de zero (graças a Arnauld por esse truque). Dentro do loop, primeiro obtemos uma lista dos fatores primos de $a(definido como $n). Este é o código emprestado da Prime Factors Buddies. Se a entrada $ajá estiver pronta, isso retornará apenas $a(importante mais tarde). Isso (potencialmente apenas $a) é armazenado $d.

Em seguida é um if/ elsecondicional. Para a ifparte, verificamos se $né -in $d. Se for, isso significa que $né primo, então tomamos $n=2*$n-1ou $n+=$n-1. Caso contrário, é composto, portanto, precisamos encontrar o maior fator primo. Isso significa que temos de tomar o último [-1]de $de subtrair que a partir de $ncom $n-=. Isso funciona porque estamos retornando 2e, portanto, o último elemento de $djá será o maior.

Quando terminamos o loop, colocamos $n%38(novamente, graças a Arnauld) no pipeline e a saída está implícita.


1

APL (Dyalog Unicode) , 113 90 59 bytes

CY 'dfns'
g←{1pco ⍵:f(2×⍵)-1f⍵-⊃⌽3pco ⍵}
f←{⍵∊3 19:⍵⋄g ⍵}

Experimente online!

O TIO trabalha com valores de até ~ 3200. Testado no meu PC para o último caso de teste. Para testar no TIO, basta adicionar f valuena parte inferior do código. Não se aplica mais, obrigado a @ Adám por apontar que meu algoritmo de verificação de primalidade era muito ruim e por me fornecer uma substituição; também para os 23 bytes salvos.

Editado para corrigir a contagem de bytes.

Como funciona

CY 'dfns'                      # Imports every Defined Function, which is shorter than importing just the function I used (pco).

g←{1pco ⍵:f(2×⍵)-1f⍵-⊃⌽3pco ⍵} 
g                              # define g as
   1pco ⍵:                      # if the argument ⍵ is prime
          f(2×⍵)-1              # Call f over 2×⍵-1
                  f            # else, call f over
                               # the first element of the
                      3pco     # list of prime factors of ⍵
                               # reversed

f←{⍵∊3 19:⍵⋄g ⍵}
f                              # Define f as
        :                      # if the argument ⍵
                               # is in
     3 19                       # the list [3, 19]
                               # return the argument ⍵
                               # else
            g                  # call g over the argument ⍵

1

Axioma, 93 bytes

h(n)==(repeat(n=3 or n=19 or n<2=>break;prime? n=>(n:=2*n-1);n:=n-last(factors(n)).factor);n)

teste:

(4) -> [[i,h(i)] for i in [10,74,94,417,991,9983]]
   (4)  [[10,3],[74,19],[94,3],[417,3],[991,19],[9983,19]]
                                                  Type: List List Integer

Haveria função de 68 bytes

q x==(n<4=>3;n=19=>n;prime? n=>q(2*n-1);q(n-last(factors n).factor))

mas para n = 57991 (se bem me lembro), o espaço de pilha é reservado.


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.