29 iunie 2010
X si 0
#include"stdlib.h"
#define B_SIZE 3
#define WIN 10000
#define LOSS -10000
#define DRAW 0
#define OCHAR(ch) ((ch=='X')?'O':'X')
char gameboard[3][3] =
{' ',' ',' ',
' ',' ',' ',
' ',' ',' '
};
int curX,curY;
int nodesSearched;
void clrscr(void)
{
#ifdef __linux__
system("clear");
#else
system("CLS");
#endif
}
// Draws the game board accourding to the accupancy matrix
void DrawBoard(char board[3][3])
{
printf("\n 0 1 2\n +-+-+-+\n");
for(int i=0; i < B_SIZE;i++)
{
printf("%d ",i);
for(int j=0; j < B_SIZE;j++)
printf("|%c",board[i][j]);
printf("|\n +-+-+-+\n");
}
}
// Evaluates the win
int CheckStatus(char board[3][3],char ch)
{
int i,j,ord;
for(i=0; i < B_SIZE;i++)
{
ord=0;
for(j=0; j < B_SIZE;j++)
{
if(board[i][j]==ch) ord++;
else break;
}
if(ord==3) return 1;
}
ord=0;
for(i=0; i < B_SIZE;i++)
{
ord=0;
for(j=0; j < B_SIZE;j++)
{
if(board[j][i]==ch) ord++;
else break;
}
if(ord==3) return 1;
}
ord=0;
for(i=0;i < B_SIZE;i++)
if(board[i][i]==ch) ord++;
if(ord==3) return 1;
else ord=0;
for(i=0; i < B_SIZE;i++)
if(board[i][B_SIZE-i-1]==ch) ord++;
if(ord==3) return 1;
return 0;
}
int Negamax(char board[3][3],int occ,int depth,char ch)
{
int score, max=LOSS;
int i,j;
nodesSearched++;
if(CheckStatus(board,ch)==1) return WIN*(10-depth); //*(10-depth) is there so we choose the shortest path to victory
else if(CheckStatus(board,OCHAR(ch))==1) return LOSS*(10-depth);
else if(occ>=9) return DRAW;
for(i=0; i < B_SIZE;i++)
for(j=0;j < B_SIZE;j++)
if(board[j][i]==' ')
{
board[j][i]=ch;
score=-Negamax(board,occ+1,depth+1,OCHAR(ch));
board[j][i]=' ';
if(score > max)
{
max=score;
if(depth==0)
{
curX=i;
curY=j;
}
}
}
return max;
}
int AlphaBeta(char board[3][3],int occ,int depth,int alpha,int beta,char ch)
{
int score,bestscore=LOSS;
int i,j;
nodesSearched++;
if(CheckStatus(board,ch)==1) return WIN*(10-depth); //*(10-depth) is there so we choose the shortest path to victory
else if(CheckStatus(board,OCHAR(ch))==1) return LOSS*(10-depth);
else if(occ>=9) return DRAW;
for(i=0; i < B_SIZE;i++)
for(j=0; j < B_SIZE;j++)
if(board[j][i]==' ')
{
board[j][i]=ch;
score=-AlphaBeta(board,occ+1,depth+1,-beta,-alpha,OCHAR(ch));
board[j][i]=' ';
if(score > beta) return score; // beta cutoff
if(score > bestscore)
{
bestscore=score;
if(depth==0)
{
curX=i;
curY=j;
}
if(score>alpha) alpha=score;
}
}
return bestscore;
}
int main()
{
int x,y,occ=0;
char mych='X',winner=0;
do
{
clrscr();
DrawBoard(gameboard);
printf("Previous move explored %d nodes\nIntroduce (x,y) coordinates:\n",nodesSearched);
scanf("%d",&y);
scanf("%d",&x);
if(x>=B_SIZE || x<0>=B_SIZE || y<0 || gameboard[y][x]!=' ') continue;
gameboard[y][x]=mych;
if(CheckStatus(gameboard,mych))
{
winner=mych;
continue;
}
if((++occ)>=9) break;
nodesSearched=0;
//Negamax(gameboard,occ,0,OCHAR(mych));
AlphaBeta(gameboard,occ,0,LOSS*11,WIN*11,OCHAR(mych));
gameboard[curY][curX]=OCHAR(mych);
if(CheckStatus(gameboard,OCHAR(mych)))
{
winner=OCHAR(mych);
continue;
}
if((++occ)>=9) break;
}while(!winner);
clrscr();
DrawBoard(gameboard);
printf("\n\nWinner is %c",winner);
return 0;
}
27 iunie 2010
Exercitii Prolog
is_palindrome(L) :- reverse(L,L).
% daca un numar este prim
radacina(X, Y):-
N is Y*Y, N =< X, X mod Y =:= 0.
radacina(X, Y):-
Y < X, Y1 is Y + 1, radacina(X, Y1).
prim(X):-
Y is 2, X > 1 , \+radacina(X, Y).
% duplicarea elem unei liste
dupli([],[]).
dupli([X|Xs],[X,X|Ys]) :- dupli(Xs,Ys).
se aplica: dupli([1,2,3], L).
% o lista care contine toate elementele intre 2 limite
range(I,I,[I]).
range(I,K,[I|L]) :- I < K, I1 is I + 1, range(I1,K,L).
se aplica: range(1,5, L).
altele
Quicksort (Haskell)
Problema reginelor in Clips
Prolog
?- before_last(X, [1, 2, 3]). X = 2
k
dintr-o lista. Exemplu:?- kth(X, 3, [4, 3, 2]). X = 2
?- len(X, [1, 2, 3]). X = 3
?- concat([1, 2], [3], L). L = [1, 2, 3]
?- rev([1, 2, 3], L). L = [3, 2, 1]
26 iunie 2010
Partitiile unui numar in Haskell si Clips
Problema reginelor in Scheme
Grafuri in Scheme - ciclicitate
Generarea mai multor numere prime in Scheme
25 iunie 2010
Inversarea unei liste in Clips
23 iunie 2010
Problema de decodificare in Verilog
07 iunie 2010
04 iunie 2010
Noduri critice intr-un graf
Folosind algoritmul pentru nodurile critice :
Considerăm că avem un graf (neorientat și conex) cu N noduri si M muchii. Un nod al grafului se numește critic dacă prin eliminarea lui din graf (și a muchiilor adiacente cu acest nod), graful nu mai rămâne conex. Ne punem problema de a determina care sunt nodurile critice ale unui graf (aceasta este o problemă care apare des în practică, deoarece multe structuri pot fi modelate cu ajutorul grafurilor, iar nodurile critice pot reprezenta punctele vulnerabile ale acestor structuri).
Pași de execuție
Se face o parcurgere DF dintr-un nod oarecare al grafului, pe care îl vom numi în continuare nod rădăcină. Știm că o parcurgere DF determină un arbore parțial de acoperire al grafului, având rădăcină în nodul rădăcină. În cadrul parcurgerii, vom calcula nivelul pe care se află fiecare nod (nivelul rădăcinii este 1, iar nivelul fiecărui nod este egal cu nivelul nodului tată plus 1). Ca urmare a unei parcurgeri DF, muchiile grafului pot fi împărțite în două categorii : muchii ce fac parte din arborele DF (muchii înainte sau muchii directe) și muchii ce nu fac parte din acest arbore (muchii de întoarcere, muchii înapoi sau muchii inverse). Pentru fiecare nod vom calcula, pe langa nivelul acestuia, și nivelul minim la care poate ajunge nodul respectiv mergând numai pe muchii directe din subarborele său din cadrul arborelui DF și folosind ca ultima muchie o muchie inversă. Acestă valoare, pe care o vom numi nivelul minim accesibil este egală cu minimul dintre urmatoarele 3 valori :
- nivelul nodului curent
- minimul dintre nivelurile nodurilor cu care este legat nodul curent printr-o muchie inversă
- minimul dintre nivelurile minime accesibile ale fiiilor nodului curent din cadrul arborelui DF
Se poate observa ușor că un nod (diferit de rădăcină) este critic dacă are cel puțin un fiu pentru care nivelul minim accesibil este mai mare sau egal cu nivelul nodului. Rădăcina este nod critic dacă are cel puțin 2 fii.
=== Implementare in C ===#include "stdio.h"
int n, a[20][20], viz[20];
void citire()
{ FILE * f = fopen("neorientat","r");
fscanf(f,"%d", &n); int i,j;
while(!feof(f))
{ fscanf(f,"%d %d", &i, &j);
a[i][j]=1; a[j][i]=1;
a[i][i]=1; a[j][j]=1; }
}
/* Determinarea nodurilor critice pt graf neorientat */
void df(int vf)
{ int i; viz[vf]=1;
for(i=1; i<=n; i++)
if(a[vf][i]==1 && viz[i]==0)
df(i);
}
int conex()
{ int i, p=0;
for (i=1; i<=n; i++)
if(viz[i]==0)
{ df(i); p++; }
if(p==1)
return 1;
return 0;
}
int main()
{ int i,j;
citire();
printf("Noduri critice: ");
for(i=1;i<=n;i++) //elimin fiecare nod
{ for(j=1;j<=n;j++)
if(a[i][j]==1)
{ a[i][j]=2; a[j][i]=2; }
if(i==n)
df(i-1);
else
df(i+1);
if(!conex())
printf("%d ", i) ;
for(j=1;j<=n;j++)
if(a[i][j]==2)
{ a[i][j]=1; a[j][i]=1; }
for(j=1;j<=n;j++)
viz[j]=0;
}
printf("\n");
return 0;
}
Componentele tare conexe ale unui graf orientat
#include "stdio.h"
int n, a[20][20], viz[20], d[20][20];
void citire()
{ FILE * f = fopen("proba","r");
fscanf(f,"%d", &n); int i,j;
while(!feof(f))
{ fscanf(f,"%d %d", &i, &j);
a[i][j]=1; d[i][j]=1;
a[i][i]=1; d[i][i]=1;
a[j][j]=1; d[j][j]=1; }
}
/* afisarea componentelor tare conexe */
int conex_tare()
{ /* Roy Warshall */
int i,j,k;
for(k=1; k<=n; k++)
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
if(d[i][k] && d[k][j])
d[i][j]=1;
int ok=1;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
if(d[i][j]==0)
ok=0;
return ok;
}
void df(int vf)
{ int i; viz[vf]=1;
printf("%d ",vf); //afisare
for(i=1; i<=n; i++)
if((d[vf][i]==1 && d[i][vf]) && viz[i]==0)
df(i);
}
int main()
{ citire();
if(conex_tare())
printf("este tare conex\n");
else printf("nu este tare conex\n");
int i;
df(1);
for (i=1; i<=n; i++)
if(viz[i]==0)
{ printf("\n"); df(i); }
printf("\n");
return 0;
}
Componentele conexe ale unui graf neorientat
#include "stdio.h"
int n, a[20][20], viz[20];
void citire()
{ FILE * f = fopen("graf.txt","r");
fscanf(f,"%d", &n); int i,j;
while(!feof(f))
{ fscanf(f,"%d %d", &i, &j);
a[i][j]=1; a[j][i]=1; a[i][i]=1; a[j][j]=1; }
}
/* afisare componente conexe pt graf neorientat */
void df(int vf)
{ int i; viz[vf]=1;
printf("%d ",vf); //afisare
for(i=1; i<=n; i++)
if(a[vf][i]==1 && viz[i]==0)
df(i);
}
int main()
{ int p,i; p=0;
citire();
for (i=1; i<=n; i++)
if(viz[i]==0)
{ df(i); printf("\n"); p++; }
if(p==1)
printf(" graf conex\n");
else
printf("are %d componente conexe\n", p);
return 0;
}
Algoritmul lui Kruskal, folosind operatii cu multimi disjuncte
Dandu-se un graf conex si neorientat G=(V, E), unde V = multimea nodurilor, iar E multimea muchiilor grafului G, se numeste arbore minim de acoperire un graf conex si neorientat G' = (V, E'), unde E' inclus in E cu proprietatile:
- G' este este un arbore (graf aciclic);
- suma costurilor muchiilor din E' sa fie minima.
Dintre algoritmii clasici care se ocupa de determinarea arborelui minim de acoperire amintim: algoritmul Kruskal si algoritmul Prim.
=== Pseudocod ===
Fie G=(V, E), graf neorientat si conex
1) AMA = multimea vida
2) Pentru fiecare nod din V
creeaza_multime(v)
3) Sorteaza muchiile din E crescator dupa cost
4) Pentru fiecare muchie (u, v) din E in ordine crescatoare
- Daca gaseste_multime(u) != gaseste_multime(v)
a) Se adauga muchia (u, v) in AMA
b) reuneste(u, v)
=== Implementare in C ===
#include "stdio.h"
#include "stdlib.h"
#define MAX 100
#define INF -1
int n,m,**b;
typedef struct multime {
int c; //contorul multimii
int S[MAX]; //elementele multimii
} Set;
typedef struct muchie {
int x; int y; int cost;
} Muchie;
Muchie mu[MAX];
Set C[MAX]; //colectia
int nset; //nr de seturi
void citire()
{ FILE *f=fopen("in","r");
fscanf(f,"%d",&n);
int i,j,k,cost;
fscanf(f,"%d",&m); //nr muchii
for(i=0;i<=m-1;i++)
{ fscanf(f,"%d %d %d",&j,&k,&cost); mu[i].x=j; mu[i].y=k; mu[i].cost=cost; }
}
/* functii pt multimi disjuncte */
void Make_Set (int n)
{ int i; nset=n;
for(i=0; i<=n-1; i++)
{ C[i].c=1;
C[i].S[0]=i; }
}
void Print_Set()
{ int i,j;
for(i=0; i<=nset-1; i++)
{ for(j=0; j<=C[i].c-1 ; j++)
printf("%d ",C[i].S[j]);
printf("\n"); }
}
//identific a cata multime este multimea in care se afla un element
int Find(int x)
{ int j,i;
for(i=0;i<=nset-1;i++) // pt fiecare set
{ for(j=0; j<=C[i].c-1; j++)
if(x==C[i].S[j])
return i;
}
return -1;
}
void Set_Union(int a,int b) // reuniunea se face in C[a],se sterge C[b]
{ int i;
for(i=0;i<=C[b].c-1;i++)
if(Find(C[b].S[i])!=a)
{ C[a].S[C[a].c]=C[b].S[i]; C[a].c++; }
for(i=b; i<=nset-1; i++)
C[i]=C[i+1];
nset--;
}
void print_muchii()
{ int i;
for(i=0;i<=m-1;i++)
printf("%d %d %d \n",mu[i].x,mu[i].y,mu[i].cost);
}
Muchie arc_min() //gaseste arcul de cost minim si apoi il sterge!
{ int i,min=mu[0].cost,poz=0;
Muchie x=mu[0];
for(i=1; i<=m-1; i++)
if(mu[i].cost < min)
{ min=mu[i].cost; poz=i; x=mu[i]; }
for(i=poz; i<=m-2; i++)
mu[i]=mu[i+1];
m--;
return x;
}
void kruskal()
{
Make_Set(n);
Muchie a;
int u,v,i,j;
b=(int **)malloc(n*sizeof(int *));
for(i=0; i<=n-1; i++)
b[i]=(int *)malloc(n*sizeof(int));
for(i=0; i<=n-1; i++)
for(j=0; j<=n-1; j++)
{ if(i!=j)
b[i][j]=INF;
else
b[i][j]=0; }
int nm=0;
while (nm < n-1) // cat timp nu am atins n-1 muchii
{ a=arc_min();
u=a.x; v=a.y;
if(Find(u)!=Find(v)) // daca se afla in seturi diferite
{ Set_Union(Find(u),Find(v));
b[u][v]=a.cost; b[v][u]=a.cost; nm++; } //adaug muchie la graf nou
}
}
int *viz;
void afisare(int vf)
{
int i; viz[vf]=1;
printf("%d ",vf);
for(i=0; i<=n-1; i++)
if(b[vf][i]>=0 && viz[i]==0)
afisare(i);
}
void afisare2()
{ int i,j,w;
for(i=0; i<=n-1; i++)
for(j=i+1; j<=n-1; j++)
{ w=b[i][j];
if(w > 0)
printf("muchia %d-%d cost %d\n", i,j, w);
}
}
int main()
{ citire();
kruskal();
viz=(int *)malloc(n*sizeof(int));
int i;
for(i=0; i<=n-1 ;i++)
viz[i]=0;
afisare2();
free(viz);
return 0;
}