Pertimbangkan S
panjang string biner n
. Dari pengindeksan 1
, kita dapat menghitung jarak Hamming antara S[1..i+1]
dan S[n-i..n]
untuk semua i
dalam urutan dari 0
ke n-1
. Jarak Hamming antara dua string dengan panjang yang sama adalah jumlah posisi di mana simbol yang sesuai berbeda. Sebagai contoh,
S = 01010
memberi
[0, 2, 0, 4, 0].
Ini karena 0
pertandingan 0
, 01
memiliki jarak Hamming dua 10
, 010
pertandingan 010
, 0101
memiliki jarak Hamming empat 1010
dan akhirnya 01010
cocok dengan dirinya sendiri.
Kami hanya tertarik pada output di mana jarak Hamming paling banyak 1, namun. Jadi dalam tugas ini kami akan melaporkan Y
jika jarak Hamming paling banyak satu dan N
sebaliknya. Jadi dalam contoh kita di atas kita akan dapatkan
[Y, N, Y, N, Y]
Tentukan f(n)
jumlah array yang berbeda dari Y
s dan N
s yang didapat ketika iterasi semua 2^n
string bit S
panjang yang mungkin berbeda n
.
Tugas
Untuk meningkatkan n
mulai dari 1
, kode Anda harus ditampilkan f(n)
.
Contoh jawaban
Sebab n = 1..24
, jawaban yang benar adalah:
1, 1, 2, 4, 6, 8, 14, 18, 27, 36, 52, 65, 93, 113, 150, 188, 241, 279, 377, 427, 540, 632, 768, 870
Mencetak gol
Kode Anda harus beralih dari n = 1
memberikan jawaban untuk masing-masing n
pada gilirannya. Saya akan mengatur waktu seluruh pelarian, membunuhnya setelah dua menit.
Skor Anda adalah yang tertinggi yang n
Anda dapatkan pada waktu itu.
Dalam kasus seri, jawaban pertama menang.
Di mana kode saya akan diuji?
Saya akan menjalankan kode Anda di laptop Windows 7 (agak lama) saya di bawah cygwin. Sebagai hasilnya, tolong berikan bantuan yang Anda bisa untuk mempermudah ini.
Laptop saya memiliki RAM 8GB dan CPU Intel i7 [email protected] GHz (Broadwell) dengan 2 core dan 4 thread. Set instruksi termasuk SSE4.2, AVX, AVX2, FMA3 dan TSX.
Entri terkemuka per bahasa
- n = 40 di Rust menggunakan CryptoMiniSat, oleh Anders Kaseorg. (Dalam VM tamu Lubuntu di bawah Vbox.)
- n = 35 dalam C ++ menggunakan perpustakaan BuDDy, oleh Christian Seviers. (Dalam VM tamu Lubuntu di bawah Vbox.)
- n = 34 di Clingo oleh Anders Kaseorg. (Dalam VM tamu Lubuntu di bawah Vbox.)
- n = 31 in Rust oleh Anders Kaseorg.
- n = 29 in Clojure oleh NikoNyrh.
- n = 29 in C oleh bartavelle.
- n = 27 in Haskell oleh bartavelle
- n = 24 in Pari / gp oleh alephalpha.
- n = 22 in Python 2 + pypy oleh saya.
- n = 21 dalam Mathematica by alephalpha. (Dilaporkan sendiri)
Karunia masa depan
Sekarang saya akan memberikan hadiah 200 poin untuk setiap jawaban yang mencapai n = 80 pada mesin saya dalam dua menit.
Jawaban:
Rust + CryptoMiniSat , n ≈ 41
src/main.rs
Cargo.toml
Bagaimana itu bekerja
Ini melakukan pencarian rekursif melalui pohon dari semua tugas parsial untuk awalan array Y / N, menggunakan SAT solver untuk memeriksa pada setiap langkah apakah tugas parsial saat ini konsisten dan memangkas pencarian jika tidak. CryptoMiniSat adalah pemecah SAT yang tepat untuk pekerjaan ini karena optimasi khusus untuk klausa XOR.
Tiga keluarga kendala adalah
S i ⊕ S k + i ⊕ D ki , untuk 1 ≤ k ≤ n - 2, 0 ≤ i ≤ n - k ;
D ki 1 ∨ D ki 2 ∨ ¬ A k , untuk 1 ≤ k ≤ n - 2, 0 ≤ i 1 < i 2 ≤ n - k ;
¬ D ki 1 ∨ ⋯ ∨ ¬ D ki n - k - 1∨ A k , untuk 1 ≤ k ≤ n - 2, 0 ≤ i 1 <⋯ < i n - k - 1 ≤ n - k ;
kecuali itu, sebagai optimisasi, S 0 dipaksa ke false, sehingga D k 0 sama dengan S k .
sumber
cargo build
saya mendapatkan--- stderr CMake Error: Could not create named generator Visual Studio 14 2015 Win64
Karat, n ≈
30 atau31 atau 32Di laptop saya (dua core, i5-6200U), ini bisa melalui n = 1,…, 31 dalam 53 detik, menggunakan sekitar 2,5 GiB memori, atau melalui n = 1,…, 32 dalam 105 detik, menggunakan sekitar 5 GiB memori. Kompilasi dengan
cargo build --release
dan jalankantarget/release/correlations
.src/main.rs
Cargo.toml
Cobalah online!
Saya juga memiliki varian yang sedikit lebih lambat menggunakan memori yang sangat sedikit.
sumber
C ++ menggunakan perpustakaan BuDDy
Pendekatan yang berbeda: memiliki rumus biner (sebagai diagram keputusan biner ) yang mengambil bit
S
sebagai input dan jika benar yang memberikan beberapa nilai tetapY
atauN
pada posisi tertentu yang dipilih. Jika rumus itu tidak konstan salah, pilih posisi bebas dan berulang, coba keduanyaY
danN
. Jika tidak ada posisi bebas, kami telah menemukan kemungkinan nilai output. Jika rumusnya konstan salah, mundurlah.Ini bekerja relatif masuk akal karena ada beberapa nilai yang mungkin sehingga kita dapat sering mundur lebih awal. Saya mencoba ide yang sama dengan pemecah SAT, tetapi itu kurang berhasil.
Untuk mengkompilasi dengan debian 8 (jessie), instal
libbdd-dev
dan lakukang++ -std=c++11 -O3 -o hb hb.cpp -lbdd
. Mungkin bermanfaat untuk menambah argumen pertama menjadibdd_init
lebih banyak.sumber
Clingo, n ≈
30 atau 3134Saya sedikit terkejut melihat lima baris kode Clingo mengambil alih solusi Rust brute-force saya dan mendekati solusi BuDDy Christian — sepertinya itu akan mengalahkan itu juga dengan batas waktu yang lebih tinggi.
corr.lp
corr.sh
sumber
bdd_init
membantu, atau memungkinkan untuk meningkatkan tabel simpul lebih banyak dengan meneleponbdd_setmaxincrease
dengan nilai jauh di atas standar 50000. - Apakah Anda menggunakan versi program saya yang berubah?--configuration=crafty
(jumpy
dantrendy
memberikan hasil yang serupa).Pari / GP , 23
Secara default, Pari / GP membatasi ukuran stack hingga 8 MB. Baris pertama kode
default(parisize, "4g")
,, menetapkan batas ini menjadi 4 GB. Jika masih memberikan aliran stackover, Anda dapat mengaturnya hingga 8 GB.sumber
Clojure, 29 dalam
7538 detik, 30 dalam 80 dan 31 dalam 165Runtimes dari Intel i7 6700K , penggunaan memori kurang dari 200 MB.
project.clj (menggunakan com.climate / claypoole untuk multithreading):
Kode sumber:
Solusi brute-force, setiap thread melewati subset rentang (2 ^ 12 item) dan membangun satu set nilai integer yang menunjukkan pola yang terdeteksi. Ini kemudian "disatukan" bersama-sama dan dengan demikian penghitungan yang berbeda dihitung. Saya harap kode ini tidak terlalu sulit untuk diikuti walaupun menggunakan banyak threading macro . Saya
main
menjalankan tes beberapa kali untuk mendapatkan pemanasan JVM.Pembaruan: Iterasi lebih dari setengah bilangan bulat, mendapat hasil yang sama karena simetri. Juga melewatkan angka dengan jumlah bit lebih tinggi pada bagian bawah dari angka saat mereka menghasilkan duplikat juga.
Uberjar pra-dibangun ( v1 ) (3,7 MB):
Hasil pada perangkat keras yang berbeda, runtime yang diharapkan adalah
O(n * 2^n)
?Anda dapat dengan mudah membuat ini single-threaded dan menghindari ketergantungan pihak ke-3 itu dengan menggunakan standar untuk:
Nah, built-in pmap juga ada tetapi claypoole memiliki lebih banyak fitur dan kemampuan merapikan.
sumber
Mathematica, n = 19
tekan alt +. untuk membatalkan dan hasilnya akan dicetak
sumber
Mathematica, 21
Sebagai perbandingan, jawaban Jenny_mathy diberikan
n = 19
di komputer saya.Bagian paling lambat adalah
Tr@IntegerDigits[#, 2] &
. Sangat disayangkan bahwa Mathematica tidak memiliki built-in untuk berat Hamming.Jika Anda ingin menguji kode saya, Anda dapat mengunduh uji coba gratis Mathematica .
sumber
Versi AC, menggunakan popcount bawaan
Bekerja dengan lebih baik
clang -O3
, tetapi juga berfungsi jika Anda hanya memilikigcc
.sumber
Haskell, (tidak resmi n = 20)
Ini hanyalah pendekatan naif - sejauh ini tanpa optimasi. Saya bertanya-tanya seberapa bagus tarifnya terhadap bahasa lain.
Cara menggunakannya (dengan asumsi Anda telah menginstal platform haskell ):
approx_corr.hs
(atau nama lain, ubah langkah-langkah berikut sesuai)ghc approx_corr.hs
approx_corr.exe
n
Kode:
sumber
main = putStrLn "Hello World!"
?Data.Bits
Modul mungkin berguna. Untuk loop utama Anda, Anda bisa menggunakan sesuatu seperti dimain = do maxn <- getmax; t0 <- gettime; loop 1
manaloop n|n==maxn = return ()
danloop n = do printresult n (f n); t <- gettime; printtime (t-t0); loop (n+1)
.getmax
misalnya bisa digunakangetArgs
untuk menggunakan argumen program.Solusi Haskell, menggunakan popCount dan paralelisme yang dikelola secara manual
Menyusun:
ghc -rtsopts -threaded -O2 -fllvm -Wall foo.hs
(jatuhkan
-llvm
jika tidak bekerja)Lari :
./foo +RTS -N
sumber
-O3
, dan mungkin lebih cepat dengan-O3 -fllvm
...Python 2 + pypy, n = 22
Berikut ini adalah solusi Python yang sangat sederhana sebagai semacam tolok ukur dasar.
sumber