Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
aa:lab:sol:1 [2024/10/05 16:03] dmihai |
aa:lab:sol:1 [2024/10/16 23:18] (current) dmihai |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Solutii Mașina Turing ====== | ====== Solutii Mașina Turing ====== | ||
- | 1. | + | 1. {{:aa:lab:sol:1.xlsx|}} |
+ | <hidden> | ||
<code> | <code> | ||
// Scrieți o Mașină Turing care primește un șir binar și verifică dacă începe | // Scrieți o Mașină Turing care primește un șir binar și verifică dacă începe | ||
Line 55: | Line 56: | ||
Y, 1, - | Y, 1, - | ||
</code> | </code> | ||
+ | </hidden> | ||
- | 2. | + | 2. {{:aa:lab:sol:2.xlsx}} |
+ | |||
+ | <hidden> | ||
<code> | <code> | ||
// Rezolvați exercițiul anterior pentru input în baza 10. | // Rezolvați exercițiul anterior pentru input în baza 10. | ||
Line 749: | Line 753: | ||
Y, 8, - | Y, 8, - | ||
</code> | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 3. {{:aa:lab:sol:3.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un șir binar și verifică dacă | ||
+ | // are lungime impară și simbolul din mijloc este 0 (e.g. 101100011). | ||
+ | name: l1e3 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | start, 0 | ||
+ | got0, _, > | ||
+ | |||
+ | start, 1 | ||
+ | find_end, _, > | ||
+ | |||
+ | start, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | find_end, 0 | ||
+ | find_end, 0, > | ||
+ | |||
+ | find_end, 1 | ||
+ | find_end, 1, > | ||
+ | |||
+ | find_end, _ | ||
+ | delete_last, _, < | ||
+ | |||
+ | |||
+ | delete_last, 0 | ||
+ | reset, _, < | ||
+ | |||
+ | delete_last, 1 | ||
+ | reset, _, < | ||
+ | |||
+ | // input was just "1" | ||
+ | delete_last, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | reset, 0 | ||
+ | reset, 0, < | ||
+ | |||
+ | reset, 1 | ||
+ | reset, 1, < | ||
+ | |||
+ | reset, _ | ||
+ | start, _, > | ||
+ | |||
+ | |||
+ | got0, 0 | ||
+ | find_end, 0, > | ||
+ | |||
+ | got0, 1 | ||
+ | find_end, 1, > | ||
+ | |||
+ | got0, _ | ||
+ | Y, _, - | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 4. {{:aa:lab:sol:4.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un șir binar și | ||
+ | // lasă pe bandă complementul lui (e.g. “100110100” → “011001011”) | ||
+ | name: l1e4 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | start, 0 | ||
+ | start, 1, > | ||
+ | |||
+ | start, 1 | ||
+ | start, 0, > | ||
+ | |||
+ | start, _ | ||
+ | H, _, - | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 5. {{:aa:lab:sol:5.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care curăță toată banda | ||
+ | // (atât la stânga cât și la dreapta) și apoi lasă scris doar “1”. | ||
+ | name: l1e5 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | start, 0 | ||
+ | start, 0, < | ||
+ | |||
+ | start, 1 | ||
+ | start, 1, < | ||
+ | |||
+ | start, _ | ||
+ | delete, _, > | ||
+ | |||
+ | |||
+ | delete, 0 | ||
+ | delete, _, > | ||
+ | |||
+ | delete, 1 | ||
+ | delete, _, > | ||
+ | |||
+ | delete, _ | ||
+ | H, 1, - | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 6. {{:aa:lab:sol:6.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care inversează cuvântul primit pe bandă. | ||
+ | name: l1e6 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | // mașina o să memoreze primul simbol, o să-l șteargă, apoi va parcuge inputul | ||
+ | // până ajunge la final, lasă un spațiu liber și plasează simbolul memorat pe | ||
+ | // prima celula goală, după spațiul liber; apoi revine la începutul șirului, | ||
+ | // făcând recursiv această acțiune. | ||
+ | start, 0 | ||
+ | mem0, _, > | ||
+ | |||
+ | start, 1 | ||
+ | mem1, _, > | ||
+ | |||
+ | start, _ | ||
+ | H, _, > | ||
+ | |||
+ | |||
+ | mem0, 0 | ||
+ | mem0, 0, > | ||
+ | |||
+ | mem0, 1 | ||
+ | mem0, 1, > | ||
+ | |||
+ | mem0, _ | ||
+ | write_at_end_0, _, > | ||
+ | |||
+ | |||
+ | mem1, 0 | ||
+ | mem1, 0, > | ||
+ | |||
+ | mem1, 1 | ||
+ | mem1, 1, > | ||
+ | |||
+ | mem1, _ | ||
+ | write_at_end_1, _, > | ||
+ | |||
+ | |||
+ | write_at_end_0, 0 | ||
+ | write_at_end_0, 0, > | ||
+ | |||
+ | write_at_end_0, 1 | ||
+ | write_at_end_0, 1, > | ||
+ | |||
+ | write_at_end_0, _ | ||
+ | reset, 0, < | ||
+ | |||
+ | |||
+ | write_at_end_1, 0 | ||
+ | write_at_end_1, 0, > | ||
+ | |||
+ | write_at_end_1, 1 | ||
+ | write_at_end_1, 1, > | ||
+ | |||
+ | write_at_end_1, _ | ||
+ | reset, 1, < | ||
+ | |||
+ | |||
+ | reset, 0 | ||
+ | reset, 0, < | ||
+ | |||
+ | reset, 1 | ||
+ | reset, 1, < | ||
+ | |||
+ | reset, _ | ||
+ | reset2, _, < | ||
+ | |||
+ | |||
+ | reset2, 0 | ||
+ | reset2, 0, < | ||
+ | |||
+ | reset2, 1 | ||
+ | reset2, 1, < | ||
+ | |||
+ | reset2, _ | ||
+ | start, _, > | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 7. {{:aa:lab:sol:7.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un șir de “X”-uri și | ||
+ | // verifică dacă lungimea acestuia este o putere a lui 2. | ||
+ | name: l1e7 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | // Vom folosi simbolul D pentru a marca X-uri (nu le ștergem ca să putem știi | ||
+ | // unde începe și se termină șirul (la simboluri blank). | ||
+ | // | ||
+ | // Vom șterge 1 din două X-uri, apoi ne vom întoarce la început și vom repeta | ||
+ | // procesul. | ||
+ | // | ||
+ | // Dacă găsim un nr. impar de X-uri, inputul e respins; în afară de cazul în | ||
+ | // găsim un singur X (singura putere impară a lui 2), caz în care acceptăm. | ||
+ | start, X | ||
+ | check_if_just_one_X, D, > | ||
+ | |||
+ | start, D | ||
+ | start, D, > | ||
+ | |||
+ | // 0 nu e o putere a lui 2. | ||
+ | start, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | check_if_just_one_X, D | ||
+ | check_if_just_one_X, D, > | ||
+ | |||
+ | check_if_just_one_X, _ | ||
+ | Y, _, - | ||
+ | |||
+ | check_if_just_one_X, X | ||
+ | skip, X, - | ||
+ | |||
+ | |||
+ | skip, X | ||
+ | delete, X, > | ||
+ | |||
+ | skip, D | ||
+ | skip, D, > | ||
+ | |||
+ | skip, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | delete, X | ||
+ | skip, D, > | ||
+ | |||
+ | delete, D | ||
+ | delete, D, > | ||
+ | |||
+ | delete, _ | ||
+ | reset, _, < | ||
+ | |||
+ | |||
+ | reset, X | ||
+ | reset, X, < | ||
+ | |||
+ | reset, D | ||
+ | reset, D, < | ||
+ | |||
+ | reset, _ | ||
+ | start, _, > | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 8. {{:aa:lab:sol:8.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un șir de paranteze “(”, “)” | ||
+ | // și verifică dacă sunt echilibrate. | ||
+ | name: l1e8 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | |||
+ | // Whenever we find an open paranthesis, we search for a match and delete it. | ||
+ | // As before, we don't want to include blank symbols in the middle of the tape, | ||
+ | // so we'll delete it by overwriting it with the symbol "D". | ||
+ | start, ) | ||
+ | N, ), - | ||
+ | |||
+ | start, ( | ||
+ | find_), _, > | ||
+ | |||
+ | start, D | ||
+ | start, _, > | ||
+ | |||
+ | start, _ | ||
+ | Y, _, - | ||
+ | |||
+ | |||
+ | find_), ( | ||
+ | find_), (, > | ||
+ | |||
+ | find_), D | ||
+ | find_), D, > | ||
+ | |||
+ | find_), ) | ||
+ | reset, D, < | ||
+ | |||
+ | |||
+ | reset, ( | ||
+ | reset, (, < | ||
+ | |||
+ | reset, ) | ||
+ | reset, ), < | ||
+ | |||
+ | reset, D | ||
+ | reset, D, < | ||
+ | |||
+ | reset, _ | ||
+ | start, _, > | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 9. {{:aa:lab:sol:9.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un număr în baza 2 și verifică dacă | ||
+ | // e divizibil cu 5. | ||
+ | name: l1e9 | ||
+ | init: r0 | ||
+ | accept: H, Y | ||
+ | |||
+ | // Ideea este să reținem în starea curentă, resturile împărțirii la 5, care sunt | ||
+ | // cinci la număr: 0, 1, 2, 3, 4 | ||
+ | // Putem să ne imaginăm că la orice moment de timp, am citit primii biți din | ||
+ | // input, formând un număr n, despre care ținem minte doar restul împărțirii | ||
+ | // la 5, numit r; când ne mutăm la dreapta, citind un nou bit din input, | ||
+ | // avem de fapt un nou număr: | ||
+ | // - dacă citim 0, avem n * 2 | ||
+ | // - dacă citim 1, avem n * 2 + 1 | ||
+ | // | ||
+ | // Dar nu trebuie să ținem minte tot numărul, doar restul împărțirii la 5; deci, | ||
+ | // de exemplu, dacă avem r = 3, și citim un 1, atunci r devine 2 | ||
+ | // (adică 3 * 2 + 1 mod 5). | ||
+ | r0, 0 | ||
+ | r0, 0, > | ||
+ | |||
+ | r0, 1 | ||
+ | r1, 1, > | ||
+ | |||
+ | r0, _ | ||
+ | Y, _, - | ||
+ | |||
+ | |||
+ | r1, 0 | ||
+ | r2, 0, > | ||
+ | |||
+ | r1, 1 | ||
+ | r3, 1, > | ||
+ | |||
+ | r1, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | r2, 0 | ||
+ | r4, 0, > | ||
+ | |||
+ | r2, 1 | ||
+ | r0, 1, > | ||
+ | |||
+ | r2, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | r3, 0 | ||
+ | r1, 0, > | ||
+ | |||
+ | r3, 1 | ||
+ | r2, 1, > | ||
+ | |||
+ | r3, _ | ||
+ | N, _, - | ||
+ | |||
+ | |||
+ | r4, 0 | ||
+ | r3, 0, > | ||
+ | |||
+ | r4, 1 | ||
+ | r4, 1, > | ||
+ | |||
+ | r1, _ | ||
+ | N, _, - | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 10. {{:aa:lab:sol:10.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un cuvânt binar, găsește primul | ||
+ | // simbol “0” și inserează un “1” în stânga lui (deci tot ce apare la | ||
+ | // dreapta va trebui mutat cu o poziție). | ||
+ | name: l1e10 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | start, 0 | ||
+ | shift_input0, 1, > | ||
+ | |||
+ | start, 1 | ||
+ | start, 1, > | ||
+ | |||
+ | start, _ | ||
+ | H, _, - | ||
+ | |||
+ | |||
+ | shift_input0, 0 | ||
+ | shift_input0, 0, > | ||
+ | |||
+ | shift_input0, 1 | ||
+ | shift_input1, 0, > | ||
+ | |||
+ | shift_input0, _ | ||
+ | H, 0, - | ||
+ | |||
+ | |||
+ | shift_input1, 0 | ||
+ | shift_input0, 1, > | ||
+ | |||
+ | shift_input1, 1 | ||
+ | shift_input1, 1, > | ||
+ | |||
+ | shift_input1, _ | ||
+ | H, 1, - | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 11. {{:aa:lab:sol:11.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește două numere în baza 2, big-endian, | ||
+ | // separate de un # și lasă pe bandă suma lor (e.g. “1011#11001” → “100100”). | ||
+ | name: l1e11 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | // E mai ușor să adunăm cel de-al doilea număr la primul, creând rezultatul | ||
+ | // "peste" primul număr (altfel în cazul în care al doilea număr e mai scurt, | ||
+ | // sau adunarea produce overflow, ar trebui să shiftăm rezultatul). | ||
+ | // Ca să știm la ce cifră din primul număr am jos, vom folosi simboluri | ||
+ | // auxiliare Z și O (pentru 0 și 1), cât lucrăm, și le vom înlocui abia la | ||
+ | // final. | ||
+ | start, 0 | ||
+ | go_to_#, 0, > | ||
+ | |||
+ | start, 1 | ||
+ | go_to_#, 1, > | ||
+ | |||
+ | start, # | ||
+ | H, _, > | ||
+ | |||
+ | |||
+ | go_to_#, 0 | ||
+ | go_to_#, 0, > | ||
+ | |||
+ | go_to_#, 1 | ||
+ | go_to_#, 1, > | ||
+ | |||
+ | go_to_#, Z | ||
+ | go_to_#, Z, > | ||
+ | |||
+ | go_to_#, O | ||
+ | go_to_#, O, > | ||
+ | |||
+ | go_to_#, # | ||
+ | go_to_end, #, > | ||
+ | |||
+ | |||
+ | go_to_end, 0 | ||
+ | go_to_end, 0, > | ||
+ | |||
+ | go_to_end, 1 | ||
+ | go_to_end, 1, > | ||
+ | |||
+ | go_to_end, _ | ||
+ | get_lsd, _, < | ||
+ | |||
+ | |||
+ | get_lsd, 0 | ||
+ | lsd_0, _, < | ||
+ | |||
+ | get_lsd, 1 | ||
+ | lsd_1, _, < | ||
+ | |||
+ | |||
+ | // n-au mai rămas cifre de prelucrat din al doilea număr | ||
+ | get_lsd, # | ||
+ | rewrite_first, _, < | ||
+ | |||
+ | lsd_0, 0 | ||
+ | lsd_0, 0, < | ||
+ | |||
+ | lsd_0, 1 | ||
+ | lsd_0, 1, < | ||
+ | |||
+ | lsd_0, # | ||
+ | lsd_0_after_#, #, < | ||
+ | |||
+ | |||
+ | lsd_1, 0 | ||
+ | lsd_1, 0, < | ||
+ | |||
+ | lsd_1, 1 | ||
+ | lsd_1, 1, < | ||
+ | |||
+ | lsd_1, # | ||
+ | lsd_1_after_#, #, < | ||
+ | |||
+ | |||
+ | // Sărim peste cifrele "deja afectate". | ||
+ | lsd_0_after_#, Z | ||
+ | lsd_0_after_#, Z, < | ||
+ | |||
+ | lsd_0_after_#, O | ||
+ | lsd_0_after_#, O, < | ||
+ | |||
+ | |||
+ | lsd_1_after_#, Z | ||
+ | lsd_1_after_#, Z, < | ||
+ | |||
+ | lsd_1_after_#, O | ||
+ | lsd_1_after_#, O, < | ||
+ | |||
+ | |||
+ | // marcăm o nouă cifră prelucrată din primul număr | ||
+ | lsd_0_after_#, 0 | ||
+ | go_to_#, Z, > | ||
+ | |||
+ | lsd_0_after_#, 1 | ||
+ | go_to_#, O, > | ||
+ | |||
+ | lsd_0_after_#, _ | ||
+ | go_to_#, Z, > | ||
+ | |||
+ | |||
+ | lsd_1_after_#, 0 | ||
+ | go_to_#, O, > | ||
+ | |||
+ | // acum ar trebui să intrăm într-un mod de "binary increment" al primului număr, | ||
+ | // în care incrementăm tot spre stânga, fără a marca cifrele! | ||
+ | lsd_1_after_#, 1 | ||
+ | increment, Z, < | ||
+ | |||
+ | increment, 1 | ||
+ | increment, 0, < | ||
+ | |||
+ | increment, 0 | ||
+ | go_to_#, 1, > | ||
+ | |||
+ | increment, _ | ||
+ | go_to_#, 1, > | ||
+ | |||
+ | lsd_1_after_#, _ | ||
+ | go_to_#, O, > | ||
+ | |||
+ | |||
+ | rewrite_first, 0 | ||
+ | rewrite_first, 0, < | ||
+ | |||
+ | rewrite_first, 1 | ||
+ | rewrite_first, 1, < | ||
+ | |||
+ | rewrite_first, Z | ||
+ | rewrite_first, 0, < | ||
+ | |||
+ | rewrite_first, O | ||
+ | rewrite_first, 1, < | ||
+ | |||
+ | rewrite_first, _ | ||
+ | H, _, > | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | 12. {{:aa:lab:sol:12.xlsx}} | ||
+ | |||
+ | <hidden> | ||
+ | <code> | ||
+ | // Scrieți o Mașină Turing care primește un șir binar și lasă pe bandă, | ||
+ | // după un caracter “#”, numărul de 0-uri, în bază 2 | ||
+ | // (e.g. “100010110” → “100010110#101”). | ||
+ | name: l1e12 | ||
+ | init: start | ||
+ | accept: H, Y | ||
+ | |||
+ | // De fiecare dată când găsim un 0, vom incrementa un contor. | ||
+ | // De data asta, ne vom folosi de soluția de la ex. 10, ca să shiftăm contorul | ||
+ | // spre dreapta, de fiecare dată când mai trebuie adăugat un bit. | ||
+ | // Nu putem șterge 0-urile, dar o să le marcăm temporar cu Z. | ||
+ | |||
+ | start, 1 | ||
+ | start, 1, > | ||
+ | |||
+ | start, 0 | ||
+ | goto_counter, Z, > | ||
+ | |||
+ | start, Z | ||
+ | start, Z, > | ||
+ | |||
+ | start, # | ||
+ | restore_0, #, < | ||
+ | |||
+ | // dacă nu am găsit niciun 0, trebuie lăsat numărul "0" pe bandă. | ||
+ | start, _ | ||
+ | w0, #, > | ||
+ | |||
+ | |||
+ | w0, _ | ||
+ | H, 0, - | ||
+ | |||
+ | |||
+ | goto_counter, 0 | ||
+ | goto_counter, 0, > | ||
+ | |||
+ | goto_counter, 1 | ||
+ | goto_counter, 1, > | ||
+ | |||
+ | // "inițializăm" contorul prima dată când ajungem la sfârșit | ||
+ | goto_counter, _ | ||
+ | goto_end, #, > | ||
+ | |||
+ | goto_counter, # | ||
+ | goto_end, #, > | ||
+ | |||
+ | |||
+ | goto_end, 0 | ||
+ | goto_end, 0, > | ||
+ | |||
+ | goto_end, 1 | ||
+ | goto_end, 1, > | ||
+ | |||
+ | goto_end, _ | ||
+ | increment, _, < | ||
+ | |||
+ | |||
+ | increment, 0 | ||
+ | reset, 1, < | ||
+ | |||
+ | increment, 1 | ||
+ | increment, 0, < | ||
+ | |||
+ | increment, # | ||
+ | start_shift, #, > | ||
+ | |||
+ | |||
+ | start_shift, 1 | ||
+ | shift1, 1, > | ||
+ | |||
+ | start_shift, 0 | ||
+ | shift0, 1, > | ||
+ | |||
+ | // asta se poate întâmpla doar când inițializem contorul | ||
+ | start_shift, _ | ||
+ | reset, 1, < | ||
+ | |||
+ | |||
+ | shift1, 0 | ||
+ | shift0, 1, > | ||
+ | |||
+ | shift1, 1 | ||
+ | shift1, 1, > | ||
+ | |||
+ | shift1, _ | ||
+ | reset, 1, < | ||
+ | |||
+ | |||
+ | shift0, 0 | ||
+ | shift0, 0, > | ||
+ | |||
+ | shift0, 1 | ||
+ | shift1, 0, > | ||
+ | |||
+ | shift0, _ | ||
+ | reset, 0, < | ||
+ | |||
+ | |||
+ | reset, 0 | ||
+ | reset, 0, < | ||
+ | |||
+ | reset, 1 | ||
+ | reset, 1, < | ||
+ | |||
+ | reset, # | ||
+ | reset, #, < | ||
+ | |||
+ | reset, Z | ||
+ | reset, Z, < | ||
+ | |||
+ | reset, _ | ||
+ | start, _, > | ||
+ | |||
+ | |||
+ | restore_0, Z | ||
+ | restore_0, 0, < | ||
+ | |||
+ | restore_0, 1 | ||
+ | restore_0, 1, < | ||
+ | |||
+ | restore_0, _ | ||
+ | H, _, > | ||
+ | |||
+ | </code> | ||
+ | </hidden> | ||
+ |