Pertanyaan ini adalah tentang tumpukan pasir abelian . Baca tantangan sebelumnya dan tonton video numberphile ini untuk mempelajari lebih lanjut.
Tumpukan abelian ukuran n oleh n adalah kotak yang berisi angka 0, 1, 2 dan 3 (mewakili jumlah butiran pasir). Menambahkan dua tumpukan pasir bekerja dengan pertama-tama menambahkan elemen demi elemen, dan kemudian menggulingkan elemen apa pun yang berada di atas 3. Urutan di mana Anda menjatuhkan tidak masalah, hasil akhirnya sama. Ketika sel menjatuhkan jumlahnya berkurang 4, dan masing-masing tetangga langsungnya bertambah 1. Ini dapat menyebabkan reaksi berantai. Jika sebuah sel berada di tepi kisi, setiap butir yang jatuh dari kisi saat terguling menghilang.
Misalnya, saya menambahkan dua tumpukan pasir 3 oleh 3 (memberikan reaksi berantai yang agak ekstrem):
3 3 3 1 2 1 4 5 4 4 6 4 6 2 6 6 3 6 2 5 2 4 1 4 4 2 4 0 4 0 2 0 2 2 1 2
3 3 3 + 2 1 2 = 5 4 5 -> 6 0 6 -> 2 4 2 -> 3 0 3 -> 5 0 5 -> 1 4 1 -> 2 0 2 -> 4 0 4 -> 0 4 0 -> 1 0 1
3 3 3 1 2 1 4 5 4 4 6 4 6 2 6 6 3 6 2 5 2 4 1 4 4 2 4 0 4 0 2 0 2 2 1 2
Dalam tantangan ini kami tertarik pada subset dari semua kemungkinan n oleh n tumpukan pasir. Subset ini berisi tumpukan pasir apa pun yang bisa Anda peroleh dengan menambahkan tumpukan pasir sewenang-wenang ke all-3s n oleh n sandpile. Sebagai contoh, tepat di atas kita melihat yang 212 | 101 | 212
ada di subset, karena kita mendapatkannya dengan menambahkan sesuatu ke-3 sandpile.
Sekarang bagian ini memiliki elemen yang menarik: elemen identitas . Jika Anda mengambil elemen ini dan menambahkannya ke elemen lain di subset , jumlahnya tidak berubah. Dengan kata lain, tumpukan pasir ini bertindak seperti nol dari subset ini. Kebetulan itu 212 | 101 | 212
adalah elemen nol untuk subset dari 3 oleh 3. Misalnya:
2 2 2 2 1 2 4 3 4 0 5 0 2 1 2 2 2 2
2 2 2 + 1 0 1 = 3 2 3 -> 5 2 5 -> 1 6 1 -> 2 2 2
2 2 2 2 1 2 4 3 4 0 5 0 2 1 2 2 2 2
Sekarang ini tantangan Anda: diberikan n , menemukan unsur identitas subset dari n oleh n jaringan . Keluarkan dengan menetapkan warna unik dengan kontras yang cukup dari pilihan Anda untuk masing-masing 0, 1, 2, 3
dan menghasilkan gambar n oleh n. Kode Anda harus dapat menghasilkan case 50 by 50 dalam waktu kurang dari satu menit pada PC modern yang wajar.
Misalnya, elemen 500 hingga 500 identitas:
Ini biru = 3, hijau = 2, merah = 1, putih = 0. Tetapi Anda tidak harus menggunakan skema warna ini dalam jawaban Anda.
Jawaban:
Oktaf,
120113 byteTerima kasih kepada JungHwan Min karena menyediakan tautan ke makalah referensi dalam jawaban Mathematica-nya.
Terima kasih kepada Stewie Griffin yang menyelamatkan saya 7 byte
[any(any(x)) -> nnz(x)]
Berikut dua fungsi yang digunakan:
1
f
.: untuk stabilisasi matriks2. Fungsi anonim yang mengambil
n
input dan menunjukkan matriks identitas.Cobalah Di rextester! untuk pembuatan matriks 50 * 50
Waktu berlalu untuk perhitungan matriks:
0.0844409 seconds
.Penjelasan:
Pertimbangkan fungsi
f
yang menstabilkan matriks, tugas menemukan identitas adalah sederhanaf(ones(n)*6 - f(ones(n)*6)
.itu
ones(n)*6
berarti * n matriks 6.jadi untuk
n=3
:Hasilnya akan
f(M-f(M))
Untuk fungsi stabilisasi, konvolusi 2D digunakan untuk mempercepat tugas; Dalam setiap iterasi kita membuat matriks biner
b
dengan ukuran yang sama dari matriks input dan mengaturnya menjadi 1 jika elemen yang sesuai dari matriks input adalah> 3. Kemudian kami menerapkan konvolusi 2D dari matriks biner dengan mask berikutmewakili empat tetangga langsung.
Hasil konvolusi ditambahkan ke matriks dan 4 kali matriks biner dikurangi darinya.
Lingkaran berlanjut sampai semua elemen dari matriks adalah <= 3
Versi tidak disatukan :
sumber
Mathematica,
177157135133 byteMembawa nomor
n
. Outputnya adalah sandpile identitas. 0 berwarna hitam, 1 berwarna abu-abu muda, 2 berwarna magenta, dan 3 berwarna biru-abu-abu.Sayangnya, Mathematica tidak memiliki builtin untuk ini ...
Menggunakan algoritma yang dinyatakan dalam makalah Scott Corry dan David Perkinson .
Memakan waktu 91,7 detik pada laptop saya yang berusia 5 tahun untuk menghitung sandpile identitas 50x50. Saya yakin bahwa komputer desktop modern yang masuk akal lebih dari 50% lebih cepat. (Saya juga punya kode cara yang lebih cepat di akhir).
Penjelasan
Tentukan fungsi
f
(inputnya adalah matriks pasir): fungsi yang ...... mengulangi
BlockMap
operasi sampai output tidak berubah.BlockMap
operasi: ...... pad array input dengan satu layer 0 ...
... mempartisi ke dalam matriks 3x3, dengan offset 1 ...
... dan untuk setiap partisi, tambahkan jumlah butiran pasir yang dijatuhkan ke sel tengah dan nilai sel pusat mod 4.
yaitu output dari
f
versi input yang distabilkan.Mendefinisikan
k
sebagai n oleh n array 6s.Hitung f (k - f (k)).
Terapkan warna ke hasilnya.
Versi lebih cepat (142 byte)
Kode yang sama, tetapi menggunakan rotasi daftar bawaan bukan
BlockMap
. Menghitung n = 50 dalam 4,0 detik di laptop saya.sumber
Python 3 + Numpy + PIL,
385370364 byteMengambil input pada STDIN. Output gambar sebagai skala abu-abu ke
i.png
. Hitam sesuai dengan 0, abu-abu gelap ke 1, abu-abu terang ke 2, dan putih ke 0.Menggunakan rumus
I = R(S - R(S))
, di manaI
elemen identitas,S
adalah matriks yang diisi dengan enam, danR
merupakan fungsi reduksi.Saya mungkin bisa menyimpan beberapa byte dengan beralih ke Python 2 dan melakukan
from numpy import*
, tetapi (1) saya tidak memiliki Numpy diinstal pada Python 2 dan (2) program tidak berakhir denganfrom numpy import*
.Tidak Disatukan:
sumber
scipy
ataumatplotlib
menampilkan data daripada menghasilkan gambar secara eksplisit dengan PIL.