Encode - Shuffle - Decode


23

Tantangan

Tugas Anda adalah menyandikan integer sebagai string karakter ASCII , lalu berhasil mendekodekannya setelah string tersebut diacak secara acak.

Anda akan menulis dua program / fungsi , yang akan disebut sebagai Encoder dan Decoder .

Encoder

  • Input: bilangan bulat n dalam kisaran [0,2311] .
  • Output: string s dari ASCII karakter (tidak harus dicetak).

Dekoder

  • Input: permutasi acak s dari string s .
  • Output: bilangan bulat n .

Mencetak gol

Biarkan A menjadi panjang maksimum dari s di semua nilai yang mungkin dari n . Jika Encoder bertindak non-deterministik (yang diizinkan, lihat di bawah), maka A akan menjadi panjang maksimum s yang mungkin terjadi (mungkin ).

Biarkan LE menjadi panjang Encoder dalam byte dan LD yang panjang Decoder dalam bytes.

Maka skor Anda adalah A(LE+LD) .

Kemenangan diberikan kepada pengajuan tersebut skor terendah .

Batas waktu

Ada batas waktu yang agak arbitrer 1 menit pada waktu eksekusi Encoder dan Decoder untuk testcase tunggal (yaitu nilai tunggal n ).

Tujuannya adalah untuk menghindari solusi yang menemukan bahwa memaksa enkode dengan menghitung semua urutan dengan sifat-sifat tertentu. Jika solusi Anda melakukan sesuatu yang lebih pintar dari itu, kemungkinan besar akan sesuai dengan batasan waktu dan akan dianggap valid. Demikian juga, jika bekerja pada TIO untuk beberapa nilai n yang dipilih secara acakn itu akan dianggap valid. Kalau tidak, saya akan mengujinya di komputer saya, tetapi perhatikan bahwa jika solusi Anda murni kasar, hampir pasti akan gagal.

Aturan

  • The Encoder dan Decoder harus ditulis dalam bahasa yang sama .
  • The Decoder keharusan output yang benar bilangan bulat n untuk setiap permutasi yang mungkin s dari string s dikembalikan oleh Encoder .
  • The Encoder dan Decoder yang tidak diizinkan untuk berbagi informasi dengan cara apapun (misalnya dengan cara variabel global atau file).
  • Output dari Encoder perlu tidak menjadi deterministik (yaitu, input yang sama n dapat menghasilkan string output yang berbeda jika Encoder dijalankan beberapa kali), tetapi Decoder harus selalu menebak bilangan bulat yang benar n .
  • The Encoder dan Decoder dapat mengambil dan mengembalikan bilangan bulat n dalam setiap cara yang nyaman (misalnya jika n=14 itu baik untuk masukan untuk menjadi 14, "14"atau [1,4]).
  • The Encoder mungkin keluaran string s baik dengan mencetak pada stdout atau dengan mengembalikan string, daftar / array karakter atau daftar / array bilangan bulat dalam rentang [0,127] ; perhatikan bahwa Decoder akan menerima sebagai input permutasi dari s seperti yang dikembalikan oleh Encoder , sehingga ia harus menerima string s dalam format yang sama dengan s .
  • Celah standar dilarang.
  • Jika memungkinkan, jelaskan cara kerja kode Anda dan mengapa skor yang Anda klaim benar.

Contoh

Asumsikan n=14 .

  • The Encoder menerima 14sebagai masukan. Ini dapat menghasilkan "qwerty".
  • The Decoder menerima permutasi dari "qwerty"sebagai masukan, misalnya "tweyqr". Ini harus menampilkan 14(dalam format apa pun yang nyaman).

The Encoder bisa kembali [113,119,101,114,116,121]juga, dalam hal ini Decoder akan menerima (misalnya) [116,119,101,121,113,114].

Perhatikan bahwa string yang dikembalikan oleh Encoder juga dapat menyertakan karakter ASCII yang tidak dapat dicetak (tetapi selalu dalam jangkauan [0x00, ..., 0x7F]).


Tentunya panjang output tidak dapat menjadi tak terbatas, Anda tidak dapat mengocok string yang tak terbatas
H.PWiz

@ H.PWiz Tidak tidak bisa, tetapi panjang mungkin tidak dibatasi jika Encoder tidak deterministik
Delfad0r

"Encoder dan Decoder tidak diizinkan untuk berbagi informasi dengan cara apa pun" Apakah ini termasuk fungsi pembantu? yaitu Fungsi kustom yang menghitung faktorial N ditambah tiga (contoh acak)
pizzapants184

Bisakah Encoder kami mengembalikan string / daftar kosong?
pizzapants184

2
@ Kalpeb Ya, sampai sekarang aturan mengatakan Anda harus menghitung byte dua kali. Saya sangat tertarik melihat kiriman dengan dua program yang identik.
Delfad0r

Jawaban:


12

Jelly , (17 byte + 18 byte) × panjang 6 = 210 poin

b36μỤỤ + × 3μŒ¿b3U + Ṣ
Ṣ: 3_J
Ṣ% 3Uḅ3œ? Çḅ36

Cobalah online! (atau dengan info debug tambahan)

Setelah mencoba menyelesaikan tantangan ini dengan tujuan pada kondisi kemenangan yang dinyatakan, saya pikir akan menarik untuk mencari kondisi kemenangan alternatif hipotetis: memberikan panjang maksimum minimum yang mungkin untuk output.

Penjelasan

Pengkodean

Langkah pertama dalam encoding adalah merepresentasikan input sebagai basis 36 ( b36). 36 6 = 2176782336> 2147483647, sehingga akan ada paling banyak 6 digit dalam hasil, yang masing-masing berada dalam kisaran 0–35.

Selanjutnya, kami mengubah ini menjadi representasi yang berisi 6 digit berbeda . Ada beberapa kemungkinan algoritma untuk ini, tetapi yang digunakan di sini adalah menambahkan 1 ke digit terkecil, 2 ke terkecil terkecil, 3 ke terkecil ketiga, dan seterusnya. Ini berarti bahwa jika dua digit sama, salah satunya akan dianggap lebih kecil, dan dengan demikian mereka akan menjadi berbeda; dan jelas, algoritma ini tidak dapat menyebabkan dua digit yang berbeda menjadi sama. Untuk mewakili ini dalam Jelly, kami menggunakan ("urutkan indeks menurut nilai") untuk mendapatkan daftar indeks dalam urutan yang diurutkan; lagi untuk membalikkan itu, secara efektif memetakan setiap elemen asli ke posisinya dalam urutan diurutkan; danµ…+untuk menambahkan yang asli ke daftar baru. Hasilnya adalah representasi dari nomor input sebagai enam digit yang berbeda dalam rentang 1-41 (minimum 0 + 1, maksimum 35 + 6).

Kami kemudian membaginya menjadi bentuk lain: daftar angka yang diurutkan dalam kisaran 1-41, di samping angka dari 1 hingga 720 yang mewakili dari 720 kemungkinan permutasi yang ada di dalamnya. ( Œ¿Dan ekstrak nomor permutasi dan diurutkan daftar masing-masing.)

Akhirnya, kami mengubah angka dari 1 menjadi 720 menjadi basis 3 ( b3), membalikkannya ( U), dan menyandikan enam basis 3 digit dan enam 1-41 digit melalui pengemasan masing-masing menjadi karakter ASCII tunggal menggunakan reverse divmod (nilai dari karakter mod 3 adalah angka dasar 3, nilai yang dibagi 3 adalah angka 1-41). Kisaran hasil yang mungkin adalah (1 × 3) + 0 = 3 minimum, dan (41 × 3) + 2 = 125 maksimum, sesuai dengan rentang ASCII kami. Pengepakan dilakukan melalui ×3dan +, bersama dengan tambahan µuntuk memastikan bahwa setiap perintah beroperasi pada bit data yang tepat. (Ada sedikit trik bermain golf di sini, karena kita melakukan perkalian dengan 3 sebelum mengekstraksi permutasi; yang menghemat kebutuhan untuk menghabiskan satu byte pada karakter pengelompokan.)

Kebetulan, alasan untuk membalikkan angka dasar 3 adalah karena ia mungkin memiliki lebih sedikit digit daripada angka 1-41. (Tidak dapat memiliki lebih banyak; angka terkecil yang n !> 3 n sedikit di atas 6.) Jelly secara efektif memasukkan angka nol saat menambahkan dua angka dengan panjang yang berbeda, untuk membuatnya cocok; membuntuti nol akan memengaruhi interpretasi angka, tetapi memimpin nol tidak akan, jadi sebaliknya digunakan untuk memastikan bahwa nol tambahan berakhir di suatu tempat yang tidak akan mengacaukan jawaban kami.

Decoding

Langkah pertama dalam decoding adalah mengekstraksi dua angka (angka dasar 3 dan angka 1-41). Kita dapat memperoleh digitnya cukup mudah dengan masing-masing divisi ( :3) dan modulo ( %3), tetapi bagaimana cara mengetahui urutannya? Nah, angka 1-41 memiliki digit dalam urutan, dan digit pada posisi yang sesuai dari dua angka itu disimpan dalam karakter yang sama; dengan demikian, kita dapat menentukan urutan angka 1-41 yang diacak (dengan melihat nilai relatifnya) dan mengetahui bahwa angka angka dasar-3 harus dikocok dengan cara yang sama. Faktanya, karena karakter pengkodean ASCII kami mengurutkan dengan cara yang sama dengan digit angka 1-41 (ini semua berbeda dan mereka lebih signifikan daripada angka dasar 3),. Jadi kedua ekstraksi dimulai dengan , diikuti oleh %3atau :3sesuai.

Sementara angka 1-41 angka masih dalam urutan, kami memiliki cara yang sangat mudah untuk kembali ke angka 0–35 dari basis 36; kurangi saja 1 dari yang pertama, 2 dari yang kedua, 3 dari yang ketiga, dan seterusnya. Di Jelly, kita bisa melakukannya dengan _J("kurangi indeks").

Sementara itu, di cabang lain dari decode, kita membalikkan digit angka 3 basis kembali ke urutan ( U), dan mengubahnya dari basis 3 kembali menjadi indeks permutasi dengan ḅ3.

Kami kemudian dapat menggabungkan dua cabang dengan œ?Ç; œ?berarti "permutasi yang diberikan indeks permutasi ini", dan Çberarti "hasil penerapan garis di atas", yaitu yang memberitahu Jelly untuk menjalankan kedua saluran secara terpisah pada input yang sama.

Apa yang kita miliki sekarang adalah digit dari angka asli, dalam basis 36 (karena _J), dan dalam urutan asli (karena œ?), jadi kita bisa melakukan a ḅ36untuk mengubah kembali dari basis 36 menjadi bilangan bulat tunggal.

Komentar

TIO! tautan di atas menggunakan 312699167 sebagai nomor untuk disandikan. Angka ini dalam basis 36 adalah [5, 6, 6, 8, 7, 35], dan dengan demikian menunjukkan semua aspek pengkodean: 35 menguji batas kisaran 0-127 yang kita miliki; duplikat 6s menguji resolusi angka identik dalam basis asli 36; dan fakta bahwa angka-angka hampir (tetapi tidak cukup) diurutkan berarti bahwa angka permutasi sangat kecil, sehingga memberikan angka lebih sedikit daripada angka dasar 36, dan dengan demikian menunjukkan kebutuhan untuk membalikkannya sebelum menambahkannya ke aslinya.

Sangat nyaman bagaimana semua konstanta di sini cocok bersama. 36 6 hanya cukup tinggi untuk memenuhi 2 31 , 3 6 hanya cukup tinggi untuk masuk ke 6 !, dan (36 + 6) × 3 hanya cukup tinggi untuk masuk dalam 128 kemungkinan yang kita miliki. (Kendala terakhir di sini adalah yang paling ketat, karena kita bisa menggunakan pengindeksan 0 daripada pengindeksan 1 untuk menggunakan karakter dalam kisaran 0-2. Namun, itu hanya akan memberikan ruang yang cukup untuk menggunakan 37 sebagai basis daripada dari 36.)


9

Jelly , ( 4 3 byte + 6 5 byte) × panjang 8 = 80 64 poin

b⁴Ä
ṢŻIḅ⁴

Cobalah online!

Jelly , ( 2 1 byte + 4 3 byte) × panjang 10 = 60 40 poin

SEBUAH
ṢŻ aku

Cobalah online!

Penjelasan

Solusi 1

Ini menggunakan algoritma yang berbeda dari sebagian besar jawaban lainnya. Kami mulai dengan menyandikan nilai dalam heksadesimal ( b⁴), seperti dengan jawaban lainnya, kemudian mengambil jumlah kumulatif ( Ä). Setiap input jelas akan memberikan output yang berbeda (karena kedua operasi ini dapat dibalik), dan mengingat bahwa pengkodean heksadesimal akan berisi paling banyak 8 digit yang maksimumnya 7 (untuk digit terakhir ke-8) dan 15 (untuk yang terakhir hingga ke-7- digit terakhir), jumlah maksimum dalam daftar output adalah 7+ (7 × 15) = 112, kurang dari 127 yang diminta oleh pertanyaan. Selain itu, output harus dalam urutan, memungkinkan kami untuk membalikkan acak.

Untuk dekoder, pertama-tama kita membalikkan shuffle dengan sort ( ); lalu balikkan jumlah kumulatif, dengan mendahulukan nol ( Ż) dan mengambil perbedaan pasangan berturut-turut ( I); lalu konversikan kembali dari heksadesimal ( ḅ⁴).

Solusi 2

Pertanyaannya sebenarnya memungkinkan kita untuk mengambil input sebagai daftar (mungkin desimal) digit, sehingga kita dapat "menipu" dengan hanya menghapus konversi basis; jumlah maksimum yang digunakan dalam output kemudian akan menjadi 2 + (9 × 9) = 83 (sebenarnya 82 karena 2999999999 berada di luar jangkauan, jadi input terburuk yang mungkin adalah 1999999999). Pengkodean yang dihasilkan cukup mengerikan ketika pengodean untuk masalah ini berjalan, tetapi memiliki keuntungan menjadi sangat singkat untuk dihasilkan, yang lebih penting daripada verbositas pengodean.

Jawaban ini terasa sangat curang. Itu bukan solusi utama saya untuk masalah ini, tetapi sepertinya layak untuk ditambahkan karena secara teknis sesuai dengan aturan dan menghasilkan skor yang lebih baik.

Komentar

Saya memiliki beberapa algoritma dalam pikiran untuk mendapatkan di bawah panjang 8, tetapi tampaknya tidak mungkin Anda dapat menerapkan algoritma panjang-7 dalam ≤9 byte (non-curang) atau ≤5 byte (curang), jadi dengan penilaian dalam pertanyaan, ini kemungkinan cara terbaik untuk melakukannya. (Namun saya mungkin harus mencoba solusi untuk alternatif "meminimalkan panjang penyandian", hanya untuk bersenang-senang.)

Tidak seperti beberapa solusi, penggunaan 16 sebagai basis di sini tidak kritis; ada banyak nomor lain yang bisa digunakan untuk solusi panjang 8 (mis. 18). Saya memilih 16 untuk solusi pertama hanya karena Jelly memiliki cara 1-byte untuk menyatakan hal itu, dan basis-basis lain yang layak perlu menggunakan banyak byte dari program. Tentu saja, solusi kedua perlu menggunakan 10 sebagai basis untuk mengeksploitasi celah.

Terima kasih kepada @Dennis karena menunjukkan beberapa perintah Jelly yang lebih baru yang membuat algoritma ini lebih sulit untuk ditulis.


3
Äkependekan dari +\, Żkependekan dari 0;.
Dennis

7

Bahasa Pemrograman Shakespeare , 10 * (264 + 494) = 8650 7910 7580

Encoder: 264 byte

,.Ajax,.Ford,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Be you nicer zero?You be the sum ofyou the product ofthe sum ofI a big big pig the sum ofa big big big big cat a big big pig.If soSpeak thy.Ford:You are the sum ofyou a cat.If soLet usAct I.

Cobalah online!

Decoder: 494

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Is you nicer a pig?If soRemember you.If soLet usAct I.Scene V:.Ford:Remember I.Ajax:Recall.Is you worse the sum ofPage twice the sum ofa big big cat a cat?If soYou be the difference betweenyou Page.If soOpen heart.If notlet usScene V.Scene X:.Ford:Recall.Ajax:Be I nicer zero?If soRemember I.If soLet usScene X.[Exit Ajax][Enter Page]Ford:You be the sum ofyou twice twice the sum ofa big big cat a pig.Let usAct I.

Cobalah online!

Ini suatu hal.

Encoder mengkodekan setiap digit sebagai digit plus indeks dari digit dua belas kali. Decoder menyimpan semua input dalam memori Ford dan kemudian loop di atas penghitung, mengeluarkan kemudian menghapus setiap digit lebih rendah dari penghitung * 12 + 10.

Penjelasan:

Encoder

,.Ajax,.Ford,.Act I:.Scene I:.      Boilerplate introducing the two characters
[Exeunt][Enter Ajax and Ford]       Enter the two characters Ajax and Ford
                                    Ford will be handling the input
                                    Ajax will be the counter
Ajax:Open mind.                     Set Ford to the next character of input
Be you nicer zero?                  Check if it is EOF
You be the sum of                   Set Ford to the sum of 
    you                             His original value (48 to 58)
    the product of                 
          the sum of               
              I                     Ajax's value
              a big big pig         Minus 4 (this handles the offset of 48)
          the sum of                Multiplied by
              a big big big big cat 2^4
              a big big pig.        + -2^2 = 12
                                    This essentially sets Ford to (F+12*(A-4))
If soSpeak thy.                      If not EOF, print Ford's value
Ford:You are the sum ofyou a cat.   Increment Ajax's value
If soLet usAct I.                   If not EOF, Repeat again.

Dekoder

,.Ajax,.Ford,.Page,.Act I:.Scene I:.  Boilerplate introducing three characters
                                      Ajax is the spare stack
                                      Ford is the storage stack
                                      Puck is the counter, increasing by 12
[Exeunt][Enter Ajax and Ford]            Enter Ajax and Ford onto the stage
Ajax:Open mind.                          Get the next character of input
Is you nicer a pig?                      If not EOF
If soRemember you.                         Store the value in Ford's memory
If soLet usAct I.                          And repeat the loop
Scene V:.                                Otherwise move to the next scene
Ford:Remember I.                         Store Ford's value (initially -1 from EOF) in Ajax's memory
Ajax:Recall.                             Get the next value from Ford's memory
Is you worse the sum of                  Is the value smaller than
        Puck                                  Puck's value
        twice the sum ofa big big cat a cat?  + 10 ?
                                              i.e. is it the next digit?
If soYou be the difference betweenyou Puck.   If so, subtract Puck's value from Ford
If soOpen heart.                              And print Ford's value
If notlet usScene V.                     If that was not the digit, repeat
Scene X:.
Ford:Recall.                             Get the next value from Ajax's memory
Ajax:Be I nicer zero?                    Until the -1
If soRemember I.                         Returning the values to Ford's memory
If soLet us Scene X.                     Repeat until Ajax's memory is exhausted
[Exit Ajax][Enter Page]                  Swap Ajax and Page
Ford:You be the sum of                   Set Puck's value to
              you                        Puck +   
              twice twice the sum of     2*2*(
                           a big big cat      4
                           a pig.             -1) = 12
Let usAct I.                             And start from the beginning again, having removed one number

5

Python 2.7, 31 * (52 + 37) = 2759

Encoder ( 69 52 byte):

lambda n:[chr(i)if n&(1<<i)else""for i in range(32)]

Dekoder ( 41 37 byte):

lambda s:sum([1<<(ord(c))for c in s])

Menyimpan semua bit non-nol dalam jumlah input sebagai nilai ascii. Nilai karakter ascii menyimpan posisi bit yang ditetapkan. Misalnya nilai 'a' akan berarti bahwa bit ke-97 diatur.

Beberapa perbaikan, terima kasih kepada @ Delfad0r

Cobalah online!


Selamat datang di PPGC! Anda dapat menghapus e = dan d = di awal - fungsi anonim baik-baik saja. Juga, perhatikan bahwa pernyataan masalah dengan jelas mengatakan bahwa Encoder dapat mengembalikan daftar bilangan bulat alih-alih karakter, sehingga Anda dapat menghindari integer konversi-> karakter-> integer. Selain itu, Anda dapat menggunakan dan n&(1<<i)bukannya n&(1<<i)>0menyimpan 2 byte. Akhirnya, batas atas untuk i(127) terlalu banyak, 32 sudah cukup dan menghemat 1 byte.
Delfad0r

1
Silakan sebutkan skor Anda sesuai dengan bagian Penilaian dalam pernyataan masalah.
Delfad0r

@ Delfad0r Apakah skor sudah benar sekarang? Dan terima kasih atas tipsnya.
Hein Wessels

Saya pikir angkanya adalah (52+37)*31=2759sejak terpanjang adalah ketika semua 31 bit ditetapkan.
Jonathan Allan

Encoder dapat lambda n:[chr(i)*(n&1<<i>0)for i in range(32)]menyimpan 6 byte.
mypetlion

5

Stax , skor 8 × (10 + 9) = 152

Encoder, 10 byte

Ç·MÉJ'♀τ│½

Jalankan dan debug itu

16|E{i16*+m Full program, implicit input
16|E        Get hexadecimal digits
    {     m Map:
     i16*+    Add 16 * loop index
            Implicit output as string

Encoder menampilkan string dalam urutan yang meningkat.

Decoder, 9 byte

üL∟n╫k∞‼9

Jalankan dan debug itu

o{16%m16|E Full program, implicit input
o          Sort string
 {16%m     Module each element by 16
      16|E Interpret as array of hex digits


5

Python 3 , 8 * (45 + 38) = 664

Encoder (45 byte):

lambda n:[16*i+(n>>4*i)%16 for i in range(8)]

Dekoder (38 byte):

lambda l:sum(x%16<<x//16*4 for x in l)

Cobalah online!


1
Anda dapat menghapus spasi sebelum "untuk", lambda l:sum(x%16<<x//16*4for x in l)berfungsi dengan baik :)
FatalError

4
Ini tidak bekerja. Output tidak biasa ASCII (dalam kisaran 0..127)
GB

2
@ GB kesalahanku. Saya memecahkannya dengan suntingan terakhir saya. Kembalikan sekarang
Curtis Bechtel

simpan 3 byte di encoder: lambda n:[n>>4*i&15|i<<4for i in range(8)]dan 1 di decoder: lambda l:sum(x%16<<x//16*4for x in l)untuk skor total 632
Aaron

4

JavaScript (ES6), 8 * (40 + 32) = 576

Encoder menampilkan larik 0 untuk 8bilangan bulat. Dekoder mengambil format yang sama dengan input.

Encoder (40 byte)

E=(n,k=0)=>n?[k|n&15,...E(n>>4,k+16)]:[]

Dekoder (32 byte)

s=>s.map(c=>s|=c%16<<(c/4&~3))|s

Demo

Cobalah online!

Bagaimana?

Input dibagi menjadi 8 blok 4 bit dan setiap blok dikodekan dengan 1 di antara 16 karakter yang mungkin. Bit paling signifikan dari blok terakhir tidak pernah disetel.

       3222222222211111111110000000000
bit:   0987654321098765432109876543210
       \_/\__/\__/\__/\__/\__/\__/\__/
block:  7  6   5   4   3   2   1   0

block #0 is encoded with char. 00 to 0F (NUL to SI)
block #1 is encoded with char. 10 to 1F (DLE to ES)
block #2 is encoded with char. 20 to 2F (' ' to '/')
block #3 is encoded with char. 30 to 3F ('0' to '?')
block #4 is encoded with char. 40 to 4F ('@' to 'O')
block #5 is encoded with char. 50 to 5F ('P' to '_')
block #6 is encoded with char. 60 to 6F ('`' to 'o')
block #7 is encoded with char. 70 to 77 ('p' to 'w')

4

Jelly , (8 + 9) byte * 8 panjang maksimal = 136

b⁴+J’Ɗ⁴¡

Encoder (footer memformat daftar seperti yang akan dijelaskan oleh Python)

Ṣ_J‘Ɗ⁴¡ḅ⁴

Dekoder

Secara teori dimungkinkan untuk memiliki panjang maksimal enam, dapatkah itu dilakukan dalam 22 byte atau kurang?

Tidak mungkin dengan maksimal lima panjang sejak itu saya=0saya=5(127+saya127)=321402081<231-1

Bagaimana?

Sejak 231-1dapat dikodekan sebagai 8 digit heksadesimal ( 7fffffffatau [7,15,15,15,15,15,15,15]) kita kemudian dapat menambahkan indeks berbasis nol dari masing-masing hex-digit dikalikan dengan 16 untuk memastikan konversi seperti itu selalu dalam urutan yang disortir dengan tetap menjaga nilai yang paling kanan pun dalam batas (yaitu [7,15,15,15,15,15,15,15] + [0,16,32,48,64,80,96,112] = [7,31,47,63,79,95,111,127]). Decoding kemudian membalikkan proses yang sama ini.

Encoder :

b⁴+J’Ɗ⁴¡ - Link: integer, n    e.g. 1234
 ⁴       - literal 16               16          
b        - convert to base          [4,13,2]
       ¡ - repeat...
      ⁴  - ...16 times:
     Ɗ   -   last 3 links as a monad:
   J     -     range of length        [1,2,3]     iter 2    iter 3    ...  iter 16
  +      -     add                    [5,15,5]   [5,16,7]   [5,17,9]  ...  [5,30,35]
    ’    -     decrement              [4,14,4]   [4,15,6]   [4,16,8]  ...  [4,29,34]
         -                                                                 [4,29,34]

Dekoder :

Ṣ_J‘Ɗ⁴¡ḅ⁴ - Link: list of integers   e.g. [29,34,4]
Ṣ         - sort                          [4,29,34]
      ¡   - repeat...
     ⁴    - ...16 times:
    Ɗ     -   last 3 links as a monad:
  J       -     range of length           [1,2,3]
 _        -     subtract                  [3,27,31]   [3,26,29]   [3,25,27]  ...  [3,12,1]
   ‘      -     increment                 [4,28,32]   [4,27,30]   [4,26,28]  ...  [4,13,2] 
        ⁴ - literal 16                    16
       ḅ  - from base                     1234

"digit heksadesimal", tentu. ("digit menggunakan heksadesimal polos" lebih panjang, dan "digit" saja menyiratkan desimal.)
Erik the Outgolfer

Saya mengubahnya meskipun seharusnya sudah jelas dari konteks karena saya kemudian segera merujuk ke hex-digit.
Jonathan Allan

Penghitungan Anda dimatikan satu: ada 321402081 kombinasi dengan penggantian dengan panjang maksimal 5, dan 7177979809 dengan panjang maksimum 6.
Anders Kaseorg

@AndersKaseorg oops, begitulah - jadi dimungkinkan dengan panjang maksimum 6 ... memberikan 22 byte untuk dimainkan!
Jonathan Allan

4

Bahasa Pemrograman Shakespeare , 31 * (472 + 383 379 344) = 26505 26381 25296

Skor sebelumnya: 16909322 * (246 + 217) = 7829016086

Ini masih sangat tinggi, tetapi ini adalah yang terendah yang dapat saya pikirkan saat ini.

Encoder:

,.Ajax,.Ford,.Act I:.Scene I:.[Enter Ajax and Ford]Ajax:Remember a pig.Ford:Listen tothy.Scene V:.Ajax:Remember the remainder of the quotient betweenI a big cat.Ford:You be the quotient betweenyou a big cat.Be you nicer zero?If solet usScene V.Remember a pig.Scene X:.Ajax:Recall.Ford:Am I worse zero?If notremember I.If notlet usScene X.Ajax:You zero.Scene L:.Ford:Recall.Ajax:You be the sum ofyou a cat.Am I nicer zero?If sospeak thy.Am I worse zero?If notlet usScene L.

Cobalah online!

Dekoder:

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:You cat.Ford:Open mind.Remember the sum ofyou I.Scene V:.Ajax:Am I nicer a cat?If soyou be twice you.Ford:If soyou be the sum ofyou a pig.If solet usScene V.[Exit Ford][Enter Page]Page:Recall.Ajax:Am I worse a cat?If notyou be the sum ofyou Ford.If notlet usAct I.Open heart

Cobalah online!

Pada dasarnya, jika string berisi karakter dengan kode ASCII (n +1), digit biner ke-n diatur.


344 byte untuk dekoder
Jo King

3

Python 3, (208 byte + 200 byte) * 6 panjang = 2448

Cobalah online! (mengandung keduanya, byte tambahan adalah baris baru di antara mereka).

-4 byte (skor -24) dengan memanfaatkan daftar kosong (yang memungkinkan lebih banyak hal dimulai pada 0)

Encoder (208 byte)

def E(n,h=128):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    d=l=0
    s=[]
    while n>=T(h,d):
        n-=T(h,d)
        d+=1
    for i in range(d):
        while n>=T(h-l,d+~i):
            n-=T(h-l,d+~i)
            l+=1
        s+=[l]
    return s

Dekoder (200 byte)

def D(s):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    s.sort()
    l=0
    d=len(s)
    n=sum(T(128,D)for D in range(d))
    for i in s:
        for j in range(l,i):
            n+=T(128-j,d-1)
        l=i
        d-=1
    return n

Pengamatan:

  • Pengocokan dapat dibalikkan tanpa kehilangan untuk daftar ketat yang tidak bertambah (yaitu diurutkan).

  • Daftar numerik yang tidak bertambah dengan panjang yang sama dapat dipesan secara total (seperti dalam Python).

  • Kita dapat mendefinisikan bahwa daftar diurutkan berdasarkan panjangnya terlebih dahulu untuk membentuk urutan total dari semua daftar yang diurutkan.

  • Kita dapat membentuk urutan diindeks dari daftar ini jika kita mendefinisikan bahwa nilai-nilai hanya berlaku dalam daftar adalah bilangan bulat dari 0ke 127inklusif (yaitu terdapat jumlah terbatas daftar valid dengan panjang L).

Strategi:

  • Encoder: Diberi nomor N, temukan daftar yang Nbenar-benar tidak meningkat.

  • Decoder: Diberikan daftar yang valid (dikocok), urutkan dan kembalikan indeksnya dalam urutan daftar yang valid.

Penjelasan kode umum:

  • T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1

  • Menghitung nth dnomor -simplex

    • Karena d=0selalu1

    • Untuk d=1, n(jumlah titik dalam satu garis titik dengan panjang n)

    • Untuk d=2,saya=1nsaya, (jumlah titik dalam segitiga titik dengan panjang sisi n)

    • Untuk d=3,j=1nsaya=1jsaya, (jumlah titik dalam tetrahedron titik dengan panjang sisi n)

Penjelasan pembuat enkode:

  • def E(n,h=128): d=l=0, s=[]

  • nadalah nomor input, hadalah "nilai tinggi" (yaitu angka tertinggi yang diizinkan + 1), dadalah panjang output akan, sadalah output, ladalah "nilai rendah" (mulai dari 0, dijelaskan lebih lanjut nanti)

  • while n>=T(h,d):, n-=T(h,d),d+=1

  • Ada daftar panjang yang T(h,d)valid d, dan perhitungan kami lebih mudah jika nmerupakan indeks relatif terhadap daftar [0]*d(pada indeks 0) daripada indeks yang sebenarnya, jadi turunkan nsesuai. Ini juga menyesuaikan d(panjang) menjadi benar untuk yang diberikan n.

  • for i in range(d):

  • Secara efektif: "untuk i+1nomor ke-10 dalam daftar"

    • Di sinilah saya akan menjelaskan l, "nilai rendah"

    • Setelah nomor dimasukkan ke dalam daftar, tidak kurang dari itu dapat dimasukkan ke dalam daftar (untuk tetap diurutkan), jadi ladalah nomor terakhir yang ditambahkan ke daftar.

    • while n>=T(h-l,d+~i):, n-=T(h-l,d+~i),i+=1

    • Jika nterlalu besar untuk dikodekan dengan l"angka" ini, maka sesuaikan ndan naikkanl

    • s+=[l]

    • Encode ndengan l"digit" ini.

    • Pada awalnya, kami memiliki hopsi untuk "digit" apa yang akan dimasukkan berikutnya, tetapi begitu kami memasukkan "digit" (yang ditugaskan ke l), kami terbatas pada h-lopsi untuk "digit" berikutnya.

    • Pada awalnya ada T(h,d)daftar yang valid, tetapi kami telah menambahkan "digit" l, mengurangi jumlah "digit" yang tersisa d-1dan jumlah "digit" selanjutnya yang valid h-l, sehingga jumlah daftar yang valid setelah ini adalahT(h-l,d-1)

Penjelasan dekoder:

  • def D(s):, s.sort(), l=0,d=len(s)

  • sadalah daftar input (dikocok), jadi s.sort()itu; ladalah "nilai rendah" ( h"nilai tinggi" hanya literal 128dalam kode untuk menyimpan byte), nadalah nomor keluaran, dadalah panjangnya.

  • n=sum(T(128,D)for D in range(d))

  • Sesuaikan nke titik dalam urutan[0]*length

  • for i in s:

  • Untuk setiap digit:

    • for j in range(l,i):, n+=T(128-j,d-1)

    • Sesuaikan nke titik dalam urutan[...prevdigits, thisdigit, 0...]

      • l=i: Setel "nilai rendah" ke digit terbaru

      • d-=1: Kurangi panjang sejak kami menggunakan angka

  • return n: Setelah n disesuaikan untuk semua digit, itu adalah angka yang tepat; Kembalikan.

Maaf jika ini tidak jelas, tapi ini versi debug nongolf asli saya Coba online! , yang tidak menggunakan daftar kosong, jadi 1 off dari semua angka yang digunakan dalam versi ini


3

Rubi , (36 + 29 bytes) * 8, skor 520

Menyandi:

->n{(0..7).map{|x|(n>>x*=4)%16+x*4}}

Cobalah online!

Membaca sandi:

->a{a.sum{|x|x%16<<(x/4&28)}}

Cobalah online!

Bagaimana itu bekerja:

Angka dikodekan menggunakan potongan 4-bit dan indeks 3-bit.

Decoder mengambil array input dan meletakkan setiap nibble ke tempatnya lagi.


3

Arang , skor 10 * (10 + 15) = 250.

Menggunakan desimal; solusi berbasis basis 16 sebelumnya mencetak 328 296 264.

Dapat menampilkan karakter yang tidak dapat dicetak. Secara khusus, karakter 10 sulit untuk dimasukkan ke Arang.

Encoder, 10 byte:

⭆⮌S℅⁺Iι×χκ

Cobalah online! Tautan adalah untuk mengucapkan versi kode.

Dekoder, 15 byte:

IΣES×﹪℅ιχXχ÷℅ιχ

Cobalah online! Tautan adalah untuk mengucapkan versi kode.

Versi menggunakan daftar skor bilangan bulat 360 296 (basis 16; desimal akan skor 310):

Encoder, 19 byte:

NθIE⁸⁺﹪÷θX¹⁶ι¹⁶×¹⁶ι

Cobalah online! Tautan adalah untuk mengucapkan versi kode.

Dekoder, 18 byte:

IΣEE⁸N×﹪ι¹⁶X¹⁶÷ι¹⁶

Cobalah online!Tautan adalah untuk mengucapkan versi kode.

Versi menggunakan karakter yang dapat dicetak mencetak 360 (adalah 416 384 368 pada basis 16):

Encoder, 19 byte:

⭆⮌S℅⁺Iι×χ⁺κ×⁵⊕׳÷κ⁵

Cobalah online!Tautan adalah untuk mengucapkan versi kode.

Dekoder, 17 byte:

Fθ⊞υ⌈Φθ¬№υκ⭆υ﹪℅ιχ

Cobalah online! Tautan adalah untuk mengucapkan versi kode.


2

Brachylog , 17 + 18 byte * 8 panjang = 280

Encoder:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐ

Dekoder:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐp

Sebuah p dapat ditambahkan ke ujung encoder tanpa efek. Dekoder dijalankan dengan meletakkan hasil (dikocok) sebagai output dan mendapatkan nomor asli di input.

Jika akan ada predikat jumlah kumulatif (diterapkan dengan benar), skor bisa turun menjadi 20

Cobalah online!


@ Delfad0r menambahkan p ke encoder akan membuatnya menjadi kode yang sama untuk encoding dan decoding
Kroppeb

2

05AB1E , skor: (2 + 2 byte ) * 11 panjang maksimum = 44

Encoder (2 byte ):

Cobalah online.

Dekoder (2 byte ):

Cobalah online.

Input dari encoder dan output dari decoder adalah daftar digit.

Port dari jawaban Jelly ke-2 @ ais523 .

Penjelasan:

    # Undelta (automatically prepends a 0)
      #  i.e. [3,0,4,7,8,2,0,1,9] → [0,3,3,7,14,22,24,24,25,34]

{     # Sort
      #  i.e. [14,7,22,25,24,3,0,24,34,3] → [0,3,3,7,14,22,24,24,25,34]
 ¥    # Deltas
      #  i.e. [0,3,3,7,14,22,24,24,25,34] → [3,0,4,7,8,2,0,1,9]

Karena menambahkan nol ke output, panjang output adalah panjang input + 1. Sejak231-1 memiliki panjang 10 digit, panjang maksimum output adalah 11.


2

Gol> <> , 8 * (14 + 13) = 216

Encoder, Coba online! , 14 byte:

I8FfPSD8*L+o|;

Dekoder Coba online! , 13 byte:

iEh8SD4*2$X*+

Karena ini dapat menampilkan karakter ascii yang tidak dapat dicetak, sehingga mengacaukan dekoder, sekarang ada versi yang menggunakan angka dalam output / input:

Encoder, Coba online! , 14 byte:

I8FfPSD8*L+N|;

Dekoder Coba online! , 13 byte:

IEh8SD4*2$X*+

Pengkodean:

Pengkodean bekerja dengan memecah nomor yang diberikan menjadi potongan 8 x 4bit. Potongan-potongan ini kemudian bergeser ke kanan sebanyak 3 bit dan lokasi asli potongan ditambahkan pada bagian akhir sebagai angka antara 0 dan 7. Dengan demikian pengodeannya terlihat seperti ini:

0AAAABBB
 |__|    -> the original part of the number
     |_| -> the position of the chunk inside the original number 0 = LSB and 7 = MSB

2

Perl 6 , 10 * (10 + 12) = 340 220

Encoder:

{^@_ Z~@_}

Dekoder:

{.sort X%10}

Cobalah online!

Fungsi enkoder mengunci setiap digit dengan indeks-0 angka. Kemudian encoder mengurutkan daftar angka dan mendapatkan modulo sebanyak 10, dengan kata lain digit kedua dari angka tersebut.

Totalnya adalah 10, karena itu panjang maksimum 2 31 -1.


1

Haskell , 10 * (23 + 51) = 740

Berikut adalah program yang menyandikan, mengacak, mendekode, dan memvalidasi nilai: Cobalah secara online!

Encoder, 23 byte

zipWith((+).(10*))[0..]

Cobalah online!

Decoder, 51 byte

map snd.sortOn fst.map(`divMod`10)
import Data.List

Cobalah online!

Penjelasan

Karena kami diizinkan menggunakan input sebagai digit desimal, kami akan menggunakannya .. Encoder memetakan setiap digit yang terjadi 10*index + digit, perhatikan bahwa semua digits akan berada di [0..9]sehingga kami dapat membalikkan di atas dengan menggunakandivMod . Setelah mengembalikan indeks dan digit itu hanya masalah mengurutkan berdasarkan indeks dan menyingkirkannya.

Solusinya diharapkan bekerja untuk nilai hingga 231-1=2147483647 yang panjangnya 10 digit, jadi titik kode maksimum yang akan kita dapatkan adalah 99=81<128. Juga setiap digit akan dikonversi ke "karakter", jadi kita akan berakhir dengan panjang maksimal 10.


1

Sekam , 10 * (7 + 8) = 150

Port langsung dari solusi Haskell saya hanya dengan pengamatan itu 109=90<128(Husk Nadalah berbasis 1):

Encoder, 7 byte

zo+*10N

Cobalah online!

Decoder, 8 byte

m→Ö←m‰10

Cobalah online!


1

APL (Dyalog Unicode) ,L.E+L.D=36;SEBUAH=8288.

d←{16n-16×⍳≢n←⍵[⍋⍵]}
e←(⊢+16×⍳∘≢)16⊥⍣¯1

Cobalah online!(berisi 5 byte tambahan untuk penugasan dan baris baru).

Penggunaan ⎕IO←0

Bagaimana:

(⊢+16×⍳∘≢)16⊥⍣¯1  Encoder; input 1234
          16⊥⍣¯1  Convert input to base 16  4 13 2
      ⍳∘≢           [0..length of the list-1]  0 1 2
   16×              times 16  0 16 32
 ⊢+                 plus the original list  4 29 34

{16n-16×⍳≢n←⍵[⍋⍵]}  Decoder; input   34 4 29
              [⍋⍵]   Grade  up  2 0 1
                    Index  with that list  4 29 34
           n        assign that to n
      16×⍳≢          16×[0..length(n)-1]  0 16 32
    n-               subtract that from n  4 13 2
 16                 Decode from base 16  1234

1

PHP, 8 * (44 + 53) = 776

encoder, 44 byte:

for(;$n=&$argn;$n>>=4)echo$n&15|16*$i++," ";

mencetak daftar integer yang dipisahkan spasi. Jalankan sebagai pipa dengan -nR.

maksimum 8 byte dengan 4 bit data (nibble bawah) dan 3 bit berat (nibble atas).

Sederhananya:
Letakkan setiap digit hex dalam karakter sendiri dan gunakan bagian atas byte untuk menyimpan posisi digit.

contoh:

1457893891( 0x56e5b203) Akan berubah menjadi
0x03, 0x10, 0x22, 0x3b, 0x45, 0x5e, 0x66, 0x75
3 16 34 59 69 94 102 117

dekoder, 53 byte:

while($i++<8)$n+=(15&$x=$argv[$i])<<($x>>4)*4;echo$n;

atau

while($i++<8)$n+=(15&$x=$argv[$i])<<($x/4&~3);echo$n;

atau

for(;$i<9;$x=$argv[++$i])$n+=$x%16<<($x/4&~3);echo$n;

ambil bilangan bulat dari argumen baris perintah. Jalankan dengan -nr.


Cobalah secara online .


0

Python 2 , 10 * (68 + 54) = 1220

e=lambda n:"".join(chr(int(`i`+j))for i,j in enumerate(`n`)if j<'L')
d=lambda s:int("".join(`ord(c)%10`for c in sorted(s)))

Cobalah online!

EDIT: Terima kasih kepada Jo King untuk petunjuknya - tidak yakin mengapa saya mengimbangi 32, dalam retrospeksi.

Mengkodekan posisi dan nilai setiap tempat sebagai karakter tunggal, dimulai dengan [spasi] (posisi 0, nilai 0) byte NUL 0x0.

Dipecahkan oleh:

  • mengurutkan string (Python akan mengurutkan karakter berdasarkan nilai urut mereka)
  • mengubah setiap karakter menjadi nilai ordinalnya
  • mengambil digit terakhir dari setiap bilangan bulat ordinal
  • bergabung dengan bilangan bulat menjadi sebuah string
  • mengubah string yang bergabung kembali menjadi int

Apakah Anda perlu 32offset? Selain itu, [-1]bisa jadi %10, di tempat yang tepat
Jo King

0

C (gcc) , 10 * 112 = 1120

c,i;e(i,s)char*s;{for(c=1;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=--c%10*pow(10,c/10));s=i;}

Cobalah online!

Saya memiliki variabel global, tetapi sebenarnya tidak menyampaikan info apa pun di antara dua fungsi. Deklarasi variabel untuk cdigunakan di kedua fungsi menghemat saya 2 byte dalam panjang kode.

Versi yang menggunakan ASCII yang dapat dicetak hanya untuk penalti 3 byte ada di sini:

c,i;e(i,s)char*s;{for(c=32;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=(c-=32)%10*pow(10,c/10));s=i;}

Terima kasih @ceilingcat untuk peningkatan 70 poin.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.