Prime Factoral Kökleri


14

Dijital köklerden esinlenen, bir sayının asal faktörel kökü, bir sayının asal çarpanlarını aldığınız, bunları topladığınız ve bir asal sayı ile bitene kadar devam eden sonuç üzerinde işlemi tekrarladığınız sayıdır ( kendini tek asal faktörü olan ve dolayısıyla kendi asal faktöriyel kökü olan). 4'ün ana faktöriyel kökü 2'dir, 2 * 2 = 2 + 2'dir ve bu 1'den büyük bir tamsayının tek birincil olmayan faktöriyel köküdür (bu, birincil faktörleri olmadığı için başka bir özel durumdur). Ana faktöriyel köklerin oluşturduğu OEIS dizisi A029908'dir .

Örneğin, 24'ün ana faktöriyel kökü:

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.  

Senin görevin:

Girdi tamsayısının asal çarpan kökünü bulan bir program veya işlev yazın.

Giriş:

Herhangi bir makul yöntemle girilen bir tamsayı, 2 ile dilinizin destekleyeceği en büyük tam sayı (dahil). Özellikle makul olmayan bir şekilde maksimum tamsayı boyutuna sahip bir dil seçilmesine izin verilmez (ve bu standart boşlukları da ihlal eder )

Çıktı:

Bir tamsayı, girdinin ana faktöriyel kökü.

Test Durumları:

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

puanlama:

Bu , bayt kazanır en düşük puan!


3
4Bir istisna olduğu ve bir cevabı test ederken unutması kolay olduğu için test senaryolarını ekleyebilir misiniz ?
scottinet

1 için 1 çıktı almamız gerekiyor mu?
zamirim

@someone bağlı OEIS dizisine göre, 1 için 0 çıktı
scottinet

2
@someone Zorluk girdinin en az 2 olacağını belirtir.
Martin Ender

@someone Bir süreliğine kapalı olduğum için üzgünüm. Martin'in dediği gibi, meydan okuma özellikle girdinin birden büyük olacağını ve dolayısıyla girdi 1 olduğunda davranış tanımsız olduğunu söylüyor.
Gryphon

Yanıtlar:



14

Haskell , 61 bayt

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

Çevrimiçi deneyin!

açıklama

until=<<((==)=<<)bir fonksiyon alır fve xbir düzeltme noktasına ulaşılana kadar girişe uygular , yani f xeşittir x. primeFactorsbir sayının asal çarpanları listesini döndürür, sumbir sayılar listesinin toplamını verir.

Ama bekleyin, neden bu until=<<((==)=<<) kadar tuhaf görünüyor?

Varsa f=sum.primeFactors, daha doğal bir tanım olacaktır until(\x->f x==x)f, çünkü untilyüklem (boole döndüren bir işlev) alır, aynı giriş ve dönüş türüne (örneğin Int -> Int) ve bu tür değere sahip bir işlev alır ve daha sonra işlevi yüklem yerine getirilene kadar değeri.

until(\x->f x==x)file aynıdır until(\x->(==)(f x)x)fve sahip olduğu g (h x) xgibi (g=<<h)x, elde ettiğimizle aynıdır until(\x->((==)=<<f)x)f. Eta dönüşümünden sonra , bu olur until((==)=<<f)f. Şimdi tedavi Ama eğer (==)=<<uygulanan bir fonksiyonu olarak f, biz görebilirsiniz until(((==)=<<)f)fformun yine g (h x) xbirlikte g=until, h=((==)=<<)ve x=fbunun için tekrar yazılabilir, böylece (until=<<((==)=<<))f. $Dış parantezlerden kurtulmak için operatörün kullanılması ve ikame file değiştirilmesi sum.primeFactors, çözeltiyi yukarıdan verir.


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

2
@icrieverytim Bir açıklama ekledim. Bu büyücünün nasıl çalıştığı hakkında başka sorularınız varsa Haskell sohbet odasında soru sormaktan çekinmeyin .
Laikoni



4

Python 2 , 84 bayt

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

Çevrimiçi deneyin!


Bu oldukça aptalca bir soru olabilir, ama nasıl f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))çalışır? Ben hiç Python (çoğunlukla Java ve C #) programlanmış, bu yüzden bu fonksiyonun sonucunun ne olduğundan emin değilim. Bu işlev girişi değiştirir nve daha sonra döndürür mü yoksa n>1and(n%d and f(n,d+1)or d+f(n/d))0 veya 1, 0 veya nbaşka bir şey olan bir boole benzer mi? Bunun bir portunun Java / C #'da nasıl göründüğünü görselleştirmeye çalışıyorum, ancak genel olarak böyle Python lambdaları gerçekten anlamadım çünkü yapamıyorum.
Kevin Cruijssen

1
@KevinCruijssen buna eşdeğerdir n>1 ? (n%d!=0 ? f(n, d+1) : d+f(n/d)) : n>1. Genel olarak x and yeşdeğerdir x ? y : x. çoğu durumda x and y or zeşdeğerdir x ? y : z.
ovs

1
@KevinCruijssen bir Java portu gibi bir şey olurdu f=(n,d=2)->n>1?n%d>0?f(n,d+1):d+f(n/d):0.
ovs

Ah tamam. Açıklama için teşekkürler, şimdi çok daha mantıklı. Ve hatırlamak x and yvarlık x ? y : xsıra JavaScript dan. Teşekkürler!
Kevin Cruijssen

4

Java 8, 175 144 142 141 bayt

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

@Nevay sayesinde -1 bayt .

Bazı golf dillerindeki tek baytlardan farklı olarak, Java, prime kontroller, asal faktörler, rakam toplamları ve benzeri için oldukça ayrıntılıdır, bu yüzden 200'den azı çok düşkün değildir.
Büyük olasılıkla döngüler birleştirilerek ve rakam toplamı için ayrı bir özyinelemeli yöntem kullanılmadan golf yapılabilir .

Açıklama:

Burada deneyin.

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, bu bir golf diliymiş gibi ayrıntılı bir açıklama yazmaktan rahatsız olduğu için.
zamirim

@someone Teşekkürler! Birisi bana geçmişte bir kez Java cevabımla ilgili bir açıklama sorduğundan, bunları tüm cevaplarıma ekledim. :)
Kevin Cruijssen

i,t=n,xPython,
haha'ya

@ETHproductions Hehe, çok kötü hala lider eklemek zorunda int (Python aksine). ;)
Kevin Cruijssen

Bunun i++<nyerine kullanabilirsiniz ++i<=n.
Nevay


3

Retina , 30 bayt

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

Giriş ve çıkış tekli .

Çevrimiçi deneyin! (Kolaylık sağlamak için ondalık / tekli dönüşüm gerçekleştirir.)

açıklama

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

{Tam geçiş sabit bir noktaya ulaşılıncaya kadar, yani dize değiştirmek için başarısız olmasına kadar talimatı Retina bir döngüde tüm programı çalıştırmak için. Sonuç olarak, programın kendisi mevcut değerin asal faktörlerini toplamanın bir adımını hesaplar.

Bu aşamanın kendisi, girdinin birincil çarpanlarına ayırmasını hesaplar. Bu şuna +benzer, {ancak dizeyi değiştirmeyi bırakana kadar yalnızca bu aşamayı döngüler. Normal ifade 1, aynı alt dizeyi (yani faktörü) art arda eşleştirerek son işlemlerini eşleştirmeye çalışır . Bunun yapılma şekli, ileri referans nedeniyle biraz kıvrıktır \1. İlk yinelemede, grup 1henüz hiçbir şey yakalamadı, bu nedenle \1koşulsuz başarısız oluyor. Bunun yerine, \b11+?\Bçalışmanın başında başlayan, en az iki 1saniye içeren ve tüm çalışmayı kapsamadığından mümkün olan en küçük alt dize olan eşleşmemiz gerekir . Sonraki yinelemeler nedeniyle bu alternatifi bir daha kullanamazsınız \b. Diğer tüm yinelemelerde,\1, yani aynı alt dizeyi tekrar tekrar. Bu işlem, $yakaladığımız ve gerçek bölen olduğundan emin olmak için dizenin sonuna ( ) tam olarak vurmak zorundadır . Bu biraz zor yaklaşımı kullanmanın yararı, grubun 1tam olarak n / d kez, yani böleni böldükten sonra kalanın d olmasıdır .

Bu eşleşmeyi bir ayırma ve n / d (ile kopyaları ekleyen , grup tarafından yapılan yakalama sayısı olan ) d ( $1) ile değiştiriyoruz .;$#1$*$#11$#11

Bu işlem, dizedeki son çalıştırma bir asal olduktan sonra durur, çünkü normal ifade artık eşleşmez.

;

Asalları toplamak için tek yapmamız gereken tüm ayırıcıları çıkarmaktır.



2

Aslında 7 bayt

⌠w♂πΣ⌡Y

Çevrimiçi deneyin!

Açıklama:

⌠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 + prakma , 53 bayt

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

Çevrimiçi deneyin! (R-keman)

R bir yerleşik asal çarpanları, ancak çok sayıda paketleri (yok pracma, numbersben bir konuma kısa bir aldı, böylece, vs.) yapmak.


1

Jöle , 6 bayt

Bu cevap, Jelly'in birçok ana çarpanlarına ayırma yerleşiklerinden birini kullanır ve hızlıdır repeat until the results are no longer unique.

ÆfSµÐL

Çevrimiçi deneyin!


Bence geride kaldın ama yaklaşımın göz önüne alındığında, bu cevabın işe
yarayıp yaramadığından

@cairdcoinheringaahing Cevabını (veya daha doğrusu Python eşdeğerini) 1'den 100000'e kadar kontrol ettim ve işe yarıyor. Sanırım 1gerekli adım sayısının eşit olduğu tek durum n(ki bu iyi; 1sadece bir kez çalıştırmamız gerekiyor) ve adım sayısının daha fazla olduğu herhangi bir durum görünmüyor n(yani herhangi bir karşı örnek yok gibi görünüyor). Ah iyi, ben fazla oldum: D
Sherlock9

Şey, olur. Her ne kadar bu kodu gördüğümde düşündüğüm tam olarak aynı kod olduğu için +1
caird coinheringaahing

N'nin asal faktörlerinin toplamı her zaman n'den küçük veya ona eşittir, bu da n'nin her zaman fazlasıyla yeterli olduğunu kanıtlamayı oldukça kolaylaştırır.
Chris

1

MATL , 6 bayt

Scottinet'in gerekenden daha fazla döngü yapma fikrini kullanır . Ayrıca Shaggy'ye bir hatayı işaret ettiği için teşekkürler , şimdi düzeltildi.

t:"Yfs

Çevrimiçi deneyin!

açıklama

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

Bu başarısız gibi görünüyor 4.
Shaggy

@Shaggy Teşekkürler! Bunun üzerinde çalışıyor
Luis Mendo

@Shaggy Çözüldü
Luis Mendo

1

PowerShell , 124 bayt

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

Çevrimiçi deneyin!

PowerShell'de herhangi bir birincil çarpanlara ayırma yerleşik yoktur, bu nedenle çarpanlara ayırma hesaplamaları yapmak için Prime Factors Buddies (en üst satır) üzerindeki cevabımdaki kodu kullanır .

İkinci satır, bu programın etidir. Biz girdi alan $argsiçine $x, o forkadar döngü $lolduğunu -not equal için $x. (Birinci tekrarda, $lbir $nullve $xbir kez, en az bu yüzden olacak döngü, bir tam sayıdır).

Döngünün içinde, döngünün $l = $xsonuna ulaşıp çarpmadığımızı belirlemek için ayarladık . Sonra faktörlerini almak $xile f($x), -joinbirlikte olanlar +ve |iexonları (kısaca Invoke-Expressionve benzeri eval). Geri depolanır $x. Böylece, bir araya toplanan asal çarpanlaştırmanın kendi başına olduğu "son" a ulaştık. Sonra, sadece $xboru hattına yerleştiriyoruz ve çıktı örtük.


0

Mathematica, 35 bayt

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

Çevrimiçi deneyin!

(Matematik desteklemiyor Tr. Manuel olarak uygulamak zorundayım)


4
1##&için kısa Timesve FixedPointneredeyse her zaman kısaltılabilir //.:#//.x_:>Tr[1##&@@@FactorInteger@x]&
Martin Ender

@MartinEnder Teşekkürler! Zaten bilmeliydim Times, ama FixedPointhileyi bilmiyordum .
user202729

Kodunuz Mathematica dilinde yazılmıştır. Bu bir Matematik işlevi değildir. Dil adını Mathematica veya Tr olarak Toplam olarak değiştirmelisiniz
J42161217

@ {hiç kimse} Üzgünüz, dil adı (Matematik) bir hataydı. {i cri evritime} bunu düzeltti.
user202729


0

Ruby , 63 bayt

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

Çevrimiçi deneyin!

Prime # prime_division öğesinden-rprime yararlanmak için bayrağı +6 bayt kullanır .

prime_divisionçiftlerini döndürür [prime, exponent](örneğin, 24 için, [2, 2, 2, 3]bu nedenle veren faktörler vardır [[2, 3], [3, 1]]), bu nedenle her adımda bu çiftlerin üyelerini birlikte çarparız ve sonuçları toplarız.


0

Javascript (ES6), 63 bayt

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 bayt

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

Port @ovs 'un şaşırtıcı Python 2 cevabı .

Açıklama:

Burada deneyin.

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