The VIC cipher adalah salah satu pensil dan kertas cipher yang paling rumit yang pernah disusun. Digunakan pada 1950-an oleh mata-mata Soviet Reino Häyhänen, dengan nama sandi "VICTOR", prinsip utamanya adalah keamanan melalui kebingungan; a banyak kebingungan.
Tugas Anda adalah menulis program atau fungsi yang akan mengambil pesan dan menyandikannya menggunakan sandi VIC. Saya juga telah memposting tantangan decoder cipher VIC di sini . Jika salah satu dari petunjuk berikut tidak jelas, jangan ragu untuk menanyakannya di komentar. Instruksi diadaptasi dari situs ini .
Menyandikan sandi VIC
Persiapan
Anda akan membutuhkan lima input:
- pesan teks biasa
- kata kunci atau frasa pendek yang berisi huruf paling umum dalam bahasa Anda
- frasa kunci, seperti kutipan atau garis dari sebuah lagu (setidaknya 20 karakter)
- tanggal (atau nomor lain yang enam digit atau lebih)
- nomor agen pribadi
Dalam praktiknya, keempat terakhir ini harus disepakati sebelumnya oleh pengirim dan penerima, termasuk apakah nomor agen pengirim atau penerima digunakan dalam penyandian.
Contoh pesan saya adalah: We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
Kami akan menyandikannya dalam bahasa Inggris (meskipun Anda dapat menggunakan bahasa dan alfabet apa pun yang Anda suka) dan huruf paling umum dalam alfabet bahasa Inggris adalah A, E, I, N, O, R, S, T
. Saya akan menggunakan kata kunci SENATORI
.
Ungkapan kunci saya adalah kutipan oleh Richard Feynman: "Prinsip pertama adalah bahwa Anda tidak boleh membodohi diri sendiri - dan Anda adalah orang yang paling mudah untuk dibodohi."
Sebagai tanggal, saya akan menggunakan 31 Juli 2016 (dalam format 3172016
), yang merupakan hari ketika saya menulis deskripsi ini.
Nomor pribadi yang saya pilih untuk diri saya adalah 9
.
Ringkasan langkah-langkah
- Turunkan kunci perantara untuk digunakan dalam langkah-langkah berikut.
- Bangun dan terapkan kotak-kotak straddling.
- Bangun dan terapkan tabel transposisi pertama.
- Bangun dan terapkan tabel transposisi kedua (terganggu).
- Akhiri pesan dengan memasukkan grup indikator pesan.
Submekanisme
Dua hal lagi untuk dijelaskan sebelum kita masuk ke inti permasalahan: proses penambahan rantai dan pengurutan.
Selain rantai, juga dikenal sebagai generator Fibonacci yang lambat, bekerja dengan mengambil urutan digit awal, menambahkan dua digit pertama tanpa membawa (menambahkannya bersama-sama lalu mod 10
) dan menambahkan hasilnya ke akhir. Sebagai contoh:
79081
7 + 9 = 6
790816
9 + 0 = 9
7908169
0 + 8 = 8
79081698
8 + 1 = 9
790816989
1 + 6 = 7
7908169897
... and so on
Sequentializing pada dasarnya mengambil urutan huruf atau digit dan memberi label berdasarkan urutan abjad / numerik. Duplikat berlabel kiri ke kanan. Sebagai contoh:
E X A M P L E
0 # A
1 0 2 # Es
1 0 3 2 # L
1 0 4 3 2 # M
1 0 4 5 3 2 # P
1 6 0 4 5 3 2 # X
3 3 0 5 8 4 2 0 4 7 5 4 8 1
0 1 # 0s
0 1 2 # 1
0 3 1 2 # 2
4 5 0 3 1 2 # 3s
4 5 0 6 3 1 7 8 2 # 4s
4 5 0 9 6 3 1 7 10 8 2 # 5s
4 5 0 9 6 3 1 7 11 10 8 2 # 7
4 5 0 9 12 6 3 1 7 11 10 8 13 2 # 8s
Saya menggunakan pengindeksan nol di sini, tetapi indeks sesuka Anda.
1. Tombol Menengah
Membagi 20 huruf pertama dari frasa kunci menjadi dua kelompok 10 dan mengurutkan masing-masing secara individual, yang akan kita panggil S1
dan S2
.
THEFIRSTPR
S1: 8201357946
INCIPLEIST
S2: 2603751489
Pilih pengidentifikasi pesan 5 digit acak, M
(ini bisa menjadi salah satu input jika Anda mau):
M = 47921
Kurangi, tanpa meminjam (kurangi mod 10
), lima digit pertama dari tanggal utama 3172016
dari M
:
M 47921
date - 31720
= 16201
Chain menambahkan hasilnya hingga Anda memiliki sepuluh digit:
1620178218
Tambahkan digit ini ke S1
, tanpa membawa atau mod 10
, untuk mendapatkan G
:
1620178218
S1 + 8201357946
G = 9821425154
Di atas S2
, tulis urutan 0123456789. Temukan setiap digit G
dalam urutan 0123456789 dan ganti dengan angka tepat di bawahnya S2
. Hasilnya adalah T
.
0123456789
S2 2603751489
G 9821425154
T 9806705657
Gunakan penambahan rantai untuk memperluas T
ke 60 digit.
9806705657
becomes
980670565778637511245490262369939288595822106344304316978734
50 digit terakhir ini, dalam lima baris masing-masing sepuluh digit, membentuk U
blok.
T 9806705657
U 7863751124
5490262369
9392885958
2210634430
4316978734
Dua digit terakhir yang tidak sama dari U
blok secara individual ditambahkan ke nomor pribadi agen untuk memberikan lebar dari dua transposisi, p
dan q
.
9 + 3 = 12 (p, lebar transposisi pertama) 9 + 4 = 13 (q, lebar transposisi kedua)
Urutkan T
dan gunakan urutan ini untuk menyalin kolom U
blok, dari atas ke bawah, ke baris digit baru V
,.
T 9806705657
seqT 9804612537
U 7863751124
5490262369
9392885958
2210634430
4316978734
V 69911 56837 12548 26533 30206 13947 72869 49804 84323 75924
Urutkan p
digit pertama untuk mendapatkan kunci untuk transposisi pertama K1
, dan q
digit berikut untuk kunci untuk yang kedua K2
.
First 12 6 9 9 1 1 5 6 8 3 7 1 2
K1 6 10 11 0 1 5 7 9 4 8 2 3
Next 13 5 4 8 2 6 5 3 3 3 0 2 0 6
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
Akhirnya, sekuensial baris terakhir dari U
blok yang akan Anda dapatkan C
, tajuk kolom untuk kotak-kotak yang mengangkang:
U5 4316978734
C 3105968724
2. Kotak-kotak Straddling
Pertama, saya akan memberikan contoh pada kotak-kotak saya kemudian menjelaskan prinsip-prinsip dalam membuatnya dengan cara itu:
3 1 0 5 9 6 8 7 2 4
S E N A T O R I
2 B D G J L P U W Y .
4 C F H K M Q V X Z #
Baris pertama huruf adalah kata kunci singkat kami SENATORI
. Kata kunci Anda dapat berupa string apa pun tanpa duplikat, tetapi karena itu menentukan baris teratas kotak-kotak Anda, pilihlah dengan bijak. Di atas kata kunci C
, dan baris lainnya adalah sisa dari alfabet Anda dalam urutan apa pun yang Anda pilih. Dalam kasus saya, saya mengisi kotak-kotak dengan alfabet Latin lainnya, tanda baca .
dan tanda untuk demarkasi angka #
. Pada dasarnya, kotak-kotak adalah sandi pengganti yang bagus. Misalnya, "E" akan diganti dengan 1
, dan "W" akan diganti dengan 27
.
Setelah kami menyandikan pesan plaintext kami dengan kotak-kotak ini, tetapi pertama-tama, kita perlu membuat awal pesan kami menjadi kurang jelas dengan memecahnya pada posisi acak, dan membuatnya menjadi huruf besar semua. Untuk menunjukkan awal asli lainnya, kami menggunakan dua pemberhentian penuh..
We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
menjadi
HING ELSE. MOVE TO SAFEHOUSE FOXTROT#3#.. WE ARE
DISCOVERED. TAKE WHAT YOU CAN. BURN EVERYT
Kami menyandikan dengan kotak-kotak, memberi kami:
407020 1293124 496481 96 354114062831 416479869443442424 271 581
2173436481812124 95451 274059 22628 435024 232880 14818229
Jika panjang pesan tidak habis dibagi 5, kami menambahkan beberapa karakter nol untuk mengisi pesan. Pesan kami adalah 109 digit, jadi saya akan menambahkan satu nol: "4".
40702 01293 12449 64819 63541 14062 83141 64798 69443 44242 42715
81217 34364 81812 12495 45127 40592 26284 35024 23288 01481 82294
Catatan: Karena pesan contoh saya tidak mengandung angka, saya akan mengatakan di sini bahwa Anda dapat menunjuk, katakanlah, sebagai #3#
, yang disandikan seperti di 44344
sini.
3. Transposisi Pertama
Buat tabel transposisi dengan menulis K1
(dari bagian Tombol Menengah) diikuti dengan pesan yang disandikan dari langkah sebelumnya, dalam baris dengan panjang yang sama, di bawah tombol:
K1 6 10 11 0 1 5 7 9 4 8 2 3
4 0 7 0 2 0 1 2 9 3 1 2
4 4 9 6 4 8 1 9 6 3 5 4
1 1 4 0 6 2 8 3 1 4 1 6
4 7 9 8 6 9 4 4 3 4 4 2
4 2 4 2 7 1 5 8 1 2 1 7
3 4 3 6 4 8 1 8 1 2 1 2
4 9 5 4 5 1 2 7 4 0 5 9
2 2 6 2 8 4 3 5 0 2 4 2
3 2 8 8 0 1 4 8 1 8 2 2
9 4
Mengambil kolom bernomor sesuai nomornya, kita dapat:
060826428 246674580 151411542 246272922 961311401 082918141
4414434239 118451234 334422028 293488758 0417249224 794943568
4. Transposisi Kedua
Transposisi pertama relatif sederhana. Yang ini, bagaimanapun, adalah transposisi yang terganggu. Pola gangguan ditentukan oleh lebar tabel dan kunci. Dalam contoh kita, kita memiliki 110 digit dan 13 kolom, artinya kita akan memiliki 8 baris penuh dan 6 sisanya. Kami mulai mengisi baris pertama, tetapi berhenti di kolom 0, dan melanjutkan sebagai berikut:
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 stop at 0
2 4 6 6 7 4 5 8 0 1 continue in a triangle pattern
5 1 4 1 1 5 4 2 2 4 6
2 7 2 9 2 2 9 6 1 3 1 1
4 0 1 0 8 2 9 1 8 1 4 1 4 until the end
4 1 4 4 3 4 2 3 9 1 1 restart and stop at 1
8 4 5 1 2 3 4 3 3 4 4 2
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 restart and stop at 2
Kemudian kita mengisi beberapa ruang terakhir dengan digit yang tersisa.
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 7 2 4 9
2 4 6 6 7 4 5 8 0 1 2 2 4
5 1 4 1 1 5 4 2 2 4 6 7 9
2 7 2 9 2 2 9 6 1 3 1 1 4
4 0 1 0 8 2 9 1 8 1 4 1 4
4 1 4 4 3 4 2 3 9 1 1 9 4
8 4 5 1 2 3 4 3 3 4 4 2 3
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 5 6 8
Sekarang, kita membaca kolom dengan cara yang persis sama dengan yang kita lakukan pada transposisi pertama.
71431148 42711925 861904185 22614147 45499243 28261334 80218938
641701404 025244820 645224398 271283226 94944438 064214521
Dan bagi semuanya menjadi 5 kelompok:
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189
38641 70140 40252 44820 64522 43982 71283 22694 94443 80642 14521
5. Finalisasi Pesan
Langkah terakhir adalah menyisipkan pengidentifikasi pesan acak kami 47921
,, ke dalam pesan itu sendiri. Digit terakhir dari tanggal kunci 6
menunjukkan jarak grup dari akhir.
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189 38641
70140 40252 44820 64522 43982 47921 71283 22694 94443 80642 14521
Catatan untuk tantangan ini
- Anda diberi minimal lima input: pesan, kata kunci huruf, frasa kunci, tanggal, dan nomor pribadi. Anda dapat memasukkan dua input tambahan: pengidentifikasi pesan acak dan null yang diperlukan untuk mengganti pesan, atau fungsi Anda dapat menghasilkan beberapa angka acak sendiri.
- Anda dapat mengasumsikan semua input valid, dengan jumlah digit dan huruf yang benar (pengidentifikasi pesan 5 digit, setidaknya 20 digit untuk frasa kunci, dan sebagainya). Anda dapat mengasumsikan bahwa string Anda (pesan dan kata kunci) telah menghapus semua tanda baca dan spasi kecuali untuk yang Anda izinkan dalam versi Anda, dan bahwa angka-angka tersebut sudah ditandai dengan tanda-tanda angka.
- Kata kunci pertama tidak boleh memiliki surat duplikat di dalamnya, dan dalam kode Anda, Anda dapat mengasumsikan bahwa tidak pernah ada surat duplikat.
- Bahasa yang Anda gunakan untuk menyandikan tidak menjadi masalah, selama bahasa tersebut sudah ada sebelumnya, alfabetnya sudah ada sebelumnya, dan Anda menentukan bahasa yang Anda gunakan dalam jawaban Anda.
- Alfabet mana pun yang Anda gunakan untuk kotak-kotak yang mengangkang, Anda dapat menambah atau menghapus simbol untuk menutup kotak-kotak itu. Tetapkan untuk apa Anda menggunakan simbol-simbol itu (misalnya, tanda baca, simbol "pesan awal" yang terpisah, simbol untuk kata-kata umum). Anda dapat meninggalkan tanda angka sepenuhnya dan mengeja angka-angka atau memasukkan setiap digit di kotak-kotak, menggunakan slot di mana tanda angka adalah untuk sesuatu yang lain. Silakan tentukan kotak-kotak mana yang Anda gunakan dalam jawaban Anda.
- Outputnya harus berupa string kelompok lima digit yang dipisahkan ruang, daftar bilangan bulat lima digit, atau yang serupa.
- Saya menggunakan pengindeksan nol dan
0123456789
dalam contoh saya. Anda dapat menggunakan pengindeksan 1 dan1234567890
, atau beberapa sistem lain dalam jawaban Anda, selama Anda menentukan apa yang Anda gunakan.
Berikut ini contoh implementasi pada Ideone .
Ini adalah posting yang panjang dan saya menulis sebagian besar dengan tangan, jadi jika ada bagian yang membingungkan dalam posting ini atau kesalahan dalam penghitungan dan transpos saya, beri tahu saya. Semoga berhasil dan bermain golf dengan baik!
sumber
adding the first two digits without adding
Apakah maksud Anda membawa?without borrowing
danwithout carrying
? Apakah yang Anda maksud menambah dan mengurangi mod10
, yaitu(6+7) mod 10 = 3
dan(6-8) mod 10 = 8
?Jawaban:
Python 3 ,
14231348132413161300128612501249120912061204 byteIni jelas merupakan golf terpanjang yang pernah saya lakukan, dan satu-satunya golf di mana saya sangat khawatir kehabisan nama variabel satu karakter. Saran bermain golf diterima. Cobalah online!
Saya menyandikan dengan huruf latin huruf besar dengan karakter tambahan
.
dan#
, menggunakan pengindeksan 0 dan0123456789
ketika mengkonversig
ket
. Kotak-kotak saya dalam format yang mirip dengan contoh berikut:Sunting: -63 bytes berkat saran TuukkaX untuk mempersingkat beberapa fungsi yang sering digunakan dengan variabel satu huruf. -12 byte dari membuat
a, g, t
lebih ringkas.Edit: -24 byte dari pembuatan dengan menghapus nama variabel untuk kunci perantara yang hanya digunakan sekali, yaitu
a, g, s, S, k, K
.Edit: -74 byte dari konsolidasi
H(), T() and C()
.Edit: -1 byte terima kasih kepada Nick A untuk saran mereka berubah
ord(s[i])+ord(s[i+1])
kesum(map(ord,s[i:i+2]))
. -2 byte dari mengubah 2+=[a]
panggilan menjadi+=a,
. -13 byte dari mengubah caraG()
menemukan indeks minimums
. -2 byte dari berubahy=(y+1)%v
menjadiy=-~y%v
. -15 byte dari menugaskank.index()
keK
. -4 byte dari menugaskan10
keW
. -5 byte dari penetapan1-I(d[-1])
keX
dalamV
. -3 byte dariC()
loop utama penulisan ulang . -2 byte dari pengorganisasian kembaliT()
.Tidak melakukan pelanggaran:
sumber
ord(seq[i])+ord(seq[i+1])
untuksum(map(ord,seq[i:i+2]))
menyimpan 1 karakter, saya percaya.C,
288027692766276227432741273926992458 byteAstaga. Ini adalah program terpanjang yang pernah saya miliki untuk bermain golf. Ini juga yang pertama di mana saya benar-benar kehabisan nama-nama variabel karakter tunggal untuk lingkup global dan karenanya harus beralih menggunakan beberapa karakter 2 (fakta bahwa saya tampaknya tidak dapat redecare variabel tidak membantu). Tips golf sangat dihargai.
Tidak disatukan
Kompilasi tanpa peringatan, tidak seperti versi golf. Perubahan kecil yang dilakukan pada versi golf tidak akan tercermin dalam versi yang tidak diklik ini.
Catatan
Ini menggunakan kotak-kotak yang mirip dengan yang berikut ini untuk menyandikan pesan:
Ini mengasumsikan bahwa semua string yang berlaku diberikan dalam huruf besar. Pesan juga harus memiliki semua tanda baca kecuali periode dihapus dan semua angka ditandai dengan
#
s, sedangkan frasa kunci harus menghapus semua tanda baca.Pesan yang dikodekan yang dihasilkan adalah output ke STDOUT sebagai string kelompok lima digit yang dipisahkan oleh ruang.
Pesan input harus dalam bahasa Inggris.
Saya akan menggabungkan beberapa fungsi yang saya gunakan, tetapi kemudian saya harus menggunakan lebih banyak nama variabel dua huruf, membuat program akhir lebih lama daripada dengan beberapa fungsi lainnya.
Ini saat ini tidak mengasumsikan bahwa kata kunci (setidaknya dalam bahasa Inggris) selalu akan berisi set huruf yang sama, dan dengan demikian menggantikannya dengan menghapus duplikat, memanipulasi kotak-kotak, dll. Kemampuan ini tampaknya tidak diperlukan oleh OP, jadi saya saat ini bermain golf dari byte ekstra yang tidak perlu yang mengambil.Diperbarui untuk versi golf.sumber
JavaScript (ES6),
946938953 byteSaya melihat selama akhir pekan belum ada entri JS untuk ini, jadi inilah upaya saya (menit terakhir). Menerapkan dan bermain golf ini gila seperti menyenangkan!
Cuplikan Demo
Tampilkan cuplikan kode
Edit: -8 byte
Menyadari ada tanda kurung tambahan di sekitar fungsi
S,J,A,Q
Edit: +15 byte
Memperbarui logika untuk bagaimana
message id
ditempatkan dalam pesan akhir (sekarang 1-diindeks dan 0 tidak termasuk dalam output).Tidak disatukan
Catatan
Ini menggunakan kotak-kotak yang mirip dengan yang berikut ini untuk menyandikan pesan:
Semua string diberikan dalam huruf besar. Pesannya adalah alfanumerik Latin (plus
.
dan#
) dan seharusnya semua tanda baca (kecuali periode) dihapus. Semua angka harus sudah ditandai dengan#
s. Frasa kunci harus menghapus semua tanda baca / spasi.Pesan yang dihasilkan dikembalikan sebagai array string 5 digit.
Perangkat tambahan
Saya merasa ada cara untuk menyalahgunakan "Semua bahasa" untuk menghemat beberapa byte. Jika saya punya lebih banyak waktu, saya akan mengonfigurasi ulang ini untuk menganggap bahasa itu seperti bahasa Hawaii yang hanya memiliki 12 huruf.
Saran bermain golf selalu diterima.
sumber
message identifier
sepertinya7
jauh dari akhir, bukan6
. Juga, dalam versi Anda yang tidak disatukan, hal yang samaId
tampaknya6
jauh dari awal alih-alih akhir.1
berarti akhir di mana Anda mengatakanmessage identifier
harus pergi pada0
? Saya bisa mengubahnya, saya hanya perlu tahu.0
yangmessage identifier
harus dihilangkan dari output.Clojure,
11971212 byteWah, saya lelah.
Pembaruan: Menambahkan lokasi pemisahan pesan yang diperlukan secara acak, versi ungolfed menggunakan lokasi yang sama dengan contoh yang diberikan sehingga algoritme dapat dengan mudah diverifikasi.
Input sampel dan uji kasus:
Tidak Disatukan:
Ini memiliki implementasi alternatif pada kotak-kotak
B
yang sama dengan definisi tugas. Tetapi pengiriman menggunakan yang lain di mana huruf yang tidak terpakai pertama mengisi baris ke-2 dan kemudian ke-3 alih-alih mengisi kolom demi kolom.sumber
coords
dihasilkan dua kali, pertama menghasilkan bentuk segitiga dan kemudian mengisi koordinat yang hilang. "Padding to length of multiply of N" mungkin memiliki solusi yang lebih elegan daripada menggabungkan elemen N - 1 dan mempartisi ke panjang N.(split-at 49 mymsg)
, 49 harus seperti(rand-int(count mymsg))
jawaban yang benar akan sedikit lebih dari 1200 byte. zzz