Tantangannya adalah untuk menulis kode tercepat yang mungkin untuk menghitung Hafnian dari sebuah matriks .
The Hafnian dari simetris 2n
-by- 2n
matriks A
didefinisikan sebagai:
Di sini S 2n mewakili himpunan semua permutasi bilangan bulat dari 1
ke 2n
, yaitu [1, 2n]
.
Tautan wikipedia juga memberikan rumus tampilan berbeda yang mungkin menarik (dan bahkan metode yang lebih cepat ada jika Anda melihat lebih jauh di web). Halaman wiki yang sama berbicara tentang matriks kedekatan tetapi kode Anda juga bisa digunakan untuk matriks lain. Anda dapat mengasumsikan nilai-nilai semua akan menjadi bilangan bulat tetapi bukan berarti semuanya positif.
Ada juga algoritma yang lebih cepat tetapi tampaknya sulit untuk dipahami. dan Christian Sievers adalah yang pertama mengimplementasikannya (dalam Haskell).
Dalam pertanyaan ini semua matriks berbentuk bujur sangkar dan simetris dengan dimensi genap.
Implementasi referensi (perhatikan ini menggunakan metode paling lambat yang mungkin).
Berikut ini beberapa contoh kode python dari Mr. Xcoder.
from itertools import permutations
from math import factorial
def hafnian(matrix):
my_sum = 0
n = len(matrix) // 2
for sigma in permutations(range(n*2)):
prod = 1
for j in range(n):
prod *= matrix[sigma[2*j]][sigma[2*j+1]]
my_sum += prod
return my_sum / (factorial(n) * 2 ** n)
print(hafnian([[-1, 1, 1, -1, 0, 0, 1, -1], [1, 0, 1, 0, -1, 0, -1, -1], [1, 1, -1, 1, -1, -1, 0, -1], [-1, 0, 1, -1, -1, 1, -1, 0], [0, -1, -1, -1, -1, 0, 0, -1], [0, 0, -1, 1, 0, 0, 1, 1], [1, -1, 0, -1, 0, 1, 1, 0], [-1, -1, -1, 0, -1, 1, 0, 1]]))
4
M = [[1, 1, 0, 0, 0, 0, 0, 1, 0, 0], [1, 1, -1, 0, -1, 1, 1, 1, 0, -1], [0, -1, -1, -1, 0, -1, -1, 0, -1, 1], [0, 0, -1, 1, -1, 1, -1, 0, 1, -1], [0, -1, 0, -1, -1, -1, -1, 1, -1, 1], [0, 1, -1, 1, -1, 1, -1, -1, 1, -1], [0, 1, -1, -1, -1, -1, 1, 0, 0, 0], [1, 1, 0, 0, 1, -1, 0, 1, 1, -1], [0, 0, -1, 1, -1, 1, 0, 1, 1, 1], [0, -1, 1, -1, 1, -1, 0, -1, 1, 1]]
print(hafnian(M))
-13
M = [[-1, 0, -1, -1, 0, -1, 0, 1, -1, 0, 0, 0], [0, 0, 0, 0, 0, -1, 0, 1, -1, -1, -1, -1], [-1, 0, 0, 1, 0, 0, 0, 1, -1, 1, -1, 0], [-1, 0, 1, -1, 1, -1, -1, -1, 0, -1, -1, -1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0], [-1, -1, 0, -1, 0, 0, 1, 1, 1, 1, 1, 0], [0, 0, 0, -1, 0, 1, 1, -1, -1, 0, 1, 0], [1, 1, 1, -1, 0, 1, -1, 1, -1, -1, -1, -1], [-1, -1, -1, 0, 0, 1, -1, -1, -1, 1, -1, 0], [0, -1, 1, -1, 1, 1, 0, -1, 1, -1, 1, 1], [0, -1, -1, -1, -1, 1, 1, -1, -1, 1, 0, -1], [0, -1, 0, -1, 0, 0, 0, -1, 0, 1, -1, 1]]
print(hafnian(M))
13
M = [[-1, 1, 0, 1, 0, -1, 0, 0, -1, 1, -1, 1, 0, -1], [1, -1, 1, -1, 1, 1, -1, 0, -1, 1, 1, 0, 0, -1], [0, 1, 1, 1, -1, 1, -1, -1, 0, 0, -1, 0, -1, -1], [1, -1, 1, -1, 1, 0, 1, 1, -1, -1, 0, 0, 1, 1], [0, 1, -1, 1, 0, 1, 0, 1, -1, -1, 1, 1, 0, -1], [-1, 1, 1, 0, 1, 1, -1, 0, 1, -1, -1, -1, 1, -1], [0, -1, -1, 1, 0, -1, -1, -1, 0, 1, -1, 0, 1, -1], [0, 0, -1, 1, 1, 0, -1, 0, 0, -1, 0, 0, 0, 1], [-1, -1, 0, -1, -1, 1, 0, 0, 1, 1, 0, 1, -1, 0], [1, 1, 0, -1, -1, -1, 1, -1, 1, 1, 1, 0, 1, 0], [-1, 1, -1, 0, 1, -1, -1, 0, 0, 1, -1, 0, -1, 0], [1, 0, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 1], [0, 0, -1, 1, 0, 1, 1, 0, -1, 1, -1, 1, 1, -1], [-1, -1, -1, 1, -1, -1, -1, 1, 0, 0, 0, 1, -1, -1]]
print(hafnian(M))
83
Tugas
Anda harus menulis kode itu, diberikan 2n
oleh 2n
matriks, menampilkan Hafniannya.
Karena saya perlu menguji kode Anda, akan sangat membantu jika Anda dapat memberikan cara sederhana bagi saya untuk memberikan matriks sebagai input ke kode Anda, misalnya dengan membaca dari standar. Saya akan menguji kode Anda dalam matriks yang dipilih secara acak dengan elemen. dipilih dari {-1, 0, 1}. Tujuan pengujian seperti ini adalah untuk mengurangi peluang Hafnian akan menjadi nilai yang sangat besar.
Idealnya kode Anda akan dapat dibaca dalam matriks persis seperti yang saya miliki dalam contoh-contoh dalam pertanyaan ini langsung dari standar masuk. Itu adalah input akan terlihat seperti [[1,-1],[-1,-1]]
misalnya. Jika Anda ingin menggunakan format input lain, tanyakan dan saya akan melakukan yang terbaik untuk mengakomodasi.
Skor dan dasi
Saya akan menguji kode Anda pada matriks acak dengan ukuran yang meningkat dan menghentikan pertama kali kode Anda membutuhkan lebih dari 1 menit di komputer saya. Matriks penilaian akan konsisten untuk semua pengiriman untuk memastikan keadilan.
Jika dua orang mendapatkan skor yang sama maka pemenangnya adalah yang tercepat untuk nilai tersebut n
. Jika itu adalah dalam 1 detik satu sama lain maka itu adalah yang diposting pertama.
Bahasa dan perpustakaan
Anda dapat menggunakan bahasa dan pustaka yang tersedia yang Anda suka tetapi tidak ada fungsi yang sudah ada sebelumnya untuk menghitung Hafnian. Jika memungkinkan, alangkah baiknya untuk dapat menjalankan kode Anda jadi harap sertakan penjelasan lengkap tentang cara menjalankan / kompilasi kode Anda di Linux jika memungkinkan. `
Mesin Saya Pengaturan waktu akan dijalankan pada mesin 64-bit saya. Ini adalah instalasi ubuntu standar dengan RAM 8GB, Prosesor Delapan-Core AMD FX-8350 dan Radeon HD 4250. Ini juga berarti saya harus dapat menjalankan kode Anda.
Panggil jawaban dalam lebih banyak bahasa
Akan sangat bagus untuk mendapatkan jawaban dalam bahasa pemrograman super cepat favorit Anda. Untuk memulai, bagaimana dengan fortran , nim dan rust ?
Papan peringkat
- 52 oleh miles menggunakan C ++ . 30 detik.
- 50 oleh ngn menggunakan C . 50 detik.
- 46 oleh Christian Sievers menggunakan Haskell . 40 detik.
- 40 oleh miles menggunakan Python 2 + pypy . 41 detik.
- 34 oleh ngn menggunakan Python 3 + pypy . 29 detik.
- 28 oleh Dennis menggunakan Python 3 . 35 detik. (Pypy lebih lambat)