Jump to content
MrGrj

[CHALLANGE]Cum functioneaza ?

Recommended Posts

  • Active Members
Posted (edited)

Avem urmatoarea bucata de cod scris in C:

 

main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}

Programul poate fi compilat exact asa cum este (testat cu gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)), outputul fiind:

 

[mrgrj@localhost tmp]# vim challangeRST.c
[mrgrj@localhost tmp]# gcc challangeRST.c -o challangeRST
[mrgrj@localhost tmp]# ./challangeRST 
!!!!!!  !!!!!!          !!!!!!  !!!!!!              !!  !!!!!! 
!!  !!  !!  !!              !!      !!              !!      !! 
!!  !!  !!  !!              !!      !!              !!      !! 
!!  !!  !!!!!!    !!      !!!!    !!!!    !!        !!    !!!! 
!!  !!  !!  !!              !!      !!              !!  !!     
!!  !!  !!  !!              !!      !!              !!  !!     
!!!!!!  !!!!!!          !!!!!!  !!!!!!              !!  !!!! 

Cum functioneaza programul ? (explicati output-ul)

 

O sa va rog sa folositi buttonul de spoiler in momentul in care dati un raspuns decent. Challange-ul expira vineri la ora 23:59.

 

Solvers:

1. @MasterLight

2.

3.

 

 

Edited by MrGrj
  • Upvote 1
Posted (edited)
  Reveal hidden contents

 

Edited by MasterLight
  • Upvote 1
  • Active Members
Posted (edited)
  On 3/31/2016 at 9:28 PM, MasterLight said:
  Reveal hidden contents

 

Expand  

 

Close enough. Uite la ce ma gandisem eu ca ar fi un raspuns complet:

 

Se indenteaza putin codul:

 

main(_) {
    _^448 && main(-~_);
    putchar(--_%64
        ? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
        : 10);
}

Se introduc ceva variabile pentru a face codul putin mai readable:

 

main(int i) {
    if(i^448)
        main(-~i);
    if(--i % 64) {
        char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
        char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
        putchar(32 | (b & 1));
    } else {
        putchar(10); // newline
    }
}

A se nota ca -~i == i + 1 deci avem:

 

main(int i) {
    if(i != 448)
        main(i+1);
    i--;
    if(i % 64 == 0) {
        putchar('\n');
    } else {
        char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
        char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
        putchar(32 | (b & 1));
    }
}

Acum, a se nota faptul ca a[ b ] e acelasi lucru ca si b[ a ], iar aplicand -~ == 1+ avem: 

 

main(int i) {
    if(i != 448)
        main(i+1);
    i--;
    if(i % 64 == 0) {
        putchar('\n');
    } else {
        char a = (">'txiZ^(~z?"-48)[(__TIME__-i/8%8)[7]] + 1;
        char b = a >> ";;;====~$::199"[(i*2&8)|i/64]/(i&2?1:8)%8;
        putchar(32 | (b & 1));
    }
}

Facand trecere de la recursivitate la un loop + incercand sa simplificam putin codul, obtinem:

 

main() {
    int i;
    for(i=447; i>=0; i--) {
        if(i % 64 == 0) {
            putchar('\n');
        } else {
            char t = __TIME__[7 - i/8%8];
            char a = ">'txiZ^(~z?"[t - 48] + 1;
            int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
            if((i & 2) == 0)
                shift /= 8;
            shift = shift % 8;
            char b = a >> shift;
            putchar(32 | (b & 1));
        }
    }
}

Asta va afisa cate un caracter per iteratie. Fiecare al 64-lea caracter va printa un new-line. Altfel, foloseste o pereche de valori dintr-un table pentru a-si da seama ce sa printeze si pune ori caracterul 32(space) sau caracterul 33 ( '!' ).

 

Primul tabel (

">'txiZ^(~z?"

) este un set de 10 bitmaps care descriu aparitia fiecarui caracter, iar cel de-al doilea tabel: (

";;;====~$::199"

) selecteaza bit-ul necesar din bitmap.

 

Al doilea tabel:

 

int shift = ";;;====~$::199"[(i*2&8) | (i/64)];

 

i/64 -> este numarul linie (6-0)

i&2&8 -> 8 daca i = 4, 5, 7 mod 8.

 

if((i & 2) == 0) shift /= 8; shift = shift % 8

- linia de mai sus selecteaza ori "the high octal digit" (pentru i%8 = 0,1,4,5) sau "the low octal figit" (pentru i%8 = 2,3,6,7). Deci tabelul va arata cam asa:

 

rand col val
6   6-7 0
6   4-5 0
6   2-3 5
6   0-1 7
5   6-7 1
5   4-5 7
5   2-3 5
5   0-1 7
4   6-7 1
4   4-5 7
4   2-3 5
4   0-1 7
3   6-7 1
3   4-5 6
3   2-3 5
3   0-1 7
2   6-7 2
2   4-5 7
2   2-3 3
2   0-1 7
1   6-7 2
1   4-5 7
1   2-3 3
1   0-1 7
0   6-7 4
0   4-5 4
0   2-3 3
0   0-1 7

Sau, intr-o forma mai tabulara:

 

00005577
11775577
11775577
11665577
22773377
22773377
44443377

A se observa ca s-a folosit null terminator pentru primele doua valori din tabel :D

 

Primul tabel:

 

__TIME__ este un macro special definit de preprocesor. Aceasta este folosita ca un constant string continand timpul la care preprocesorul a fost rulat, in forma: "HH:MM:SS". Mai pe romaneste, odata cu fiecare compilare, programul va arata ora exacta a compilarii. A se observa ca ora nu se schimba atunci cand dati Run.

 

De sesizat faptul ca HH:MM:SS contine exact 8 caractere. De notat ca 0-9 in ASCII inseamna 48-57 iar semnul ":" are valoarea 58 in tabelul cu valori ASCII. Outputul contine 64 caractere / linie => 8 chars / caracter din __TIME__.

 

7 - i/8%8

este indexul lui __TIME__ care este de fapt outputul ( 7- este necesar pentru ca iteram valoarea lui i invers). Deci, este ceea ce __TIME__ printeaza.

 

sfarsteste prin a fi egal cu una din urmatoarele valori binare, in functie de inputul t:

 

0 00111111
1 00101000
2 01110101
3 01111001
4 01101010
5 01011011
6 01011111
7 00101001
8 01111111
9 01111011
: 01000000

 

Din moment ce caracterele sunt 7-bit ASCII, cel mai mare bit va fi mereu clearuit => va fi printat mereu ca blank. Deci, al doilea tabel va arata asa, dupa ce 7 = blank

 

000055  
11  55  
11  55  
116655  
22  33  
22  33  
444433  

Deci, de exemplu, 4 = 01101010 (bits 1,3,5, si 6 set) care e printat astfel:

 

----!!--
!!--!!--
!!--!!--
!!!!!!--
----!!--
----!!--
----!!--

Ca sa vedem ca am inteles cu adevarat codul, sa ajustam putin outputul folosind acest tabel:

 

  00  
11  55
11  55
  66  
22  33
22  33
  44

Asta este encodat ca: 

 

"?;;?==? '::799\x07"

 

In scop artistic, vom adauga 64 la cateva caractere (din moment ce doar ultimii 6 biti sunt folositi, asta nu va afecta ouputul); asta va rezulta in:

 

"?{{?}}?gg::799G"

( de notat ca al 8-lea caracter nu este folosit -> deci practic putem sa il transformam in orice dorim).

 

 

Edited by MrGrj
  • Upvote 2
  • Downvote 1
Posted (edited)

Hai ba garaj... sa pui challenge-ul ala e o chestie, dar sa copiezi rezolvarea cuvant cu cuvant de pe stackoverflow e aiurea :| 

@MasterLight a facut macar singur rezolvarea, chiar daca e incompleta.. (cel putin nu am gasit rezolvarea lui pe net)

Edited by Byte-ul
Posted (edited)
  On 4/2/2016 at 1:43 PM, Byte-ul said:

Hai ba garaj... sa pui challenge-ul ala e o chestie, dar sa copiezi rezolvarea cuvant cu cuvant de pe stackoverflow e aiurea :| 

@MasterLight a facut macar singur rezolvarea, chiar daca e incompleta.. (cel putin nu am gasit rezolvarea lui pe net)

Expand  

 

ahhaha

Edited by Webz
  • Active Members
Posted

Ba, nu inteleg de ce va cacati atat pe voi. Am explicat si la @Byte-ul  :(

 

In cazul in care un chall e facut de tine, evident vei veni cu o solutie personala. In cazul de fata, chall-ul nu a fost al meu, insa mi s-a parut extrem de nice, asa ca l-am postat :) La fel si cu rezolvarea: aia a fost cea mai completa pe care am gasit-o, deci am postat-o. Puteam sa vin cu solutia mea, insa era cu mult mai putine detalii fata de ceea ce am postat mai sus.

 

Poti sa-l inchizi

Guest
This topic is now closed to further replies.


×
×
  • Create New...