ユニークな乗算スパイラル


13

これは、カルビンの趣味の最近の乗算表の挑戦に触発されています

N入力として整数を受け取り、N行N列の一意の乗算スパイラルを出力または返す関数またはプログラムを作成します。コードは(理論上)0から1000の間のNで動作する必要があります(これを出力するのは難しい場合があります)。出力は、次の手順で作成されたテーブルと同等である必要があります。

  1. N行N列の乗算テーブルに入力します。たとえば、N = 3の場合:

    1 2 3
    2 4 6
    3 6 9
    
  2. 左上隅から時計回りにらせん状に進み、訪れた数字に注意してください。すでに訪問した番号にアクセスするときは、0に置き換えます。

いくつかの例を使用すると、より明確になります。

n = 0:
0

n = 1:
1

n = 2:       //   Spiral order:
1  2         //   1  2
0  4         //   4  3

n = 3:
1  2  3      //   1  2  3
0  4  6      //   8  9  4
0  0  9      //   7  6  5

n = 4:
1  2  3  4   //   1   2   3   4
0  0  6  8   //  12  13  14   5
0  0  9 12   //  11  16  15   6
0  0  0 16   //  10   9   8   7

n = 5:
1   2   3   4   5
0   0   6   8  10
0   0   9  12  15
0   0   0  16  20
0   0   0   0  25

n = 10:
1   2   3   4   5   6   7   8   9  10
0   0   0   0   0  12  14  16  18  20
0   0   0   0  15   0  21  24  27  30
0   0   0   0   0   0  28  32  36  40
0   0   0   0  25   0  35   0  45  50
0   0   0   0   0   0  42  48  54  60
0   0   0   0   0   0  49  56  63  70
0   0   0   0   0   0   0  64  72  80
0   0   0   0   0   0   0   0  81  90
0   0   0   0   0   0   0   0   0 100

番号は次のように見つかります。

ここに画像の説明を入力してください

適切な出力形式はすべて使用できますが、N行N列の行列である必要があり、単なるリストにすることはできません。簡単に区別できるN個の1行N列またはN行1列が存在するため、以下のような形式が受け入れられます。

[[1 2 3][0 4 6][0 0 9]]   <-- OK

[[1 0 0][2 4 0][3 6 9]]   <-- OK

ans =                     <-- OK
    1  2  3
    0  4  6
    0  0  9   

バイト単位の最短コードが勝ちます。


私は小さな目でエラトステネスの修正されたふるいをスパイします!どこかで見たことがあるパターンをここで使用できると確信しています。
アディソンクランプ

2
n=0乗算表にゼロがない場合に出力があるのはなぜですか。私n=1は出力1 を理解することができますが、なぜゼロを含めるのですか?
トムカーペンター

@TomCarpenter、それは悪い決断だったかもしれませんが、「What about N = 0?」という質問があることを知っていたので、N = 0-> 0ルールを作成しました。振り返ってみると、N> 0と言う方が良かったかもしれませんが、今は少し遅すぎます==
Stewie Griffin

2
@StewieGriffin出力はN行N列の行列であるn=0必要があるため、出力は0行0列の行列である必要があります。そうしないと、質問に矛盾が生じます。
-alephalpha

回答:



8

Mathematica 123122117 98 92 92 73バイト

LegionMammal978とalephalphaによる別の19のおかげで24バイトが節約されました!


驚いたことに、このテーブルでは、整数の複数のインスタンスはn、テーブル自体と同じように、らせんの相対的な順序付けが同じになります!番号の最初の外観はn、テーブル内でその番号が最初に表示されるセルにあります(行ごとにテーブルに入力する場合)。これは、アプローチがスパイラル制約を完全に無視できることを意味します。なぜなら、それは結果に関係がないからです。(以下の説明を参照してください。)

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&[10]

{{1、2、3、4、5、6、7、8、9、10}、{0、0、0、0、0、12、14、16、18、20}、{0、0、 0、0、15、0、21、24、27、30}、{0、0、0、0、0、0、28、32、36、40}、{0、0、0、0、25、 0、35、0、45、50}、{0、0、0、0、0、0、42、48、54、60}、{0、0、0、0、0、0、49、56、 63、70}、{0、0、0、0、0、0、0、64、72、80}、{0、0、0、0、0、0、0、0、81、90}、{ 0、0、0、0、0、0、0、0、0、100}}


Grid[%]

tble


説明

任意の数字nの位置のらせん順序が、関数によって返されるrow-col位置の順序と同じであるという事実を活用しますPositions

各番号の最初の出現位置(スパイラルまたはテーブルの位置のいずれかによる順序)は、によって返される最初の要素になりPositionます。その最初の発生セルはそのまま残されます。番号の残りのインスタンスは0に置き換えられます。

これがどのように機能するかを見てみましょうn==18。アイデアは、乗算表から始めることです。

(t = Table[k Range@#, {k, #}] &[10]) // Grid

各番号の行と列の位置を見つけます。たとえば、18は行2、列9(最初のインスタンス)にあります。行3、列6。行6、列3。列9、列2。これらは、それぞれの螺旋順序位置{44、58、68、82}を持っています。

Position[t, 18]

{{2、9}、{3、6}、{6、3}、{9、2}}

次の表に示すように。

テーブル2

18の最後の3つのインスタンスを0に置き換える必要があります(簡単に見つけられるように、大きな太字の青いゼロを使用します)。

ReplacePart[%, {{3, 6}, {6, 3}, {9, 2}} -> Style[0, {Blue, Bold, 16}]]// Grid

表3


を書かない理由はありFunctionますか?
LegionMammal978

1
ネストされた純粋な関数で問題が発生していましたが、この反復にはそれは必要ありません。ありがとう。
DavidC

改行を除く117バイトをカウントします。
LegionMammal978


さらにいくつかのゴルフ:ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
alephalpha

2

Python、99 95 90 89 87 81バイト

ゴルフコード:

n=range(1,input()+1);m=[]
for x in n:l=[(x*y,0)[x*y in m]for y in n];m+=l;print l

ゴルフをしていない:

n=range(1,input()+1);
m=[]
for x in n:
  l=[(x*y,0)[x*y in m]for y in n];
  m+=l;
  print l

出力:

10 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
[0, 0, 0, 0, 0, 12, 14, 16, 18, 20]
[0, 0, 0, 0, 15, 0, 21, 24, 27, 30] 
[0, 0, 0, 0, 0, 0, 28, 32, 36, 40]
[0, 0, 0, 0, 25, 0, 35, 0, 45, 50] 
[0, 0, 0, 0, 0, 0, 42, 48, 54, 60]
[0, 0, 0, 0, 0, 0, 49, 56, 63, 70] 
[0, 0, 0, 0, 0, 0, 0, 64, 72, 80]
[0, 0, 0, 0, 0, 0, 0, 0, 81, 90] 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 100]

入力バイト剃るためのありがとう@valuah
CSᵠ

2

MATLAB、96 88 87 86 79バイト

これは、出力例に続く79バイトのコードです(具体的にはn = 0の場合)。

n=input('');m=+(n>0);for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

これは75バイトで、n = 0の場合と同じ動作をします。n= 0の場合、質問の意味に従って空の配列を生成します(N x N配列= 0 x 0 =空の配列)。

n=input('');m=[];for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

これはOctaveでも動作します。こちらからオンライン試すことができます。コードは、「multspiral.m」という名前のファイルとして既に追加されています。したがって、Octaveプロンプトで、multspiralEnter キーを押して入力します。次に、テーブルのサイズ(4など)を入力する必要があります。その後、出力が印刷されます。


どのように機能しますか?

最初に、必要に応じて入力番号を取得します(6、4など)。

n=input('');

次に、n=0とのケースを処理します。n=1これらは、配列の生成に使用しているルールに従わない2つの特殊な処理が施されていますn=0

m=+(n>0);

次に、のすべての値についてn>2、マトリックスが正しいサイズに成長するまでループを行います。

for i=2:n;

間の唯一の3つの簡単な違い、実際に存在するnn+1、すべてのためにn>=2。これらは:

  1. 数値を含む配列の右端に新しい列が追加されますn(1:n)。これは簡単に計算できます:

     a=i*(1:i);
    
  2. その新しい列に追加される要素は、既存のマトリックスから削除する必要があります(ゼロに設定)。これらの要素は常に新しい列よりもスパイラルの後半に来るためです。これは、新しい列にある現在のマトリックスのすべての要素をゼロに設定するためにネストされたforループを使用して削除されます。

    for j=a;
        m(m==j)=0;
    end;
    
  3. 新しい列の下にある要素を除くすべての要素がゼロになる新しい行の一番下があります。意図的に作成された範囲外のインデックスのために新しい列が追加されると、自動的に0が埋め込まれます。MATLABの強力な機能の1つは、特別な処理なしで配列を拡大できるため、新しい行と列を簡単に追加できることですで:

    m(1:i,i)=a;
    

最後にforループの終わりがありmます。これに達すると、マトリックスに出力が含まれます。出力形式に柔軟性がmあるため、セミコロンなしの新しい行としてマトリックスが表示されます。

end;
m

例として、プログラムを実行する場合、数値10を入力すると、次の出力が得られます。

m =
     1     2     3     4     5     6     7     8     9    10
     0     0     0     0     0    12    14    16    18    20
     0     0     0     0    15     0    21    24    27    30
     0     0     0     0     0     0    28    32    36    40
     0     0     0     0    25     0    35     0    45    50
     0     0     0     0     0     0    42    48    54    60
     0     0     0     0     0     0    49    56    63    70
     0     0     0     0     0     0     0    64    72    80
     0     0     0     0     0     0     0     0    81    90
     0     0     0     0     0     0     0     0     0   100

1

Haskell、103 99バイト

import Data.Lists
f 0=[[0]]
f n=chunksOf n$foldr(\c d->c:replace[c][0]d)[][a*b|a<-[1..n],b<-[1..n]]

使用例:f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]]

Data.Listsリスト()などの素晴らしい機能replaceと再エクスポートData.ListData.List.Splitおよびを備えたモジュールを発見しましたData.List.Extras


1

ルビー、67 63 61バイト

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}

63バイト

->n{s,x=1..n,{};s.map{|c|s.map{|r|e=x[v=c*r]==1?0:v;x[v]=1;e}}}

67バイト

->n{s,x=1..n,[];s.map{|c|s.map{|r|e=x.include?(v=c*r)?0:v;x<<v;e}}}

使用法:

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}[10]
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 0, 0, 0, 0, 12, 14, 16, 18, 20], [0, 0, 0, 0, 15, 0, 21, 24, 27, 30], [0, 0, 0, 0, 0, 0, 28, 32, 36, 40], [0, 0, 0, 0, 25, 0, 35, 0, 45, 50], [0, 0, 0, 0, 0, 0, 42, 48, 54, 60], [0, 0, 0, 0, 0, 0, 49, 56, 63, 70], [0, 0, 0, 0, 0, 0, 0, 64, 72, 80], [0, 0, 0, 0, 0, 0, 0, 0, 81, 90], [0, 0, 0, 0, 0, 0, 0, 0, 0, 100]]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.