Le dilemme du prisonnier v.2 - Battle Royale


15

Dans cette question , un jeu a été conçu dans lequel les joueurs s'affronteraient paire par paire dans le dilemme du prisonnier, afin de déterminer quelle stratégie itérative a marqué le plus haut contre les autres.

Dans cette question , j'ai imaginé un moyen pour plusieurs personnes de jouer le dilemme des prisonniers les uns contre les autres en même temps. Dans cette variante, la matrice des gains n'est pas nécessaire, chaque résultat entre chaque paire de deux joueurs étant la somme de deux décisions fonctionnellement indépendantes.

Votre tâche consiste à créer une IA pour jouer à cette version symétrique et généralisée du dilemme du prisonnier multijoueur qui atteindra le meilleur score possible.


Règles du jeu

À chaque tour de ce dilemme du prisonnier multijoueur et à plusieurs tours, un joueur Apeut décider de "prendre 1" à un autre joueur B. Dans ce cas, Ale score de augmente de 1, tandis que Ble score de diminue de 2. Cette décision peut se produire entre chaque paire ordonnée de joueurs.

C'est la seule décision prise pour chaque joueur - soit de «prendre 1», soit de ne pas «prendre 1» de chaque autre joueur, qui sont respectivement homologues à la défection et à la coopération. La matrice de gain efficace entre deux joueurs P1et P2se présente comme suit:

  P1/P2     P1 Take1   P1 Don't
P2 Take1     -1/-1      -2/+1
P2 Don't     +1/-2       0/ 0

Procédure du tournoi

Le jeu se composera de P * 25tours, où Pest le nombre de joueurs participants. Tous les joueurs commencent avec un score de 0. Chaque tour comprendra la procédure suivante:

Au début d'un cycle, chaque programme recevra un historique des cycles précédents à partir de l'entrée standard , dans le format suivant:

  • Une ligne contenant 3 numéros, P, Det N.

    • Pest le nombre total de joueurs dans le jeu. Chaque joueur se voit attribuer au hasard un numéro d'identification de 1à Pau début de la partie.

    • D est l'ID du joueur actuel.

    • N est le nombre de tours qui ont été joués.

  • Nlignes, chaque ligne représentant les résultats d'un tour. En ligne kde N, il y aura un certain nombre n_kde paires ordonnées (a, b), séparées par des espaces, qui représentent que le joueur avec ID a"a pris 1" du joueur avec ID bdans ce tour.

  • Un nombre uniformément aléatoire Rde 0à 18446744073709551615(2 64 - 1), pour agir comme une graine pseudo-aléatoire. Ces chiffres seront lus à partir d'un fichier pré-généré, qui sera publié à la fin du tournoi afin que les gens puissent vérifier eux-mêmes les résultats.

  • Une ligne supplémentaire qui représente une forme d'état à lire dans votre programme, si votre programme a produit une telle sortie lors du cycle précédent. Au début du jeu, cette ligne sera toujours vide. Cette ligne ne sera pas modifiée par le code de notation ou d'autres programmes.

Chaque programme utilisera ensuite sa stratégie pour produire les résultats suivants en sortie standard :

  • Une liste de Knuméros, qui sont les identifiants des programmes qu'il "prendra 1" de ce tour. Une sortie vide signifie qu'elle ne fera rien.

  • Facultativement, une ligne supplémentaire représentant une certaine forme d'état à transmettre aux tours ultérieurs. Cette ligne exacte sera renvoyée au programme lors du prochain tour.

Voici un exemple d'entrée pour le début du jeu pour un joueur d'ID 3dans un jeu à 4 joueurs:

4 3 0
4696634734863777023

Voici un exemple d'entrée pour le même jeu avec quelques tours déjà joués:

4 3 2
(1, 2) (1, 3) (1, 4) (4, 2)
(1, 3) (2, 1) (2, 4) (3, 1) (4, 1)
4675881156406346380

Chaque programme recevra exactement la même entrée pour un tour, à l'exception du numéro d'identification Dqui est unique à chaque programme.

Voici un exemple de sortie dans laquelle le joueur 3prend 1 à tout le monde:

1 2 4

À la fin de tous les tours requis, le joueur avec le score final le plus élevé sera le vainqueur.


Chronologie

Le codage de ce tournoi durera 7 jours au total. La date limite de soumission est 2014-05-09 00:00 UTC.

Ne publiez pas de programmes réels avant cette date - publiez le hachage SHA256 du code source de votre programme comme engagement. Vous pouvez modifier ce hachage à tout moment avant la date limite, mais les engagements postés après la date limite ne seront pas acceptés pour jugement. (Veuillez utiliser la notation base 64 pour vos hachages, car mon programme de vérification crache la base 64 et c'est une notation plus compacte.)

Une fois la date limite dépassée, vous aurez 1 jour (jusqu'à 2014-05-10 00:00 UTC) pour publier le code source réel de votre programme pour votre soumission. Si le hachage SHA256 de votre code source publié ne correspond à aucun hachage que vous avez publié avant la date limite, votre code ne sera pas accepté dans le tournoi.

Après cela, je téléchargerai toutes les soumissions sur mon propre ordinateur et exécuterai toutes les entrées du tournoi dans cette bataille royale, en espérant publier les résultats dans les 2 jours à compter de ce moment 2014-05-12 00:00 UTC.

J'accepterai la réponse avec le score le plus élevé et j'accorderai une prime de +100 à cette réponse si son score final est supérieur à 0.

Une fois le tournoi terminé, je publierai le fichier de départ aléatoire utilisé pour organiser la compétition, et les gens peuvent commencer à publier d'autres solutions en essayant de dépasser celles utilisées dans le tournoi. Cependant, ils ne compteront pas pour l'acceptation ou la prime.

La machine hôte

J'exécuterai ces solutions sur une machine virtuelle sur mon ordinateur. Cette machine virtuelle exécutera Ubuntu Linux 14.04, avec 2 gigaoctets de RAM. Ma machine de base possède un processeur Intel i7-2600K fonctionnant à 3,40 GHz.

Exigences

Votre programme doit être écrit dans une langue pour laquelle un compilateur ou un interprète qui compilera votre programme existe et est facilement disponible pour la dernière version d'Ubuntu Linux, afin que je puisse exécuter toutes les soumissions et les juger dans une machine virtuelle.

Votre programme ne doit pas prendre plus que 2.000 secondsd'exécuter chaque tour. Si votre programme manque de temps ou produit une erreur, sa sortie sera considérée comme vide pour ce tour.

Votre programme doit être déterministe; c'est-à-dire qu'il doit toujours renvoyer la même sortie pour la même entrée. Les solutions pseudo-aléatoires sont autorisées; cependant, leur caractère aléatoire doit dépendre de la graine aléatoire qui lui est donnée en entrée et rien d'autre. Le fichier de départ a été généré à l'aide de Python os.urandom. Il contient un total de 500 lignes (d'autres seront générées si nécessaire), et son hachage SHA256 l'est K+ics+sFq82lgiLanEnL/PABQKnn7rDAGmO48oiYxZk=. Il sera téléchargé ici une fois le tournoi terminé.


Les plantes

Pour commencer, il y aura quatre "usines", représentant les premières stratégies naïves. Ceux-ci joueront dans le tournoi avec vos soumissions. Cependant, dans le cas peu probable où l'un d'entre eux gagne, le score le plus élevé obtenu par un joueur autre qu'une plante sera considéré comme gagnant.

Pour calculer le hachage du fichier de chaque plante, remplacez chaque groupe de 4 espaces par une tabulation, car le formateur ici ne semble pas aimer les caractères de tabulation.

Le paresseux - ne fait jamais rien.

n1bnYdeb/bNDBKASWGywTRa0Ne9hMAkal3AuVZJgovI=

pass

The Greedy - prend toujours 1 à tout le monde.

+k0L8NF27b8+Xf50quRaZFFuflZhZuTCQOR5t5b0nMI=

import sys

line1 = sys.stdin.readline()
n = [int(i) for i in line1.split()]
for i in range(n[0]):
    if i+1 != n[1]:
        print i+1,
print

Le courroucé - prend 1 à tous les autres au premier tour et prend 1 à tous ceux qui en ont pris 1 au tour suivant.

Ya2dIv8TCh0zWzRfzUIdFKWj1DF9GXWhbq/uN7+CzrY=

import sys
import re

line1 = [int(i) for i in sys.stdin.readline().split()]

players = line1[0]
pid = line1[1]
rounds = line1[2]

lines = []

if rounds == 0:
    for i in range(players):
        if i+1 != pid:
            print i+1,
    print
else:
    for i in range(rounds):
        lines.append(sys.stdin.readline())
    lastline = lines[-1]
    takes = re.findall(r'\([0-9]+, [0-9]+\)', lastline)
    for take in takes:
        sides = [int(i) for i in re.findall(r'[0-9]+', take)]
        if sides[1] == pid:
            print sides[0],
    print

The Envious - prend 1 sur 50% des joueurs avec le score le plus élevé actuel en excluant lui-même, en arrondissant.

YhLgqrz1Cm2pEcFlsiIL4b4MX9QiTxuIOBJF+wvukNk=

import sys
import re

line1 = [int(i) for i in sys.stdin.readline().split()]

players = line1[0]
pid = line1[1]
rounds = line1[2]

lines = []
scores = [0] * players

if rounds == 0:
    for i in range(players):
        if i+1 != pid:
            print i+1,
    print
else:
    for i in range(rounds):
        takes = re.findall(r'\([0-9]+, [0-9]+\)', sys.stdin.readline())
        for take in takes:
            sides = [int(i) for i in re.findall(r'[0-9]+', take)]
            scores[sides[0] - 1] += 1
            scores[sides[1] - 1] -= 2
    score_pairs = [(i+1, scores[i]) for i in range(players)]
    score_pairs.sort(key=lambda x:(x[1], x[0]))
    score_pairs.reverse()
    taken = 0
    j = 0
    while taken < (players) / 2:
        if score_pairs[j][0] != pid:
            print score_pairs[j][0],
            taken += 1
        j += 1

Dans un tournoi de 100 rounds juste parmi ces quatre, ils reçoivent des scores de:

Lazy: -204
Greedy: -100
Wrathful: -199
Envious: -199

Programme de jugement

J'ai publié le programme de juge que j'utiliserai sur Github . Téléchargez-le et testez-le. (Et peut-être corriger un bogue ou deux si vous en trouvez un.: P)

Il n'a pas d'options de compilation pour autre chose que Python pour le moment. Je les inclurai plus tard - si les gens pouvaient contribuer à la compilation ou à l'interprétation de scripts pour d'autres langues, je serais très obligé.


Phase 2: Soumission du code source

J'ai posté une nouvelle branche tournament dans le référentiel Github pour le concours, contenant le fichier pd_rand et d'autres entrées d'usine. Vous pouvez publier votre code source ici ou le soumettre à cette branche en tant que demande de tirage.

L'ordre des candidats sera le suivant:

'begrudger'
'regular'
'patient'
'lazy'
'backstab'
'bully'
'lunatic'
'envious'
'titfortat'
'greedy'
'wrathful'
'judge'
'onepercent'

Scores finaux

La sortie de mon programme de test:

Final scores:
begrudger -2862
regular -204
patient -994
lazy -2886
backstab -1311
bully -1393
lunatic -1539
envious -2448
titfortat -985
greedy -724
wrathful -1478
judge -365
onepercent -1921

Classements:

 1. regular      -204
 2. judge        -365
 3. greedy       -724
 4. titfortat    -985
 5. patient      -994
 6. backstab    -1311
 7. bully       -1393
 8. wrathful    -1478
 9. lunatic     -1539
10. onepercent  -1921
11. envious     -2448
12. begrudger   -2862
13. lazy        -2886

Il s'avère donc que le gagnant est bien un joueur - c'est The Regular, avec -204 points!

Malheureusement, son score n'était pas positif, mais on peut difficilement s'attendre à cela dans une simulation du dilemme du prisonnier itéré où tout le monde joue pour gagner.

Quelques résultats surprenants (du moins que je trouvais surprenants):

  • The Greedy a marqué plus que Tit pour Tat, et en fait, généralement plus que la plupart des buteurs.

  • Le juge, qui était censé être une sorte de personnage «respecteur de moralité» (il en a fallu 1 à quiconque avait pris 1 à quiconque un nombre supérieur à la moyenne) a fini par obtenir un score plutôt élevé, alors que dans les tests de simulation, il obtenir un score assez faible.

Et d'autres qui (je pensais) n'étaient pas si surprenantes:

  • Le patient a marqué 484 points de plus que The Wrathful. Cela vaut vraiment la peine de coopérer cette première fois.

  • One Percent n'a eu très rapidement presque personne pour donner des coups de pied alors qu'ils étaient à terre. Il semble que le 1% ne peut rester que parce qu'il y a plus de joueurs dans le jeu.

Quoi qu'il en soit, maintenant que le tournoi est terminé, n'hésitez pas à poster autant de joueurs supplémentaires que vous le souhaitez et à tester avec eux en utilisant le programme des juges.


3
La publication de la source dans le programme de contrôle et / ou les usines nuirait-elle à quelque chose? Nous savons ce qu'ils font de toute façon, et je préférerais pouvoir tester quelque chose sans écrire cinq programmes supplémentaires.
Geobits

2
Je ne comprends pas. Y a-t-il une sorte de pénalité pour tout le monde qui en prend 1 tout le temps? Ne serait-il pas plus avantageux de toujours en prendre 1?
DankMemes

1
Comment les gourmands ne peuvent-ils pas maximiser les dégâts? Si nous prenons à un autre joueur, l'autre joueur ne peut obtenir que -1 ou -2, tandis que si nous ne prenons pas, l'autre joueur peut obtenir 1 ou 0. Évidemment, prendre 1 à un autre joueur maximisera les dégâts. Et donc Greedy ne perdra jamais. Et il gagnera presque toujours, à moins que tous les adversaires ne soient aussi gourmands, comme vous l'avez dit.
juste la moitié

1
@Trimsty Lorsque le défi a été relevé pour la première fois, le code des plantes n'était pas affiché. Pendant toute la phase de codage, nous n'avons pas pu voir d'autres réponses. Dupes aurait pu se produire purement par accident en choisissant la stratégie gourmande très évidente .
Geobits

2
@justhalf Si vous avez réellement lu une recherche sur les stratégies du dilemme itératif du prisonnier, vous saurez que ce que vous dites est faux. L' article Wikipedia est un bon point de départ.
Joe Z.

Réponses:


3

The Regular

La version de cette entrée que j'ai choisie pour le tournoi (SHA-256 :)ggeo+G2psAnLAevepmUlGIX6uqD0MbD1aQxkcys64oc= utilise la stratégie de " Random sucker " de Joey (bien qu'avec un changement mineur et probablement insignifiant), qui est arrivée en deuxième position lors du dernier concours. Malheureusement, une version plus récente et plus efficace soumise seulement 3 minutes 25 secondes avant la date limite a un bug sérieux, elle n'a donc pas pu être utilisée. Néanmoins, cette version se porte encore relativement bien.

<?php

$secretKey = '95CFE71F76CF4CD2';
$hashOutput = '';
$hashSeq = 0;
$hashIndex = 64;

function psRand($min = null, $max = null) {
    global $secretKey, $state, $hashOutput, $hashSeq, $hashIndex;
    if ($hashIndex > 56) {
        $hashOutput = hash_hmac('sha256', ++$hashSeq . ' ' . $state['rand'], $secretKey);
        $hashIndex = 0;
    }

    $num = (int)(hexdec(substr($hashOutput, $hashIndex, 8)) / 2);
    $hashIndex += 8;

    return $min === null ? $num : (int)($min + $num * ($max - $min + 1) / 2147483648);
}

$line = fgets(STDIN);
sscanf($line, "%d %d %d", $numPlayers, $myPlayerId, $roundsPlayed);
$roundsCount = 25 * $numPlayers;
$roundsRemaining = $roundsCount - $roundsPlayed - 1;

$betrayalCount = array_fill(1, $numPlayers, 0);
for ($round = 0; $round < $roundsPlayed; ++$round) {
    $line = fgets(STDIN);
    preg_match_all('/\((\d+), (\d+)\)/', $line, $matches, PREG_SET_ORDER);
    foreach ($matches as $m) {
        $defector = (int)$m[1];
        $victim = (int)$m[2];
        if ($victim === $myPlayerId) {
            ++$betrayalCount[$defector];
        }
    }
}

$hashOutput = rtrim(fgets(STDIN), "\n");
$state = unserialize(rtrim(fgets(STDIN), "\n"));
if (!$state) {
    $state = ['rand' => ''];
}

$state['rand'] = hash_hmac('sha256', $state['rand'] . $line, $secretKey);
$victims = [];

if ($roundsPlayed > 1) {
    for ($other = 1; $other <= $numPlayers; ++$other) {
        if ( $other === $myPlayerId) {
            continue;
        }

        if ($betrayalCount[$other] > 7 || psRand() % 1024 < 32 || !$roundsRemaining ) {
            $victims[] = $other;
        }
    }
}

echo implode(' ', $victims), "\n", serialize($state), "\n";

La version buggy a un hachage SHA-256 de 2hNVloFt9W7/uA5aQXg+naG9o6WNmrZzRf9VsQNTMwo=:

<?php

$secretKey = '95CFE71F76CF4CD2';
$hashOutput = '';
$hashSeq = 0;
$hashIndex = 64;

function psRand($min = null, $max = null) {
    global $secretKey, $state, $hashOutput, $hashSeq, $hashIndex;
    if ($hashIndex > 56) {
        $hashOutput = hash_hmac('sha256', ++$hashSeq . ' ' . $state['rand'], $secretKey);
        $hashIndex = 0;
    }

    $num = (int)(hexdec(substr($hashOutput, $hashIndex, 8)) / 2);
    $hashIndex += 8;

    return $min === null ? $num : (int)($min + $num * ($max - $min + 1) / 2147483648);
}

$line = fgets(STDIN);
sscanf($line, "%d %d %d", $numPlayers, $myPlayerId, $roundsPlayed);
$roundsCount = 25 * $numPlayers;
$roundsRemaining = $roundsCount - $roundsPlayed - 1;

$betrayalCount = array_fill(1, $numPlayers, 0);
$scoreWindow = array_fill(1, $numPlayers, array_fill(1, $numPlayers, 0));
$lastMove = array_fill(1, $numPlayers, array_fill(1, $numPlayers, false));
for ($round = 0; $round < $roundsPlayed; ++$round) {
    $line = fgets(STDIN);
    preg_match_all('/\((\d+), (\d+)\)/', $line, $matches, PREG_SET_ORDER);
    foreach ($matches as $m) {
        $defector = (int)$m[1];
        $victim = (int)$m[2];
        if ($victim === $myPlayerId) {
            ++$betrayalCount[$defector];
        }
TAB>TAB>if ($round >= $roundsPlayed - 10) {
TAB>TAB>TAB>$scoreWindow[$defector][$victim] -= 2;
TAB>TAB>TAB>$scoreWindow[$victim][$defector] += 1;
TAB>TAB>}
TAB>TAB>if ($round === $roundsPlayed - 1) {
TAB>TAB>TAB>$lastMove[$defector][$victim] = true;
TAB>TAB>}
    }
}

$line .= fgets(STDIN);
$state = unserialize(rtrim(fgets(STDIN), "\n"));
if (!$state) {
    $state = ['rand' => '', 'copying' => array_fill(1, $numPlayers, 0)];
}

$state['rand'] = hash_hmac('sha256', $state['rand'] . $line, $secretKey);
$victims = [];

if ($roundsPlayed > 1) {
    for ($other = 1; $other <= $numPlayers; ++$other) {
        if ($other === $myPlayerId) {
            continue;
        }

TAB>TAB>if ($roundsPlayed >= 10) {
TAB>TAB>TAB>$myScore = $scoreWindow[$other][$myPlayerId];
TAB>TAB>TAB>foreach ($scoreWindow[$other] as $betterPlayer => $betterScore) {
TAB>TAB>TAB>TAB>if ($betterScore >= 0.5 * $myScore && !psRand(0, $betterPlayer)) {
TAB>TAB>TAB>TAB>TAB>$state['copying'][$other] = $betterPlayer;
TAB>TAB>TAB>TAB>}
TAB>TAB>TAB>}
TAB>TAB>}

TAB>TAB>if ($state['copying'][$other]) {
TAB>TAB>TAB>if ($lastMove[$state['copying'][$other]][$other]) {
TAB>TAB>TAB>TAB>$victims[] = $other;
TAB>TAB>TAB>}
        } elseif ($betrayalCount[$other] > 7 || psRand() % 1024 < 32 || !$roundsRemaining ) {
            $victims[] = $other;
        }
    }
}

echo implode(' ', $victims), "\n", serialize($state), "\n";

Pour le réparer, faites ces remplacements:

  • Remplacez $hashOutput = rtrim(fgets(STDIN), "\n");par$line .= fgets(STDIN); (pas ce qui compte vraiment).
  • Remplacez if ($betterScore >= 3 * $myScore) {par if ($betterScore >= 0.5 * $myScore && !psRand(0, $betterPlayer)) {(c'est ce qui l'a tué).

1
3 minutes et 25 secondes avant la date limite. Je suis impressionné.
Joe Z.

Juste un rappel amical: la phase de codage est terminée; vous avez un jour pour publier votre code source. (La procédure est au bas de la question.)
Joe Z.

Que j'utilise votre ancienne version ou votre nouvelle version, votre programme sort toujours en premier. Toutes nos félicitations!
Joe Z.

2

Un pourcent

b61189399ae9494b333df8a71e36039f64f1d2932b838d354c688593d8f09477

Regarde les prisonniers qu'il considère sous lui.


Prend simplement de tous ceux qui ont des points inférieurs ou égaux à lui-même. L'hypothèse est que ces prisonniers sont moins susceptibles de recevoir en retour (ou ils en auraient plus). Je ne sais pas à quel point cette hypothèse est bonne , mais c'est ce sur quoi il opère.

Prend également de tout le monde au dernier tour. Il n'y a littéralement aucun inconvénient à cela, car personne ne peut se venger de voler après cela.

Si vous rencontrez des problèmes pour obtenir le hachage à cause des tabulations / espaces du code collé, voici un lien vers le fichier lui-même.

import java.io.BufferedReader;
import java.io.InputStreamReader;

class OnePercent {

    static int numPlayers;
    static int me;
    static int turn;
    static int[] values;

    public static void main(String[] args) {
        if(!readInput())
            return;
        String out = "";
        for(int i=1;i<values.length;i++){
            if(i != me && (values[i] <= values[me] || turn > (numPlayers*25-2)))
                out += i + " ";
        }
        out.trim();
        System.out.print(out);
    }

    static boolean readInput(){
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String line = reader.readLine();
            if(line == null)
                return false;
            String[] tokens = line.split(" ");
            if(tokens.length < 3)
                return false;
            numPlayers = Integer.valueOf(tokens[0]);
            me = Integer.valueOf(tokens[1]);
            turn = Integer.valueOf(tokens[2]);
            values = new int[numPlayers+1];
            for(int i=0;i<values.length;i++)
                values[i]=0;

            for(int i=0;i<turn;i++){
                line = reader.readLine();
                line = line.replaceAll("[)]",",");
                line = line.replaceAll("[( ]", "");
                tokens = line.split(",");
                for(int j=0;j<tokens.length-1;j+=2){
                    int thief = Integer.valueOf(tokens[j]);
                    int poor = Integer.valueOf(tokens[j+1]);
                    if(thief<1||poor<1||thief>numPlayers||poor>numPlayers)
                        continue;
                    values[thief]++;
                    values[poor] -= 2;
                }
            }
            reader.close();
        } catch(Exception e) {
            return false;
        }
        return true;
    }

}

N'oubliez pas que vous pouvez continuer à apporter des améliorations à vos solutions jusqu'à la 05-09 00:00date limite.
Joe Z.

Oui. Si je pense à autre chose, je le ferai. J'ai du mal à croire que quelqu'un va réclamer cette prime, cependant. Devenir positif dans ce jeu serait ... inhabituel.
Geobits

Ouais, je ne m'attends pas à ce que quelqu'un atteigne réellement cette prime. Ce serait vraiment un accomplissement défiant la théorie des jeux, qui vaut probablement de l'argent réel dans les possibilités de recherche (une solution qui fonctionne mieux que deux personnes coopérant toujours! Imaginez cela!) Au lieu d'une maigre réputation de 100 sur Stack Exchange.
Joe Z.

1
@JoeZ. Avec la connaissance de ce que les autres feraient, bien sûr;) Contre les entrées inconnues, je ne vois pas de stratégie très fiable . Les valeurs aberrantes seront aberrantes, je suppose.
Geobits

1
Je pense que je l'accepterai cette fois-ci, car la stratégie de votre code ne semble pas être malveillante et il y a trop peu d'entrées pour que cela ait de toute façon une importance.
Joe Z.

1

Voici quelques autres plantes qui participeront au jeu. Celles-ci sont plus avancées et leur code source ne sera révélé qu'à la fin de la phase de codage.

Tout comme les quatre plantes de la question, si elles réussissent à marquer plus haut que tous les autres joueurs, seul le score le plus élevé atteint par un concurrent réel sera considéré comme gagnant.


Le harceleur

29AGVpvJmDEDI5Efe/afmMJRLaJ+TpjwVcz1GkxgYZs=

Choisit les gens.


Le juge

yjdCQ3uQ4YKe7xAKxdTFLF4d72fD4ACYpDLwkbzdISI=

Punit les malfaiteurs.


Le fou

m3FsRPocekCcK6GDswgnobV2CYOxX8LquChnKxrx1Wo=

N'a aucune idée de ce qu'il fait.


Le patient

nd7Pt3bVpFnuvDVeHQ5T9EPTq7KjNraVzp/KGtI73Vo=

Ne fait jamais le premier pas.


S'il ne s'agit que de plantes, je ne vois aucune raison de ne pas les autoriser. Si ce sont des candidats qui peuvent gagner , je pense qu'il est juste que vous n'obteniez qu'une seule inscription par les commentaires ci-dessus.
Geobits

J'ai brièvement envisagé d'avoir ma propre entrée, puis j'ai décidé que c'était une proposition tout à fait injuste même si je n'en ai entré qu'une de plus, car trop d'autres éléments du jeu sont sous mon contrôle. Donc, toutes les entrées que je place ici ne seront que des plantes.
Joe Z.

La raison pour laquelle je pensais que les gens n'en auraient peut-être pas voulu, même en tant que plantes, c'est parce que cela représente un changement assez radical des joueurs de base disponibles (et donc des stratégies de base) qui n'étaient pas disponibles au début du jeu. Mais si nous partons de l'hypothèse que les solutions doivent être codées pour être optimales quels que soient les acteurs insérés en tant que plantes, je suppose que je pourrais également les saisir.
Joe Z.

Eh bien, les entrées doivent être codées comme "optimales" (si cela existe ici) quels que soient les joueurs impliqués simplement parce que nous ne pouvons pas voir les autres réponses de toute façon. Cela ne fait aucune différence s'il s'agit de plantes ou d'autres réponses au programme, sauf qu'elles ne peuvent pas "gagner". En supposant que le gagnant est défini comme le non-plant avec le score le plus élevé, je ne vois pas comment cela importera beaucoup. Je dis de les laisser entrer.
Geobits

1

Tit-for-tat

9GkjtTDD2jrnMYg/LSs2osiVWxDDoSOgLCpWvuqVmSM=

Similaire à Wrathful, avec quelques changements (espérons-le) améliorant les performances.

import sys
import re

line1 = [int(i) for i in sys.stdin.readline().split()]

players = line1[0]
pid = line1[1]
rounds = line1[2]

lines = []

if rounds == 0:
    print
elif rounds == 25 * players - 1:
    for i in range(players):
        if i+1 != pid:
            print i+1,
    print
else:
    for i in range(rounds):
        lines.append(sys.stdin.readline())
    lastline = lines[-1]
    takes = re.findall(r'\([0-9]+, [0-9]+\)', lastline)
    for take in takes:
        sides = [int(i) for i in re.findall(r'[0-9]+', take)]
        if sides[1] == pid:
            print sides[0],
    print

Avez-vous obtenu mon adresse e-mail?
Joe Z.

@Joe; Oui; Merci. (Je ne suis pas certain que j'en aurai besoin, mais merci d'être accommodant.)
Ypnypn

D'accord, je voulais juste savoir pour pouvoir le supprimer.
Joe Z.

1
@luserdroog Les gens publient des hachages du code source de leur programme au lieu du programme lui-même. Une fois que les 7 jours pour écrire le code sont écoulés, les gens dévoileront leurs programmes réels pour les tests.
Joe Z.

1
Ouais c'est vrai. Une soumission devrait probablement avoir un titre et au moins un slogan comme celui de Geobits là-haut.
Joe Z.

1

Poignarder dans le dos

Python 3

Malgré son nom, ce bot est en fait assez gracieux. Mais ne cochez pas.

import sys, math

inp = [int(i) for i in sys.stdin.readline().split()]
inp.append([])
for i in range(inp[2]):
    inp[3].append(
        [eval(i+')') for i in sys.stdin.readline().split(')')[:-1]]
    )
inp += sys.stdin.readline()

# inp is [P, D, N, [M1, M2...], R]

dat = [[], inp[2] % 2] # average runlength take and don't per player, parity of round

lastatk = []

for i in range(inp[0]):
    dat[0].append([])
    lastatk.append(0)

for i,r in enumerate(inp[3]): # each round
    for m in r: # each move
        if m[1] == inp[1]:
            dat[0][m[0]-1].append(i) # round num they attacked
            lastatk[m[0]-1] = i # keep track of last attack

# now that we know who attacked me when, i can do some stats

nav = []
rl = []

for i in range(inp[0]):
    nav.append([[0], False])
    rl.append([[], []]) # attack, don't

for i in range(inp[2]): # each round
    for p in range(1, inp[0]+1): # each player
        if p != inp[1]: # let's not judge ourselves
            if i in dat[0][p-1]: # p attacked me in round i
                if nav[p-1][1]: # attack chain?
                    nav[p-1][0][-1] += 1
                else: # start attack chain!
                    rl[p-1][1] += [nav[p-1][0][-1]] # copy peace chain
                    nav[p-1][0].append(1)
                    nav[p-1][1] = True
            else: # peace!
                if not nav[p-1][1]: # peace chain?
                    nav[p-1][0][-1] += 1
                else: # peace to all!
                    rl[p-1][0] += [nav[p-1][0][-1]] # copy atk chain
                    nav[p-1][0].append(1)
                    nav[p-1][1] = False

print(nav)

print(inp[3])

# now, rl has runlengths for each player.

print(rl)

rl = [[sum(i[0])/len(i[0]+[0]), sum(i[1])/len(i[1]+[0])] for i in rl]

# rl now contains the averages w/ added zero.

# So, now we have average runtime and last attack. Let's quickly make some descisions.

out = []

for p in range(1, inp[0]+1): # each player
    if p != inp[1]: # again, let's not judge ourselves
        if lastatk[p-1] == inp[0]-1: # they attacked us!
            out.append(p)
        else: # whew, we can recover
            if inp[0] - lastatk[p-1] > rl[p-1][0]: # they're due to defend!
                out.append(p)
            elif int(__import__('binascii').b2a_hex(inp[-1].encode()), 16) % 4 == 0: # 1 in 4 chance of doing this
                out.append(p) # backstab!!1!!1one!!!1!!

print(*out)

EDIT 2 : Source publiée. Yay.

EDIT : Après quelques tests, j'ai corrigé quelques défauts que j'ai trouvés. Ils ne sont pas algorithmiques, juste quelques problèmes de lecture de l'entrée.


Juste un rappel amical: la phase de codage est terminée; vous avez un jour pour publier votre code source. (La procédure est au bas de la question.)
Joe Z.

@JoeZ. Posté. J'espère que je suis à temps. : P
cjfaure

P, D, N, R sonne comme les lecteurs dans lesquels une voiture peut passer.
Joe Z.

1
@JoeZ. xD Ils viennent de votre message, donc; 3
cjfaure

Oh, ma mauvaise. Désolé: S
Joe Z.

1

le Begrudger

g1TXBu2EfVz/uM/RS24VeJuYMKLOaRatLxsA+DN1Mto=

Code

J'avoue que je n'y ai pas passé beaucoup de temps ...

import sys
p, d, n, o = input().split(' ') + ['']
p, d, n = int(p), int(d), int(n)
for i in range(n):
    r = input()
    r = r[1:len(r)-1].split(') (')
    for a in r:
        if int(a.split(', ')[1]) == d and not a.split(', ')[0] in o:
            o += a.split(', ')[0] + " "

input()
print(o)

Juste un rappel amical: la phase de codage est terminée; vous avez un jour pour publier votre code source. (La procédure est au bas de la question.)
Joe Z.

J'ai essayé de l'exécuter et j'ai rencontré le bogue suivant: o += a.split(', ')[0]ne laisse pas d'espace entre les chiffres.
PleaseStand

@PleaseStand J'ai corrigé cela, mais je pense que la version testée se retrouvera avec le bug car la compétition est terminée.
kitcar2000

Oui, votre code a produit un bogue chaque fois que je l'ai exécuté, et je n'ai pas pu trouver de solution. Il a fait un peu mieux que The Lazy, cependant.
Joe Z.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.