Logiciel : Kitsune 2.0 : jeu de lettres et de chiffres
Posté par Lapinot (page perso, ). Modéré le 12 juin 2007.
Kitsune est un logiciel libre destiné à résoudre les problèmes de chiffres du jeu télévisé "Des chiffres et des lettres". Etant donné un compte, il calcule toutes les façons de le résoudre, ou, à défaut, d'obtenir la meilleure approximation. Kitsune permet donc au téléspectateur de pallier aux (rares) défaillances de l'animateur de l'émission, mais également au candidat potentiel de s'entraîner sur des tirages aléatoires.
La version 2.0 apporte la possibilité de rentrer sa solution, ce qui permet de jouer dans des conditions approchant celles des candidats de l'émission. Si le joueur a rentré la solution du problème (ou la meilleure approximation), le chronomètre s'arrête et toutes les solutions sont affichées.
Kitsune a été programmé avec Qt4. Il est distribué sous licence GPL, et disponible sous Linux, Mac et Windows.
La version 2.0 apporte la possibilité de rentrer sa solution, ce qui permet de jouer dans des conditions approchant celles des candidats de l'émission. Si le joueur a rentré la solution du problème (ou la meilleure approximation), le chronomètre s'arrête et toutes les solutions sont affichées.
Kitsune a été programmé avec Qt4. Il est distribué sous licence GPL, et disponible sous Linux, Mac et Windows.
Kitsune (1047 hits)
Copies d'écran (1386 hits)
Règles du jeu télévisé (233 hits)
Notice sur Framasoft (167 hits)
> Lire la suite (31 commentaires, moyenne: 2). [dépêche : 1409 caractères]
Vous avez demandé le commentaire #841068.



Une version texte en C "pur"
Voila un bout de code pondu par un pote et qui doit bien avoir 20/25 ans... (le code, pas lui :-) A l'époque, on arrivait tout juste à rester sous les 45 secondes... Avec les machines actuelles c'est évidemment instantané ! Bon, allez, on va dire que c'est du Gpl 2+ :-)
/* contebon.c */ #include "math.h" /* #include "process.h" */ #include "stdio.h" #include "string.h" unsigned _stklen = 60000U ; #define MAXNB 6 typedef struct { long val; char text[80]; } elt_rech; long obj,best_delta; int cherche(elt_rech jeu[]) { int i; for(i=0;jeu[i].val;i++) { int j; if(labs(jeu[i].val-obj)<best_delta) { best_delta=labs(jeu[i].val-obj); printf("%s=%ld\n",jeu[i].text,jeu[i].val); if(jeu[i].val==obj)return(1); } for(j=i+1;jeu[j].val;j++) { elt_rech jeulocal[MAXNB+1]; long big,small; char tbig[80],tsmall[80]; int k,nbout=1; for(k=0;jeu[k].val;k++) if(k!=i&&k!=j) { jeulocal[nbout].val=jeu[k].val; strcpy(jeulocal[nbout].text,jeu[k].text); nbout++; } jeulocal[nbout].val=0; if(jeu[i].val>jeu[j].val) { big=jeu[i].val; small=jeu[j].val; strcpy(tbig,jeu[i].text); strcpy(tsmall,jeu[j].text); } else { big=jeu[j].val; small=jeu[i].val; strcpy(tbig,jeu[j].text); strcpy(tsmall,jeu[i].text); } jeulocal[0].val=big+small; sprintf(jeulocal[0].text,"(%s+%s)",tbig,tsmall); if(cherche(jeulocal))return(1); if(big!=small) { jeulocal[0].val=big-small; sprintf(jeulocal[0].text,"(%s-%s)",tbig,tsmall); if(cherche(jeulocal))return(1); } jeulocal[0].val=big*small; sprintf(jeulocal[0].text,"%sx%s",tbig,tsmall); if(cherche(jeulocal))return(1); if(!(big%small)) { jeulocal[0].val=big/small; sprintf(jeulocal[0].text,"(%s/%s)",tbig,tsmall); if(cherche(jeulocal))return(1); } } } return(0); } int main() { short nbnb,i; elt_rech jeu[MAXNB+1]; printf("Combien de nombres "); scanf("%d",&nbnb); if(nbnb>MAXNB) { printf("Pas plus que 6.\n"); exit(0); } for(i=0;i<nbnb;i++) { printf("Nombre %d ",i+1); scanf("%ld",&jeu[i].val); sprintf(jeu[i].text,"%ld",jeu[i].val); } jeu[nbnb].val=0; printf("Tri des valeurs ...."); for(i=0;i<nbnb;i++) { int j; for(j=i+1;j<nbnb;j++)if(jeu[i].val<jeu[j].val) { elt_rech swap; swap=jeu[i]; jeu[i]=jeu[j]; jeu[j]=swap; } } for(i=0;i<nbnb;i++)printf(" %ld",jeu[i].val); printf("\nObjectif "); scanf("%ld",&obj); best_delta=labs(obj-jeu[0].val); if(cherche(jeu))printf("Solution exacte trouvee\n"); else printf("Solution approchee trouvee\n"); }[^]Re: Une version texte en C "pur"
À mes tous débuts en C, j'étais tombé sur un programme un peu plus court - mais beaucoup plus compliqué à comprendre! Le voici:
#define GAP(a,b) (((a)>(b))?((a)-(b)):((b)-(a))) #define SPRINTOP(a,b,k,res) \ ({strcpy(str_tmp,str_result);\ sprintf(str_result,"%3d %c %3d = %d\n%s",(((a)>(b))?(a):(b)),s[k],(((a)>(b))?(b):(a)),res,str_tmp);}) #define NBCH 6 int best_tot = 0, best_gap = 999; char str_result[255],str_tmp[255]; int plus (int *a, int b) { return (*a += b); } int moins(int *a, int b) { return (*a = GAP(*a,b)); } int multi(int *a, int b) { return (*a *= b ); } int divis(int *a, int b) { if (*a < b) { *a^=b; b^=*a; *a^=b; } if ( !(*a%b) ) return (*a /= b ); return 0; } #define NBOP 4 int (*f[])(int *,int) = { plus , moins , multi, divis }; char s[] = "+-*/"; int lcb(int *tab, int nb, int tot) { int i,j,k,t[NBCH]; for ( i=0 ; i<nb-1 ; i++ ) for ( j=i+1 ; j<nb ; j++) for ( k=0; k<NBOP; k++) { memcpy(t,tab,sizeof(int)*NBCH); if ( (*f[k])(&t[i],t[j]) ) { if ( t[i] == tot ) return SPRINTOP(tab[i],tab[j],k,t[i]); if ( GAP(t[i],tot) < best_gap) { best_tot = t[i] ; best_gap = GAP(best_tot,tot); } t[j]=t[nb-1]; if (lcb(t,nb-1,tot)) return SPRINTOP(tab[i],tab[j],k,t[i]); } } return 0; } int main(void) { int t[NBCH], i, tot; *str_result = 0x00; for ( i=0; i<NBCH ; scanf("%d",(printf("nombre %d : ",i+1),&t[i++]))) ; printf("total : "); scanf("%d",&tot); if ( ! lcb(t,NBCH,tot) ) lcb(t,NBCH,best_tot); else printf("Le compte est bon : \n"); return ! printf(str_result); }Usage extensif des (deux) macros, presque obfusqué, avec un algorithme d'une complexité apparemment plus élevée. Je ne connais pas l'auteur, donc je ne peux pas donner de licence par contre...[^]En Prolog
/*
mettre par ex
cptbon([2,3,25,7,1,3],347).
*/
cptbon(L,X):-
cptf(L,L2),
dans(L2,X),
cptfa(L,L2).
dans([X|_],X).
dans([_|L],X):-
dans(L,X).
cptfa(L,L).
cptfa(L1,L2):-
cpt(L1,L3),
cptfa(L3,L2),
write(L3),nl.
cptf(L,L).
cptf(L1,L2):-
cpt(L1,L3),
cptf(L3,L2).
cpt([X|Q1],[X|Q2]):-
cpt(Q1,Q2).
cpt([X|Q1],Q2):-
cpt2(X,Q1,Q2).
cpt2(X,[A|Q1],[A|Q2]):-
cpt2(X,Q1,Q2).
cpt2(X,[Y|Q1],[Z|Q1]):-
Z is X+Y;
X>Y, Z is X-Y;
X<Y, Z is Y-X;
Z is X*Y;
X>Y,0 is X mod Y, Z is X/Y;
X<Y,0 is Y mod X, Z is Y/X.
[^]Re: Toutes, vraiment toutes ?
Je n'ai pas le niveau pour comprendre ni le code en Prolog, ni en C.
Mais j'avais une petite question ... (qui est bonne aussi pour le code en C++ de kitsune (et pas katsumi ;)
Peut-on être sûr d'avoir toutes les solutions ?
N'y a-t-il pas des solutions non analysées ?
Sinon, je le redis ici, mais c'est vraiment un beau projet, simple, mais qui est agréable. Ça fait déjà 3/4 d'h qu'il tourne chez moi :( et http://pour_mon_bac.saimal.fr/ )
[^]Re: Toutes, vraiment toutes ?
De par sa nature, Prolog trouve toutes les solutions (sauf si on force ...) à une subtilité près : prolog ne sait pas inférer sur les calculs de sa calculatrice. Il faut soit définir les nombres de façon fonctionnelle, soit utiliser un langage (comme chips) qui sache inférer sur sa calculatrice.
Soutenez le logiciel libre, en adhérant dès maintenant à l'April
[^]Re: Toutes, vraiment toutes ?
Tu veux parler de CLIPS ? Si c'est bien ça, je doute qu'il soit très adapté à ce type de problème où on part de la solution.
En effet, CLIPS, contrairement à Prolog, fait du chaînage avant : on part des faits (les nombres) et on construit de nouveaux faits dès qu'une règle peut s'appliquer (ici, les opération arithmétiques élémentaires). On génère alors tous les nombres possibles à partir de ceux proposés. On vérifie alors à la fin si le nombre voulu se trouve dedans. Dans ce cas, ça pourrait peut être aller vu qu'il n'y a pas tant de nombres que ça, mais ça explose vite.
Avec Prolog (qui fait du chaînage arrière), on part du but (le nombre en question à trouver), et on regarde si un enchaînement de règle permet d'y arriver à partir des faits (les nombres de départ).
Bon, je ne sais pas si j'ai été très clair, et peut être que "chips" existe et que je suis complètement à côté de la plaque (en même temps, faites donc une recherche sur "chips" dans google :-)
[^]Re: Toutes, vraiment toutes ?
Oui, Clips ... (désolé mon cerveau n'est pas ECC ...)
Je ne l'ai jamais utilisé ... et vu ce que tu me dis, je pense que le prof qui m'en a parlé non plus ;-) Il nous avait expliqué que clips était comme prolog, mais avec une calculatrice qui "marche".
C'est marrant le chainage avant ... en mini projet d'IA, j'avais essayé de réaliser un moteur de chainage avant en prolog ... ça n'a jamais abouti (pas le temps).
Soutenez le logiciel libre, en adhérant dès maintenant à l'April
[^]Re: Toutes, vraiment toutes ?
Pour préciser un peu, CLIPS est un outil pour faire des systèmes experts développé par la NASA (en C) à l'époque où les systèmes experts étaient faits en LISP, étaient très lents et très chers. Comme ils sont sympa, ils l'ont versé dans le domaine public.
[^]Re: Toutes, vraiment toutes ?
Il y a des Prolog avec contraintes (p.ex. ECLIPSe (attention à la casse)) qui ajoutent la gestion de contraintes et des possibilités arithmétiques au Prolog.
[^]Re: Toutes, vraiment toutes ?
GNU Prolog aussi permet d'utiliser les contraintes :-)
Sinon, il y a aussi Sictus Prolog qui s'interface très bien avec Java (mais qui coûte très cher).
[^]Re: Toutes, vraiment toutes ?
Pour Kitsune, il est fabriqué de façon à te renvoyer toutes les solutions. Néanmoins, pour éviter de parasiter l'affichage avec trop de solutions, il évite d'afficher des "solutions équivalentes", c'est expliqué sur cette page : http://kitsune.tuxfamily.org/wiki/doku.php?id=solutions_equi(...)