25 martie 2010
Probleme in Scheme
Problema reginelor
In program, *s este vectorul care retine pe ce linie se afla fiecare regina pusa pe o singura coloana. Ex. s[1]=3 inseamna `regina de pe coloana 1 se afla pe linia 3`.
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
int n , *s;
int vf;
void avans () {
vf++;
s[vf]=-1;
int succesor () {
s[vf]++;
return s[vf] < n;
}
int valid () {
int ok = 1;
int i;
for (i=0; i < vf; i++)
if(s[i]==s[vf] || abs(s[vf]-s[i])==vf-i)
ok=0;
return ok;
}
int sol () {
return vf==n-1;
}
void tipar () {
int i,j;
printf("solutie\n");
for(i=0; i < n; i++) {
for(j=0; j < n; j++) {
if(s[i]==j) printf("Q");
else printf("#"); }
printf("\n"); }
printf("\n");
}
void back() {
vf = -1;
avans ();
while(vf > -1) {
if(succesor()) {
if(valid()) { if(sol()) tipar();
else avans(); }
else ; }
else vf--; }
}
int main() {
printf("\n");
printf("n= ");
scanf("%d", &n);
s = (int *) malloc (n*sizeof(int));
back();
return 0;
}
23 martie 2010
Functii cu continuari in Scheme
22 martie 2010
Protocoale cu fereastra glisanta pentru legatura de date
Protocolul cu fereastra glisanta de un bit utilizeaza metoda stop-and-wait, deoarece emitatorul transmite un cadru si asteapta confirmarea sa inaintea transmiterii urmatorului cadru.
Urmatoarea aplicatie emitator / receptor functioneaza conform cu descrierea protocolului cu fereastra glisanta de un bit. Cele doua aplicatii transmit date intre ele prin intermediul unor pipe-uri, contorizand numarul pachetului trimis/receptionat.
Emitatorul trimite cadre dintr-un pachet pe care le contorizeaza, trimite si contorul acestora. Receptorul stie la ce contor sa se astepte, si daca primeste un cadru nedorit, trimite la randul sau propriul contor neupdatat, astfel emitatorul mai trimite o data cadrul respectiv.
In plus, s-a folosit codificarea si decodificarea crc pentru a verifica si mai bine datele. Emitatorul calculeaza propriul tabel crc si, pentru fiecare cadru trimis, calculeaza acumulatorul, pe care il transmite. Receptorul la randul lui si-a creat tabelul crc, primeste acumulatorul dar si calculeaza un nou acumulator pe baza cadrului primit. In plus fata de conditia de concordanta a numarului cadrelor, diferenta intre acumulatoare trebuie sa fie 0.
sender.c
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "fcntl.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "crc.h"
char *text = "smoke this in your pipe and stuff it please";
int main () {
int fd1, fd2;
fd1 = open ("pipe1", O_RDONLY );
fd2 = open ("pipe2", O_WRONLY );
int inc = 0, i=0, primit=0, j, acum=0;
word *tabel;
tabel = tabelcrc(CRCCCITT);
int ok=1;
do {
if(ok)
crctabel(text[i], &acum, tabel);
ok = 0;
write (fd2, &text[i], 1);
write (fd2, &inc, 4);
write(fd2, &acum, 2);
printf("%d\n",acum);
read (fd1, &primit, 4);
if(primit==inc)
{ inc++;
i++;
ok = 1;
}
} while(i < strlen(text)+1);
close (fd1);
close(fd2);
return 0;
}
receiver.c
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "crc.h"
int main () {
int fd1, fd2;
char buf;
int contor=-1;
int cadru;
fd1 = open ("pipe1", O_WRONLY );
fd2 = open ("pipe2", O_RDONLY );
word acum, acum_nou=0;
word * tabel = tabelcrc(CRCCCITT);
word ac;
while(1) {
read ( fd2, &buf, 1);
read ( fd2, &cadru,4);
read(fd2, &acum, 2);
crctabel(buf, &acum_nou, tabel);
ac = acum_nou;
crctabel(ac>>8, &acum, tabel);
crctabel(ac& 0x00FF, &acum, tabel);
// printf("%d\n", acum);
printf ( "%c\n", buf );
if(cadru == contor+1 && acum==0) {
contor++;
write(fd1, &contor, 4);
}
else
write (fd1, &contor, 4);
}
close (fd1);
close (fd2);
return 0;
}
La compilare se va folosi si fisierul crc.c definit aici.
21 martie 2010
17 martie 2010
15 martie 2010
Comanda semaforului de trafic
// By Dan Hyde,
module traffic;
parameter on = 1, off = 0, red_tics = 35, amber_tics = 3, green_tics = 20;
reg clock, red, amber, green;
// va opri simularea dupa 1000 unitati de timp
initial begin: stop_at
#1000; $stop;
end
// initializeaza luminile si seteaza monitorizarea registrelor.
initial begin: Init
red = off; amber = off; green = off;
$display(" Timpul green amber red");
$monitor("%3d %b %b %b", $time, green, amber, red);
$vw_dumpvars();
$vw_group("all", $time, green, amber, red);
end
// task de asteptare pentru aparitiile fronturilor pozitive ale ceasului
// inainte de a stinge (off) luminile
task light;
output color;
input [31:0] tics;
begin
repeat(tics) // asteapta detectarea fronturilor pozitive ale ceasului
@(posedge clock);
color = off;
end
endtask
// forma de unda pentru o un ceas cu o perioada de doua unitati de timp
always begin: clock_wave
#1 clock = 0;
#1 clock = 1;
end
always begin: main_process
red = on;
light(red, red_tics); // cheama task-ul de asteptare
green = on;
light(green, green_tics);
amber = on;
light(amber, amber_tics);
end
endmodule
Iesirea este urmatoare
(Time green amber red)
0 0 0 1
70 1 0 0
110 0 1 0
116 0 0 1
186 1 0 0
226 0 1 0
232 0 0 1
302 1 0 0
342 0 1 0
348 0 0 1
418 1 0 0
458 0 1 0
464 0 0 1
534 1 0 0
574 0 1 0
580 0 0 1
650 1 0 0
690 0 1 0
696 0 0 1
766 1 0 0
806 0 1 0
812 0 0 1
882 1 0 0
922 0 1 0
928 0 0 1
998 1 0 0
Detectarea si corectarea erorilor in legatura de date
Sistemele actuale care inglobeaza calculatoare si echipamente automate necesita o transmisie cit mai corecta a informatiei; pentru aceasta semnalul trimis este prelucrat inainte de a fi emis. Prelucrarea semnalului se realizeaza foarte usor in cazul transmisiei de semnale discrete, prin codificare. Receptorul va decodifica semnalul primit si va incerca sa estimeze daca au aparut erori. Pentru tratarea codificarii/decodificarii s-a dezvoltat un amplu aparat matematic, bazat pe calculul vectorial si polinomial. Astfel, in cazul codurilor bloc, folosind alfabetul binar {0,1}, se pot realiza 2^n combinatii (cuvinte de cod de aceeasi lungime n) folosind n biti.
Aceste cuvinte de cod pot fi asimilate cu vectori sau cu polinoame. Daca toate cele 2^n combinatii reprezinta cuvinte utile (cu sens), atunci aparitia unei erori transforma un cuvint de cod in altul, fara a se putea realiza detectia sau corectia erorilor. De aceea, informatia utila va fi codificata pe k
Un program de calcul al codului de control ciclic CRC-CCITT este urmatorul:
crc.h
#define CRCCCITT 0x1021 // polinomul generator
#include "stdio.h"
#include "stdlib.h"
typedef unsigned short int word;
typedef unsigned char byte;
word calculcrc (word, word, word);
word* tabelcrc (word);
crc.c
#include "crc.h"
#include "stdio.h"
#include "string.h"
//
// calculeaza noul rest partial pe baza vechiului rest
// (acum), a unui octet de date (data) si a polinomului
// generator (genpoli)
//
word calculcrc (word data, word genpoli, word acum)
{
int i;
data <<= 8;
for (i=8; i > 0; i--)
{
if ((data^acum) & 0x8000)
acum = (acum << 1) ^ genpoli;
else
acum <<= 1;
data <<= 1;
}
return acum;
}
/*
Functia "calculcrc" determina efectul aplicarii procedeului clasic de calcul CRC asupra unui octet de date. Generatorul polinomial (genpoly) si continutul initial al acumulatorului
(accum) sint date ca argumente.
Calculul prin program al secventei de control sugereaza posibilitatea de a trata problema nu la nivelul fiecarui bit al unui mesaj, ci la nivelul octetilor. Ideea este de a gasi o modalitate mai simpla prin care, dat fiind un octet de date si continutul vechi al acumulatorului (registrul de deplasare) sa se calculeze noua valoare a acumulatorului. Facind o simulare a operatiilor, se poate constata ca octetul de date se combina doar cu bitii mai semnificativi ai acumulatorului, noua valoare a acumulatorului fiind suma (modulo 2 a) secventei de control corespunzatoare acestei valori combinate si a octetului mai putin semnificativ al acumulatorului. Deoarece valoarea combinata ocupa 8 biti, ea poate avea 256 de valori diferite, secventele de control pentru toate aceste valori putind fi calculate si pastrate intr-un tablou. In acest mod calculul noului acumulator se poate face foarte simplu, prin insumarea modulo 2 a octetului inferior al acumulatorului cu o valoare precalculata, din cea totala.
Functia tabelcrc construieste acest tablou; ea are ca parametri:
generatorul polinomial si un pointer la o functie CRC (de ex. calculcrc) si intoarce (unsigned short * ) un pointer in tabela.
*/
//
// calculeaza tabelul codurilor CRC
// alcatuieste tabelul codurilor CRC pentru un anumit
// polinom generator (poli); apeleaza "calculcrc" pentru
// toate cele 256 combinatii posibile ale octetului de date
// intoarce un pointer la tabelul de coduri, alocat dinamic
//
word* tabelcrc (word poli )
{
word* ptabelcrc;
int i;
if ((ptabelcrc = (word*) malloc (256 * sizeof (word))) == NULL)
return NULL;
for (i=0; i < 256; i++)
ptabelcrc [i] = calculcrc (i, poli, 0);
return ptabelcrc;
}
// calculeaza CRC partial (acum) corespunzator unui octet
// (data) prin utilizarea tabelului codurilor CRC (tabelcrc)
void crctabel (word data, word* acum, word* tabelcrc)
{
word valcomb;
valcomb = ((*acum >> 8) ^ data) & 0x00FF;
*acum = ((*acum & 0x00FF) << 8) ^ tabelcrc [valcomb];
}
//
// calculeaza CRC pentru un fisier al carui nume este dat de utilizator; pentru verificare, dupa calculul CRC corespunzator fisierului, se continua calculul considerind si valoarea CRC gasita;
// rezultatul (acumulator) dupa adaugarea CRC este nul
int main ()
{
char s [] = "stuff this in your pipe";
word acum = 0, *tabel = tabelcrc(CRCCCITT); // CRCCCITT este generatorul de polinoame
int i;
for(i=0; i < strlen(s); i++)
crctabel(s[i], &acum, tabel); // pt toate car din string
printf("%d\n",acum);
word ac = acum;
crctabel(ac>>8, &acum, tabel);
crctabel(ac& 0x00FF, &acum, tabel);
printf("%d\n",acum);
return 0;
}
Probleme cu programare dinamica
//fie un tablou de dimensiune n x m , alcatuit doar din 1 sau 0 .
// de afisat cel mai mare patrat care poate fi asezat doar pe pozitiile de 1 din matrice
//se afiseaza coltul din dreapta jos si dimensiunea patratului
// complexitatea sa fie O(n*m)
#include "stdio.h"
#include "stdlib.h"
int **a, **c, n , m;
int minim(int i, int j) {
int min1=c[i][j-1], min2=0;
if(c[i-1][j] > c[i-1][j-1])
min2 = c[i-1][j-1];
else min2 = c[i-1][j];
return min1>min2? min2:min1;
}
int main() {
FILE *f = fopen("in","r");
int i,j;
fscanf(f,"%d %d",&n,&m);
a = (int **)malloc(n*sizeof(int));
c = (int **)malloc(n*sizeof(int));
for( i=0; i < n; i++) {
a[i]=(int *) malloc(m*sizeof(int));
c[i]=(int *) malloc(m*sizeof(int));
}
for(i=0; i < n ; i++ )
for(j=0; j < m ; j++ )
{fscanf(f,"%d", &a[i][j]);
if(i == 0 || j ==0)
c[i][j] = a[i][j];
}
for(i=1; i < n ; i++)
for(j=1 ; j < m ; j++)
if(a[i][j]) c[i][j] = 1 + minim(i,j);
else c[i][j]=0;
int max =0, ii=0, jj=0;
for(i=0; i < n ; i++)
for(j=0; j < m ; j++)
if(c[i][j]>max) { max = c[i][j]; ii=i; jj=j; }
printf("colt dreapta jos %d %d\nDimensiune %d\n",ii,jj,max);
return 0;
}
2.
// avem N dreptunghiuri de dimensiune variabile,date prin lungime si latime
// de aflat cel mai mare nr de dreptunghiuri incluse unul in altul
//analiza intr-o anumita ordine
#include "stdio.h"
#include "stdlib.h"
typedef struct dr { int x; int y;} drept;
int n;
drept * d;
int *best ;
int maxim (int i) {
int j, max = 0;
for(j=0; j < i ; j++)
if( best[j] > max && d[j].y > d[i].y )
max=best[j];
return max;
}
int main() {
FILE *f = fopen("intr","r");
fscanf(f,"%d",&n);
d = (struct dr*)malloc(n*sizeof(struct dr));
int i,j,k;
for(i=0; i < n ; i++ ) {
fscanf(f,"%d %d", &j, &k);
d[i].x = j; d[i].y=k; }
best = (int *)malloc(n*sizeof(int));
// sortare descrescatoare dupa x
int ok;
drept aux;
do {
ok=0;
for(i = 0; i < n-1; i++)
if( d[i].x < d[i+1].x ) {
ok=1; aux = d[i]; d[i]=d[i+1]; d[i+1]=aux; }
} while(ok);
for(i=0; i < n ; i++ )
best[i]=1;
for(i=1; i < n ; i++ )
best[i] = 1 + maxim(i);
int max=0;
for(i=0; i < n ; i++ )
if(max < best[i]) max = best[i];
printf("Nr max este %d\n", max);
return 0;
}
11 martie 2010
Protocolul SLIP
Protocolul SLIP (Serial Line Internet Protocol) actioneaza la nivelul legaturii de date, realizand incapsularea pachetelor IP pentru transmisia acestora pe linii seriale si pe conexiuni modem. SLIP a fost primul protocol de acest gen, si datorita numarului mic de functionalitati pe care le ofera a fost inlocuit de-a lungul timpului cu alte protocoale, cel mai cunoscut fiind PPP (Point-to-Point Protocol).
Principalul obiectiv realizat de SLIP este de a delimita pachetele de date (pentru ca acestea sa fie percepute ca separate). In acest scop, la sfarsitul fiecarui pachet de date se adauga un caracter special numit, in cadrul acestui protocol, END; END este caracterul cu codul ASCII 192. Astfel apare problema ca, daca in interiorul pachetului de date se afla un caracter cu codul 192, acesta sa fie interpretat gresit de catre receiver ca fiind "sfarsit de pachet". Problema se rezolva prin inlocuirea caracterelor 192 din interiorul pachetelor, astfel:
Se defineste un caracter special numit ESC, cu codul ASCII 219 (nu trebuie confundat cu caracterul ESC din codul ASCII; in cazul de fata ESC e doar o denumire ce tine de protocolul SLIP). Daca in interiorul unui pachet de date apare un caracter END, acesta e inlocuit cu o secventa de 2 caractere: caracterul ESC urmat de caracterul cu codul 220. Si caracterele ESC trebuie modificate - ele se inlocuiesc cu secventa formata din caracterul ESC urmat de caracterul 221.
O varianta imbunatatita a protocolului consta din adaugarea de caractere END si la inceputul pachetelor, care il ajuta pe receiver sa poata ignora niste eventuali octeti ce apar "in plus" intre pachete din cauza zgomotului de pe linie.
RFC 1055 (specificatia protocolului SLIP): http://tools.ietf.org/html/rfc1055
sender.c
#include "stdio.h"#include "string.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
char send220 = 220;
char send221 = 221;
char END = '%';
char ESC = '#';
int fd1;
void send (char *phrase)
{
int len=strlen(phrase), i=0;
while (len--)
{
if(phrase[i] == END)
{
write (fd1, &ESC, 1 );
write (fd1, &send220, 1 );
}
else if(phrase[i]==ESC)
{
write (fd1, &ESC, 1 );
write (fd1, &send221, 1 );
}
else
write (fd1, &phrase[i], 1 );
i++;
}
}
int main ()
{
fd1 = open ( "mypipe", O_WRONLY );
char * phrase = "Stuff this#in your pipe% and smoke it\n";
char * phrase1 = "SMOKE%IT!!!\n";
send(phrase);
send(phrase1);
write (fd1, &END, 1 );
close (fd1);
return 0;
}
receiver.c
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
char END = '%';
char ESC = '#';
int main ()
{
int fd1;
char buf, b;
fd1 = open ( "mypipe", O_RDONLY );
do{
read ( fd1, &buf, 1 );
if(buf==ESC)
{
read ( fd1, &b, 1 );
if(b==220)
printf("%c",END);
else if(b==221)
printf("%c",ESC);
}
else if(buf !=END)
printf("%c",buf);
}while(buf!=END);
close (fd1);
return 0;
}
08 martie 2010
Cel mai lung subsir crescator dintr-un sir
Exemplu: pentru sirul 24 12 15 15 8 19 raspunsul este sirul 12 15 19.
Se observa ca daca incercam o abordare greedy nu putem stabili nici macar elementul de inceput intr-un mod corect.
Se poate rezolva si cu un algoritm care alege toate combinatiile de numere din sir, valideaza ca sirul obtinut este strict crescator si il retine pe cel de lungime maxima, dar aceasta abordare are complexitatea temporala O(2^N). Cu optimizari este posibil sa se ajunga la O(N!).
O metoda de rezolvare mai eficienta foloseste Programarea Dinamica. Incepem prin a stabili pentru fiecare element lungimea celui mai lung subsir strict crescator care incepe cu primul element si se termina in elementul respectiv. Numim aceasta valoare best(i) si aplicam formula recursiva best(i)= 1+ max(best(j)), cu j < elem(i).
Aplicand acest algoritm obtinem:
elem 24 12 15 15 8 19
best 1 1 2 2 1 3
Pentru 24 sau 12 nu exista nici un alt element in stanga lor strict mai mici decat ele, de aceea au best egal cu 1. Pentru elementele 15 se poate gasi in stanga lor 12 strict mai mic decat ele. Pentru 19 se gaseste elementul 15 strict mai mic decat el. Cum 15 deja este capat pentru un subsir-solutie de 2 elemente, putem spune ca 19 este capatul pentru un subsir-solutie de 3 elemente.
Cum pentru fiecare element din multime trebuie sa gasim un element mai mic decat el si cu best maxim, avem o complexitate O(N) pentru fiecare element. In total rezulta o complexitate O(N^2). Se pot obtine si rezolvari cu o complexitate mai mica folosind structuri de date avansate.
Pentru a gasi care sunt elementele ce alcatuiesc subsirul strict crescator putem sa retinem si o „cale de intoarcere”. Reconstructia astfel are complexitatea O(N). Exemplu: subproblema care se termina in elementul 19 are subsirul de lungime maxima 3 si a fost calculata folosind subproblema care se termina cu elementul 15 (oricare din ele). Subsirul de lungime maxima care se termina in 15 a fost calculat folosindu-ne de elementul 12. 12 fiind cel mai mic element din subsir marcheaza sfarsitul reconstructiei.
Programul in C este:
// sir de n numere se cere implementarea unui progr care det cel mai lung sir crescator O(n^2)
#include "stdio.h"
int main () {
int v [] = {24, 12, 15, 15, 8, 19}, n = 6;
int s[6], m =0, prec[6], l=0, best[6];
int i,j,k;
for(i=0; i < n;i++) {
best[i]=0;
prec[i]=-1;
}
best[0]=1;
for(i=1; i < n;i++) {
int max = 0;
for(j=0;j < i; j++) {
if(v[j] < v[i] && max < =v[j]) {
max = v[j];
best[i]=1+best[j];
prec[i]=j;
}
if(v[j]==v[i]) best[j]=best[i];
}
if(best[i]==0) best[i]=1;
}
int maxbest =0;
for(i=0; i < n; i++)
if(best[i] > maxbest)
maxbest = best[i];
j=0;
for(i=n-1; i > =0;i--)
if(best[i]==maxbest) {
s[j++]=v[i];
if(prec[i] > =0)
s[j++]=v[prec[i]];
i = prec [i];
maxbest=maxbest - 2;
}
for(i=j-1; i > =0; i--)
printf("%d ", s[i]);
printf("\n");
return 0;
}
03 martie 2010
Merge Sort in Scheme
(letrec ([split-h (lambda (ls ls1 ls2)
(cond
[(or (null? ls) (null? (cdr ls))) ;daca are un element sau e vida
(cons (reverse ls2) ls1)]
[else (split-h (cddr ls) ; lista mai putin primele 2 elemente
(cdr ls1) (cons (car ls1) ls2))]))])
(split-h ls ls '())))
(define (merge pred ls1 ls2) ; combina elementele a doua liste -> o lista ordonata
(cond
[(null? ls1) ls2]
[(null? ls2) ls1]
[(pred (car ls1) (car ls2))
(cons (car ls1) (merge pred (cdr ls1) ls2))]
[else (cons (car ls2) (merge pred ls1 (cdr ls2)))]))
(define (merge-sort pred ls) ; corpul principal
(cond
[(null? ls) ls]
[(null? (cdr ls)) ls]
[else (let ([splits (split ls)])
(merge pred
(merge-sort pred (car splits))
(merge-sort pred (cdr splits))))]))
(merge-sort < '(5 2 4 0 1))
Sortare prin insertie in Scheme
- se creeaza o functie simpla insert care adauga un element intr-o lista deja sortata. Merge pe principiul: ia o lista, verifica primul element, daca e mai mare decat elementul de inserat acesta se va insera chiar inaintea lui, altfel listei i se aplica `tail`, iar listei ce rezulta fara primul element i se aplica acelasi tratament pana cand elementul de inserat isi gaseste locul in lista (recursivitate).
- se creeaza o lista vida in care se vor insera pe rand fiecare element din lista noastra.
Forme curry si uncurry in Scheme
In urmatorul exemplu, se realizeaza concatenarea a doua liste folosind functii recursive in forma curry si uncurry:
appendcurry.ss
(define l1 '(1 2 3))
(define l2 '(5 6 7))
(define appendc
(lambda (l1)
(lambda (l2)
( if (null? l1) l2
(cons (car l1) ((appendc (cdr l1)) l2 ) ) ) )
))
(display ((appendc l1) l2))
appenduncurry.ss
(define l1 '(1 2 3))
(define l2 '(5 6 7))
(define appendu
(lambda (l1 l2)
( if (null? l1) l2
(cons (car l1) (appendu (cdr l1) l2 ) ) ) )
)
(display (appendu l1 l2))
Trecerea de la curry la uncurry sau invers a unei functii se face astfel:
(define f (lambda(x y) (+ x y)))
; curry -> uncurry
(define uc
(lambda (f)
( lambda(x)
(lambda(y)
(f x y)
))))
(((uc f ) 2 )3)
(define g (lambda (x)
(lambda (y)
(+ x y))))
; uncurry -> curry
( define cu
(lambda (f)
(lambda (x y)
((f x) y))))
((cu g) 2 3)
01 martie 2010
Protocolul ABP folosind comunicatia prin pipe-uri
ABP (alternating bit protocol) este un transmitator de date simplu care transmite date corupte sau pierdute. Fiecare mesaj de la A la B contine doua parti: data (ce se transmite propriu-zis) si o secventa de 1 bit (0 sau 1) numita tag. In schimb, B transmite lui A un mesaj de confirmare (ACKnowledgement) ACK0 sau ACK1. Cand A trimite un mesaj, il trimite in mod continuu, pana cand primeste mesajul de confirmare de la B care contine acelasi lucru ca si tag. Cand acest lucru se intampla, A transmite urmatorului mesaj.
Cand B primeste un mesaj care nu este corupt si are ca si continut 0, incepe sa trimita ACK0, pana cand primeste un mesaj valid cu numarul 0. Apoi incepe sa trimita ACK1, etc.
Mai jos, sunt prezentate 2 programe in C care simuleaza transmiterea de date intre doua programe. In Linux se deschid 2 console, unde se creeaza 2 pipe-uri cu numele date in program:
mkfifo pipe1
mkfifo pipe2
Apoi se ruleaza programele in acelasi timp si se observa transmiterea de date.
receiver.c
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "string.h"
#include "sys/stat.h"
#include "fcntl.h"
//receiver
int main ()
{
char tag;
int fd1, fd2;
fd1 = open ( "pipe1", O_RDONLY );
fd2 = open ("pipe2", O_WRONLY);
char buf [100];
int p;
while(1) {
read ( fd1, buf, 100 );
p=strlen (buf);
printf ( "%s \n", buf );
tag = buf [p-1];
write (fd2, &tag, 1);
}
close (fd1);
close (fd2);
return 0;
}
sender.c
#include "stdio.h"
# include "string.h"
#include "sys/types.h"
#include "unistd.h"
#include "sys/stat.h"
#include "fcntl.h"
// sender
char * phrase = "Stuff this in your pipe and smoke it";
int main ()
{ int fd1, fd2;
char tag;
fd1 = open ( "pipe1", O_WRONLY );
fd2 = open ("pipe2", O_RDONLY);
int i;
for(i=0 ; i < strlen (phrase); i+=3) {
write (fd1, phrase+i, 3);
read (fd2, &tag, 1);
}
close (fd1);
close(fd2);
return 0;
}
Merge Sort
- Dacă lista este de lungime 0 sau 1, atunci este deja sortată. Altfel:
- Împarte lista nesortată în două subliste aproximativ egale.
- Sortează fiecare sublistă recursiv prin reaplicarea algoritmului merge sort.
- Se interclaseaza cele două liste şi se obţine lista iniţială sortată.
#include "stdio.h"
#include "stdlib.h"
int *x;
void merge (int s,int d) {
int *y=(int *)malloc((d-s+1)*sizeof(int));
int i,j,k,m;
m=(s+d)/2;
for(i=s, j=m+1, k=0; i < =m && j < =d; k++)
if(x[i] < x[j])
y[k]=x[i++];
else y[k]=x[j++];
for(; i < =m; k++)
y[k]=x[i++];
for(; j < =d; k++)
y[k]=x[j++];
for(k=0, i=s; k<d-s+1; k++)
x[k+i]=y[k];
}
void ms (int i,int j) {
if(i < j) { ms(i,(i+j)/2);
ms((i+j)/2+1,j);
merge(i,j); }
}
int main()
{
int n, i;
scanf("%d",&n);
x=(int *)malloc(n*sizeof(int));
for(i=0; i < n; i++)
scanf("%d",&x[i]);
printf("\n");
ms(0,n-1);
for(i=0; i < n ; i++)
printf("%d ",x[i]);
return 0;
}
Sortare rapida (Quick sort)
Quicksort efectuează sortarea bazându-se pe o strategie divide et impera. Astfel, el împarte lista de sortat în două subliste mai uşor de sortat. Paşii algoritmului sunt:
- Se alege un element al listei, denumit pivot.
- Se reordonează lista astfel încât toate elementele mai mici decât pivotul să fie plasate înaintea pivotului şi toate elementele mai mari să fie după pivot. După această partiţionare, pivotul se află în poziţia sa finală.
- Se sortează recursiv sublista de elemente mai mici decât pivotul şi sublista de elemente mai mari decât pivotul.
O listă de dimensiune 0 sau 1 este considerată sortată.
#include "stdlib.h"
#include "time.h"
#include "stdio.h"
int *x;
int poz (int s, int d) {
int i=s, j=d, di=0, dj=1, aux;
while(i < j)
{ if(x[i] > x[j])
{ aux=x[i];
x[i]=x[j];
x[j]=aux;
di=1-di;
dj=1-dj; }
i+=di;
j-=dj; }
return i;
}
void quick (int s, int d) {
if(s < d) { int k=poz(s,d);
quick(s,k-1);
quick(k+1,d); }
}
int main () {
srand(time(NULL));
int n;
scanf("%d",&n);
x=(int *)malloc(n*sizeof(int));
int i;
for(i=0; i < n ;i++)
x[i]=rand()%100;
for(i=0; i < n ;i++)
printf("%d ",x[i]);
quick(0,n-1);
printf("\n");
for(i=0; i < n ;i++)
printf("%d ",x[i]);
printf("\n");
return 0;
}