champion 2008

prologin s'acheve sur une dure bataille de pommes :)

je vous passe mon "champion"
 * _   _                     _            _
*| | | | __ _ _ __ ___ ___| |_ ___ _ __( )___ __ ____ _ _ __
*| |_| |/ _` | '_ ` _ \/ __| __/ _ \ '__|// __| \ \ /\ / / _` | '__|
*| _ | (_| | | | | | \__ \ || __/ | \__ \ \ V V / (_| | |
*|_| |_|\__,_|_| |_| |_|___/\__\___|_| |___/ \_/\_/ \__,_|_|
ouais, bon, jme suis fait plaisir sur l'ascii art :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
/*
* Champion (ou pas) prologin 2008 (rendu le 10 mai 2008)
*
* Style de programmation
* les fonctions devront faire une seule chose, une chose precise, et la faire bien.
* J'ai choisi quelques variables globales pour stoquer mes donnees
*
*
* Strategie envisagees (en resume...) :
* - aller chercher et ramener des pommes dans ma zone
* - tirer sur quelques ennemis (quand ca a l'air interessant
* - sauver quelques hamsters lorsqu'ils tombent dans une fosse
* - tenter de traverser quelques ravins

On gere le moteur general par une liste d'etats,
et des pointeurs sur fonctions pour gerer les operations de facon assez abstraite.

Tirer
seulement lorsque c'est notre tour de jouer en premier, histoire de ne pas
gaspiller nos precieux trognons.
Je n'envoie aussi des trognons dans la gueule de nos ennemis,
que quand ils sont en face, histoire de ne pas perdre trop de temps.
Si notre enemie ne tombe pas dans une fosse,
alors il est inutile d'envoyer un trognon.

Se deplacer
On se deplace vers la pomme la plus proche qui n'est pas occupee par nos mecs.
Ensuite, on ramene les pommes dans notre zone pour recommencer.

Quand un hamster tombe dans la fosse, c'est chiant,
faut qu'un autre aille tenter de le sauver, mais je sais pas trop si ca fonctionne bien...

Quand on n'a rien a faire (pommes innaccessibles par exemple) on devrait chercher a aller
de l'autre cote des fosses (fonction bouge_ton_cul) mais en pratique,
c'est tres difficile de gerer correctement le grapin, et donc...

Les sauver (tentative morbide a base de "je te pousse")

Les points forts de mon IA : sa recuperation de points, son cote safe, et son attaque.

*/


#include "prologin.h"
#include <stdlib.h>
#include <stdio.h>


//! Notre structure de donnees copeaux de bois.
typedef struct {
//int pomme;
int sol; //! peut-etre normal, un obstacle ou un trou
int x, y; //! ses coordonnees
} copBois;

struct hamstruct;
//! notre type de pointeurs sur fonctions
// ces fonctions sont des fonctions d'actions
typedef void (*HamAction)(struct hamstruct *h, int toD);

struct hamstruct {
int id; // son id
int x, y; // la position de notre hamestere
int toD[3]; // les parametres des actions de notre hamstere (to Direction)
HamAction actions[3]; // les trois actions de notre jambon (ou hamster, je sais plus)

int used_ordres; // le nombre d'ordres qu'il utilise

int traverse; // si il a droit de traverser un fosse ou pas

int Ntrognons; // le nombre de trognons qu'il lui reste a prendre
int Hpomme; // ca aurait pu etre utile, mais en fait non...
int mission;

int utile; // dit si sa mission est vraiemnt importante ou pas;

int mtx, mty; // mission target x. y

int s; // quand on a besoin de suivre qqn

int m; // l'etat du grapin
int timefreeze, opx, opy;
};

typedef struct hamstruct ham;

#define GR if (r!=SUCCESS) printf("747---bad argument hamster %d ligne %d erreur %d\n\n", h->id, __LINE__, r);
#define HAMSTER_NOMBRE 3
#define NTROGNONS 2

#define CHERCHER_POMMES 0
#define TOMBER_POMMES 1
#define RAMASSER_POMMES 2
#define POMMES_SAVEHOME 3
#define PROTEGER_POMMES 4
#define SUIVRE 5
#define GRAPPINER 6

//! ma valeur absolue
int mabs(int a){
if (a<0) return -a; return a;
}

void decider(ham *h); //! prototype de la fonction de decision.

//! les fonctions de type HamAction.

//! fonction de deplacement
void aller(ham *h, int toD){
//printf("747---deplacement du hamster %d, vers %d\n",
//   h->id, toD );
int r = deplacer(h->id, toD); GR
}
//! fonction qui lache une pomme
void lacher(ham *h, int toD){
printf("747---le hamster %d, lache une pomme en %d, %d\n",
h->id, h->x, h->y );
int r = lacher_pomme(h->id, toD); GR
}
//! fonction de ramassage de pomme
void ramasser(ham *h, int toD){
printf("747---le hamster %d, ramasse une pomme en %d, %d\n",
h->id, h->x, h->y );
int r = ramasser_pomme(h->id); GR
}
//! fonction qui sert a poser le grapin sur un ham
void grappiner(ham *h, int toD){
printf("747---le hamster %d, grappine en %d\n",
h->id, toD );
int r = grappin(h->id, toD); GR
}
//! fonction qui envoie un trognon sur un ham
void trogner(ham *h, int toD){
printf("747---le hamster %d, trogne en %d\n",
h->id, toD );
int r = trognon(h->id, toD); GR
}
//! fonction de repos d'un hamstere
void patienter(ham *h, int toD){
//printf("747--- Le hamster %d ne fout rien\n", h->id);
int r=attendre(h->id); GR
}
/*
Ces fonction auraient pu etres utilisees, je les ai codees quand j'etais
+
*/


/*
int getX(int pos){
return pos & 0xFFFF;
}
int getY(int pos){
return (pos & 0xFFFF0000 ) >> 16;
}
int pos(int x, int y){
return x + ( y << 16) ;
}
*/



//! dit si c'est ta zone
int macase(int x, int y){
return y==0 || y==1;
}


// VAR globales

copBois *cases, **map; // la map
int sx, sy, tmap, /* size x, y, taille map*/
end; /* nombre de tours */

ham hamster[HAMSTER_NOMBRE]; // les hamsters

int haswhite; // dit si on a les blancs ce tour la ou pas.

//int strategie; // soit on met 1, soit 3

// dit si la position est valide ou non
int isValidPos(int x, int y){
return x>=0 && x < sx && y < sy && y >=0;
}

//! met a jours l'etat de la case *o au niveau des pommes
//void updatePomme(copBois *o){
// o->pomme = pomme(o->x, o->y);
//}
//! dit ou un gars est
void tayou(ham *h){
int x, y;
x=pos_x(h->id);
y=pos_y(h->id);
h->Hpomme= porte_pomme(h->id);

if (x==h->opx && y==h->opy){
h->timefreeze++;
}else{
h->timefreeze=0;
}
h->opx=x; h->opy=y;

h->x=x;
h->y=y;
}
//! fait bouger un gars
void agir(ham *h){
int i;

printf("747---HAMSTER %d -- %d-- mission : %d, (%d, %d) %d\n",
   h->id, h->traverse, h->mission, h->mtx, h->mty, h->utile);

for (i=0;i<h->used_ordres;i++){
h->actions[i](h, h->toD[i]);
}
}
//! dit si un hamster veut deja aller en cette position
int people_has(int x, int y){
int i;
for(i=0;i<HAMSTER_NOMBRE; i++ ){
if (hamster[i].mtx ==x && hamster[i].mty == y) return 1;
}
return 0;
}


//! fonction qui trouve une pomme interessante a ramenner
int findPomme(ham *h){
int x, y, bx=-1, by=-1, minT=9999, d;
for (x=0;x<sx; x++){
for (y=0;y<sy;y++){
if ((!macase(x, y)) && NORMAL == map[x][y].sol && pomme(x, y)){
if (people_has(x, y)) continue; // si qqn s'occupe deja de cette pomme
  d=distance(x, y, h->x, h->y, h->traverse);
if (d < minT){
   bx=x; by=y; minT=d;
  }
}
}
}
//printf("747---pomme interessante en %d, %d (%d, %d, t=%d)\n",
// bx, by, h->x, h->y, minT);
h->mtx = bx;
h->mty = by;
if (h->mtx == -1 && h->mty == -1){
h->mtx=0; h->mty=0;
// on a deja toutes les pommes
return 0;
}else{
return 1;
}
}
//! applique une direction a une position
void applyDir(int x, int y, int d, int *dx, int *dy){
switch(d){
case HAUT:
*dy=y-1; *dx=x;
break;
case GAUCHE:
*dy=y; *dx=x-1;
break;
case BAS:
*dy=y+1; *dx=x;
break;
case DROITE:
*dy=y; *dx=x+1;
break;
default:
printf("747---ERREUR DE PARAMETRE %d\n\n", __LINE__);
break;
}
}
//! dit si un hamster est en x, y (donc si on le pousserait en y allant)
int jepousse(int x, int y){
int i;
for (i=0;i<3;i++){
if (hamster[i].x==x && hamster[i].y==y){
return 1;
}
}
return 0;
}
//! cherche la direction pour aller a h
int allera(ham *h){
int i, p=ICI, x, y, dmin=-1, d;

if (h->x==h->mtx && h->y==h->mty)
return ICI;
for (i=0;i<4;i++){
applyDir(h->x, h->y, i, &x, &y);
if (jepousse(x, y)) continue; // on interdit de pousser son partenaire
if (isValidPos(x, y)){
// fake pour eviter les cases tranchees
d= distance(x, y, h->mtx, h->mty, h->traverse)*2 + (map[x][y].sol!=NORMAL);
if (dmin==-1 || d < dmin){
  //printf("747---d = %d %d\n", d, i);
  dmin=d;
  p=i;
}
}
}
return p;
}

// organise le retour a la maison d'une pomme
void retour_maison(ham *h){
int d;

if (!porte_pomme(h->id)){
//h->mission = CHERCHER_POMMES;
//decider(h);
//return;
}

//printf("747--- Retour maison\n");
// on definit la nouvelle destination
h->mtx=0; h->mty=0;
while (pomme(h->mtx, h->mty) || NORMAL != map[h->mtx][h->mty].sol ){
h->mtx++;
if (h->mtx==sx){
h->mty++; h->mtx=0;
}
//printf("747--- CASE NOT EMPTY !!! %d %d\n", h->mtx, h->mty);
}
d=allera(h);
if (d==ICI){ // si tu deposes la pomme
//printf("747--- Bienvenu a la maison !\n");
h->actions[h->used_ordres]=lacher;
h->toD[h->used_ordres]=d;
h->used_ordres++;
h->mission=CHERCHER_POMMES;
}else{ // deplacement vers la maison
//printf("747--- On va en %d %d\n", h->mtx, h->mty);
h->actions[h->used_ordres]=aller;
h->toD[h->used_ordres]=d;
h->used_ordres++;
applyDir(h->x, h->y, d, &h->x, &h->y);
}
}

//! protege les pommes
void blinde_home(ham *h){
//printf("747---On blinde nos pommes\n");
int d;

while (NORMAL != map[h->mtx][h->mty].sol ){
h->mtx++;
if (h->mtx==sx){
h->mty++; h->mtx=0;
}
}
// printf("747---On sait ou on va\n");
d=allera(h);
if (d==ICI){ // si tu dois changer de mission
h->actions[h->used_ordres]=patienter;
h->toD[h->used_ordres]=d;
h->used_ordres++;
h->mission=CHERCHER_POMMES;
}else{ // deplacement vers la maison
h->actions[h->used_ordres]=aller;
h->toD[h->used_ordres]=d;
h->used_ordres++;
applyDir(h->x, h->y, d, &h->x, &h->y);
}
}

//! dit si les cases sont a cote ou non
int isnear(ham *h1, ham *h2){
int ax=mabs(h1->x - h2->x);
int ay=mabs(h1->y - h2->y);
return (ax==0 && ay==1 ) || (ax==1 && ay==0);
}
//! donne la direction pour aller d'un point a un autre
int directionde(int x1, int y1, int x2, int y2){
if (y1<y2) return BAS;
if (x1<x2) return DROITE;
if (y1>y2) return HAUT;
return GAUCHE;
}
//! pose un grapin
void ograppiner(ham *h1, ham *h2){
printf("747--- grappin %d ----) %d\n", h1->id, h2->id);
h1->actions[h1->used_ordres]=grappiner;
h1->toD[h1->used_ordres]=directionde(h2->x, h2->y, h1->x, h1->y);
printf("747--- On grapine en %d\n", h1->toD[h2->used_ordres]);
h1->used_ordres++;
}
//! renvoie la direction opposee
int oltherd(int d){
switch (d){
case HAUT: return BAS;
case BAS: return HAUT;
case DROITE: return GAUCHE;
case GAUCHE: return DROITE;
default: return ICI;
}
}
//! fonction principale de suivit d'une unitee
void suivre_p(ham *h1, ham *h2){
printf("747---Suivre\n");
int d;
h1->traverse=1;
h1->mtx = h2->x;
h1->mty = h2->y;
if (isnear(h1, h2)){
if (map[h2->x][h2->y].sol!=NORMAL){
d=directionde(h1->x, h1->y, h2->x, h2->y);
  h1->mission=GRAPPINER;
  h1->s=h2->id;
  h1->m=0;
return;
}else{
d=ICI;
}
}else{
d=allera(h1);
}

if (d==ICI){
printf("747--- t'es sur le mec que tu suis...\n");
h1->actions[h1->used_ordres]=patienter;
h1->toD[h1->used_ordres]=ICI;
h1->used_ordres++;
}else{
h1->actions[h1->used_ordres]=aller;
h1->toD[h1->used_ordres]=d;
h1->used_ordres++;
applyDir(h1->x, h1->y, d, &h1->x, &h1->y);
if (h1->x == h2->x && h1->y == h2->y){
applyDir(h2->x, h2->y, d, &h1->x, &h1->y);
}
}
h1->traverse=0;
}

//! verifie si un mur horizontale est present
int murdeaH(int x, int xe, int y){
for (; x<=xe;x++){
if (map[x][y].sol == OBSTACLE){
return 1;
}
}
return 0;
}
//! verifie si un mur vertical est present
int murdeaV(int x, int y, int ye){
for (; y<=ye;y++){
if (map[x][y].sol == OBSTACLE){
return 1;
}
}
return 0;
}
// dit si on a un interret a balancer le truc
int Hinteret(int x, int y, int d){
while (isValidPos(x, y)){
if (map[x][y].sol == TRANCHEE) return 1;
applyDir(x, y, d, &x, &y);
}
return 0;
}

// shot l'ennemy (a base de trognons de pommes)
int hamstershot(ham *h, int can){
//return 0;
int i, ex, ey, d=ICI, p;
if (!can) return 0;
if (h->Ntrognons==0) return 0;
for (i=3;i<6;i++){
ex = pos_x(i);
ey = pos_y(i);
p=porte_pomme(i);
//printf("747---- |||||||||||||| EX=%d\tEY=%d IAMIN %d %d\n", ex, ey, h->x, h->y);
if (ey == h->y){
if ( ex < h->x ){
  if (murdeaH(ex, h->x, ey)) continue;
  if (ex==0) continue;
  if (Hinteret(ex, ey, GAUCHE) || p) d=GAUCHE;
}else{
  if (murdeaH(h->x, ex, ey)) continue;
  if (ex==sx-1) continue;
  if (Hinteret(ex, ey, DROITE) || p) d=DROITE;
  //printf("747--- SHOT !!!!\n");
}
}else if (ex == h->x){
if ( ey < h->y ){
  if (murdeaV(ex, ey, h->y)) continue;
  if (ey==0) continue;
  if (Hinteret(ex, ey, HAUT) || p) d=HAUT;
}else{
  if (murdeaV(ex, h->y, ey)) continue;
  if (ey==sy-1) continue;
  if (Hinteret(ex, ey, BAS) || p) d=BAS;
}
}
}
if (d!=ICI){
h->actions[h->used_ordres]=trogner;
h->toD[h->used_ordres]=d;
h->used_ordres++;
h->Ntrognons--;
printf("747---SHOT %d\n", d);
return 1;
}else{
return 0;
}
}

// lance le suivi d'un ami, pour lui permettre de traverser, ou le sauver
void suivre(ham *h, int suivreId, int pt){
h->mission = SUIVRE;
h->s = suivreId;
h->m=pt;
}

// la fonction qui envoie un hamstere dans les tranchees
void bouge_ton_cul(ham *h){
if (h->traverse) return;
printf("747---Le hamstere %d bouge enfin le cul et va par delas des ravins\n", h->id);
h->mission = CHERCHER_POMMES;
h->traverse = 1;
}

//! fonction qui decide ce qu'un hamster fait
void decider(ham *h){
int d;
if (hamstershot(h, haswhite)) return;

if (h->mission == CHERCHER_POMMES){
if (findPomme(h)){
h->mission=RAMASSER_POMMES;
h->utile = 1; // mec utile
}else{
h->mission=PROTEGER_POMMES;
h->utile=0; // mec inutile
}
}
if (h->mission == PROTEGER_POMMES){
blinde_home(h);
h->utile = 0; // mec inutile
}else if (h->mission == RAMASSER_POMMES){
h->utile = 1; // mec utile
d=allera(h);
if (d==ICI){
printf("747--- pomme spotted\n");
h->mission = POMMES_SAVEHOME; // on decide de rameter la pomme a la maison
h->actions[h->used_ordres]=ramasser; // on ramasse la pomme
h->used_ordres++;
}else{
h->actions[h->used_ordres]=aller;
h->toD[h->used_ordres]=d;
h->used_ordres++;
//printf("747--- d=%d (%d %d)\n", d, h->x, h->y);
applyDir(h->x, h->y, d, &h->x, &h->y);
}
}else if ( h->mission == POMMES_SAVEHOME ){
retour_maison(h); // on ramene la pomme a la maison

}else if (h->mission == GRAPPINER){
if (h->m==0){
h->m=1;
ograppiner(h, &hamster[h->s]);
}else{
h->traverse=0;
h->mission=CHERCHER_POMMES;
decider(h);
}
}else if (h->mission == SUIVRE){
suivre_p(h, &hamster[h->s]);
}
}
void resetHamster(ham *h){
h->mission=CHERCHER_POMMES;
h->timefreeze=0;
h->traverse=0;
}
//! mise a jours des pommes
/*id pommes_update(){
int i;
for (i=0;i<HAMSTER_NOMBRE;i++){
}
}*/

//! fonction d'initialisation
void init_game(void)
{
int i, j;
copBois *o;

// initialisation de la taille de la map
sx=taille_carte_x();
sy=taille_carte_y();
tmap = sx * sy;
// initialisation du temps
end = nombre_tours();
// initialisation des cases memoires
cases = (copBois *) malloc(sx * sy * sizeof(copBois));
map = (copBois **) malloc(sx * sizeof(copBois *));
// initialisation des pointeurs vers la map
for (i=0;i<sx;i++){
map[i]=cases + sy * i;
}
// initialisation de la map
for (i=0;i<sx;i++){
for (j=0;j<sy;j++){
o=&map[i][j];
o->x = i;
o->y = j;
o->sol = type_case(i, j);
//datePomme(o);
}
}
// initialisation des hamsters
for (i=0; i< HAMSTER_NOMBRE;i++){
hamster[i].id=i;
resetHamster(&hamster[i]);
hamster[i].Ntrognons=NTROGNONS;
hamster[i].utile = 0;
hamster[i].x=-1; hamster[i].y=-1;
for (j=0;j<3;j++)
hamster[i].actions[j]=patienter;
// tayou(&hamster[i]);
}
//strategie = 1;
}


//! fonction principale, appellee a chaque tour
void play_turn(void)
{
int i;
int now = numero_tour();
haswhite = commence();
int turn;
int ne=-1;

printf("747--- TOUR %d\n", now);

// on recherche nos hamsters
for (i=0; i< HAMSTER_NOMBRE;i++){
tayou(&hamster[i]); // ou est le hamster
hamster[i].used_ordres=0;
if (hamster[i].timefreeze >= 4){
printf("747--- TIMEFREEZE %d %d\n", i, hamster[i].timefreeze);
resetHamster(&hamster[i]);
}
}


// pommes_update(); // on update quelques infos de la map

// on decide de bouger
for (turn=0;turn<3;turn++){
int fait=0;
for (i=0;i<HAMSTER_NOMBRE;i++){
if (hamster[i].used_ordres <=turn){
  printf("747---Decision du tour : %d du hamster %d (%d)\n",
   turn, i, NORMAL==map[hamster[i].x][hamster[i].y].sol,
   hamster[i].timefreeze);
  if (ne!=-1){
   suivre(&hamster[i], ne, 0);
  }else{
   if (map[hamster[i].x][hamster[i].y].sol != NORMAL && hamster[i].traverse==0){
   ne=i;
   }
   // on ne bouge que sur un sol normal
   decider(&hamster[i]);
   if (hamster[i].utile)
   fait=1;
  }
}
}
if (!fait){
// bouge_ton_cul(&hamster[1]);
//suivre(&hamster[2], 1, 1);
}
}
// on bouge (donne les ordres)
for (i=0;i<HAMSTER_NOMBRE;i++){
agir(&hamster[i]); //break;
}
printf("747--- FIN TOUR\n");
}
Prologin 2008 : la bataille des pommes

j'aurais bientot mon classement, il reste encore quelques bugs (pour passer les tranchees) mais il faisait pas mal de points :)

Classé sous , , , ,
Attachment(s): audouinm.zip

prologin

Bon, ce matin (vers 16h) j'avais commence un spitch sur prologin, mais j'ai pas trop compris pourquoi, mon aimable firefox 3 beta 5, s'est mis a bugger, (histoire de bien tennir son nom de beta...)
Bref, apres avoir debute sur un serveur qui fonctionne, prologin se termine avec une photo innoubliable.

[ocaml/F#] derivez une fonction

Ocaml ou F#

Je ne sais pas vraiment si mon code compile en F#, mais apres avoir lu quelques lignes de F#, je suis sur qu'il peut se traduire facilement.

Les types en ocaml

Je développe de temps en temps en ocaml, c'est un langage surprenant, on en fait des choses magnifiques cote structures de données. En effet, on peut faire des types remarquables, que l'on obtient difficilement dans d'autres langages.

(*ceci est un commentaire*)
(*nous allons faire un enum*)
type enum = Valeur1 | Valeur2 | Valeur3;;

le | se prononce "ou", ce qui permet de comprendre facilement a quoi sert le type. Un nom de type commence par une minuscule (comme une valeur), et une partie du type (on appelle ca constructeur) commence par une majuscule.

On peut paramétrer ces constructeurs, de telle sorte d'obtenir un type algébrique.

type boolean = Vrai | Faux | And of boolean * boolean | Or * boolean * boolean;;

Ce code permet de stocker une valeur formelle d'un boolean.

Quand on stocke des choses de facon formelle, on s'intéresse a la forme de ce qu'on a stocke, plus qu'a ce qu'on stocke vraiment.

Une fonction ?

Une fonction est une valeur paramétrée par une ou plusieurs variables. Voici le type que j'ai choisi pour représenter une variable.

type var = V of string;;

Ca peut paraître étrange de ne pas mettre directement une chaîne. J'ai mis un type isomorphe a string, pour pouvoir ensuite bien différencier une chaîne d'une variable (ca ajoute aussi un niveau d'abstraction).

type 'a func =
	Val of 'a                 |
	Var of var                |
	Plus of 'a func * 'a func |
	Fois of 'a func * 'a func |
	Div of 'a func * 'a func  |
	Powct of 'a func * 'a     |
	Neg of 'a func            |
	Ln of 'a func             |
	E of 'a func              |
	Sin of 'a func            |
	Cos of 'a func            |
	Compose of 'a func * 'a func;; (* a(b(x))*)

Voila une fonction de 'a vers 'a. 'a étant la forme de génériques qu'on trouve en ocaml. Le constructeur Powct sert a élever une valeur variable a une puissance constante. Avec une représentation aussi simple des choses, dériver est un jeu d'enfant...

(* permet de deriver mfunc par rapport a v*)
let derive zero'a un'a moins v mfunc=
let zero = Val zero'a and un = Val un'a in (* on prend 1 et 0 dans des types fonctionnels *)
let rec dx = function
| Val _ -> zero
| Var var -> if var = v then un else zero (* la partie qui fait des derivees partielles*)
| Neg a -> Neg (dx a)
| Plus (a, b) -> Plus ( (dx a), (dx b) )
| Fois (a, b) -> Plus ( Fois ( (dx a), b) , Fois ( (dx b), a ) )
| Div (a, b) -> Div (
	Plus ( Fois ( (dx a), b), Neg (Fois ((dx b), a)) ),
	Fois ( b, b ) )
| Powct (a, n) -> Fois ( (Val n), Powct(a, moins n un'a) )
| Ln a -> Div ( (dx a), a)
| E a as f-> Fois ((dx a), f)
| Compose (a, b) -> Fois ( (dx b), Compose( (dx a), b ) )
| Cos a -> Neg( Sin a)
| Sin a -> Cos a
in dx mfunc;;

Le reste est une simple application des formules de dérivations... Pour couvertir en float, il nous faut faire des evaluations partielles : remplacer chaque variable par sa valeur.

let rec parteval v a mfunc = (* c'est en fait la composition par fonctions constantes.*)
let rec pe = function
| Var var as f -> if var = v then a else f
| Neg a -> Neg (pe a)
| E a -> E (pe a)
| Ln a -> Ln (pe a)
| Cos a -> Cos (pe a)
| Sin a -> Sin (pe a)
| Plus (a, b) -> Plus ((pe a), (pe b))
| Fois (a, b) -> Fois ((pe a), (pe b))
| Div (a, b) -> Div ((pe a), (pe b))
| Compose(a, b) -> let c = (pe b) in parteval v c a
| Powct(a, n) -> Powct( (pe a), n)
| Val a as f -> f
in pe mfunc;;

Ensuite, on doit pouvoir faire évaluer une fonction constante :

let eval (*evalue une fonction constante.*)
 un zero
 moins plus fois div pow
 exp ln
 cos sin
 mfunc =
let rec e = function
| Val a -> a
| Var _ -> failwith "eval"
| Neg a -> moins zero (e a)
| Plus (a, b) -> plus (e a) (e b)
| Fois (a, b) -> fois (e a) (e b)
| Div (a, b) -> div (e a) (e b)
| Compose (a, b) -> e a
| E a -> exp (e a)
| Ln a -> ln (e a)
| Sin a -> sin (e a)
| Cos a -> cos (e a)
| Powct (a, n) -> pow (e a) n
in e mfunc;;

On trainnait alors sur des types 'a, on va alors faire une application sur des floats.

let pow a b = exp (b *. (log a));; (* a^b sur des float*)
(*fonction d'évaluation de fonctions constantes sur des floats.*)
let evalfloatfunc = eval 1. 0. (-.) (+.) ( *.) (/.) pow exp log cos sin;;

Un exemple

let x = V "x";;
let f = Plus (Var x, Val 1.);;
derive 0. 1. (-.) x f;;
evalfloatfunc (parteval x (Val 4.) f);;

Conclusion

ocaml est Vraiment un langage adapte aux mathématiques, On obtient un programme facilement, en écrivant juste quelques relations mathématiques et quelques types qui semblent plutôt naturels.

Ce genre de valeurs formelle n'est pas a utiliser partout, parce-que son utilisation massive provoquerait des consommations énormes de mémoire, des temps de calculs assez impressionnants, et des algos qui sont simples sur d'autres représentations de donnees, difficiles ici. Exemple, si vous faites ca pour un polynôme, vous obtenez :

type 'a poly =
	Zero |
	Un |
	X |
	Add of 'a poly * 'a poly |
	Mult of 'a poly * 'a poly |
	Scal of 'a poly * 'a;;

On appercoit ici de quoi faire la base de l'espace vectoriel : Zero, Un, Mult of 'a poly * 'a poly, ce qui permet de faire tout les X^n et le 0. Cette notation permet énormément de choses, en effet, pour additionner deux polynômes, vous ne faites pas beaucoup d'opérations... Mais par contre, pour l'evaluer ou même pour savoir si deux polynômes sont égaux... c'est beaucoup moins simples.


Classé sous , , ,

nouveau tuto sur le site du zero

Sur le site du zero, ils ont ajoute un tuto et un forum sur le java, apres quelques reactions des membres habitues, on peut retennir quelques reactions :

  • c'est mieux que ce que fait l'auteur habituel
  • au moins, ceux qui font du java n'occuperont plus le forum autres langages
  • ce tuto a l'air plus complet que celui sur le Cpp (pour la partie objet)
  • Apres une lecture rapide du tuto, on a convenu que ce tuto etait a l'image du site du zero, celui qui l'a fait ne sait pas coder... (j'ai tente de les prevenir, mais leur serveur sql est tombe en panne)

    Bref, pour ceux qui ne voient pas :

            String a, b, c;
            a=new String("test"); b=new String(" de debutant");
            c=a.concat(b);
            System.out.println(c);
    

    Ici, on a pas besoin de mettre c=new String(); avant de faire le concat...


    Les 10 derniers blogs postés

    - Disparition de variables de session PHP après une redirection ? par MadMatt le il y a 9 heures et 36 minutes

    - [MOSS 2007] Publier ses formulaires InfoPath via feature par Adrien Siffermann le il y a 12 heures et 43 minutes

    - Imagine Cup 2008 - Paris - Les résultats par TheSaib .NET blog le il y a 14 heures et 5 minutes

    - L'Egypte accueille Imagine Cup 2009 par Code is poetry le il y a 14 heures et 17 minutes

    - PowerShell : Mise en ligne de fonctions intéressantes pour SharePoint par Blog Technique de Romelard Fabrice le il y a 15 heures et 24 minutes

    - Raccourcis clavier et CRM 4 par Clark, C#, MSCRM, SBS le il y a 19 heures et 30 minutes

    - [Silverlight] Comment échanger des données entre une application Silverlight et une page ASP.NET via cookies ? par Thomas Lebrun le il y a 20 heures et 6 minutes

    - SharePoint 2007 : Trouver les fichiers CheckOut dans une librairie de document par Philippe Sentenac [MVP SharePoint] le il y a 22 heures et 34 minutes

    - [Open XML] Travailler avec Open XML : Linq To XML (Partie 2 - Requêtes/XPath) par Julien Chable le 07-08-2008, 02:05

    - [Open XML] Travailler avec Open XML : Linq To XML (Partie 1 - Namespace) par Julien Chable le 07-08-2008, 00:44