%% Fonction principale
% La fonction "poker" évalue la probabilité d'obtention d'un brelan par la
% méthode de Monte-Carlo. Elle prend en argument le nombre de simulations
% demandées.
function poker(N)
% "succes" comptera le nombre de succès.
succes = 0;
% On lance la boucle de Monte-Carlo.
for i = 1:N
    % Les simulations sont assurées par la routine "simulation" (programmée
    % plus loin), qui renvoie 1 en cas de succès et 0 en cas d'échec.
    succes = succes + simulation;
end
% On évalue l'estimateur p de la probabilité de succès.
p = succes / N;
% Puisqu'ici on évalue une probabilité, la variance sigma peut s'exprimer
% en fonction de p.
sigma = sqrt(p - p * p);
% On calcule les extrêmités "pinf" et "psup" de l'intervalle de confiance à
% 2 sigmas.
pinf = p - 2 * sigma / sqrt(N);
psup = p + 2 * sigma / sqrt(N);
% On affiche le résultat.
disp(['L''intervalle de confiance à 2 sigmas pour la probabilité ',...
    'd''obtenir un brelan est [',num2str(pinf,'%.7f'),',',...
    num2str(psup,'%.7f'),'].']);
% Le programme s'arrête.
return
end

%% Routine de simulation
% La fonction "simulation" simule un joueur de poker cherchant à obtenir un
% brelan ; elle renvoie "true" si celui-ci a réussi et "false" sinon.
function brelan = simulation
% "cartestirees" contiendra les identités des cartes déjà tirées. 0 est une
% valeur “cimetière” ne correspondant à aucune carte.
cartestirees = zeros(1,8);
% On tire cinq cartes. Cela est assuré par la sous-routine interne
% "tirernouvelle" (programmée plus loin).
for i = 1:5,
    tirernouvelle;
end
% "main" est la liste des cinq hauteurs que le joueur a en main.
main = mod(cartestirees(1:5),13);
% On regarde quelle hauteur revient le plus souvent dans "main", et quel
% est son nombre d'occurrences. Cela est réalisé par la sous-routine
% "comptage", programmée plus loin.
[compte,hauteur] = comptage(main);
% Il y a trois cas possibles : soit le joueur a déjà un brelan et c'est
% fini ; soit il a une paire et il cherchera à l'améliorer ; soit il n'a
% rien et il conserve deux cartes arbitraires. Dans les deux derniers cas,
% "cartesgardees" est la hauteur des deux cartes conservées par le joueur.
if (compte >= 3)
    brelan = true;
    return
elseif (compte == 2);
    cartesgardees = [hauteur,hauteur];
else
    cartesgardees = [main(1),main(2)];
end
% À ce stade, il faut re-tirer 3 cartes.
for i = 6:8
    tirernouvelle;
end
% On compose la nouvelle main "nouvellemain" à partir de "cartesgardees" et
% de la conversion modulo 13 des trois nouvelles cartes tirées.
nouvellemain = [cartesgardees,mod(cartestirees(6:8),13)];
% On renvoie "true" si "nouvellemain" contient un brelan, et "false" sinon.
brelan = (comptage(nouvellemain) >= 3);
return

%% Sous-routine interne "tirernouvelle"
% "tirernouvelle" s'occupe de tirer une nouvelle carte, sachant que c'est
% la "i"-ième carte qu'on tire.
    function tirernouvelle
        % Pour faire un tirage uniforme sur les cartes qui restent, on
        % procède en fait à un tirage sur toutes les cartes, en
        % recommençant si on obtient une carte déjà tirée. "test" est un
        % booléen qui dit si la dernière carte simulée était une carte déjà
        % tirée ; il faut l'initialiser à "true".
        test = true;
        while(test)
            % On choisit l'identité d'une carte au hasard, codée par un
            % entier entre 1 et 52, qu'on stocke dans "carte".
            carte = randi(52);
            % On regarde si "carte" figure déjà dans la liste des cartes
            % tirées.
            test = any(carte == cartestirees);
        end
        % Une fois qu'on a obtenu une nouvelle carte, on ajoute "carte" à
        % la liste des cartes tirées.
        cartestirees(i) = carte;
    end
end

%% Sous-routine "comptage"
% La fonction "comptage" compte le plus grand nombre d'occurrences d'une
% même hauteur dans une main de cinq cartes. Elle prend en argument la main
% en question, et renvoie le nombre maximal d'occurrences, ainsi qu'une
% réponse auxiliaire donnant la hauteur correspondant à ce maximum.
function [compte,hauteur] = comptage(main)
compte = 0;
for i = 1:5
    score = sum(main == main(i));
    if(score > compte)
        compte = score;
        hauteur = main(i);
    end
end
end