Markov Ants

Page web ISIMA
Fichier .org source
Défi de programmation - Markov Ants

pnas.1706439114fig01.jpeg

1. Introduction

Le problème consiste en compter le nombre moyen de secondes qu’une fourmi met à sortir d’une fourmilère, en connaissant sa vitesse de déplacement et la taille de la fourmilière. La fourmi se déplace dans une direction aléatoire à chaque pas.

2. Approche utilisée

2.1. Description synoptique

Mon approche est de compter en combien de temps une seule fourmi sort de la fourmilère puis de répéter ceci un grand nombre de fois afin d’en faire une moyenne.

2.2. Algorithme

M : Constante définissant le nombre de simulations sur lesquelles faire la moyenne
Fonction leave :
Prend en entrée une position pos (x, y), un entier step la taille du pas de la fourmi et la taille de la grille (w, h) et renvoie le nombre de seconde que la fourmi met pour sortir de la grille.
Si la pos n’est pas dans la grille :

  • Renvoyer 0

direction = entier aléatoire compris entre 0 et 3 (inclus)
mise à jour de pos en fonction de direction et step
Renvoyer 1 + valeur de retour de leave avec la nouvelle position pos

Fonction principale :
pos : la position (x, y) de la fourmi
w, h : respectivement la largeur et hauteur de la grille
step : la taille du pas de la fourmi
Somme = 0
Boucle allant de 0 à M:

  • Somme = Somme + leave(pos, step, w, h)

Fin boucle
average = Somme / M
Afficher average

3. Résolution

3.1. Programme

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

#define M 1000000

// Fonction renvoyant 1 si la position donnée est en dehors de la grille de taille (w, h)
int isOutside(int pos[2], int w, int h) {
    return pos[0]<=0 || pos[0]>=w-1 || pos[1]<=0 || pos[1]>=h-1;
}

// Fonction récursive comptant le nombre de seconde pour sortir de la grille
int leave(int pos[2], int step, int w, int h) {
    if (isOutside(pos, w, h)) {
        return 0;
    }
    int offX[4] = {0, 1, 0, -1};
    int offY[4] = {-1, 0, 1, 0};
    int dir = rand()%4;
    pos[0] += offX[dir] * step;
    pos[1] += offY[dir] * step;
    return 1 + leave(pos, step, w, h);
}

int main()
{
    srand(0);
    int step;
    scanf("%d", &step);
    int w;
    int h;
    int pos[2]; // x, y
    scanf("%d%d", &w, &h); fgetc(stdin);
    for (int i = 0; i < h; i++) {
        char row[32];
        scanf("%[^\n]", row); fgetc(stdin);
        for (int j=0; j<32; ++j) {
            // Récupère la position de la fourmi
            if (row[j] == 'A') {
                pos[0] = j; pos[1] = i;
            }
        }
    }

    // Moyenne sur un grand nombre de test
    int sum = 0;
    for (int i = 0; i<M; ++i) {
        int tmp[2] = {pos[0], pos[1]};
        sum += leave(tmp, step, w, h);
    }

    float avg = (float) sum / M;
    printf("%0.1f\n", avg);

    return 0;
}

3.2. Test

A partir du test suivant (markovAnts.txt) :

1
9 5
+-------+
|.......|
|....A..|
|.......|
+-------+

Le programme fait une moyenne du temps de sortie de la colonie et affiche :

6.9

4. Comparaison avec une autre solution

A partir de cette solution externe :

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>

#define BEFORE(__time)  while((double)clock()<__time*CLOCKS_PER_SEC)

int n,m;
int sx=-1,sy;
int step;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int walk(int x,int y){
    int t=0;
    while(x>0&&x+1<n&&y>0&&y+1<m){
        int d=rand()%4;
        x+=dx[d]*step;
        y+=dy[d]*step;
        ++t;
    }
    return t;
}
int main()
{
    srand(time(0));
    scanf("%d", &step);
    scanf("%d%d", &m, &n); fgetc(stdin);
    for (int i = 0; i < n; i++) {
        char a[32];
        scanf("%[^\n]", a); fgetc(stdin);
        if(sx==-1)for(int j=0;j<m;++j)if(a[j]=='A'){
            sx=i;
            sy=j;
        }
    }
    int t_s=0;
    int k;
    BEFORE(0.499){
        t_s+=walk(sx,sy);
        ++k;
    }
    fprintf(stderr,"%d %d %d %d\n",sx,sy,t_s,k);
    printf("%.1f",(double)t_s/k);
    return 0;
}

Cette solution propose elle aussi un calcul de moyenne, mais utilise une boucle while pour déplacer la fourmi.
Cette solution calcule la moyenne en un temps constant et n’utilise pas un nombre de simulation déjà fixé.

5. Bilan

Après avoir analyser le problème, je l’ai trouvé plutôt simple à résoudre et je n’ai pas rencontré de difficultés.

Auteur: Rémi SCHIRRA

Created: 2024-05-03 ven. 13:46