Saya ingin secara kompak kode bilangan bulat positif x
menjadi bit, dengan cara yang memungkinkan decoding kembali ke bilangan bulat asli untuk decoder stateless mengetahui nilai maksimum m
masing-masing x
; akan mungkin untuk secara unik memecahkan kode penyandian pengkodean, seperti halnya dalam pengkodean Huffman.
[Pengantar di atas memotivasi yang lain, tetapi bukan bagian dari definisi formal]
Notasi: untuk bilangan bulat non-negatif i
, biarkan n(i)
jumlah bit yang diperlukan untuk direpresentasikan i
dalam biner; itu adalah bilangan bulat non-negatif terkecil k
sehinggai>>k == 0
i : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ..
n(i): 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 ..
Saya ingin fungsi yang F(x,m)
didefinisikan untuk 0<x
dan x<=m
, dengan menghasilkan string ' 0
' atau ' 1
', memiliki properti ini:
F(x,m)
memiliki panjang kurang dari2*n(x)
atau2*n(m)-1
, mana yang lebih kecil.- Jika
x<y
kemudian:F(x,m)
tidak lebih dariF(y,m)
;F(x,m)
danF(y,m)
berbeda pada beberapa posisi sepanjangF(x,m)
;- ada
0
diF(x,m)
pada posisi yang pertama.
- Ketika untuk
m
properti tertentu 1 dan 2 tidak secara unik mendefinisikanF(x,m)
untuk semua positifx
paling banyakm
, kami menolak setiap pengkodean memberikan lebihF(x,m)
dari beberapa pengkodean yang dapat diterima, untuk yang terkecilx
yang panjangnya tidak cocok.
Catatan: Dalam contoh di atas, secara implisit, 0<x
, 0<y
, 0<m
, x<=m
, dan y<=m
, sehingga F(x,m)
dan F(y,m)
didefinisikan.
Diminta program terpendek yang, mengingat x
dan m
memenuhi batasan di atas dan hingga 9 angka desimal, menghasilkan F(x,m)
konsisten dengan aturan di atas. Kerangka kerja C berikut (atau yang setara dalam bahasa lain) tidak dihitung:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C(c) putchar((c)?'1':'0') // output '0' or '1'
#define S(s) fputs((s),stdout) // output a string
typedef unsigned long t; // at least 32 bits
void F(t x,t m); // prototype for F
int main(int argc,char *argv[]){
if(argc==3)F((t)atol(argv[1]),(t)atol(argv[2]));
return 0;}
void F(t x,t m) { // counting starts on next line
} // counting ends before this line
Komentar: Properti 1 secara agresif membatasi panjang yang disandikan; properti 2 memformalkan bahwa decoding tidak ambigu dimungkinkan, dan mengkanonik encoding; Saya menegaskan (tanpa bukti) ini cukup untuk secara unik mendefinisikan output F
kapan m+1
kekuatan dua, dan bahwa properti 3 cukup untuk secara unik mendefinisikan F
untuk lainnya m
.
Ini adalah tabel parsial (buatan tangan; versi pertama yang diposting penuh dengan kesalahan, maaf):
x : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
F(x,1) : empty
F(x,2) : 0 1
F(x,3) : 0 10 11
F(x,4) : 0 10 110 111
F(x,5) : 0 10 110 1110 1111
F(x,6) : 0 100 101 110 1110 1111
F(x,7) : 0 100 101 1100 1101 1110 1111
F(x,8) : 0 100 101 110 11100 11101 11110 11111
F(x,15) : 0 100 101 11000 11001 11010 11011 111000 111001 111010 111011 111100 111101 111110 111111
11111
, membuat penguraian sandi mustahil dilakukan. Dengan pengkodean yang diusulkan, gabungan beberapa output dapat diterjemahkan secara unik (termasuk denganm
perubahan maksimum secara dinamis). Saya mencoba mengklarifikasi itu.Jawaban:
Python 3, 163 byte
Abaikan
c=0
parameter, itu trik golf.Ini dengan rakus memilih representasi yang sesingkat mungkin untuk setiap angka, dengan syarat bahwa jumlah yang tersisa masih dapat diwakili. Oleh karena itu, dengan konstruksi, itu persis memenuhi sifat yang diinginkan. Sebenarnya tidak sulit untuk memodifikasi kode ini untuk mendukung serangkaian aturan pengkodean yang berbeda.
Sebagai contoh, berikut adalah output hingga
m=15
:sumber
Python, 171
Perhatikan bahwa garis yang tampaknya dimulai dengan 4 spasi sebenarnya dimulai dengan tab.
Pengujian, dengan skrip uji bitpwner:
Penjelasan:
Ini semua didasarkan pada pengamatan bahwa antara dua elemen berturut-turut dari kode, F (x, m) dan F (x + 1, m), kami selalu menambahkan satu ke nomor biner, lalu mengalikannya dengan dua beberapa kali. Jika langkah-langkah ini diikuti, maka itu adalah kode yang valid. Sisanya hanya menguji untuk memastikan itu cukup pendek.
Golf: 175 -> 171: diubah 2 ** (2 * ... menjadi 4 **
sumber
Python - 370
Membuat pohon huffman, menyeimbangkannya agar sesuai dengan aturan, lalu berjalan-jalan di pohon untuk mendapatkan nilai akhir.
Untuk solusi yang lebih ringkas yang didasarkan pada pola yang muncul, lihat jawaban isaacg.
Ini adalah contoh yang baik tentang bagaimana pendekatan yang sama sekali berbeda dapat menyelesaikan masalah.
Uji:
Hasil:
sumber
F(7,8)
dari111110
yang salah, untuk itu memiliki panjang 6, dan "kurang dari2*n(x)
" menyiratkan kurang dari 6.