Hasilkan urutan sisa minimal

21

Setiap angka dapat direpresentasikan menggunakan urutan sisa panjang yang tak terhingga. Misalnya, jika kita mengambil angka 7, dan melakukan 7mod2, maka 7mod3, lalu 7mod4, dan seterusnya, kita dapatkan 1,1,3,2,1,0,7,7,7,7,.....

Namun, kita memerlukan urutan sisa sesingkat mungkin yang masih dapat digunakan untuk membedakannya dari semua angka yang lebih rendah. Menggunakan 7 lagi, [1,1,3]adalah urutan terpendek, karena semua kalimat sebelumnya tidak dimulai dengan [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...

Catatan yang [1,1] tidak berfungsi untuk mewakili 7, karena itu juga dapat digunakan untuk mewakili 1. Namun, Anda harus menampilkan [1]dengan input 1.

Input output

Input Anda adalah bilangan bulat non-negatif. Anda harus menampilkan urutan atau daftar urutan sisa minimal seperti yang didefinisikan di atas.

Kasus uji:

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

Berikut adalah 10.000 urutan pertama , jika Anda tertarik (nomor baris dimatikan oleh 1).

Ini adalah , jadi buat sesingkat mungkin dalam bahasa favorit Anda. Poin bonus palsu untuk setiap jawaban yang cepat!

Nathan Merrill
sumber
Terkait
Peter Taylor
@nimi kami membicarakan hal itu dalam obrolan, dan saya memutuskan bahwa urutannya harus setidaknya 1 elemen.
Nathan Merrill
1
Saya sedikit terkejut Anda tidak membatasinya pada sisa utama.
Neil
Apakah boleh jika output dikembalikan dalam daftar?
R. Kap
@neil, saya juga mempertimbangkan itu, tetapi karena sisanya berbeda dengan angka gabungan, saya memilih untuk menyimpannya
Nathan Merrill

Jawaban:

5

Mathematica, 60 53 byte

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

Agak cepat (menangani 10.000 dalam ~ 0,1 detik, tetapi kemungkinan akan kehabisan memori untuk 100000).

Kode melempar kesalahan tetapi menghitung hasilnya dengan benar.

Penjelasan

Kami telah menemukan sebelumnya dalam obrolan bahwa pembagi yang diperlukan selalu dapat ditentukan sebagai daftar terpendek {1, 2, ..., n}yang kelipatannya paling sedikit melebihi input. Argumen singkat mengapa itu adalah: jika LCM kurang dari input, maka mengurangi LCM dari input akan membuat semua pembagi tidak berubah, sehingga representasi tidak unik. Namun, untuk semua input kurang dari LCM, sisanya akan menjadi unik, jika tidak perbedaan antara dua angka dengan sisa yang sama akan menjadi kelipatan yang lebih kecil dari semua pembagi.

Adapun kode ... seperti biasa urutan membaca golf Mathematica agak lucu.

Range[#+2]

Ini memberi kita daftar [1, 2, 3, ..., n+2]untuk input n. The +2adalah untuk memastikan bahwa ia bekerja dengan benar untuk 0dan 1.

2~Range~#&/@...

Peta 2~Range~#(gula sintaksis untuk Range[2,#]) di atas daftar ini, jadi kami dapatkan

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

Ini adalah daftar calon pembagi (tentu saja secara umum itu jauh lebih banyak daripada yang kita butuhkan). Sekarang kita menemukan yang pertama dari mereka yang LCM melebihi input dengan:

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

Sintaks lebih lanjut: x_adalah pola yang cocok dengan salah satu daftar dan menyebutnya x. The /;menempel syarat untuk pola itu. Kondisi ini adalah LCM@@x>#tempat @@ menerapkan fungsi ke daftar, yaitu LCM@@{1,2,3}berarti LCM[1,2,3].

Akhirnya kami hanya mendapatkan semua sisanya, memanfaatkan fakta bahwa Modadalah Listable, yaitu secara otomatis memetakan lebih daftar jika salah satu argumen adalah daftar (atau jika keduanya daftar panjang yang sama):

#~Mod~...
Martin Ender
sumber
5

Jelly , 14 byte

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

Ini menggunakan fakta bahwa solusi (jika ada) dari sistem kongruensi linier adalah modulo LCM moduli yang unik. Cobalah online! atau verifikasi semua kasus uji .

Bagaimana itu bekerja

‘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.
Dennis
sumber
5

MATL , 24 byte

Terima kasih kepada @nimi karena menunjukkan kesalahan pada versi sebelumnya dari jawaban ini (sekarang diperbaiki)

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

Ini kehabisan memori dalam kompiler online untuk dua test case terbesar (tetapi bekerja pada komputer dengan 4 GB RAM).

Cobalah online!

Penjelasan

Ini menerapkan definisi secara langsung. Untuk input nitu menghitung array 2D yang mengandung mod(p,q)dengan pdari 0untuk ndan qdari 1ke n+1. Masing p- masing adalah kolom, dan masing-masing qadalah satu baris. Misalnya, dengan input n=7array ini

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

Sekarang kolom terakhir, yang berisi sisa-sisa n, adalah elemen-bijaksana dibandingkan dengan setiap kolom array ini. Ini menghasilkan

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

di mana 1menunjukkan kesetaraan. Kolom terakhir jelas sama dengan dirinya sendiri dan dengan demikian berisi semua. Kita perlu menemukan kolom yang memiliki jumlah awal terbanyak , selain kolom terakhir, dan mencatat jumlah awal tersebut m,. (Dalam hal ini adalah kolom kedua, yang berisi yang m=3awal). Untuk tujuan ini, kami menghitung produk kumulatif dari setiap kolom:

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

lalu jumlah masing-masing kolom

1 3 1 2 1 2 1 8

dan kemudian urutkan tanpa-semakin dan ambil nilai kedua, yaitu 3. Ini yang diinginkan m, yang menunjukkan berapa banyak sisa yang harus kita ambil.

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
Luis Mendo
sumber
4

Jelly , 13 11 byte

r¬µ%€R‘$ḟ/Ṫ

Ini tidak akan memenangkan poin brownies kecepatan ... Coba online! atau verifikasi kasus uji yang lebih kecil .

Bagaimana itu bekerja

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.
Dennis
sumber
Mengapa Anda memasukkan dua jawaban ???
Erik the Outgolfer
Karena mereka dua pendekatan yang sangat berbeda. Meskipun ini lebih pendek 3 byte, yang lain sebenarnya cukup cepat untuk menghitung semua kasus uji.
Dennis
Jika saya jadi Anda, saya tidak akan melakukannya ... kecuali jika itu suara yang naik / turun.
Erik the Outgolfer
Bahasa / pendekatan yang berbeda memiliki jawaban yang berbeda pula. Itu adalah pertanyaan meta pertama saya.
Dennis
3

Python 3.5, 117 95 78 byte

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)

Membutuhkan Python 3.5 dan sympy ( python3 -m pip install --user sympy). Kredit ke @ Dennis untuk memberi tahu saya bahwa Python 3.5 memungkinkan *ltrik dengan argumen default.

orlp
sumber
Dengan SymPy 0.7.5, Anda dapat mempersingkat M>n and lmenjadi l*(M>n).
Dennis
3

Python 2, 73 70 69 65 byte

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

Program lengkap. @Dennis menyimpan 4 byte dengan meningkatkan cara penanganan nol.

xsot
sumber
3

Haskell, 66 60 51 50 byte

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

Contoh penggunaan: f 42-> [0,0,2,2]. Ini adalah algoritma yang dijelaskan dalam jawaban @Martin Büttner .

Saya akan menyimpan versi sebelumnya untuk referensi, karena cukup cepat:

Haskell, 51 byte

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

Dibutuhkan 0,03 untuk f (10^100)laptop lima tahun saya.

Sunting: @xnor menemukan byte untuk disimpan. Terima kasih!

nimi
sumber
Menyimpan byte dengan menghitung indeks sampai lcm menjadi terlalu tinggi:h i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]
xnor
2

Pyth, 51 Bytes 66 Bytes

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

Cobalah!

Banyak lebih tinggi kecepatan 39 versi byte (tidak bekerja untuk 0-2):

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

Tampaknya berfungsi untuk angka yang sangat besar seperti 10 10 3

Catatan: jawaban ini tidak berfungsi untuk 0, 1, dan 2. Tetap!

poi830
sumber
2

JavaScript (ES6), 81 77 byte

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)

Ini secara rekursif membangun jawaban sampai LCM melebihi angka aslinya. GCD juga dihitung secara rekursif, tentu saja.

Sunting: Disimpan 4 byte berkat @ user81655.

Neil
sumber
@ user81655 Itu hanya curang ...
Neil
2

Ruby, 52 byte

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

Solusi ini memeriksa setiap kemungkinan mmulai dari 2 yang merupakan sisa yang membuat urutan unik. Apa yang membuat munik terakhir bukanlah sisanya itu sendiri, tetapi bahwa itu madalah anggota terakhir dari rentang terkecil di (2..m)mana kelipatan paling umum (LCM) dari rentang itu lebih besar daripada n. Hal ini disebabkan oleh Teorema Sisa Cina, di mana untuk secara unik menentukan angka ndengan jumlah sisa, LCM dari sisa tersebut harus lebih besar dari n(jika memilih ndari (1..n); jika memilih ndari a..b, jika memilih dari , LCM hanya perlu lebih besar daripadab-a )

Catatan: Saya meletakkan a<<n%mdi akhir kode karena until n<t=t.lcm(m+=1)hubungan arus pendek sebelumnyaa telah menerima elemen terakhir untuk membuatnya unik.

Jika ada yang punya saran bermain golf, beri tahu saya di komentar atau di obrolan PPCG .

Tidak melakukan pelanggaran:

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
Sherlock9
sumber
1

Python 3.5, 194 181 169 152 149 146 byte:

( Terima kasih kepada @ Sherlock9 untuk 2 byte! )

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)

Bekerja dengan sempurna, dan juga cukup cepat. Menghitung urutan sisa 100000output minimal[0, 1, 0, 0, 4, 5, 0, 1, 0, 10, 4, 4] dan hanya membutuhkan waktu sekitar 3 detik. Bahkan bisa menghitung urutan untuk input 1000000(1 juta), output [0, 1, 0, 0, 4, 1, 0, 1, 0, 1, 4, 1, 8, 10, 0, 9], dan butuh sekitar 60 detik.

Penjelasan

Pada dasarnya apa fungsi ini adalah pertama-tama membuat daftar,, ydengan semua di j mod imana jsetiap bilangan bulat dalam kisaran 0=>7(termasuk 7) dan isetiap bilangan bulat dalam kisaran 0=>100. Program kemudian masuk ke whileloop tak terbatas dan membandingkan jumlah konten yang sama dari masing-masing sublist dalam sublist pertama hingga kedua dari terakhir y( y[:-1:]) dengan jumlah item yang sama di sublist terakhir ( y[-1]) daftar y. Ketika sublist y[-1]adalah berbeda daripada sublist lain, loop rusak dari, dan benar minimal urutan sisanya dikembalikan.

Misalnya, jika inputnya 3, yakan menjadi:

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

Kemudian, ketika masuk ke loop sementara, ia membandingkan setiap sublist dalam daftar y[:-1:]dengan jumlah item yang sama dalam sublist y[-1]. Sebagai contoh, pertama-tama akan membandingkan [[0],[1],[0]]dan [1]. Karena sublist terakhir ada di sisa y, itu akan melanjutkan dan kemudian membandingkan [[0,0],[0,1],[0,2]]dan [1,0]. Karena [1,0]sekarang BUKAN dalam sisa y dalam urutan tertentu , itu adalah urutan pengingat minimal, dan karena itu, [1,0]akan dikembalikan dengan benar.

R. Kap
sumber
Untuk menyimpan byte, y[:c:]sama dengany[:c]
Sherlock9
0

C89, 105 byte

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);}

Kompilasi (dengan peringatan) menggunakan gcc -std=c89. Mengambil nomor tunggal pada stdin, dan menampilkan urutan sisa yang dipisahkan oleh spasi di stdout.

orlp
sumber
1
Ini tidak mencetak apa pun ketika n = 0
xsot
0

C, 89 byte

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);}

Kompilasi dengan gcc. Cobalah online: n = 59 , n = 0 .

xsot
sumber