Mendapatkan 39 byte
Ini adalah penjelasan tentang bagaimana saya mendapatkan solusi 39-byte, yang ditemukan Dennis dan JonathanFrech secara terpisah. Atau, lebih tepatnya, itu menjelaskan bagaimana seseorang bisa sampai pada jawaban di belakang, dengan cara yang jauh lebih baik daripada jalan saya yang sebenarnya untuk itu, yang penuh dengan alasan berlumpur dan jalan buntu.
n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400
Menulis ini sedikit kurang golf dan dengan lebih banyak parens, ini seperti:
n=0
for _ in range(400):
print n
n=(n+2)^(-((n+2)^n))%3
Paritas bit
Kita mulai dengan sebuah ide dari solusi 47-byte saya untuk menampilkan semua angka dari formulir di n=2*k+bmana kdihitung 0,1,...,399dan bmerupakan bit paritas yang membuat angka keseluruhan 1 genap.
Mari kita menulis par(x)untuk bit paritas dari x, itu adalah xor ( ^) semua bit dalam x. Ini adalah 0 jika ada angka genap 1-bit (angka itu jahat), dan 1 jika ada angka ganjil 1-bit. Karena n=2*k+b, kita harus par(n) = par(k)^b, untuk mencapai kejahatan yang par(n)==0kita butuhkan b=par(k), yaitu bit terakhir nuntuk menjadi bit paritas bit sebelumnya.
Upaya pertama saya dalam bermain golf adalah mengekspresikan par(k), pertama langsung dengan bin(k).count('1')%2, dan kemudian dengan sedikit manipulasi .
Pembaruan paritas
Tetap saja, sepertinya tidak ada ekspresi pendek. Alih-alih, itu membantu untuk menyadari bahwa ada lebih banyak info untuk dikerjakan. Daripada hanya menghitung paritas bit dari angka saat ini,
k ----> par(k)
kita dapat memperbarui paritas bit seperti yang kita kenaikan kuntuk k+1.
k ----> par(k)
|
v
k+1 ----> par(k+1)
Yaitu, karena kita menghitung k=0,1,2,..., kita hanya perlu mempertahankan paritas bit saat ini daripada menghitungnya dari awal setiap kali. Update bit paritas par(k+1)^par(k)adalah paritas dari jumlah bit membalik untuk pergi dari kke k+1, yang par((k+1)^k).
par(k+1) ^ par(k) = par((k+1)^k)
par(k+1) = par(k) ^ par((k+1)^k)
Bentuk dari (k+1)^k
Sekarang kita perlu menghitung par((k+1)^k). Sepertinya kita tidak mendapatkan apa-apa karena menghitung bit parity adalah masalah yang ingin kita pecahkan. Tapi, angka-angka yang dinyatakan (k+1)^kmemiliki bentuk 1,3,7,15,.., yaitu satu di bawah kekuatan 2, fakta yang sering digunakan dalam peretasan bit . Mari kita lihat mengapa begitu.
Ketika kita bertambah k, efek dari binary carry adalah membalikkan yang terakhir 0dan semuanya 1ke kanan, menciptakan pemimpin baru 0jika tidak ada. Sebagai contoh, ambilk=43=0b101011
**
101011 (43)
+ 1
------
= 101100 (44)
101011 (43)
^101100 (44)
------
= 000111 (77)
Kolom yang menyebabkan carry ditandai dengan *. Ini memiliki 1perubahan ke 0dan meneruskan sedikit carry 1, yang terus menyebar ke kiri sampai menyentuh 0dalam k, yang berubah menjadi 1. Setiap bit lebih jauh ke kiri tidak terpengaruh. Jadi, ketika k^(k+1)cek yang sedikit posisi berubah kuntuk k+1, ia menemukan posisi paling kanan 0dan 1's untuk yang benar. Yaitu, bit yang diubah membentuk akhiran, jadi hasilnya 0's diikuti oleh satu atau lebih 1's. Tanpa nol terkemuka, ada angka biner 1, 11, 111, 1111, ...yang satu di bawah kekuatan 2.
Komputasi par((k+1)^k)
Sekarang kita mengerti bahwa (k+1)^kterbatas 1,3,7,15,..., mari kita cari cara untuk menghitung bit paritas dari angka-angka tersebut. Di sini, fakta yang berguna adalah 1,2,4,8,16,...modulo alternatif itu 3antara 1dan 2, sejak 2==-1 mod 3. Jadi, mengambil memberi 1,3,7,15,31,63...modulo , yang persis paritas bit mereka. Sempurna!31,0,1,0,1,0...
Jadi, kita bisa melakukan pembaruan par(k+1) = par(k) ^ par((k+1)^k)sebagai
par(k+1) = par(k) ^ ((k+1)^k)%3
Menggunakan bsebagai variabel tempat kita menyimpan paritas, ini terlihat seperti
b^=((k+1)^k)%3
Menulis kodenya
Menyatukan ini dalam kode, kita mulai kdan paritas bkeduanya 0, kemudian berulang kali mencetak n=2*k+bdan memperbarui b=b^((k+1)^k)%3dan k=k+1.
46 byte
k=b=0
exec"print 2*k+b;b^=(k+1^k)%3;k+=1;"*400
Cobalah online!
Kami menghapus parens k+1di sekitar ((k+1)^k)%3karena prioritas Python melakukan penambahan pertama, aneh seperti yang terlihat.
Perbaikan kode
Kita bisa melakukan yang lebih baik dengan bekerja secara langsung dengan satu variabel n=2*k+bdan melakukan pembaruan langsung di atasnya. Melakukan k+=1sesuai dengan n+=2. Dan, memperbarui b^=(k+1^k)%3berkorespondensi dengan n^=(k+1^k)%3. Di sini, k=n/2sebelum memperbarui n.
44 byte
n=0
exec"print n;n^=(n/2+1^n/2)%3;n+=2;"*400
Cobalah online!
Kita dapat mempersingkat n/2+1^n/2(ingat ini (n/2+1)^n/2) dengan menulis ulang
n/2+1 ^ n/2
(n+2)/2 ^ n/2
(n+2 ^ n)/2
Sejak /2menghapus bit terakhir, tidak masalah jika kita melakukannya sebelum atau sesudah xor-ing. Jadi, sudah n^=(n+2^n)/2%3. Kita dapat menyimpan byte lain dengan mencatat modulo itu 3, /2sama dengan *2ekivalen dengan -, mencatat bahwa n+2^nmeskipun demikian pembagiannya adalah separuh sebenarnya tanpa lantai. Ini memberin^=-(n+2^n)%3
41 byte
n=0
exec"print n;n^=-(n+2^n)%3;n+=2;"*400
Cobalah online!
Akhirnya, kita bisa menggabungkan operasi n^=c;n+=2menjadi n=(n+2)^c, di mana cada sedikit. Ini berfungsi karena ^chanya bertindak pada bit terakhir dan +2tidak peduli dengan bit terakhir, jadi operasi pun jadi. Sekali lagi, diutamakan mari kita hilangkan orangtua dan menulis n=n+2^c.
39 byte
n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400
Cobalah online!