Pseudofactorial


39

Bazen matematik problemlerinde veya bilmecelerde ortaya çıkan oldukça meraklı bir sayı var. Sahtecilik (N), 1'den N'e kadar olan sayıların en az (yani en düşük) ortak katıdır; Başka bir deyişle, 1'den N'e kadar olan tüm sayıları faktör olarak gösteren en düşük sayıdır.

Mesela sözde (7) = 3 * 4 * 5 * 7, 7 ile aynı! bunun dışında 2 ve 6'nın kaldırılmış olması, çünkü başka terimler içerdiklerinde.

Sahte hesap makinesini (N) hesaplamak için bir program yaz ve her zaman olduğu gibi en kısa kod kazanır.

İşte kullanımınız için kısa bir liste. OEIS'te A003418 uyarınca daha fazla test vakası bulunabilir .

Çarpınım:

  1. 1
  2. 2
  3. 6
  4. 24
  5. 120
  6. 720
  7. 5040

Pseudofactorial:

  1. 1
  2. 2
  3. 6
  4. 12
  5. 60
  6. 60
  7. 420

6
Nedenini anladığımdan 2ve 6katları listesinden çıkarıldığından emin değilim . Lütfen kuralları netleştirir misin?
Maltysen

2
@Mattysen, psuedofactorial (N), 1'den N'e kadar olan sayıları faktör olarak gösteren en küçük sayıdır (bu sayılardan en az kullanılanı). Teknik tanım budur, ancak benim yazım tarzım bir faktöre benzer olduğunu düşündüren bir şeydi.
Tony Ruth,


4
Programlama Bulmacaları ve Kod Golf'üne Hoş Geldiniz! Bu güzel bir ilk meydan okuma!
Alex A. 0

1
İlk meydan okumanız HNQ'nun zirvesine geçti. Güzel!
Daniel M.

Yanıtlar:




8

C (x86 ile), 52 bayt

d(n,k,b,t){for(b=k=1;b;++k)for(t=n,b=0;t;b+=k%t--);}

Sayıları 1'den yukarı doğru kontrol eder. Her sayı için, onu n'den 1'e kadar olan sayılara böler ve kalanları toplar. Toplam 0 olduğunda durur.

Kullanımı:

main()
{
    printf("%d\n", d(7)); // outputs 420
}

Nasıl bir değer döndürdüğü açık değildir ( returnifade yoktur ).

X86 çağrı kuralı, işlevin eaxsicil içindeki değerini döndürmesi gerektiğini söyler . Elverişli olarak, bölme talimatı idivgiriş yapmayı bekler ve eaxsonucu eax(bölüm) ve edx(kalan) olarak verir. Son yineleme böler ktarafından 1, bu nedenle eaxzaman işlev çıkar sağ değerini içerir.

Bu sadece optimizasyonlarda çalışır (hata ayıklama modunda çıktı verir 421).


N, k, b ve t türlerini bildirmemekle nasıl kurtulursunuz?
Tony Ruth

C varsayılan int kuralına sahiptir - tüm atlanan türler intvarsayılan olarak (dönüş değeri de dahil). "Eski stil" sözdizimi kullanılarak bildirilirlerse, işlev argümanları için çalışır. Açıkça tanımlanmış tiplere sahip ilan olacaktırint d(n,k,b,t) int n,k,b,t; {...}
anatolyg

Çağıran bir sözleşmeden faydalanıyorsanız, bu gerçekten sadece "C" yerine "C (cdecl)" olarak işaretlenmelidir
Steve Cox

@SteveCox Her ikisi de cdeclve stdcallaynı değeri geri dönüş değeri için kullan, bu yüzden sanırım x86yeterlidir
anatolyg

7

Haskell, 20 bayt

f x=foldr1 lcm[1..x]

Kullanım örneği: map f [1..7]-> [1,2,6,12,60,60,420].

lcmHaskell numara.


6

Python + SymPy, 45 bayt

import sympy
lambda n:sympy.lcm(range(1,n+1))

Oldukça kendini açıklayıcı.


Python 2, 57 54 bayt

i=r=input();exec't=r\nwhile r%i:r+=t\ni-=1;'*r;print r

İdeone üzerinde test et .

Nasıl çalışır

Giriş, i ve r değişkenlerinde saklanır .

execAşağıdaki kodu r kere çalıştırır .

t=r
while r%i:r+=t
i-=1

Da i arasında değişir r için 1 , biz ilk katma değer r (saklanan t için gerekli gibi) birçok kez , r bir çoklu oluşturmak için kendini i . Sonuç, açıkçası, t'nin bir çarpımıdır .

Bu nedenle r'nin son değeri, [1, ..., n] aralığında tüm tam sayıların bir katıdır , burada n , girdidir.


1
Üçüncü taraf kütüphanelerini veya execpüf noktalarını kullanmadan , 78 baytlık bir çözüm var: from fractions import*;lambda n:reduce(lambda x,y:x*y/gcd(x,y),range(1,n+1),1) Bunu kullanan gerçeği lcm(x,y) = x*y/gcd(x,y).
Bakuriu,

6

Python, 46 bayt

g=lambda n,c=0:n<1or(c%n<1)*c or g(n,c+g(n-1))

Çoklu arıyorsunuz carasında g(n-1)doğrudan. Daha önce, bu yöntemin hatalı bir şekilde 0'ı bir şeylerin çarpımı olarak bulacağını düşünmüştüm , fakat orkısa devre yapıyor ya (c%n<1)*cda c==0atlıyor çünkü 0, Falsey.


50 bayt:

g=lambda n,i=1:n<1or(i*n%g(n-1)<1)*i*n or g(n,i+1)

Gibi Dennis'in çözümü , ancak bir özyinelemeli fonksiyon olarak. Bilgisayarlı olması g(n-1)küçük katına için, görünüyor i*nait nolduğu da bir çoklu bulunuyor g(n-1). Gerçekten yavaş.

Dennis'e 4 baytlık nyerine , katlarına bakarak teşekkürler g(n-1).


5

J, 9 bayt

[:*./1+i.

Dümdüz ileri yaklaşım. Sayı aralığını oluşturur [0, ..., n-1], ardından her birine birer tane ekler ve LCM kullanarak azaltın.

kullanım

   f =: [:*./1+i.
   f 7
420


4

Mathematica, 13 bayt

LCM@@Range@#&

Bu sadece besteleme LCMve Rangebirlikte eşdeğer değil @*mi?
Maltysen,

1
LCMöğeye geçirilebilir olan bir listesi üzerinde çalışır Rangebu sadece LCM (dönmek anlamına X için) x ile, 1 ila n . Ayrıca, &isimsiz fonksiyonu kapatacak bir eksik var. LCM@@Range@#&13 bayt gibi bir şey işe yarayacak.
mil



3

Octave, 27 bayt

@(x)lcm(1,num2cell(1:x){:})

Olarak çağrılabilecek adsız bir işlev oluşturur ans(N).

Çevrimiçi Demo

açıklama

Bu çözüm, 1ve x( 1:x) arasındaki tüm sayıların bir listesini oluşturur , bunları ile bir hücre dizisine dönüştürür num2cell. Daha sonra {:}endeksleme, lcmen az ortak çarpıyı hesaplamak için çoklu giriş argümanlarına iletilen virgülle ayrılmış bir liste oluşturur . 1 her zaman ilk argüman olarak iletilir, lcmçünkü lcmdaima en az iki girdi argümanına ihtiyaç duyar.


1
Öyleyse lcmOctave, 2'den fazla girişi kabul eder! İlginç
Luis Mendo

@LuisMendo Yup 2+
Suever

3

MATLAB, 49 bayt

@(x)find(~any(bsxfun(@rem,1:prod(1:x),(1:x)')),1)

+1 içinbsxfun
kusur

3

Perl 6 , 13 bayt

{[lcm] 1..$_}

Girdiden 1'e (dahil) kadar bir Aralık oluşturan Anonim kod bloğu ve ardından bunu azaltır &infix:<lcm>.

Örnek:

#! /usr/bin/env perl6
use v6.c;

my &postfix:<p!> = {[lcm] 1..$_}

say 1p!; # 1
say 2p!; # 2
say 3p!; # 6
say 4p!; # 12
say 5p!; # 60
say 6p!; # 60
say 7p!; # 420

say 10000p!; # 5793339670287642968692270879...
# the result from this is 4349 digits long


2

JavaScript (ES6), 92 88 80 74 69 bayt:

Teşekkürler @ConorOBrien ve @Neil

y=>(g=(a,b)=>b?g(b,a%b):a,[...Array(y)].map((_,i)=>y=y*++i/g(y,i)),y)

b?g(b,a%b):abir bayt kaydeder.
Neil

y*++i/g(y,i)biraz daha bayt kaydeder.
Neil

1

05AB1E, 20 bayt

Lpvyi¹LÒN>¢àN>*ˆ}}¯P

açıklama

Lpv                    # for each item in isprime(range(1,N)): N=7 -> [0,1,1,0,1,0,1]
   yi                  # if prime
     ¹LÒN>¢            # count occurrences of the prime 
                         in the prime-factorization of range(1,N):
                         p=2 -> [0,1,0,2,0,1,0]
           àN>*ˆ       # add max occurrence of that prime multiplied by the prime 
                         to global array: N=7 -> [4,3,5,7]
                }}     # end if/loop
                  ¯P   # get product of global array

Çevrimiçi deneyin


1

Minkolang 0.15 , 12 bayt

Ben iki 12-bayt çözümleri ve ikisini de dahil ettik.

1n[i1+4$M]N.

Burada dene!

açıklama

1               Push 1
 n              Take number from input
  [             For loop that repeats n times
   i1+          Push loop counter + 1
      4$M       Pop b, a and push lcm(a,b)
         ]      Close for loop
          N.    Output as number and stop.

Ne kadar basit olursa olsun.


11nLd[4$M]N.

Burada dene!

açıklama

11              Push two 1s
  n             Take number from input
   L            Pop b, a and push range from a to b, inclusive
    d           Duplicate top of stack (n)
     [4$M]      Pop b, a and push lcm(a,b), n times
          N.    Output as number and stop.

Bundan üçüncü bir çözüm elde edilebilir: a'yı kaldırın 1ve dakımdan sonra bir tane ekleyin d. Her iki durumda da, fazladan bir numara gereklidir çünkü for döngüsü bir çok defa çalıştırılır ve bir kez daha az çalışmasını sağlamak iki bayt alır ( 1-hemen önce [).


1

Yakut, 25 bayt

g=->n{(1..n).reduce :lcm}

Yakut, 25 bayt

g=->n{n<1?1:a[n-1].lcm n}

1
Merhaba, PPCG'ye hoş geldiniz! Harika ilk mesaj! İşlevinizi adlandırmanız gerekmez, böylece kaldırabilirsiniz g=.
NoOneIsHere

Anonim işlevlere izin verilir.
Outgolfer Erik,

1

GameMaker Dili, 60 bayt

for(b=k=1;b;++k){b=0for(t=argument0;t;b+=k mod t--)}return k

Anadolunun cevabının mantığına dayanarak.


1

PHP, 61 52 48 bayt

@ user59178, döngüleri birleştirerek 4 byte sayesinde 9 byte kaydetti.

PHP'de özyineleme, functionanahtar kelime nedeniyle hantaldır ; bu yüzden yineleme kullanıyorum.
Ve "küçük" birkaç numara ile şimdi bile Arnauld'un JS'sini yendim .

while(++$k%++$i?$i>$argv[1]?0:$i=1:$k--);echo$k;

komut satırı argümanından girdi alır. İle koş -r.

Yıkmak

while(++$k%++$i?    # loop $i up; if it does not divide $k
    $i>$argv[1]?0       # break if $i (smallest non-divisor of $k) is larger than input
    :$i=1               # while not, reset $i and continue loop with incremented $k
    :$k--);         # undo increment while $i divides $k
echo$k;         # print $k

ungolfed

Bu aslında bir arada iki döngü:

while($i<=$argv[1]) # loop while $i (smallest non-divisor of $k) is not larger than input
    for($k++,       # loop $k up from 1
        $i=0;$k%++$i<1;);   # loop $i up from 1 while it divides $k
echo$k;             # print $k

Kopyalanmış: Not yinelenen benim cevap


1

AWK, 42 bayt

{for(x=n=1;n<=$1;)if(x%n++){x++;n=1}$0=x}1

Komut satırı kullanımı:

awk '{for(x=n=2;n<=$1;)if(x%n++){x++;n=2}$0=x}1' <<< NUM

Bir AWKçözüm görmedim ve sorunun bir kopyası dün gönderildi. Bu yüzden bunu bir araya getireceğimi düşündüm. Kutum için çözme yavaş 19ya da daha büyük, ama işe yarıyor.



0

Pyke, 3 bayt, rekabetçi olmayan

S.L

Burada dene!

S   - range(1, input+1)
 .L - lowest_common_multiple(^)

0

Hoon , 67 bayt

|*
*
(roll (gulf 1 +<) |=({a/@ b/_1} (div (mul a b) d:(egcd a b))))

Listeyi oluşturun, listeyi [1..n]lcm ile katlayın. Ne yazık ki, Hoon stdlib kullanabileceğim önceden yapılmış bir şeye sahip değil: /



0

QBIC , 35 32 bayt

Bu beni buraya getirdi.

:{p=0[a|~q%b|p=1]]~p=0|_Xq\q=q+1

Açıklama:

:        Get cmd line param as number 'a'
{        Start an infinite DO loop
p=0      Sets a flag that shows if divisions failed
[a|      FOR (b=1; b<=a; b++)
~q%b     IF 'q' (which starts at 1 in QBIC) is not cleanly divisible by 'b'
|p=1     THEN Set the flag
]]   Close the FOR loop and the IF, leave the DO open
~p=0     IF 'q' didn't get flagged
|_Xq     THEN quit, printing 'q'
\q=q+1   ELSE raise 'q', redo
         [DO Loop implicitly closed by QBIC]

İşte test durur bir versiyonu qzaman btemiz bir şekilde bölmek değil. Ayrıca, test sırası b'S karşı qyüksek varsayımına tersine çevrilmiştir b(take ler tarafından sert bölümlere ayırmayı olacak' 2, 3, 4: eğer örneğin %2=0, %4olabilir !0... tersi çok değil Vice.).

:{p=0[a,2,-1|~q%b|p=1┘b=2]]~p=0|_Xq\q=q+1



0

8 , 23 bayt

kod

1 ' lcm rot 2 swap loop

Bu kod, TOS'ta ortaya çıkan sahte belgeyi bırakır

Kullanım ve örnek

ok> 7 1 ' lcm rot 2 swap loop .
420

Veya daha açık bir şekilde

ok> : pseudofact 1 ' n:lcm rot 2 swap loop ;

ok> 7 pseudofact .
420
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.