Asal kurbağa 🐸


44

"Asal kurbağa", 3 ya da 19'a gelene kadar tam sayılar arasında atlayan tuhaf bir hayvandır ...


Programınız bir tamsayıyı ngirdi olarak kabul etmeli ve aşağıdaki algoritmanın ( 3veya 19) sonucunu çıkarmalıdır .

Belirli bir tamsayı için n >= 2:

  1. fKurbağanın konumu olsun . Başlangıçta olarak ayarlanırn
  2. if f = 3veya f = 19: kurbağa sıçramayı durdurur - programı ve çıkışı durdurur f.
  3. eğer fasal ise: kurbağa pozisyonuna atlar 2×f-1. 2. adıma geri dönün.
  4. eğer fkompozit: let dolmak f'nin en büyük asal bölen. Kurbağa pozisyona atlar f-d. 2. adıma geri dönün.

Örnekler:

Bir örnek n = 5:

5 > 9 > 6 > 3 stop

Program çıktı vermeli 3.

Başka bir örnek n = 23:

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

Yine programın çıktısı alınmalı 3.

Test durumları:

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

Varsayın 1 < n < 1000000(bu değerler için programın sonunu kontrol ettim).


3
3 döngü [3 5 9 6 3] ve 19 döngü [19 37 73 145 116 87 58 29 57 38 19]
Arnaud

8
Cool Collatz değişimi.
Arthur

3
Eğer kurbağanın her zaman geldiğini 3ya da kanıtlayamazsak, kurbağanın 19herhangi bir döngüye girmişse (daha önce gördüğü bir pozisyonla karşılaştıysa), öğeyi değiştirebiliriz, algoritmadaki 2. maddeyi değiştirebiliriz. bu döngünün üyesi.
Jeppe Stig Nielsen,

4
@PyRulez Buna ulaşırsa, muhtemelen OP'yi söylemelisin.
mbomb007

3
@KeyuGan Belki de Math.SE'de yayınlamak güzel bir şey olabilir.
mbomb007

Yanıtlar:



12

C (gcc),  87  65 bayt

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

Çevrimiçi deneyin!

Açıklama:

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

Taşınabilir versiyon (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;}

Çevrimiçi deneyin!

Daha uygun değişken isimleri ile:

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

Çevrimiçi deneyin!


5
Tamamen kurbağa kelimesi ve değişkenlerinizle oyunu seviyorum. +1.
rayryeng

10

Retina , 63 62 bayt

1 baytı kurtardığı için Neil'e teşekkürler.

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

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

Çevrimiçi deneyin!

Tekli giriş ve çıkış (test paketi kolaylık sağlamak için ondalık kullanır). Bu çözüm daha büyük girdiler için inanılmaz derecede yavaşlar. 9983TIO üzerinde test durumu kez.

açıklama

Bu nedenle {, programın her iki aşaması da artık dizeyi etkilemeyene kadar basitçe bir döngüde çalıştırılır. Bir sahne işlem kompozitleri ile bir sahne işlem astarları arasında geçiş yapıyoruz. Bu, gerçek bir şartlılıktan kaçmamızı sağlar (ki bu aslında Retina'da mevcut değildir). Mevcut değer sahne için yanlış tür ise, sahne basitçe hiçbir şey yapmaz.

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

Bu, kompozitleri işler. Potansiyel bir bölenle eşleşiriz (11+), ancak daha sonra bunun birleşik olmadığını kontrol ederiz (?<!^\2+(11+)), bu yüzden sadece asal faktörleri göz önünde bulundururuz. Açgözlülüğü nedeniyle +, bu en büyük faktördür. Sonra, bu potansiyel bölenin, dizenin geri kalanını, tekrarları ile eşleştirmeye çalışarak gerçek bir bölen olduğunu kontrol ederiz (?=\1+$). Bu bölen, basitçe dizgeden çıkarılır; bu, bir şeyi tekdüzen olarak çıkartmanızdır.

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

Bu, 3 ve 19 hariç, primerleri işler . Olumsuz bakış, girişin 3 değil, 19 değil birleşik olmasını sağlar . Sonra bir tanesini eşleştirip 1dizenin tamamını değiştiririz. Bu, tabii ki 2n-1 olan n - 1 + n hesaplamasının sıradışı bir şeklidir .

Çarpmadan sonra 3 veya 19 , ne sahne dize eşleşebilir ve artık değişecektir.


1
1$'Aynı değil $_mi?
Neil

4
@Neil Evet ......
Martin Ender

8

Kabuğu , 15 bayt

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

Çevrimiçi deneyin!

açıklama

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

Jöle , 12 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

_Æ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 Dili (Mathematica) , 6566 68 bayt

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

Çevrimiçi deneyin!

Ucu tarafından ilham . Temel olarak, sadece algoritmayı yeniden oluşturur.

//.olduğu RepeatedReplaceve /;bir Condition. Dolayısıyla, kod değerlendirilinceye kadar i_(tek bir miktar) ile değiştirilecektir .If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]i!=3&&!=19True

Karşılaştırma:

kıyaslama


3
eğlenceli gerçek: Bu kod gibi büyük sayılar için işe yaramaz 10000000010çünkümaximum number of iterations is 2^16 (= 65536)
J42161217

1
3 ve 19'u kontrol etmenin biraz daha kısa bir yolu#//.i:Except[3|19]:>If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]&
Misha Lavrov

@MishaLavrov, ancak sonuç yanlış mı?
Keyu Gan

@KeyuGan Benim için, iki işlev 1 - 1000 arasında tamsayılar için tam olarak aynı sonucu veriyor.
Misha Lavrov

1
Muhtemelen yaşadığınız sorun, yorumlarınızı kopyalayıp yapıştırdığınızda bazen basılan yazdırılamayan karakterlerdir.
Misha Lavrov

6

05AB1E , 19 18 17 bayt

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

Çevrimiçi deneyin!

açıklama

[      #            # 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
Kaynak kodunuzda gerçek bir kurbağa bulundurduğunuz için +1
Arnaud


@RosLuP: Sen en iyisi çevrimdışı çok uzun test durumları çalışan gidiyoruz;)
Emigna

5

JavaScript (ES6), 73 71 69 bayt

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

Test durumları

Biçimlendi ve yorumlandı

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
Akıllı, yerine 57%nve n%38yerine n==3|n==19. Java cevabımda da 1 byte kaydedildi , teşekkürler!
Kevin Cruijssen

57991 ideone girişinde prog.js üretin: 2: 26 InternalError: çok fazla özyineleme
RosLuP 20:17

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 basıldı (f (57991)) stop programı çıktı vermiyor, bana öyle geliyor
RosLuP 20:30 '

1
@RosLuP Bu herhangi bir özel kısıtlama olmadan bir kod golf mücadelesidir. Mevcut fikir birliği , soruda aksi açıkça belirtilmediği sürece, hız veya bellek sınırlamalarının (çağrı yığını boyutu gibi) göz ardı edilebilir. Sıralama, bunun ötesinde test edilmediği için 1000000 limitinin sadece bilgi verici olduğu için kabul ediyorum. Bu arada, 70 baytlık çözümünüz mükemmel bir şekilde gayet iyi ve kod-golf mücadelesi için 93 baytlık versiyondan daha alakalı.
Arnauld


4

Python 2 , 110 105 103 101 bayt

@Lynn sayesinde -2 bayt

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)

Çevrimiçi deneyin!


Python 2 , 116 112 105 bayt

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

Çevrimiçi deneyin!


1
…n*(n&~16==3)or…2 bayt kaydeder.
Lynn

57991 sys.setrecursionlimit (20000) girişi için
RosLuP

4

MATL , 22 21 bayt

1 byte'ı kaldırmak için @Giuseppe'e teşekkürler !

`tZp?Eq}tYfX>-]tI19h-

Çevrimiçi deneyin! Veya tüm test durumlarını doğrulayın .

açıklama

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

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

Muhtemelen burada bazı golf oyunlarını özlüyorum, bu benim haskell golf'teki ilk denemem.


Merhaba ve siteye hoşgeldiniz. Desen korumaları için yeni satırlara ve boşluklara ihtiyacınız yoktur. Ayrıca çoğu zaman da kullanabilirsiniz 1>0, Trueancak genellikle bir ödev kullanmak daha iyi olabilir c<-z n.
Buğday Sihirbazı

1
[x|x<-[b-1,b-2..1],rem b x==0]Ayrıca reverse[x|x<-[1..(b-1)],brem kısa x==0].
Buğday Sihirbazı

2
Ve son bir şey, haskell golf oynamaktan bahsetmek istersen, bize Of Monads and Men'da katılabilirsin .
Buğday Sihirbazı

3

Neim , 17 16 bayt

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

Açıklama:

ͻ                   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

Çevrimiçi deneyin!


3

R + numaraları , 102 99 bayt

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

Çevrimiçi deneyin!

R kısa yapılı üniteler için bilinmemektedir ve hatta paketler buna uygundur!


3

Java 8, 140 135 134 94 bayt

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

Özyinelemeli Java 7 yöntemi döngü ile Java 8 lambda dönüştürme -5 bayt.
-1 için bayt örtük sayesinde @Arnauld 'ın JavaScript cevap değiştirerek n!=3&n!=19ve return n;karşı 57%n>0ve return n%38;.
İki döngüyü bir şekilde birleştirmek ve nbir asal olup olmadığını kontrol etmek ve aynı zamanda en büyük asal faktörü elde etmek mümkün olmalı , ancak bunu henüz çözemiyorum. Yani bu şimdilik ilk versiyon olacak.
-40 @Nevay sayesinde kırbaç bayt, yapamadığım şeyi yaparak: primerleri ve en büyük primer faktörünü bir kerede kontrol etmek için döngüler birleştirildi.

Açıklama:

Burada deneyin ( 9999991 saniyenin altında bile çalışır ).

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
Bir C # polyglot olmanın kısa 1 karakter :(
Ian H.

@IanH. Hehe, evet, genellikle böyle olur: n=>yerine n->. Ve bazen küçük / büyük harfli aramalar. ;)
Kevin Cruijssen

1
94 bayt: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 Teşekkürler! Sadece döngüleri birleştirmenin mümkün olabileceğini biliyordum ama çözemedim. Bir sürü kırk bayt size teşekkür etti!
Kevin Cruijssen

3

Bash, 73 bayt

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

Çevrimiçi deneyin! TIO üzerinde çalışmak için hafifçe değiştirildi.

Yinelemeli kullanarak kendi komut dosyasını çağırır $0, o kadar koştu olmalı çünkü TIO iş yapmaz./filename.sh . Girişi komut satırı argümanı olarak kabul eder.

@ Arnauld'un JS cevabıyla aynı modülü kullanır .

Test Kılıfları

$ 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 bayt

.W!/P57H?P_ZtyZ-ZeP

Tüm test durumlarını doğrulayın!

Kabuk cevap (2 bayt kaydetmek için bana ilham ,3 19için P57).

Bu nasıl çalışır

.W! / P57H? P_ZtyZ-ZeP - Tam program.

.W - İşlevsel A (değer) truthy olsa da, değer = B (değer). Son değeri döndürür.
    P57 - 57'nin asal çarpanları ([3, 19]).
   / H - Geçerli değerin oluşumunu say.
  ! - Mantıksal DEĞİL. 0 -> Truthy, başka bir şey -> Falsy.
        ? P_Z - Geçerli değer asal ise, o zaman:
            tyZ - Geçerli değeri iki katına düşürür.
               -ZeP - Başka, Geçerli değerin maksimum asal çarpanını kendisinden çıkarın.
                     - Örtülü yazdırın.

1

PowerShell , 150 126 bayt

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

Çevrimiçi deneyin! (uyarı: daha büyük sayılar için yavaş)

Yinelemeli yöntem PowerShell'de herhangi bir ana faktörlendirme yerleşik yok, bu yüzden bu, Prime Factors Buddies konusundaki cevabımın kodunu ödünç alıyor .

İlki bizim fordöngümüz. Kurulum $ngiriş değeri olarak ayarlanır ve koşullu döngü 57%$nsıfır olmayan sürece devam eder ( bu numara için Arnauld sayesinde ). Döngünün içinde ilk önce $a(olarak ayarlanmış $n) ana faktörlerin bir listesini alırız . Bu, Prime Factors Buddies'ten alınan koddur. Girdi $azaten asal ise, bu $adaha sonra geri dönecektir . Bu (potansiyel olarak sadece $a) içine konur $d.

Sırada bir if/ elseşartlı var. İçin ifparçası, biz kontrol $nolduğunu -in $d. Eğer öyleyse, bu $nasal olduğu anlamına gelir , öyleyse alırız $n=2*$n-1veya $n+=$n-1. Aksi halde, bileşiktir, bu yüzden en büyük ana faktörü bulmalıyız. Araçlarla Bu bizim sonuncusu almak gerekir [-1]ait $dve o çıkarma $nile $n-=. Bu işe yarıyor, çünkü biz birbirimizden ayrılıyoruz 2ve bu yüzden son elemanı $dzaten en büyüğü olacak.

Döngü işini bitirdikten sonra $n%38, boru hattına (tekrar, Arnauld sayesinde) yerleştiririz ve çıktısı örtüktür.


1

APL (Dyalog Unicode) , 113 90 59 bayt

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

Çevrimiçi deneyin!

TIO, ~ 3200'e kadar olan değerlerle çalışır. Bilgisayarımda son test durumu için test edildi. TIO'da test etmek için, sadece f valuekodun altına ekleyin . Artık geçerli değil, @ Adám sayesinde primallik kontrol algoritmamın gerçekten kötü olduğunu ve yerine yeni bir ürün verdiğimi belirttiğim için; Ayrıca 23 bayt kaydetme için.

Bayt sayısını düzeltmek için düzenlenir.

Nasıl çalışır

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

Aksiyom, 93 bayt

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)

Ölçek:

(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

68 bayt işlevi olacaktı

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

ama n = 57991 için (eğer iyi hatırlarsam), ayrılmış yığın alanından çıkar.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.