魔法のモジュロ正方形


11

私は数論の大ファンです。数論の大きなことはモジュラー算術です。m \ mid abの場合にのみ、定義はなります。楽しいことは、累乗することです。特に、モジュラスが素数の場合です。特に、amが比較的素数(1以外の共通因子を共有しない)の場合、a ^ e \ equiv 1 \ mod mのような数eが存在することが証明されています。abmodmmabM 1 E A E1am1eae1modm

例題で演習を説明します。モジュラスm=7取りましょう。プログラムまたは関数の可能な出力は次のとおりです。

3 2 6 4 5 1
2 4 1 2 4 1
6 1 6 1 6 1
4 2 1 4 2 1
5 4 6 2 3 1
1 1 1 1 1 1

各行は、その行の最初の数のべき乗のリストです。最初の行は3,32,33,,36。これは、3,2,6,4,5,1と同等です。 、1モジュロ7。上の正方形の2行目は2のべき乗などで、最後の行までは1べき乗です。

これは、次の理由から魔法のモジュロ正方形です。

  • 正方形は対称です。つまり、i番目の列はi番目の行と同じです。
  • すべての値は1m1少なくとも一度表示されます。

以下は、5の累乗で始まる、m=7その他の有効な出力です。5

5 4 6 2 3 1
4 2 1 4 2 1
6 1 6 1 6 1
2 4 1 2 4 1
3 2 6 4 5 1
1 1 1 1 1 1

チャレンジ

各行が行の最初の要素の連続するべき乗のリストであり、列についても同じになるpように、素数を与えられた魔法のモジュロ正方形、つまり辺の長さの正方形を出力する関数またはプログラムを作成p-1します。0との間のすべての数字がp発生する必要があり、正方形にはその範囲の数字のみを含めることができます。

入力は数値または文字列で、出力はascii、行列、配列の配列(任意の妥当な形式)です。

これはコードゴルフなので、最短のコードが優先されます。


関連するOEISシーケンス:A001918(左上隅の最低有効値)。
アーノールド

2
この演習が何であるかを例で説明します。」独自の用語で説明し、次に例を示します。あなたが求めているのは、がを法とする原始根であり、ような行列だと思います、しかし、それは現状の質問からその仕様を抽出するのに多大な努力です。AA1,1pAi,j=A1,1ijmodp
ピーターテイラー

2
@PeterTaylor true、それは私が意味することですが、第一に、それは探査の楽しみの一部を台無しにし、第二に、それは原始根とモジュラー算術に関する知識に依存しています。私はこの質問にそれよりも幅広い聴衆が答えられるようにしたかったので、私が意味することを簡単な言葉で説明しようとしました。
vrugtehagel

回答:


5

ゼリー13 10 バイト

-3ニックケネディのおかげ

以下のように感じている繰り返しのコードでは、あるべきゴルフ-できますが、私はしている管理していなかったdはそれを...

*€Ṗ%µQƑƇḢị

オンラインでお試しください!(フッターはグリッドとして整形されます)

どうやって?

*€Ṗ%µQƑƇḢị - Link: integer, p
 €         - for each n in [1..p]
*          -   exponentiate with:
  Ṗ        -     pop = [1..p-1]
           - ...i.e [[1^1,1^2,...,1^(p-1)],[2^1,2^2,...,2^(p-1)],...,[....,p^(p-1)]]
   %       - modulo p
    µ      - start a new monadic chain (call that list of lists X)
       Ƈ   - keep those which:
      Ƒ    -   are invariant under:
     Q     -     de-duplicate
        Ḣ  - head
         ị - index into the list of lists X


ああ、今は気分が遅くなりました; pありがとう!
ジョナサンアラン

3

、36バイト

≔E…¹θ﹪Xι…¹θIθηE⊟Φη⁼¹№ι¹⪫E§η⊖ι◧IλL⊖θ 

オンラインでお試しください!リンクは、コードの詳細バージョンです。注:末尾のスペース。説明:

≔E…¹θ﹪Xι…¹θIθη

to の累乗のp-1by p-1配列を作成1..p-1します1..p-1(モジュロp)。

E⊟Φη⁼¹№ι¹

ちょうど1つの行の1つにマップし1ます。

⪫E§η⊖ι◧IλL⊖θ 

選択した行で指定された順序に行を再配置し、出力をフォーマットします。




2

JavaScript(ES7)、 91  86バイト

このバージョンは、モジュロを適用する前にべき乗を計算しようとしますが、精度が失われるため、失敗します。それ以外の場合は、以下のコメント付きバージョンと同じロジックを使用しています。p11

f=(p,k)=>(g=k=>[...Array(i=p-1)].map(_=>k**++i%p))(k).sort()[1]>1?g(k).map(g):f(p,-~k)

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


JavaScript(ES6)、 92  87バイト

このバージョンでは、モジュラー累乗法を使用して、(非常に)高い入力値をサポートします。

f=(p,k)=>(g=k=>[...Array(p-1)].map(_=>n=n*k%p,n=1))(k).sort()[1]>1?g(k).map(g):f(p,-~k)

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

どうやって?

最初の行を見つける

与えられた、我々はヘルパー関数の使用計算するためための。1k<pgak(n)=knmodp1n<p

g = k =>              // k = input
  [...Array(p - 1)]   // generate an array of size p - 1
  .map(_ =>           // for each entry in there:
    n = n * k % p,    //   update n to (n * k) mod p
    n = 1             //   starting with n = 1
  )                   // end of map()

ような値が1つだけになるようなを探します。そのためには、配列を並べ替え、2 番目の要素がより大きいかどうかをテストします。knak(n)=11

g(k).sort()[1] > 1

これは辞書式順序でも機能します-これはデフォルトの動作ですsort()-なぜなら:

  • 複数のが存在する場合、それらはすべて数字の順序と同じようにすべて前面に移動します1
  • つしかない場合、2 番目の値は実際に数値の2 番目の値であるかどうかに関係なく、より大きくなります11

例:

以下のため:p=17

  • 以下のため、我々が得ます: k=1
    • a1=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
    • 1、1、1、1、1、1、1、1、1、1、1、1、1、1、1、1]としてソート[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
  • 以下のために、我々が得ます: k=2
    • a2=[2,4,8,16,15,13,9,1,2,4,8,16,15,13,9,1]
    • 1、13、13、15、15、16、16、2、2、4、4、8、8、9、9]としてソート[1,1,13,13,15,15,16,16,2,2,4,4,8,8,9,9]
  • 以下のため、我々が得ます: k=3
    • a3=[3,9,10,13,5,15,11,16,14,8,7,4,12,2,6,1]
    • としてソート[1,10,11,12,13,14,15,16,2,3,4,5,6,7,8,9]

マトリックスの構築

我々が見つかりましたら、我々呼び出し、再び(配列のソートされていないバージョンを取得するため)と呼び出しの各要素に対して行列の行を構築するために。kg(k)gg(k)

この部分は次のように簡単に記述できます。

g(k).map(g)

.indexOf(1)>p-33バイト以上節約します.every
ニール

@ニールありがとう。しかし、おやすみなさいの睡眠の後、より短い方法を見つけました。:)
アーナウルド

2

Zsh117 90バイト

b=$1
c=(eval set -- '$[x**'{1..$[b-1]}%b\])
for ((;${#${(u)@}}-b+1;++x))$c
for x;$c&&<<<$@

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

神が私の魂をmercれんでくださいますように。ここには多くの悪い習慣があります。少なくとも最大の犯罪者について説明しましょう。

c=(eval set -- '$[x**'{1..$[b-1]}%b\])
                      {1..$[b-1]}        # brace expansion, expands immediately
               '$[x**'           %b\]    # string literals, expand during eval
   eval set --                           # sets the positional parameters
c=(                                   )  # defines c to the words contained

b=4

c=(eval set -- '$[x**'{1..$[b-1]}%b\])
c=(eval set -- '$[x**'{1..3}%b\]     )                # $[b-1] => 3
c=(eval set -- '$[x**1%b]' '$[x**2%b]' '$[x**3%b]' )  # brace expansion

最後に、$cプログラムの残りの部分で、配列要素はとして評価されeval set -- ....ます。

最後に、${#${(u)@}}位置パラメータ内の一意の要素をカウントします(つまり、サイクルがあり1ますか、またはありますか?)

以下の117バイトの回答に関連するコメント。


克服しなければならない課題:

  • 多次元配列またはネストされた配列はありません。代わりに、ループで取得する文字列を出力します。
  • 特定の行に複数の1があるかどうかをテストするためのオプション:
    • ${#${(M)a:#1}:#一致を削除し、一致を(M)逆にします。したがって、これは配列内${# }1の数()に展開されます。残念ながら、この拡張は、ここで使用する算術forループとうまく機能しません。もしそうなら、潜在的にバイトを節約できます。
    • ${${:-1}:*a}:これは、シングルトン1とセットのセット交差点aです。1配列内で見つかった場合、これはシングルに展開されます。このオプションを使用して、ここに1文字を保存します1が、最後まで最後の行と列にsを追加することを延期する必要があるため、全体で1文字を失います。
f(){ # f [element] [modular base], puts powers up to n-2 into array $a
    a=()
    for i ({1..$[$2-2]})
        a+=($[$1**i%$2])
}
a=(1)                     # put 1 in a to force first loop iteration
for ((;${${:-1}:*a};))    # test for 1 in array $a
    f $[++x] $1           # increment x, iterate through all elements mod $1
for y ($a 1){             # for all elements in the [last array, 1]
    f $y $1               # put that row in $a
    <<<$a\ 1              # print out $a with 1 appended (space-delimited string)
}

1

Perl 6の65の 57バイト

{.[|.first(*.Set+2>$_)]}o{.&{@=(($++X**1..^$_)X%$_)xx$_}}

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

おそらく正方形自体を出力する方法はおそらくありますが、これは質問で説明したのと同じプロセスを行い、最初のリストの位置でリストをソートします。リストのリストとして返します。

ところで、シーケンスvs配列、および匿名変数に関連するPerl 6の厄介な制限のいくつかを回避しようとして、多くの騎手があります。

説明:

                               $++               xx$_    # Map 0 to i-1 to
                              (   X**1..^$_)             # n, n^2, n^3... n^(i-1)
                             (              X%$_)        # All modulo i
{                      }o{.&{                        }}  # Pass to the next function
 .[                   ]    # Index into that list of lists
   |.first(          )     # The list of the first list that
           *.Set+2>$_        # Has all the elements in the range 1 to i-1


1

05AB1E19 16 バイト

LεI<LmI%}ÐΘOÏн<è

@Emignaのおかげで-3バイト。

オンラインで試してみてください(フッターは2Dリストをきれいに印刷することです)。

説明:

L          # Create a list in the range [1, (implicit) input]
 ε         # Map each number `y` in the list to:
  I<L      #  Create a list in the range [1, input-1]
     m     #  Get number `y` to the power of each number in this list
      I%   #  Take modulo-input on each number
         # After the map: triplicate this modified matrix
   ΘO      # Get the amount of 1s in each row
     Ï     # And only leave the rows with exactly one 1
      н    # Then only leave the first row which contains a single 1
       <   # Decrease each value by 1 to make it 0-indexed
        è  # And index each into the rows of the modified matrix to create a new matrix
           # (which is output implicitly as result)

1
LεI<LmI%}ÐΘOÏн<è16バイトの場合。
エミグナ

@Emignaありがとう!私が持っていたのではなく、十分だっただろうと気づきませんでしUΣXykた。
ケビンクルーイッセン



0

APL(NARS)、29文字、58バイト

{k←⍵∣⍺*⍳⍵-1⋄⊃{m∣k*⍵}¨⍳¯1+m←⍵}

テスト:

  f←{k←⍵∣⍺*⍳⍵-1⋄⊃{m∣k*⍵}¨⍳¯1+m←⍵}
  3 f 7
3 2 6 4 5 1
2 4 1 2 4 1
6 1 6 1 6 1
4 2 1 4 2 1
5 4 6 2 3 1
1 1 1 1 1 1
  5 f 7
5 4 6 2 3 1
4 2 1 4 2 1
6 1 6 1 6 1
2 4 1 2 4 1
3 2 6 4 5 1
1 1 1 1 1 1 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.