La prima rana 🐸


44

La "rana primaria" è uno strano animale che salta tra numeri interi, fino a quando non arriva il 3 o il 19 ...


Il tuo programma dovrebbe accettare un numero intero ncome input e produrre il risultato dell'algoritmo di seguito ( 3o 19).

Per un dato numero intero n >= 2:

  1. Lascia che fsia la posizione della rana. Inizialmente è impostato sun
  2. if f = 3or f = 19: la rana smette di saltare - interrompe il programma e l'uscita f.
  3. if fis prime: la rana salta in posizione 2×f-1. Torna al passaggio 2.
  4. if fè composito: dsia fil principale divisore principale. La rana salta in posizione f-d. Torna al passaggio 2.

Esempi:

Un esempio con n = 5:

5 > 9 > 6 > 3 stop

Il programma dovrebbe essere emesso 3.

Un altro esempio con n = 23:

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

Ancora una volta, il programma dovrebbe essere prodotto 3.

Casi test:

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

Puoi presumere 1 < n < 1000000(ho verificato che il programma termina per questi valori).


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

8
Fantastica variazione Collatz.
Arthur,

3
Se non riusciamo a dimostrare che la rana arriva sempre 3o 19, potremmo cambiare il punto 2. dell'algoritmo per dire che se la rana è entrata in un ciclo (ha incontrato una posizione che ha visto prima), allora cessa il salto e restituisce il più piccolo membro di quel ciclo.
Jeppe Stig Nielsen,

4
@PyRulez Se raggiunge quello, probabilmente dovresti dirlo al PO.
mbomb007,

3
@KeyuGan Forse sarebbe una buona cosa pubblicare su Math.SE.
mbomb007,

Risposte:



12

C (gcc),  87  65 byte

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

Provalo online!

Spiegazione:

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

Versione portatile (72 byte):

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

Provalo online!

Con nomi di variabili più appropriati:

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

Provalo online!


5
Adoro il gioco con la parola rana e le tue variabili. +1.
Rayryeng - Ripristina Monica il

10

Retina , 63 62 byte

Grazie a Neil per aver salvato 1 byte.

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

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

Provalo online!

Input e output in unario (la suite di test utilizza il decimale per comodità). Questa soluzione diventa incredibilmente lenta per input più grandi. Il 9983test case scade su TIO.

Spiegazione

A causa di {, entrambe le fasi del programma vengono semplicemente eseguite in un ciclo fino a quando non influiscono più sulla stringa. Si alternano tra compositi di elaborazione di fase e primi di elaborazione di fase. Questo ci consente di evitare un vero condizionale (che in realtà non esiste in Retina). Se il valore corrente è del tipo sbagliato per lo stage, lo stage semplicemente non fa nulla.

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

Questo elabora i compositi. Abbiniamo un potenziale divisore a (11+), ma poi controlliamo che non sia composto (?<!^\2+(11+)), quindi consideriamo solo i fattori primi. A causa dell'avidità di +, questo dà la priorità al fattore più grande. Poi controlliamo che questo potenziale divisore è un vero e proprio divisore, cercando di abbinare il resto della stringa con ripetizioni di esso, (?=\1+$). Questo divisore viene semplicemente rimosso dalla stringa, che è il modo in cui si sottrae qualcosa in unario.

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

Questo elabora i numeri primi, tranne 3 e 19 . Il lookahead negativo si assicura che l'input non sia composito, non 3 e non 19 . Quindi abbiniamo un singolo 1e lo sostituiamo con l'intera stringa. Questa è una forma unaria di calcolo n - 1 + n , che ovviamente è 2n-1 .

Una volta colpiti 3 o 19 , nessuno dei due stage può eguagliare la stringa e non verrà più modificato.


1
Non è 1$'lo stesso di $_?
Neil,

4
@Neil Sì ......
Martin Ender,

8

Buccia , 15 byte

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

Provalo online!

Spiegazione

Ω€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 byte

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

Provalo online!

Come funziona

_Æ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

Wolfram Language (Mathematica) , 6566 68 byte

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

Provalo online!

Ispirato dalla punta . Fondamentalmente, ricrea semplicemente l'algoritmo.

//.è RepeatedReplaceed /;è Condition. Quindi, il codice sostituirà i_(una singola quantità) con If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i], fino alla i!=3&&!=19valutazione True.

Indice di riferimento:

segno di riferimento


3
fatto 10000000010maximum number of iterations is 2^16 (= 65536)
curioso

1
Un modo leggermente più breve per verificare 3 e 19 è#//.i:Except[3|19]:>If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]&
Misha Lavrov,

@MishaLavrov ma il risultato non è corretto?
Keyu Gan,

@KeyuGan Per me, le due funzioni danno esattamente lo stesso risultato per gli interi da 1 a 1000.
Misha Lavrov,

1
Probabilmente il problema che stai riscontrando è l'inserimento di caratteri non stampabili quando copi e incolli dai commenti, cosa che a volte accade.
Misha Lavrov,

6

05AB1E , 19 18 17 byte

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

Provalo online!

Spiegazione

[      #            # 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 per avere una vera rana nel tuo codice sorgente
Arnaud,

Per 57991 più di 1 minuto
RosLuP

@RosLuP: Farai meglio a eseguire offline test molto lunghi;)
Emigna,

5

JavaScript (ES6), 73 71 69 byte

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

Casi test

Formattato e commentato

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
Intelligente, usando 57%ne n%38invece di n==3|n==19. Ho salvato anche 1 byte nella mia risposta Java , quindi grazie!
Kevin Cruijssen,

In ideone 57991 input genera prog.js: 2: 26 InternalError: troppa ricorsione
RosLuP

In 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 stampa (f (57991)) genera programma di arresto non emesso, mi sembra
RosLuP

1
@RosLuP Questa è una sfida di code-golf senza alcun vincolo specifico. Il consenso attuale è che le limitazioni di velocità o memoria (come la dimensione dello stack di chiamate) possono essere ignorate se non diversamente specificato nella domanda. Dò per scontato che il limite di 1000000 sia solo informativo perché la sequenza non è stata testata oltre. Per inciso, la tua soluzione a 70 byte è perfettamente soddisfacente ed è probabilmente più pertinente della versione a 93 byte per una sfida di code-golf.
Arnauld,


4

Python 2 , 110 105 103 101 byte

-2 byte grazie 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)

Provalo online!


Python 2 , 116 112 105 byte

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

Provalo online!


1
…n*(n&~16==3)or…salva 2 byte.
Lynn,

Per input 57991 sys.setrecursionlimit (20000)
RosLuP

4

MATL , 22 21 byte

Grazie a @Giuseppe per aver rimosso 1 byte!

`tZp?Eq}tYfX>-]tI19h-

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

`           % 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 byte

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

Probabilmente mancano alcuni trucchi da golf qui, questo è il mio primo tentativo di haskell golf.


Ciao e benvenuto nel sito. Non sono necessarie le nuove linee e gli spazi per le protezioni dei motivi. Puoi anche usarlo 1>0per la Truemaggior parte delle volte, ma spesso potrebbe essere meglio usare un compito, per esempio c<-z n.
Mago del grano,

1
[x|x<-[b-1,b-2..1],rem b x==0]è anche breve di reverse[x|x<-[1..(b-1)],brem x==0].
Wheat Wizard

2
E un'ultima cosa, se vuoi discutere del golf haskell puoi unirti a noi in Of Monads and Men .
Mago del grano,

3

Neim , 17 16 byte

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

Spiegazione:

ͻ                   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

Provalo online!


3

Numeri R + , 102 99 byte

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

Provalo online!

R non è noto per i brevi incorporati e anche i pacchetti seguono l'esempio!


3

Java 8, 140 135 134 94 byte

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 byte convertendo il metodo ricorsivo Java 7 in Java 8 lambda con loop.
-1 byte implicito grazie alla risposta JavaScript di @Arnauld cambiando n!=3&n!=19e return n;a 57%n>0e return n%38;.
Penso che dovrebbe essere possibile in qualche modo combinare i due loop e verificare se nè un numero primo, e ottenere il suo primo fattore più grande allo stesso tempo, ma non riesco a capirlo (ancora). Quindi questa sarà la versione iniziale per ora.
-40 byte enormi grazie a @Nevay, facendo quello che non potevo fare: combinare i loop per verificare la presenza di numeri primi e il fattore primo più grande in una volta.

Spiegazione:

Provalo qui (esegue anche 999999in meno di 1 secondo).

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 personaggio a corto di essere un poliglotta C # :(
Ian H.

@IanH. Hehe, sì, di solito è così: n=>invece di n->. E a volte chiamate minuscole / maiuscole. ;)
Kevin Cruijssen,

1
94 byte: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,

@Nevay Grazie! Sapevo solo che sarebbe stato possibile combinare i loop, ma non sono riuscito a capirlo. Un enorme 40 byte salvati grazie a te!
Kevin Cruijssen,

3

Bash, 73 byte

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

Provalo online! Modificato leggermente per funzionare su TIO.

Chiama in modo ricorsivo il proprio file di script utilizzando $0, che non funziona in TIO perché deve essere eseguito come./filename.sh . Accetta input come argomento della riga di comando.

Utilizza lo stesso trucco modulo della risposta JS di @ Arnauld .

Casi test

$ 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

Pyth , 19 byte

.W!/P57H?P_ZtyZ-ZeP

Verifica tutti i casi di test!

La risposta di Husk mi ha ispirato a salvare 2 byte ( ,3 19in P57).

Come funziona

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

.W - Funzionale mentre. Mentre A (valore) è vero, valore = B (valore). Restituisce l'ultimo valore.
    P57 - I fattori primi di 57 ([3, 19]).
   / H: conta le occorrenze del valore corrente.
  ! - NOT logico. 0 -> Verità, qualsiasi altra cosa -> Falsy.
        ? P_Z - Se il valore corrente è primo, allora:
            tyZ - Raddoppia il valore corrente, diminuisce.
               -ZeP - Altrimenti, sottrai il fattore primo massimo del valore corrente da se stesso.
                     - Stampa implicitamente.

1

PowerShell , 150 126 byte

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

Provalo online! (avviso: lento per numeri più grandi)

Metodo iterativo. PowerShell non ha alcun fattore di fattorizzazione principale incorporato, quindi questo prende in prestito il codice dalla mia risposta su Amici di Prime Factors .

Il primo è il nostro forciclo. L'impostazione imposta $ncome valore di input e il condizionale mantiene il ciclo attivo fintanto che 57%$nè diverso da zero (grazie ad Arnauld per quel trucco). All'interno del loop viene innanzitutto visualizzato un elenco di fattori primi di $a(impostato su $n). Questo è il codice preso in prestito dai compagni Prime Factors. Se l'input $aè già primo, questo restituirà solo $a(importante in seguito). Quello (potenzialmente solo $a) viene archiviato $d.

Il prossimo è un if/ elsecondizionale. Per la ifparte, controlliamo se lo $nè -in $d. Se lo è, significa che $nè primo, quindi prendiamo $n=2*$n-1o $n+=$n-1. Altrimenti, è composito, quindi dobbiamo trovare il fattore primo più grande. Ciò significa che dobbiamo prendere l'ultimo [-1]di $de sottrarlo da $ncon $n-=. Questo funziona perché siamo in loop 2e quindi l'ultimo elemento di $dsarà già il più grande.

Una volta terminato il looping, posizioniamo $n%38(di nuovo, grazie Arnauld) sulla pipeline e l'output è implicito.


1

APL (Dyalog Unicode) , 113 90 59 byte

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

Provalo online!

TIO funziona con valori fino a ~ 3200. Testato sul mio PC per l'ultimo caso di test. Per testare su TIO, basta aggiungere f valuein fondo al codice. Non si applica più, grazie a @ Adám per aver sottolineato che il mio algoritmo di controllo della primalità era davvero pessimo e mi ha fornito una sostituzione; anche per il salvataggio a 23 byte.

Modificato per correggere il conteggio dei byte.

Come funziona

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

Assioma, 93 byte

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)

test:

(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

Ci sarebbero 68 byte di funzione

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

ma per n = 57991 (se ricordo bene) esce lo spazio di stack riservato.


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.