Mai intai trebuie sa te autentifici.
Diferente pentru coduri-gray intre reviziile #7 si #8
Nu exista diferente intre titluri.
Diferente intre continut:
(Categoria _Matematica_, autor _Cosmin Negruseri_)
h2. Introducere
(toc)*{text-align:center} *Cuprins*
* 'Introducere':coduri-gray#introducere
* 'Problema 1: Turnurile din Hanoi':coduri-gray#hanoi
* 'Problema 2: Becuri':coduri-gray#prob2
* 'Problema 3: Matrix':coduri-gray#matrix
* 'Problema 4: Divizori':coduri-gray#divizori
* 'Problema 5: Sortnet':coduri-gray#sortnet
Acest articol prezinta notiuneade **Cod Gray** siunele aplicatii alelui in problemede la concursuriledeprogramare.
h2(#introducere). Introducere
Un cod_Gray_de ordin<tex>n</tex>este un sir care contine toate numerele de la<tex>0</tex>la<tex>2^{n-1}</tex>, astfel ca oricare doua numere consecutive din sir diferain reprezentarea binara prin exact un bit.Pentru <tex>n >= 2</tex> exista mai multe coduri_Gray_distincte.Uncodmai des intalnit,numitinengleza**binary reflected Gray code** (in continuare cand vom vorbi despre codul_Gray_ne vom referi de fapt la acest cod). Modul de constructieal acestuicodesteunul intuitiv:lafiecarepas adaugamnumaruladaugat anterior,caruiaiimodificamcel mai putin semnificativ bit, astfel ca numarulobtinutsa nu mai fi fost adaugat inainte la sir._De exemplu_,daca ordinulestedoisiavem la inceputnumarul<tex>0</tex>insir, vom adauga<tex>1</tex>,apoi<tex>3</tex>,iarapoi<tex>4</tex>.
Un _cod Gray de ordin $n$_ este un sir care contine toate numerele de la $0$ la $2^n-1^$, astfel incat orice doua numere consecutive din sir sa difere in reprezentarea lor binara prin exact un bit. Exista mai multe coduri Gray distincte, cel mai des intalnit fiind asa-numitul **binary reflected Gray code** (in continuare cand vom vorbi despre codul Gray ne vom referi de fapt la acest cod). Modul de constructie este destul de intuitiv: fiecare numar nou este format din cel anterior prin modificarea celui mai putin semnificativ bit, astfel incat numarul sa nu mai fi fost adaugat inainte la sir (de exemplu, pentru $n = 2$ si primul numar $0$, sirul obtinut va fi $0, 1, 3, 2$).
Inacestarticolvom nota acest cod cu<tex>G_{n}</tex>.Oalta metoda de constructiecare obtineacelasi cod _Gray_ este de a determina mai intai pe <tex>G_{n-1}</tex>, apoi daca notam cu <tex>G'_{n-1}</tex>sirul<tex>G_{n-1}</tex>inversat, atunci obtinempe <tex>G_{n}</tex>daca punem cate un bitde <tex>0</tex>in fata fiecarui numar din<tex>G_{n-1}</tex>,iar acestea sunt urmatede numerele din<tex>G'_{n-1}</tex>carora le adaugam cate unbit de <tex>1</tex>ca bit semnificativ ( pe scurt<tex>G_{n} = 0G_{n-1},1G'_{n-1}</tex>(1)).Observamca acest cod esteunulcircular,adica ultimulnumarsi primul numardincod diferaprin**exact un bit**.Observamdeasemeneaca fiecare cod de ordin<tex>n</tex>il contine pe cel de<tex>n-1</tex>ca prefix, deci am putea nota prin<tex>G_{\infty}</tex>sirul numerelor naturale in care orice doua numere consecutive difera in reprezentarea binara prin exact un bit si pentru care sirul primelor<tex>2^{n}</tex>elemente coincide cu<tex>G_{n}</tex>,oricarearfiacest <tex>n</tex>un numar natural.
In continuare vom nota acest cod cu $G{~n~}$. Putem da astfel o noua metoda de constructie. Fie $G'{~n-1~}$ sirul $G{~n-1~}$ inversat, atunci obtinem $G{~n~}$ daca punem cate un bit $0$ in fata fiecarui numar din $G{~n-1~}$, urmat de numerele din $G'{~n-1~}$, carora le adaugam cate un $1$ ca bit semnificativ ( pe scurt $G{~n~} = 0G{~n-1~},1G'{~n-1~} (1)$). Se poate observa ca acest cod este circular, diferenta intre ultimul si primul numar fiind de **exact un bit**. De asemenea, orice cod de ordin $n$ il contine pe cel de $n-1$ ca prefix, deci am putea nota prin $G{~∞~}$ sirul numerelor naturale in care orice doua numere consecutive difera in reprezentarea binara prin exact un bit si pentru care sirul primelor $2^n^$ elemente coincide cu $G{~n~}$ (∀ $n$ ∈ **N**).
Fie<tex>g(x)</tex>al<tex>x</tex>-lea numar din<tex>G_{\infty}</tex> (prin<tex>g(x)</tex> notam codul _Gray_ al numarului <tex>x</tex>)si<tex>g(y)-1</tex>la cepozitie apare numarul<tex>y</tex>in sirul<tex>G_{\infty}</tex>.Ne punemproblema calcularii eficiente a celor doua functii. Se poate demonstra prin inductie ca daca avem un numar<tex>x</tex>cu reprezentarea binara<tex>(...a_{2}a_{1}a_{0})_{2}</tex>si codul lui_Gray_,cu reprezentarea binara <tex>(...b_{2}b_{1}b_{0})_{2}</tex>, atunci avem<tex>b_{i} = a_{i}</tex>^<tex>a_{i+1}</tex>(2)._De exemplu_,daca avemnumarul<tex>6</tex>cu reprezentarea binara<tex>110</tex>, atunci<tex>b_{0} = a_{0}</tex> ^ <tex>a_{1} = 0 </tex> ^ <tex>1 = 1</tex>, <tex>b_{1} = a_{1}</tex> ^ <tex>a_{2} = 1</tex> ^ <tex>1 = 0</tex>, <tex>b_{2} = a_{2}</tex> ^ <tex>a_{3} = 1</tex> ^ <tex>0 = 1</tex>, deci <tex>g(110) = 101</tex>. Din aceastarelatietragemconcluziaca<tex>g(i) = x ^ (x / 2)</tex> (unde prin / am notat **impartire intreaga**). Din (2) obtinem ca<tex>b_{i}</tex>^<tex>b_{i+1}</tex>^<tex>b_{i+2}</tex>^<tex>... = (a_{i}</tex>^<tex>a_{i+1})</tex>^<tex>(a_{i+1}</tex>^<tex>a_{i+2})</tex>^<tex>(a_{i+2}</tex>^<tex>a_{i+3})</tex>^<tex>... = a_{i}</tex>.Aceasta suma este finita deoarece vomavea un<tex>b_{i}</tex>egal cu<tex>0</tex>si un<tex>a_{i}</tex>egal cu<tex>0</tex>,daca<tex>i</tex>este indeajuns de mare.Astfel<tex>g-1(y) = y</tex>^<tex>y/2</tex>^<tex>y/4</tex>^<tex>...</tex>
Fie $g(x)$ al $x$-lea numar din $G{~∞~}$ si $g-1(y)$ pozitia la care apare numarul $y$ in sirul $G{~∞~}$. Se pune problema calcularii eficiente a celor doua functii. Se poate demonstra prin inductie ca daca avem un numar $x$ cu reprezentarea binara $(...a{~2~}a{~1~}a{~0~}){~2~}$ si codul lui Gray $(...b{~2~}b{~1~}b{~0~}){~2~}$, atunci avem $b{~i~} = a{~i~} ^∧^ a{~i+1~}$ (2). De exemplu, pentru numarul $6$ cu reprezentarea binara $110$, atunci $g(110) = 101$. De aici se deduce ca $g(i) = x ^∧^ (x / 2)$. Din (2) obtinem ca $b{~i~} ^∧^ b{~i+1~} ^∧^ b{~i+2~} ^∧^ ... = (a{~i~} ^∧^ a{~i+1~}) ^∧^ (a{~i+1~} ^∧^ a{~i+2~}) ^∧^ (a{~i+2~} ^∧^ a{~i+3~}) ^∧^ ... = a{~i~}$. Suma este finita deoarece va exista un $b{~i~}$ egal cu $0$ si un $a{~i~}$ egal cu $0$ (daca $i$ este indeajuns de mare). Rezulta astfel ca $g-1(y) = y ^∧^ y/2 ^∧^ y/4 ^∧^ ...$
Din cele de mai sus obtinem urmatoarele metode:
== == code(cpp) |
intgrayToBin(int y) {
int grayToBin(int y) {
int ret = 0;
while (y > 0) {
ret ^= y;
} ==
Sa vedem mai departe cateva probleme:
h2. Problema 1: _Turnurile din Hanoi_ Avem trei tije si <tex>n</tex> discuri de dimensiuni diferite plasate in ordinea descrescatoare a dimensiunilor pe prima tija. Se doreste mutarea tuturor discurilor pe cea de a doua tija, singurul tip de miscare posibila fiind mutarea unui disc de pe o tija pe alta, cu conditia ca pe tija destinatie discul din varf (daca exista un asemenea disc) sa fie mai mare decat discul pe care il mutam acum.
