この数値は階乗ですか?


38

タスク

入力として自然数が与えられた場合、あなたの仕事は、入力が自然数の階乗であるかどうかに基づいて、真偽値を出力することです。入力番号は常に言語でサポートされている番号の範囲内にあると想定できますが、問題を簡単にするためにネイティブの番号タイプを乱用しないでください。

標準の抜け穴が適用されます。


入力

(タイプIntegerまたは類似の)自然数が与えられます。

事前定義された変数にあると仮定する以外は、任意の方法で入力を取得できます。ファイル、コンソール、ダイアログボックス(prompt)、入力ボックスなどからの読み取りが許可されます。関数の引数としての入力も許可されています!


出力

プログラムは、入力された数値が自然数の階乗であるかどうかに基づいて、真偽値を出力する必要があります。

真実/偽の値がすべての入力に対して一貫していることを確認してください。つまり、1と0のペアを使用してそれぞれ真実と偽の値を示す場合、プログラムは真実の値を持つすべての入力に対して1を出力し、 falsey値を持つ必要があるすべての入力。

出力は、変数に書き込む以外の任意の方法で取得できます。ファイル、コンソール、画面などへの書き込みが許可されています。機能returnも許可されています!

プログラムは、入力に対してエラーを生成してはいけません!


テストケース

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

受賞基準

これはなので、バイト単位の最短コードが勝ちです!


2
言語が{0,1}の範囲の数字のみをサポートしている場合、入力は常に次のようになり1ますか?
eush77

11
@ eush77 ネイティブの数値型を乱用して問題を単純化することは、デフォルトでは禁止されています。
デニス

1
4です!真実ですか?
tuskiomi

質問:なぜI / Oのデフォルトを使用しないのですか?
CalculatorFeline

回答:


37

Brachylog、1バイト

オンラインでお試しください!

説明

は、次の関係をアサートする組み込みです。出力は入力の階乗です。単に出力を設定し、変数入力で成功するかどうかを確認します。


6
@BetaDecayそれは、Prologでの印刷方法だからです(これはtrue.声明であり、そうでtrueはないという事実に関係しています)
致命的です

6
それは些細な解決策ですが、プロローグが機能する方法のために賢いです。
エソランジングフルーツ


17
最初にカスタム言語、次にカスタムエンコード...ゴルフは死んでいます。私たちは、そもそもこれらの楽しい問題の全ポイントを完全に覆しました
アレクサンダー

13
@Alexanderカスタムエンコーディングは、あなたが話している問題とは無関係です。代わりに「既存の」エンコーディングを使用できますが、それでも1バイトのままです。読みにくいだけです。
致命的


19

ゼリー、4バイト

Œ?IE

最短のゼリーの答えではありませんが、かなり効率的です。

オンラインでお試しください!

使い方

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.

2
私たちのコードゴルファーは効率を重視しているためです。
Okx

12
それは1バイトのコストで劇的な複雑さの改善であり、私がそう言うかもしれない場合、組み込みの巧妙な使用です。¯\ _(ツ)_ /¯
デニス

興味深いことに、これは0に対してtrueを返しますが、@ LeakyNunの3バイトの回答は、一般的にはるかに遅いものの、0に対しては正しくfalseを返します。
デッドコード

@Deadcode 0をチェックするには、2バイト余分に必要です。OPの「自然数」の定義に0が含まれているかどうかわからない場合。テストケースは...ない
デニス・

17

ECMAScriptの正規表現、733+ 690+ 158 119 118 (117🐌)バイト

正規表現への私の関心は、4年半以上の非活動の後に活力を取り戻したことがきっかけとなりました。そのため、単項ECMAScript正規表現と一致するより自然な数値セットと関数を探し、正規表現エンジンの改善を再開し、PCREのブラッシュアップも開始しました。

ECMAScript正規表現で数学関数を構築することの異質さに魅了されています。問題はまったく異なる視点からアプローチする必要があり、重要な洞察が得られるまで、それらがまったく解決可能かどうかは不明です。特定の問題を解決可能にするために、どの数学プロパティを使用できるかを見つける際に、より広いネットを強制的にキャストします。

階乗数のマッチングは、2014年に取り組むことすら考慮していなかった問題でした。しかし先月、私はそれができることに気づきました。

他のECMA正規表現の投稿と同様に、警告を出します。ECMAScript正規表現の単項数学問題を解決する方法を学ぶことを強くお勧めします。それは私にとって魅力的な旅であり、自分で試してみたいと思う人、特に数論に興味のある人のためにそれを台無しにしたくありません。1つ1つ解決するための連続したスポイラータグ付きの推奨される問題のリストについては、この以前の投稿参照してください

したがって、高度な単項正規表現の魔法を台無しにしたくない場合は、これ以上読んではいけません。この魔法を自分で理解するためにショットを撮りたい場合は、上記のリンクに記載されているECMAScript正規表現の問題を解決することから始めることを強くお勧めします。

これは私のアイデアでした:

他のほとんどの場合と同様に、この番号セットの一致に関する問題は、ECMAでは通常、ループ内の2つの変化する番号を追跡することができないことです。時にはそれらを多重化することができます(例えば、同じベースのパワーを一義的に追加できます)が、それはそれらの特性に依存します。そのため、入力番号から始めて、それを1に達するまで増分的に増加する配当で割ることはできませんでした(少なくとも私はそう思っていました)。

次に、階乗数の素因数の多様性についていくつかの研究を行い、これには公式があることを学びました。これはおそらくECMA正規表現で実装できるものです。

しばらくそれを煮詰め、その間に他のいくつかの正規表現を構築した後、階乗正規表現を書く作業を始めました。数時間かかりましたが、うまくいきました。追加のボーナスとして、アルゴリズムは一致として逆階乗を返すことができます。それを避けることもできませんでした。ECMAでの実装方法の性質上、他のことを行う前に、逆要因が何であるかを推測する必要があります。

欠点は、このアルゴリズムが非常に長い正規表現を作成したことです...しかし、651バイトの乗算正規表現で使用された技術が必要になったことを嬉しく思いました(別の方法が50バイト正規表現)。このトリックを必要とする問題が発生することを期待していました:両方の同じ基数の累乗である2つの数値をループで操作し、それらを明確に加算し、反復ごとに分離します。

しかし、このアルゴリズムの難しさと長さのために、私は(?*...)それを実装するために(先読みの)分子先読みを使用しました。これはECMAScriptや他の主流の正規表現エンジンではなく、エンジンに実装した機能です。分子の先読み内にキャプチャがなければ、機能的には先読みと同等ですが、キャプチャを使用すると非常に強力になります。エンジンは先読みに戻り、これを使用して、入力の文字を消費せずに(後でテストするために)すべての可能性を循環する値を推測することができます。それらを使用すると、よりクリーンな実装が可能になります。(可変長後読みは、少なくとも分子先読みと同等ですが、後者はより簡単でエレガントな実装を実現する傾向があります。)

したがって、733および690バイトの長さは、実際にはソリューションのECMAScript互換の具体化を表すものではありません。そのアルゴリズムを純粋なECMAScriptに移植することは確かに可能です(その長さはかなり長くなります)が、私はそれには回りませんでした...私ははるかに単純でコンパクトなアルゴリズムを考えたので!分子の先読みなしで簡単に実装できるもの。また、非常に高速です。

この新しいものは、前のものと同様に、逆階乗を推測し、すべての可能性を循環させ、一致するかどうかをテストする必要があります。Nを2で割って、必要な作業のためのスペースを作り、ループをシードします。このループでは、3から始まり毎回増分する除数で入力を繰り返し除算します。(そのため、1!と2!はメインアルゴリズムと一致させることができず、個別に処理する必要があります。)除数は、実行中の商に追加することで追跡されます。これら2つの数値は、M!== N、実行中の商は、Mに等しくなるまでMで割り切れます。

この正規表現は、ループの最も内側の部分で変数による除算を行います。除算アルゴリズムは他の正規表現と同じです(乗算アルゴリズムに似ています):A≤Bの場合、C%A = 0およびBがB≤Cを満たす最大数である場合にのみA * B = C C%B = 0および(CB-(A-1))%(B-1)= 0です。ここで、Cは被除数、Aは除数、Bは商です。(A≥Bの場合にも同様のアルゴリズムを使用でき、AとBの比較方法がわからない場合は、1つの余分な可分性テストだけで十分です。)

ですから、ゴルフに最適化されたフィボナッチ正規表現よりも問題をさらに複雑さを減らすことができたことが大好きですが、同じベースの多重化手法が別の問題を待たなければならないことに失望してため息をつきます実際に必要なのは、これが必要ないからです。これは、私の651バイトの乗算アルゴリズムが50バイトのアルゴリズムに取って代わられたという話です。

編集:私はトリックを使用して1バイト(119→118)をドロップすることができたことによって見出さ汚れた商がより大きい又は除数に等しくなることが保証されている場合には短く分割futherできます。

これ以上苦労せずに、正規表現を次に示します。

真/偽バージョン(118バイト):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

オンラインでお試しください!

逆階乗または不一致(124バイト)を返します。

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

オンラインでお試しください!

ECMAScript +で逆階乗または不一致を返します\K(120バイト)でます。

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

そしてコメント付きのフリースペース版:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

これらの正規表現の私のゴルフ最適化の完全な歴史はgithubにあります:

階乗数を照合するための正規表現-多重度比較法、分子lookahead.txt
を一致させるための正規表現.txt(上記のもの)

((x*)x*)に変更できることに注意してください。正しい機能を失うことなく((x*)+)、サイズを1バイト(117バイトまで減らしますが、正規表現は指数関数的にスローダウンします。ただし、このトリックはPCREおよび.NETでは機能しますが、ECMAScriptでは機能しません。これは、ループで長さゼロの一致に遭遇したときの動作のためです。((x+)+)はECMAScriptで機能しますが、n=3!、これは正規表現に違反します!\2の値をキャプチャするために必要33=0(1-インデックスを作成する正規表現を変更するこのゴルフ利益を元に戻すことになります)。

.NET正規表現エンジンはECMAScriptモードでこの動作をエミュレートしないため、117バイトの正規表現が機能します。

オンラインでお試しください! (.NET正規表現エンジン+ ECMAScriptエミュレーションを使用した指数関数的スローダウンバージョン)


14

JavaScript(ES6)、30 29 28バイト

正の整数が必要です。-1偽りと-2真実のために戻ります。

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

:この関数はかなり大きな入力をサポートします(これは「JSにはかなり大きい」と読む必要があります)。これは、安全にまで動作するはずです2 53 1 - N = 121,645,100,408,831,992から確実に開始し、この入力は19に丸められます。= IEEE-754エンコーディングのため、121,645,100,408,832,000。丸め誤差のために、121,645,100,408,831,991の前に他の誤検出結果がある場合ありますが、私にはわかりません。


ニース- ~最後の使用が本当に好きです。
スティーブベネット

編集して投票を取り消すことができますか?(なぜ私が投票したのか知りたいなら、それはこの質問の珍しいI / Oルールを忘れたからです。)
CalculatorFeline

@Arnauld Undownvoted。
CalculatorFeline

11

Pythonの339の 38バイト

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

整数をとる再​​帰関数n、結果を表すブール値inversleyを返す(truthy:False、falsey:True

オンラインでお試しください!

繰り返し分割nすることによりi、初期値、1、残り未満またはそれに等しくなるまで1、その残りが少ないしているかどうかをテストし1、唯一の階乗に等しい残り終了します1、そして<よりバイト短いです==


@ovs 2つの一貫した出力に制限されています。残念ながら、を返す1すべての階乗1に対してを返しますTrue
ジョナサンアラン

11

Java 8、46バイト

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

これは、RomanGräfのエントリに基づいており、そのエントリから1ダースほどのバイトを削ることができました。私はそこにそれを提案したでしょうが、私はまだコメントするのに十分な評判がありません!変更したテストランナーコード:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}

9

網膜50 38バイト

@Neilのおかげで、ループの短縮と、 ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

オンラインでお試しください!

出力1真のためにと0 falseの。

.+ 全体の番号と一致します

1¶$&$* に置き換える 1改行で、マッチを単項に変換します

残りのプログラムは、下の行の単項数を連続的に増加する正の整数で除算し、上の行に追跡しますが、そうすることもできます。

+` 文字列が同じになるまでループする

  • ^(1+)¶(\1)+$一番上の行の多く1のsとそれの倍数の1一番下の行を一致させ、

  • 1$1¶$#2$*一番上の行1はもう1つ1、つまり一番上の行で表される数を1つ増やし、次に改行と一番下の行の一番上の行の一致数(つまり、2番目のキャプチャグループの一致の数)を増やします)多く1のs、つまり、一番下の数を一番上の数で割る

できなくなったら、

¶.$この正規表現の一致数を示します。1一番下の行に孤立しているのは、数が階乗である場合のみです


真/偽の値の代わりにノークラッシュ/クラッシュが許可されている場合、36 34バイトを取得できます。

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

これは同じアプローチで行われますが$*、3行目と4行目に結合します。3行目以降は同じループの一部であり、残りの行をループにグループ化する場所の{略です。階乗はループから抜け出すプログラムで終了しますが、非階乗はRetinaが最後の置換が失敗したためにOverflowExceptionをスローするまでループ内で永久にスタックします。一番下の行を10進数から単項に変換するため、すぐに爆発します。+((


置換の最後にある1ときに暗黙的に削除されるので、バイトを保存します$*
ニール

さらに良いこと$*に、他の2行と組み合わせます。
ニール


3
Retinaを条件付きでクラッシュさせる方法を見つけたことに感銘を受けました。:)
マーティン・エンダー

2
説明を追加できますか?
CalculatorFeline

8

05AB1E、4バイト

L!QO

オンラインでお試しください!

説明

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum

1
入力をLポップするため、最初に入力を複製する必要はありませんか?また、Å!入力以下の階乗のリストを提供します。
ニールA.

@NeilA。幸いなことに、操作のためのスタックに十分な引数がない場合、入力が再びポップされるため、Dここでは必要ありません。約キャッチÅ!。リストコマンドについてはいつも忘れています。バイトを保存しませんが、確かにより効率的です。
エミグナ

入力が再びポップされることを知りませんでした...確かに多くのバイトを節約できます。
ニールA.

@NeilA。これはかなり新しい機能です。追加されたのは1か月も前ではないと思います。
エミグナ

8

C ++、102 100 92バイト

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

から0までのすべての値をループしnて階乗を計算し、次に等しいかどうかをチェックしますnます。

クリストフありがとう!(8バイト保存)


こんにちは!PPCGへようこそ!素敵な最初の答え!未来に幸運を!
アルジュン

素敵な最初の答え!次のように数バイトを保存できますint a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}lroundそしてlgamma、すでにC ++ 11ですので、単純にできます#include<cmath>。私の提案をさらに改善できるかもしれません:)
クリストフ

7

Haskell43 26バイト

f n=elem n$scanl1(*)[1..n]

オンラインでお試しください!


2
f n=elem n$scanl1(*)[1..n]とんでもない非効率ですが、短いです。
ライコニ

コードの効率性に関するルールはありませんか?
sudee

1
私が知っていることはありません。code-golfは、効率の記述なしで、可能な限り少ないバイトで解決策を求めています。また、私のマシンでは、機能は40430目立った遅延なしに機能します。
ライコニ

「ソリューションは妥当な時間内に終了する必要がある」という線に沿って何かを意味しましたが、どちらの方法でも要件に適合すると思います。ありがとう!
sudee

1
素敵でシンプル。私は、分割言うともっとうまくできると思っていたdivModことにより、[1..]1の商(階乗)またはゼロ以外の残りの部分(非階乗)でゼロ余りに達するまで連続して、正しいアプローチではないようです。しかし、私はこのかわいい46文字のソリューションを見つけましたf|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%)
ジョンパーディ

6

Haskell、38バイト

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

オンラインでお試しください!使用例:(2#) 24Trueまたはを返しますFalse

これは非常に効率的でありながら、私が得ることができる最短です。数が多い場合でも

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

結果はすぐに得られます。解決策は、入力nm = 2,3,4,5,...は、結果が1になるか、またはn割り切れないまでます。m

計算はより短いが信じられないほど非効率的な26バイトのソリューションのために n!階乗ではない入力については、こちらをご覧ください



5

フーリエ40 39バイト

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

FourIDEでお試しください!

基本的に、Nが入力と等しくなる(出力1)または大きくなる(出力0)まで、数値Nに増加量を乗算します。

説明擬似コード:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While

5

Japt8 6バイト

ol x¥U

オンラインでお試しください!

これは、falseの場合は0、trueの場合は1を出力します。

説明

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result

1
私は本当に「含む」組み込みを追加する必要があります:P
ETHproductions

1
ちょっとああ、あなたは変更される可能性aU ¦Jx¥U(それぞれをマッピングXX==U、それはTIO上では動作しませんけれども、および合計)。
ETHproductions

以下のために失敗した2becuaseでoのみお渡しします[0,1]。1バイトの節約の修正があります。
シャギー

4

Perl 5、31バイト

$a=<>;$a/=++$i while$a>1;exit$a

入力はSTDINを介して取得され、出力は終了コードを介して提供されます(階乗の場合は1、非階乗の場合は0)。

入力は、1または1未満の小数になるまで連続した整数で除算され、結果に切り捨てられます。


-5バイトTIO
Nahuel Fouilleul

4

Perl 6バイト

{($_,{$_/++$}...2>*).tail==1}

試して

拡張:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}

17バイト:{$_∈[\*] 1..$_}。別の興味深いアプローチがあり2>*.polymod(1..*).sumます。
nwellnhof

4

setlX、32バイト

f:=n|=>exists(x in{0..n}|n==x!);

という関数を作成します fパラメーターとして潜在的な階乗を使用する場所します。

任意の整数サイズで動作しますが、かなり非効率的です。

(ところで:これはプログラミングパズルへの私の最初の参加です)


4

C(gcc)、33バイト

e;f(n){n=n%++e?n==!(e=0):f(n/e);}

一部の著者は、「自然数」を正の整数として定義していることに注意してください。したがって、それがf(0)無限再帰を引き起こすことは気にしません。



32バイトに落とすことができます:オンラインで試してみてください!またはfalseにゼロ以外を返すことで31バイト:オンラインで試してみてください!
デッドコード


4

C#(.NET Core)、68バイト

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

オンラインでお試しください!

最短の解決策ではありませんが、本当に大きな数字で動作します。TIOリンクには、10000!ます。

int最大値が2147483647のを使用する短いバージョンを次に示します。

C#(.NET Core)、45バイト

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

オンラインでお試しください!

両方の答えから合計3バイトのゴルフをしてくれた@KevinCruijssenに感謝します!


2
&&golfedすることができ&、および末尾は;ラムダ関数にカウントする必要はありません。また、することはできませんulong k=2ことuint k=2ご50バイトの答えに?
ケビンクルーイッセン

1
&対の良いキャッチ&&。スタックオーバーフローが発生していると思っていましたが、結局はうまくいくようです。ulongは64ビットで、uint32 ビットです。他の人が使用してintいるように見えるので、ショートバージョンに使用するだけです。末尾については;、これらはラムダではなく完全な関数なので、それらを含める必要があると思いますか?
ダナ

.NETが/andの%ulongで解決する方法は本当に奇妙ですuintが、and ではulongありませんint。知らなかった:)
ダナ

1
@Oliver- doubleある時点で丸めが見られるようになります-例えば24!そして120!失敗します。一方でSystem.Numerics.BigInteger、最も精度を持つ、int最も短い答え:)です
ダナ

1
@Deadcode-あなたは0について正しいです:)チャレンジの例に基づいて、私は「自然数」を1,2を意味すると解釈しました...私は現実の世界では短絡&&演算子を使用する方が良いことに同意します。しかし、これはコードゴルフです;)10000!例を気に入ってくれてうれしいです!
ダナ

4

C ++(clang)、51バイト

ゴルフの限り、再帰が勝ちます。

51バイト、ゼロは真:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

これは、1バイトの節約のために非常に多くの速度を犠牲にします。論理ORの短絡評価のため、|with ||を置き換えて高速にします。

オンラインでお試しください!(51バイトの低速バージョン)
オンラインでお試しください!(52バイト高速バージョン)

ゴルフされていないスローバージョン:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

Ungolfed高速バージョン:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

これを再配置するには多くの方法があります。

52バイト、ゼロ以外が真:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

オンラインでお試しください!

52バイト、ゼロは真:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

オンラインでお試しください!

再帰に頼る前に、いくつかの反復バージョンを作成してみましたが、それらは近づきました。

54バイト、ゼロ以外が真:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

オンラインでお試しください!

54バイト、ゼロはtrue(RomanGräfのJava 8提出に基づく):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

オンラインでお試しください!

さて、バレルの底部については、n==0処理のない再帰バージョン(0は自然数であり、それが定義されていない定義は非常に限られた「自然数」なので、これらは無効であると考えます)。以下のバージョンではf(0)、スタックのオーバーフローが原因でセグメンテーション違反がトリガーされるか、反復に最適化するコンパイラーで無限ループが無限ループします。

48バイト、ゼロは真:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

オンラインでお試しください!

48バイト、ゼロは真(Hagen von Eitzenの33バイトC(gcc)提出に基づく):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

オンラインでお試しください!


50 編集:49、再帰なし。
グリムミー

48の再帰に戻ります。おそらくこれは気に入らないでしょうが、グローバル変数を使用すると44になります。
グリムミー

3

Mathematica、20バイト

!FreeQ[Range[#]!,#]&

多数をテストする他のバージョン(コメントを参照)

Range[10^3]!~MemberQ~#&

最大1000までテストします!


2
私が質問を理解しているように、Mathematicaが1001を取得できるかどうか!入力として、これは仕様を満たしていません。
ピーターテイラー

2
すべての入力に対して有効にしながら、3バイトを節約することもできます。10 ^ 3を#に置き換えるだけです。あなたは#@範囲を使用して別のバイトを救うことができる
ジュリアン・クルーゲ

1243234の検索@Julien Klugethenは...永遠にかかるだろう
J42161217

1
私はあなたが交換することにより、別のバイトを保存することができると思うRange[#]Range@#:)
numbermaniac

3
中置構文を使用して、さらに1バイトを保存できるように見えます:!Range@#!~FreeQ~#&
numbermaniac

3

Cubix、24バイト

U0O@1I1>-?1u>*w;W;@Orq)p

オンラインで試す

キュビフィ

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

まず1Inputを押して、1をスタックにします。これらはそれぞれインデックス、ターゲット、およびアキュムレータになります。

その後、ループします。各反復で、入力からアキュムレーターを減算します。結果が0の場合、処理は完了しているため、プッシュ1O出力、および終了します。負の場合、行き過ぎているので、プッシュして0O出力して、終了します。そうでなければ、私たちは見ます

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.

3

ニーム、8バイト

𝐈Γ𝐈𝐩₁𝔼)𝐠

説明:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

それを試してみてください!

Neim、3バイト(非競合)

チャレンジが行われた後に、containsトークンと階乗トークンとしての非競合が追加されました。

𝐈𝐓𝕚

説明:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

それを試してみてください!


3

> <>24 22バイト

@Aaronのおかげで-2バイト

新しい言語を試しています(Mathematicaライセンスの期限が切れているため…)

01\{=n;
?!\$1+:@*:{:}(

オンライン試すか、魚遊び場で

入力番号がすでにスタック上にあり、0または1を返すと想定します。最初のn個の数値を入力より少なくなるまで乗算し、入力と等しい場合は1を出力し、等しくない場合は0を出力します。 t。


あなたはあなたを変えることができv>\n<^\\n/こちらをご覧ください
アーロン

@アーロン、それは素晴らしい、ありがとう!
ツリーではない

3

APL(Dyalog Unicode)、5 6 7バイト

エリック・ザ・アウトゴルファー×/!感謝してバイトをして

⊢∊!∘⍳

オンラインでお試しください!

説明

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?

累積合計?
リーキー修道女

@LeakyNun固定
KritixiのLithos

GNU APL 1.2の余分な1バイトN∊×\⍳N←⎕これはどのように引数を取るのですか?nどこにも見当たりません。これはDyalog固有のものですか?
Arc676

2
@ Arc676私の解決策は列車であり、あなたはそれを次のように呼び(⊢∊(×/⍳)) right_argumentます:TIOリンクで見ることができます。そして、正しい引数を指します。
KritixiのLithos

注:AGLは1バイト節約します。⊢∊×\ä⍳。「正しい」(しかしより長い)ソリューションは次のようになり0=1|!⍣¯1ます。「逆階乗は整数ですか?」
アダム

2

JavaScript(ES6)、71バイト

これは入力を関数の引数として受け取り、出力を受け取りalertます。0偽りと1真実のための出力。

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

説明

プログラムは2つの関数、fおよびで構成されていgます。f再帰的階乗計算関数でありg、プログラムの主要な関数です。g 1つの引数を持っていると仮定しますnr値0のデフォルト引数と値の別のデフォルト引数を定義します0。次に、0からのすべての整数を反復処理しn、各反復で、f適用される関数i(現在のインデックス)が等しいnかどうか、つまりnの階乗であるかどうかをチェックしますi。それはケースであることを起こる場合、rの値は関数の終了時に1に設定され、rありますalert edは。

テストスニペット

注: スニペットconsole.log()は、これらの厄介なalert()sのように誰も使用しないで出力します。

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)


Evalは、コードブロックを使用するよりも短い場合があります。
ダウンゴート

@Downgoatどうすればいいですか?あまりにも明白な場合は申し訳ありません!:P
アルジュン

2

QBIC21 19バイト

[:|q=q*a~q=b|_x1}?0

説明

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

以前

[:|q=q*a┘c=c+(q=b)}?c

説明:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.

2

Java 8、59バイト

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

テストコード

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.