最小剰余シーケンスを生成します


21

すべての数値は、無限に長い剰余シーケンスを使用して表すことができます。私たちは数7を取り、そして実行した場合たとえば、7mod2その後、7mod3その後、7mod4など、私たちが得ます1,1,3,2,1,0,7,7,7,7,....

ただし、下位のすべての下位シーケンスと区別するために使用できる、可能な限り短い残りのサブシーケンスが必要です。再度7を使用[1,1,3]するのが最も短いサブシーケンスです。これは、前のサブシーケンスのすべてが次で始まっていないため[1,1,3]です。

0: 0,0,0,0...
1: 1,1,1,1...
2: 0,2,2,2...
3: 1,0,3,3...
4: 0,1,0,4...
5: 1,2,1,0...
6: 0,0,2,1...

7を表すために[1,1] は機能しないことに注意しください。1を表すためにも使用できるためです。ただし、[1]1を入力して出力する必要があります。

入出力

入力は負でない整数です。上記で定義されているように、剰余の最小長シーケンスのシーケンスまたはリストを出力する必要があります。

テストケース:

0: 0
1: 1
2: 0,2
3: 1,0
4: 0,1
5: 1,2
6: 0,0,2
7: 1,1,3
8: 0,2,0
9: 1,0,1
10: 0,1,2
11: 1,2,3
12: 0,0,0,2
30: 0,0,2,0
42: 0,0,2,2
59: 1,2,3,4
60: 0,0,0,0,0,4
257: 1,2,1,2,5,5
566: 0,2,2,1,2,6,6
1000: 0,1,0,0,4,6,0,1
9998: 0,2,2,3,2,2,6,8,8,10
9999: 1,0,3,4,3,3,7,0,9,0

ここにある最初の10,000系列あなたが(行番号が1でオフになっている)興味を持っている場合には、。

これはですので、好きな言語でできるだけ短くしてください。高速な回答に対する偽のボーナスポイント!



@nimiはチャットでそれについて話しましたが、シーケンスは少なくとも1要素の長さが必要であると判断しました。
ネイサンメリル

1
余りを素数に限定していないことに少し驚いています。
ニール

出力がリストで返されても大丈夫ですか?
R. Kap

@neilは、私もあると考えますが、残りは合成数と異なっているので、私はそれを維持するために投票
ネイサンメリル

回答:


5

Mathematica、60 53バイト

#~Mod~FirstCase[2~Range~#&/@Range[#+2],x_/;LCM@@x>#]&

やや高速です(最大 0.1秒で10000を処理しますが、おそらく100000のメモリが不足します)。

コードはエラーをスローしますが、結果を正しく計算します。

説明

チャットの前の方で、必要な除数は常に{1, 2, ..., n}最小公倍数が入力を超える最短リストとして決定できることを発見しました。理由の簡単な説明:LCMが入力より小さい場合、入力からLCMを引くと、すべての除数が変更されないため、表現は一意ではありません。ただし、LCM未満のすべての入力の場合、剰余は一意になります。そうでない場合、剰余が等しい2つの数値の差は、すべての約数の小さい倍数になります。

コードについては...いつものように、ゴルフのMathematicaの読み順は少しおかしいです。

Range[#+2]

これにより[1, 2, 3, ..., n+2]、入力用のリストが取得されますn+2それが正しく動作することを確認するためにある01

2~Range~#&/@...

このリストの上に2~Range~#(の構文糖衣Range[2,#])をマップすると、

{{}, {2}, {2,3}, ..., {2,3,...,n+2}}

これらは候補除数リストです(もちろん、一般的には必要以上のものです)。ここで、LCMが入力を超える最初のものを見つけます。

FirstCase[...,x_/;LCM@@x>#]

その他の構文:x_は、リストのいずれかに一致し、それを呼び出すパターンxです。は/;、そのパターンに条件を付加します。この条件は、リストに関数を適用するLCM@@x>#場所、つまり手段です。@@ LCM@@{1,2,3}LCM[1,2,3]

最後に、我々は、単に事実を利用すること、すべての余りを取得しModているがListable、引数のいずれかがリストである場合(またはそれらの両方が同じ長さのリストである場合)、それは自動的にリストの上にマッピングします。すなわち:

#~Mod~...

5

ゼリー、14 バイト

‘Ræl\>iṠ2»2r⁸%

これは、線形合同システムのソリューション(もしあれば)がモジュライのLCMを法とする一意であるという事実を使用します。オンラインでお試しください!または、すべてのテストケースを確認します

使い方

‘Ræl\>iṠ2»2r⁸%  Main link. Argument: n

‘               Increment; yield n+1.
 R              Range; yield [1, ..., n+1].
  æl\           Cumulatively reduce by LCM.
                This yields [LCM(1), ..., LCM(1, ..., n+1)].
     >          Compare all LCMs with n.
      iṠ        Find the first index of sign(n).
                This yields the first m such that LCM(2, ..., m) > n if n > 0, and
                0 if n == 0.
        2»      Take the maximum of the previous result and 2, mapping 0 to 2.
          2r    Yield the range from 2 up to and including the maximum.
            ⁸%  Compute n modulo each integer in that range.

5

MATL、24バイト

この回答の以前のバージョンでエラーを指摘してくれた@nimiに感謝します(現在修正済み)

Q:qtQ!\t0Z)tb=YpsSP2):Q)

これは、2つの最大のテストケースのオンラインコンパイラのメモリを使い果たします(ただし、4 GBのRAMを搭載したコンピューターで動作します)。

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

説明

これにより、定義が簡単に適用されます。入力のn場合mod(p,q)pfrom 0to nおよびqfrom 1to を含む2D配列を計算しn+1ます。それぞれpが列であり、それぞれqが行です。たとえば、入力がある場合、n=7この配列は

0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1
0 1 2 0 1 2 0 1
0 1 2 3 0 1 2 3
0 1 2 3 4 0 1 2
0 1 2 3 4 5 0 1
0 1 2 3 4 5 6 0
0 1 2 3 4 5 6 7

の残りを含む最後の列は、nこの配列の各列と要素ごとに比較されます。これにより

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 1 0 0 1
0 0 0 1 0 0 0 1
0 0 1 0 0 0 0 1
0 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

ここで、1平等を示します。最後の列は明らかにそれ自体と等しく、したがってすべての列が含まれています。最後の列以外の最初の列の数が最も多い列を見つけ、その最初の列の数に注意する必要がありますm。(この場合、m=3最初の列を含む2番目の列です)。このために、各列の累積積を計算します。

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

その後、各列の合計

1 3 1 2 1 2 1 8

そして、増加しないようにソートし、2番目の値を取得します3。これは、mを選択する必要がある剰余の数を示す望ましいです。

Q:q    % take input n implicitly. Generare row array [0 1 ... n]
tQ!    % duplicate. Transform into column array [1; 2; ...; n-1]
\      % modulo, element-wise with broadcast. Gives the 2D array
t0Z)   % duplicate. Take last column
tb     % duplicate, bubble up
=      % test for equality, element-wise with broadcast
Yp     % cumumative product of each column
s      % sum of each column. This gives the number of initial coincidences
SP2)   % sort in decreasing order and take second value: m
:Q     % generate range [2 3 ... m+1]
)      % apply as index into array of remainders of n. Implicitly display

4

ゼリー13 11 バイト

r¬µ%€R‘$ḟ/Ṫ

これは、速度ブラウニーポイントを獲得しません... オンラインで試してみてください!または、より小さいテストケースを確認します。

使い方

r¬µ%€R‘$ḟ/Ṫ  Main link. Argument: n

r¬           Range from n to (not n).
             This yields [n, ..., 0] if n > 0 and [0, 1] otherwise.

  µ          Begin a new, monadic chain. Argument: A (range)

       $     Combine the previous two links into a monadic chain:
     R         Range; turn each k in A into [1, ..., k] or [] if k == 0.
      ‘        Increment to map k to [2, ..., k+1].
   %€        Take each k in A modulo all the integers in the 2D list to the right.
        ḟ/   Reduce by filter-not; sequentially remove all remainder sequences of
             n-1, ..., (not n) from the remainder sequences of n.
          Ṫ  Tail; take the last remainder sequence.
             This gives the shortest sequence for descending A and the longest one
             (i.e., [0]) for ascending A.

なぜ2つの回答を含めたのですか?
エリックアウトゴルファー

2つのまったく異なるアプローチだからです。これは3バイト短くなりますが、もう1つは実際にはすべてのテストケースを計算するのに十分高速です。
デニス

もし私があなただったら、私はそれをやったことはなかったでしょう...もしそれが賛成票か反対票のものかを除いて。
エリックアウトゴルファー

異なる言語/アプローチは異なる答えになります。それが私の最初のメタ質問でした。
デニス

3

Python 3.5、117 95 78バイト

import sympy
r=lambda n,m=2,M=1,*l:M>n and l or r(n,m+1,sympy.lcm(m,M),*l,n%m)

Python 3.5およびsympy(python3 -m pip install --user sympy)が必要です。Pythonの3.5ができることを私に通知する@Dennisにクレジット*lデフォルト引数を持つトリックを。


SymPy 0.7.5を使用すると、短縮することが可能M>n and ll*(M>n)
デニス

3

Python 2、73 70 69 65バイト

i=l=1
n=input()
while l<=n|1:
 i+=1;a=l;print n%i
 while l%i:l+=a

完全なプログラム。@Dennisは、ゼロの処理方法を改善することで4バイトを節約しました。


3

Haskell、66 60 51 50バイト

f i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]

使用例:f 42-> [0,0,2,2]@MartinBüttnerの回答で説明されているアルゴリズムです。

以前のバージョンは非常に高速であるため、参照用に保持します。

Haskell、51バイト

f i=mod i<$>[[2..x]|x<-[2..],foldl1 lcm[2..x]>i]!!0

f (10^100)私の5歳のラップトップでは0.03秒かかります。

編集:@xnorは保存するバイトを見つけました。ありがとう!


:LCMが高すぎる得るまでのインデックスをカウントすることでバイトを保存するh i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]
XNOR

2

Pyth、51バイト 66バイト

IqQZ[Z).q)IqQ1[1))IqQ2,0 1))FdhhQJu/*GHiGHtUd1I>JQVQ aY%QhN)<tYd.q

やってみて!

はるかに高速39バイトのバージョン(0-2動作しません):

FdhhQJu/*GHiGHtUd1I>JQVtd aY%QhN)<tYd.q

10 10 3のようなとてつもなく大きい数で機能するようです

注:この回答は、0、1、および2では機能しません。 修正されました!


2

JavaScript(ES6)、81 77バイト

f=(n,r=[n%2],l=i=2,g=(j,k)=>j?g(k%j,j):k)=>l>n?r:f(n,[...r,n%++i],i/g(i,l)*l)

これにより、LCMが元の数を超えるまで、回答が再帰的に構築されます。もちろん、GCDも再帰的に計算されます。

編集:@ user81655のおかげで4バイトを保存しました。


@ user81655それはちょうど手に負えない...-
ニール

2

ルビー、52バイト

->n{m=t=1;a=[];(a<<n%m)until n<t=t.lcm(m+=1);a<<n%m}

このソリューションmは、シーケンスを一意にする残りの2から始まる可能なすべてをチェックします。最後をm一意にするのは、それ自体ではなく、その範囲の最小公倍数(LCM)がより大きいm最小範囲の最後のメンバーです。この一意数は何を決定する中国の剰余定理、に起因する残りの数であり、それらの残りのLCMは、より大きくなければならない(選択する場合に、選択した場合に、LCMは、より大きくなる必要があります)(2..m)nnnn(1..n)na..bb-a

注:以前の短絡は、それを一意にするための最後の要素を受け取ったa<<n%mため、コードの最後に配置しました。until n<t=t.lcm(m+=1)a

誰かゴルフの提案があれば、コメントまたはPPCGチャットお知らせください

アンゴルフ:

def remainder_sequence(num)
  # starting with 1, as the statements in the until loop immediately increments divisor
  divisor = 1
  # starts with 1 instead of 2, as the statements in the until loop
  # immediately change product to a new lcm
  product = 1
  remainders = []

  # this increments divisor first then checks the lcm of product and divisor
  # before checking if num is less than this lcm
  until num < (product = product.lcm(divisor = divisor + 1))
    remainders << num % divisor
  end

  # until always short circuits before the last element is entered
  # so this enters the last element and returns
  return remainders << num % divisor
end


1

パイソン3.5、194 181 169 152 149 146バイト。

2バイトの@ Sherlock9に感謝!

def r(o,c=0):
 y=[[j%i for i in range(2,100)]for j in range(o+1)]
 while 1:
  c+=1;z=y[-1][:c]
  if z not in[f[:c]for f in y[:-1]]:break
 print(z)

完全に機能し、非常に高速です。100000出力の最小剰余シーケンスの計算には[0, 1, 0, 0, 4, 5, 0, 1, 0, 10, 4, 4]約3秒しかかかりませんでした。入力1000000(100万)、出力のシーケンスを計算することもでき[0, 1, 0, 0, 4, 1, 0, 1, 0, 1, 4, 1, 8, 10, 0, 9]、約60秒かかりました。

説明

基本的にこの関数は、最初にリストを作成している何を、yすべてでj mod i場合j範囲内のすべての整数である0=>7(7を含む)は、およびi範囲内のすべての整数です0=>100。次に、プログラムは無限whileループに入り、yy[:-1:])の最初から2番目のサブリスト内の各サブリストの同じ数のコンテンツをy[-1]、listの最後のサブリスト()の同じ数のアイテムと比較しますy。サブリストy[-1]が他のサブリストと異なる場合、ループは中断され、正しい最小剰余シーケンスが返されます。

たとえば、入力が3の場合、次のようにyなります。

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [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, 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, 1, 1], [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]]

次に、whileループに入ると、listの各サブリストをsublist y[:-1:]の同じ数のアイテムと比較しますy[-1]。たとえば、最初にとを比較[[0],[1],[0]][1]ます。最後のサブリストが残りにあるyので、それは続けて、それから比較して[[0,0],[0,1],[0,2]][1,0]。以来[1,0]の残りの部分で、今ではありませんy 、特定の順序で、それは、最小限のリマインダー配列であり、そのため、[1,0]正しく返されます。


バイトを保存するには、y[:c:]同じであるy[:c]
Sherlock9

0

C89、105バイト

g(a,b){return b?g(b,a%b):a;}main(n,m,M){scanf("%d",&n);for(m=M=1;(M=++m*M/g(m,M))<=n;)printf("%d ",n%m);}

を使用して(警告付きで)コンパイルしますgcc -std=c89。stdinで単一の数値を取得し、stdoutでスペースで区切られた剰余のシーケンスを出力します。


1
n = 0
xsot

0

C、89バイト

a,i=2;main(l,n){for(n=atoi(gets(n))?:!puts(n);n/l;printf("%d ",n%i++))for(a=l;l%i;l+=a);}

gccでコンパイルします。オンラインで試してください:n = 59n = 0

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