Hari ini, kita akan menghitung fungsi biner yang paling efisien. Lebih khusus lagi, kita akan menghitung fungsi yang, ketika ekspresi dibuat dari penerapan fungsi ke input konstan 0 atau outputnya sendiri, dapat mewakili semua bilangan bulat positif dengan ekspresi sesingkat mungkin, menempatkan prioritas yang lebih tinggi pada bilangan bulat yang lebih kecil.
Fungsi ini dibangun sebagai berikut:
Untuk setiap integer, mulai dari 1 dan naik ke atas, pilih ekspresi terpendek yang belum kami tetapkan untuk output, dan buat integer itu output dari ekspresi itu. Ikatan dalam panjang ekspresi akan dipecah oleh argumen kiri yang lebih kecil, dan kemudian oleh argumen kanan yang lebih kecil. Begini cara kerjanya:
Awalnya, 1 tidak ditugaskan. Ekspresi unassigned terpendek adalah
f(0, 0)
, jadi kami akan menetapkan itu menjadi 1.Sekarang, 2 tidak ditugaskan. Ekspresi unassigned terpendek adalah
f(f(0, 0), 0)
=f(1, 0)
danf(0, f(0, 0))
=f(0, 1)
. Ikatan dipecah menjadi argumen kiri yang lebih kecil, jadif(0, 1) = 2
.Ekspresi unassigned terpendek yang tersisa adalah
f(f(0, 0), 0)
=f(1, 0)
, jadif(1, 0) = 3
.Sekarang, kita kehabisan ekspresi dengan hanya 2
f
detik dan 30
detik, jadi kita harus menambahkan satu lagi masing-masing. Memutus ikatan dengan argumen kiri, lalu argumen kanan, kita dapatkanf(0, 2) = 4
, sejak ituf(0, f(0, f(0, 0))) = f(0, f(0, 1)) = f(0, 2)
.Melanjutkan, kita memiliki
f(0, 3) = 5
,f(1, 1) = 6
,f(2, 0) = 7
,f(3, 0) = 8
,f(0, 4) = 9
, ...
Inilah tabel yang saya isi untuk beberapa nilai pertama:
0 1 2 3 4 5 6 7 8
/---------------------------
0| 1 2 4 5 9 10 11 12 13
1| 3 6 14 15 37 38 39 40 41
2| 7 16 42 43
3| 8 17 44 45
4| 18 46
5| 19 47
6| 20 48
7| 21 49
8| 22 50
Cara lain untuk melihatnya adalah bahwa setiap output memiliki ukuran, sama dengan jumlah ukuran inputnya ditambah satu. Tabel diisi sesuai dengan peningkatan ukuran output, ikatan rusak dengan meminimalkan input kiri kemudian input kanan.
Tantangan Anda adalah, diberi dua bilangan bulat non-negatif sebagai input, menghitung dan menampilkan nilai fungsi ini. Ini golf kode. Solusi terpendek, dalam byte, menang. Celah standar dilarang.
((0, (0, (0, 0))), 0)
secara leksikografis lebih kecil dari(((0, 0), 0), (0, 0))
, namun yang kedua memiliki sisi kiri yang lebih kecil.Jawaban:
Haskell, 110 byte
Argumen di sini dianggap sebagai tuple
(x,y)
. Cukup mirip dengan jawaban di atas, tetapi daftar pencarian hanya memegang pasangan indeks kiri dan kanan, bukan pohon.sumber
head[...]
adalah[...]!!0
dan(p,i)<-zip(concat c)[0..]
dapat disingkat menjadi(i,p)<-zip[0..]$id=<<c
.id=<<
repertoar :)Python 3, 154 byte
Ini tidak terlalu cepat atau sangat golf, tapi ini awal.
sumber
Wow! Saya sebenarnya berhasil membuat algoritma perhitungan yang efisien. Saya tidak mengharapkan ini pada awalnya. Solusinya cukup elegan. Berulang kali menyimpulkan lebih dan lebih, kemudian berulang sampai ke kasus dasar 0. Dalam jawaban ini fungsi C (n) menunjukkan angka Catalan .
Langkah pertama yang penting adalah mengakui bahwa ada nilai C (0) = 1 panjang nol (yaitu 0 itu sendiri), C (1) = 1 nilai panjang satu (yaitu f (0, 0)), C (2) = 2 nilai panjang dua (f (0, f (0, 0)) dan f (f (0, 0), 0)).
Ini berarti bahwa jika kita mencari ekspresi ke-n, dan kami menemukan k terbesar sehingga C (0) + C (1) + ... + C (k) <= n maka kita tahu bahwa n memiliki panjang k .
Tapi sekarang kita bisa melanjutkan! Karena ekspresi yang kita cari adalah ekspresi n - C (0) - C (1) - ... - C (k) di kelas panjangnya.
Sekarang kita dapat menggunakan trik serupa untuk menemukan panjang segmen kiri, dan kemudian peringkat dalam subbagian itu. Dan kemudian muncul kembali pada peringkat yang kami temukan!
Ditemukan bahwa f (5030, 3749) = 1542317211 dalam sekejap mata.
Python, tidak bersaing
Saya cukup yakin saya melakukan banyak perhitungan yang tidak perlu dan banyak langkah tengah bisa dihilangkan.
sumber