Technoplaneta – šifrovací hra pro děti

Úkol 2-5 – Užvaněný šnek

Ondro z týmu ondroalicamiska pondělí, 13. březen, 20.04

nádherné, pôsobivé, trefné a veľmi zábavné

Tomáš Bláha úterý, 14. březen, 21.34

Využiju prostor a dám trochu nahlédnout do naší kuchyně. Při sestavování takovéto šifry, kdy chceme místo nečitelné změti písmenek v mřížce mít něco čitelného, tak jsme poněkud omezeni. Tak předně ukrytá zpráva musí být kratší, tj. otvorů v mřížce musí být méně než čtvrtina, aby zbyla nějaká volnost a nějaká nepoužitá písmenka, která lze doplnit libovolně a zformulovat novou zprávu.

První nejmenší mřížka byla snadná a udělal jsem ji ručně. Zvolené heslo orel bylo celkem snadné doplnit, protože jsem využil jen 4 znaky ze 16. Větší mřížky měly ale o dost méně výhodný poměř mezi znaky danými z předchozí zprávy a znaky volně k doplnění, protože jsme nechtěli, aby velikost mřížky rostla moc rychle.

Pokud byste si chtěli zašnekovat vlastní zprávu, tak níže najdete prográmek, kterým jsem větší mřížky sestavoval. Je velice primitivní, neumí ani české znaky, a prostě jen vyzkouší hrubou silou hromadu náhodných mřížek a vypíše na výstup mustr, jak by musela vypadat zpráva:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char** argv) { int len = strlen(argv[1]); int size = 1;

while(size * size < len) size++;

printf("delka textu: %d\n", len); printf("velikost mrizky: %dx%d\n\n", size, size);

char** mrizka = new char*[size]; for(int i = 0; i < size; i++) { mrizka[i] = new char[size]; for(int j = 0; j < size; j++) mrizka[i][j] = '.'; }

int x = 0, y = size - 1, dir = 0;

for(int i = 0; i < len; i++) { mrizka[x][y] = argv[1][i]; if(i == len - 1) break;

    again: switch(dir) { case 0: if(y > 0 && mrizka[x][y - 1] == '.') { y--; break; }

dir++; case 1: if(x < size - 1 && mrizka[x + 1][y] == '.') { x++; break; }

dir++; case 2: if(y < size - 1 && mrizka[x][y + 1] == '.') { y++; break; }

dir++; case 3: if(x > 0 && mrizka[x - 1][y] == '.') { x--; break; }

dir = 0; goto again; } }

for(int y = 0; y < size; y++) { for(int x = 0; x < size; x++) { printf("%c", mrizka[x][y]); } printf("\n"); } printf("\n");

for(int size2 = size + 2; size2 < size + 3; size2++) { printf("velikost nadmrizky: %dx%d\n", size2, size2); printf("pocet der: %d\n\n", size * size / 4);

for(int rep = 0; rep < 100000; rep++) { char** mrizka = new char*[size2]; for(int i = 0; i < size2; i++) { mrizka[i] = new char[size2]; for(int j = 0; j < size2; j++) mrizka[i][j] = '.'; }

for(int i = 0; i < size * size / 4; i++) { while(1) { int x = rand() % size2; int y = rand() % size2;

if(mrizka[x][y] == '.' && mrizka[size2 - 1 - y][x] == '.' && mrizka[size2 - 1 - x][size2 - 1 - y] == '.' && mrizka[y][size2 - 1 - x] == '.' && (size2 % 2 == 0 || x != size2 / 2 || y != size2 / 2)) { mrizka[x][y] = '1'; mrizka[size2 - 1 - y][x] = '2'; mrizka[size2 - 1 - x][size2 - 1 - y] = '3'; mrizka[y][size2 - 1 - x] = '4'; break; } } }

for(int y = 0; y < size2; y++) { for(int x = 0; x < size2; x++) { printf("%c", mrizka[x][y]); } printf("|"); } printf(" ");

for(int i = 0; i < len; i++) { for(int y = 0; y < size2; y++) { for(int x = 0; x < size2; x++) { if(mrizka[x][y] == '1' + i / (size * size / 4)) { mrizka[x][y] = argv[1][i]; goto za; } } }             za: continue; }

/*             for(int y = 0; y < size2; y++)             {                 for(int x = 0; x < size2; x++)                 {                     printf("%c", mrizka[x][y]);                 }                 printf("\n");             }             printf("\n"); */ /* Odsnekovani mrizky */ int x = 0, y = size2 - 1, dir = 0; for(int i = 0; i < size2 * size2; i++) { printf("%c", mrizka[x][y]); mrizka[x][y] = '*'; if(i == size2 * size2 - 1) { printf("\n"); break; }

            again2: switch(dir) { case 0: if(y > 0 && mrizka[x][y - 1] != '*') { y--; break; }

dir++; case 1: if(x < size2 - 1 && mrizka[x + 1][y] != '*') { x++; break; }

dir++; case 2: if(y < size2 - 1 && mrizka[x][y + 1] != '*') { y++; break; }

dir++; case 3: if(x > 0 && mrizka[x - 1][y] != '*') { x--; break; }

dir = 0; goto again2; } } } } }

Volal jsem ho následovně se sérií filtrů, aby se zcela nepoužitelné výsledky hned zahazovaly. Odstraňoval jsem duplicity, dvě samohlásky za sebou a také jsem odstraňoval díry ležící vedle sebe:

./snek hurAkebuleboduje|grep -v "[a-zA-Z][a-zA-Z][a-zA-Z]"|grep -v "[Aaeiou][Aaeiou]"|sort|uniq|grep -v "11"|grep -v "22" |grep -v "33"|grep -v "44"

Ale výsledek nebyl nic moc, cirka 600 možností, ale divná písmenka u sebe, nic moc mě nenapadalo, tak jsem posléze rozvolnil pravidla a připustil díry, které spolu sousedí, takže výsledné mřížky nejsou až tak rovnoměrně rozložené, jak by člověk chtěl. Ale doslova na první pohled mě upoutala varianta, ve které bylo vidět na začátku možnost slova puzzle a to byl výborný start:

.1..4.|31.222|.1....|....3.|444.31|.2..3.|    .u..l.h..d.b..á.o..uj.ru.ke.eb.e....
                                              puzzlehnedubýváformujkrutkeřeblednou

Asi je vidět, proč keře blednou, ono se toho moc udělat nedalo :-) Při sestavování té největší mřížky už bylo opravdu jen pár možností a málo volnosti a proto se už dala dát jen krátká sice čitelná, ale izolovaná slova. Na nějakou smysluplnou větu už nebyl potenciál:

.n.v.bz.p.m.ud.b.e.ft.e.e.ku.hr.u.uř.e.jl.n.or.o.el.ýz.ká.du....
o.o.zj.p.m.dř.u.e.uh.e.e.ur.ne.b.bu.z.uv.f.nk.t.lá.ýk.rl.de.....
.n.l.ju.d.p.řm.u.á.ho.u.e.re.dl.e.ub.z.ýr.o.kn.t.ek.zb.ve.uf....
e.h.ku.d.u.řb.m.j.ek.u.o.rn.e.rz.e.bý.p.lu.o.fd.e.áz.uv.lt.n....
n.o.b.jd.m.p.řu.e.f.hu.e.e.r.dá.u.uk.r.ýl.o.ke.l.ez.zb.vu.tn....
n.á.up.d.m.řu.u.l.ze.u.e.ro.ek.ý.be.j.ku.d.no.h..vt.rb.ez.lf....
o.er.ý.m.př.u.e.vl.d.e.er.n.ne.z.ud.u.bk.u.ku.o..bá.zj.fl.th....
o.lu.b.m.dř.u.e.rz.n.e.ur.n.hk.l.ub.p.ju.á.of.e.e.zý.vk.td.e....
r.v.ub.m.u.jp.ř.e.of.e.n.he.u.nr.u.ze.d.bl.k.to.á.dk.zl.ýe.u....
o.v.ru.m.u.řj.e.e.lo.e.n.rh.e.ud.d.bp.k.zý.u.fe.tn.lu.zb.ák.....
ot.lý..mř.pu..ez.ád..er.en..ne.l.ud.u.bk.r.ku.o.fe.jz.bv.hu.....
o.te.u.m.řp.u.e.zv.o.e.re.n.e.uý.d.bj.k.zd.u.fh.l.lb.ur.án.k....
.uý.k.p.řm.e.d.zd.e.e.re.o.u.or.l.ub.z.ul.á.kf.tv.bu.je.nn.h....

n.o.b.jd.m.p.řu.e.f.hu.e.e.r.dá.u.uk.r.ýl.o.ke.l.ez.zb.vu.tn.... neonbojdůmopkřupelfchumeleurodámufukarkýlaočkemlžezazbavujtnouti

z týmu CRUSHERS čtvrtek, 16. březen, 12.14

Fakt obdivuji, jakou si s úkoly dáváte práci, a že jsou rok od roku propracovanější - jinak heslo OREL je u šifer s mřížkou nějaké oblíbené ...

https://technoplaneta.cz/2012/ukoly/ukol-5-1-zase-ctverec/reseni

Tomáš Bláha čtvrtek, 16. březen, 13.30

Jo, to je. Už jsem si toho také všiml, ale až po zadání úlohy. Předtím mi to nevytanulo na myli.

Matiu z týmu Květákovo vojsko čtvrtek, 16. březen, 15.33

Jo, toho jsem si taky všiml.

Sultán Karel Petr I trolejbus bagrista bagr z týmu Přihlašovací jméno pondělí, 20. březen, 16.42

Tadle šifra byla super.

Matiu z týmu Květákovo vojsko úterý, 21. březen, 6.55

To byla.