疑似要因


39

数学の問題や謎に時々現れる奇妙な数字があります。pseudofactorial(N)は、1からNまでの数の最小(つまり最小)公倍数です。つまり、1からNまでのすべての数値を要素として持つ最も低い数値です。

例えばpseudofactorial(7)= 3 * 4 * 5 * 7、これは7と同じです!ただし、2と6は他の用語に含まれているため削除されています。

pseudofactorial(N)を計算するプログラムを作成すると、いつものように、最短のコードが優先されます。

以下は、使用するための短いリストです。A003418の下のOEISで、より多くのテストケースを見つけることができます。

階乗:

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

疑似要因:

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

6
私はなぜ理解していない26倍数のリストから削除されました。ルールを明確にしてください。
マルティセン

2
@ Mattysen、psuedofactorial(N)は、1からNまでの数値を要素として持つ最小の数値です(これらの数値の最小公倍数)。それは技術的な定義ですが、私が書いた方法は、それが階乗に似ていることをいくらか示唆しています。
トニールース


4
プログラミングパズルとコードゴルフへようこそ!これは素晴らしい最初の挑戦です!
アレックスA.

1
最初の課題は、HNQの頂点に達しました。いいね!
ダニエルM.

回答:




8

C(x86を使用)、52バイト

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

1以上の数字をチェックします。各数値について、nから1までのすべての数値で除算し、残りを合計します。合計が0になると停止します。

使用法:

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

どのように値を返すかは明らかではありません(returnステートメントはありません)。

x86の呼び出し規約では、関数はその値をeaxレジスタに返す必要があると述べています。便利なことに、除算命令idivはでの入力を予期しeax、結果をeax(quotient)およびedx(remainder)で出力します。最後の反復はで除算kされる1ためeax、関数が終了するときに正しい値が含まれます。

これは、最適化でのみ機能します(デバッグモードでは、出力します421)。


n、k、b、およびtのタイプを宣言しないことで、どのように逃げますか?
トニールース

Cにはdefault-intルールがあります-省略された型はすべてintデフォルトです(戻り値を含む)。いわゆる「古いスタイル」の構文を使用して宣言されている場合、関数の引数に対して機能します。明示的に定義されたタイプの宣言は次のようになりますint d(n,k,b,t) int n,k,b,t; {...}
anatolyg

呼び出し規約を利用している場合、これは実際には「C」ではなく「C(cdecl)」とマークする必要があります
スティーブコックス

@SteveCox両方cdeclstdcall戻り値に同じメソッドを使用するので、x86十分だと思う
アナトリグ

7

Haskell、20バイト

f x=foldr1 lcm[1..x]

使用例:map f [1..7]- > [1,2,6,12,60,60,420]

lcmHaskell のトリック。


6

Python + SymPy、45バイト

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

かなり自明です。


パイソン2、57の 54バイト

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

Ideoneでテストします。

使い方

入力は変数iおよびrに保存されます。

exec次のコードをr回実行します。

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

ながら私はごとに異なるR1、我々は、の初期値加算R(に格納されているTには、必要に応じて)何度でもRの複数作成すること自体のI。結果は明らかにtの倍数です。

したがって、rの最終値は、範囲[1、...、n]のすべての整数の倍数になります。ここで、nは入力です。


1
サードパーティのライブラリやexecトリックを使用せずに、78バイトのソリューションがあります:from fractions import*;lambda n:reduce(lambda x,y:x*y/gcd(x,y),range(1,n+1),1) という事実を使用しlcm(x,y) = x*y/gcd(x,y)ます。
バクリウ

6

Python、46バイト

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

の倍数cg(n-1)直接探します。私は以前、このメソッドが誤って0を何かの倍数として検出することを知っていましたが、0はFalseyであるため、or短絡または(c%n<1)*cスキップc==0もします。


50バイト:

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

Dennisのソリューションに似ていますが、再帰関数として。計算されたg(n-1)、最小の複数のためのルックスi*nnも、その者の倍数をg(n-1)。本当に遅い。

n代わりにの倍数を見て、4バイトのデニスに感謝しますg(n-1)


5

J、9バイト

[:*./1+i.

簡単なアプローチ。数値の範囲を作成し、[0, ..., n-1]それぞれに1つずつ追加し、LCMを使用してそれを減らします。

使用法

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


4

Mathematica、13バイト

LCM@@Range@#&

これは単に作曲LCMRangewith と同等ではありません@*か?
マルティセン

1
LCM要素単位で渡されるリスト、上の動作RangeこれはちょうどLCM(戻ってくるという意味、X用)のxを 1〜からのn。また、&匿名関数を閉じることになる欠落があります。LCM@@Range@#&13バイトのようなものが動作します。
マイル



3

オクターブ、27バイト

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

として呼び出すことができる匿名関数を作成しますans(N)

オンラインデモ

説明

このソリューションは、1x1:x)の間のすべての数値のリストを作成し、それらをでセル配列に変換しますnum2cell。次に、{:}インデックス付けによりコンマ区切りリストが作成さlcmれ、複数の入力引数として渡されて最小公倍数が計算されます。常に少なくとも2つの入力引数が必要なlcmため、1は常に最初の引数として渡されlcmます。


1
したがってlcm、Octave では2つ以上の入力を受け入れます!興味深い
ルイスメンドー

@LuisMendo Yup 2+
Suever


3

Perl 6、13バイト

{[lcm] 1..$_}

1から入力までの範囲(両端を含む)を作成し、それでを減らす匿名コードブロック&infix:<lcm>

例:

#! /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バイト:

ありがとう@ConorOBrienと@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):aバイトを保存します。
ニール

y*++i/g(y,i)さらにバイトを節約します。
ニール

1

05AB1E、20バイト

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

説明

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

オンラインで試す


1

Minkolang 0.15、12バイト

12バイトのソリューションが2つあり、両方とも含まれています。

1n[i1+4$M]N.

ここで試してみてください!

説明

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.

ほぼ同じくらい簡単です。


11nLd[4$M]N.

ここで試してみてください!

説明

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.

3番目の解決策は、これから導き出すことができます:a 1を削除しd、現在の後にa を追加しdます。どちらの場合も、forループの実行回数が1回を超えているため、余分な数が必要になり、1回実行する回数を2回減らすには(1-直前の[)が必要です。



1

GameMaker言語、60バイト

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

アナトリグの答えの論理に基づいています。


1

PHP、61 52 48バイト

@ user59178のおかげで9バイト、ループをマージして4バイト節約しました。

functionキーワードのおかげで、PHPの再帰はかさばります。繰り返しを使用します。
そして、「小さな」いくつかのトリックで、私は今ArnauldのJSを倒しました

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

コマンドライン引数から入力を受け取ります。で実行し-rます。

壊す

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

食べない

それは実際には1つの2つのループです。

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

注:複製の回答からコピー




0

フーン、67バイト

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

リストを作成し、[1..n]lcmでリストを折ります。残念ながら、Hoon stdlibには、使用できるビルド済みのものがありません:/



0

AWK、42バイト

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

コマンドラインの使用:

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

AWK解決策が見つからず、昨日の質問の複製が昨日投稿されたので、私はこれを一緒に投げると思いました。それ19は私の箱での解決が遅いか大きいですが、うまくいきます。


0

QBIC35 32バイト

これは私をここに連れてきました。

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

説明:

:        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]

これは、きれいに分割されないq場合にテストを停止するバージョンですb。また、テストのためbの反対はq高いことを前提に逆転されたb(テイクsがでにくい除算になります" 234次の場合例えば%2=0%4可能性が!0...その逆ではないので、多くの副。)。

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



0

8番目、23バイト

コード

1 ' lcm rot 2 swap loop

このコードは、TOSに結果の擬似因子を残します

使用法と例

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

またはより明確に

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

ok> 7 pseudofact .
420
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.