Take It or Leave It: Eine Spielshow für Computer


28

Kontext:

Ein zurückgezogener Milliardär hat eine Spielshow ins Leben gerufen, um die besten und intelligentesten Programmierer der Welt anzulocken. Montags um Mitternacht wählt er aus einem Pool von Bewerbern eine Person als Bewerber der Woche aus und stellt ihnen ein Spiel zur Verfügung. Sie sind der glückliche Kandidat dieser Woche!

Das Spiel dieser Woche:

Der Host bietet Ihnen API-Zugriff auf einen Stapel von 10.000 digitalen Umschlägen. Diese Umschläge sind nach dem Zufallsprinzip sortiert und enthalten einen Dollarwert zwischen 1 und 10.000 US-Dollar (keine zwei Umschläge enthalten denselben Dollarwert).

Sie haben 3 Befehle zur Verfügung:

  1. Read (): Lesen Sie die Dollarzahl im Umschlag oben auf dem Stapel.

  2. Take (): Fügen Sie die Dollar-Zahl in den Umschlag Ihrer Game-Show-Brieftasche hinzu und legen Sie den Umschlag vom Stapel.

  3. Pass (): Nehmen Sie den Umschlag oben auf dem Stapel ab.

Die Regeln:

  1. Wenn Sie Pass () für einen Umschlag verwenden, ist das darin enthaltene Geld für immer verloren.

  2. Wenn Sie Take () für einen Umschlag verwenden, der $ X enthält, dürfen Sie Take () von diesem Punkt an niemals für einen Umschlag verwenden, der <$ X enthält. Nehmen Sie () auf einen dieser Umschläge, um Ihrem Portemonnaie $ 0 hinzuzufügen.

Schreiben Sie einen Algorithmus, der das Spiel mit dem maximalen Geldbetrag beendet.

Wenn Sie eine Lösung in Python schreiben, können Sie diesen Controller zum Testen von Algorithmen verwenden, mit freundlicher Genehmigung von @Maltysen: https://gist.github.com/Maltysen/5a4a33691cd603e9aeca

Wenn Sie den Controller verwenden, können Sie nicht auf globale Variablen zugreifen. Sie können nur die drei bereitgestellten API-Befehle und Variablen mit lokalem Gültigkeitsbereich verwenden. (@Beta Decay)

Hinweise: "Maximal" bedeutet in diesem Fall den Medianwert in Ihrem Portemonnaie, nachdem N> 50 ausgeführt wurden. Ich gehe davon aus, dass der Medianwert für einen gegebenen Algorithmus konvergiert, wenn N auf unendlich ansteigt, obwohl ich mich gerne als falsch erweisen würde. Versuchen Sie stattdessen, den Mittelwert zu maximieren, aber ich habe das Gefühl, dass der Mittelwert mit größerer Wahrscheinlichkeit von einem kleinen N abgelöst wird als der Median.

Bearbeiten: Die Anzahl der Umschläge wurde zur einfacheren Verarbeitung in 10 KB geändert und Take () wurde expliziter.

Bearbeiten 2: Die Preisbedingung wurde im Lichte dieses Beitrags auf Meta entfernt.

Aktuelle Höchstpunktzahlen:

PhiNotPi - 805.479 USD

Reto Koradi - $ 803.960

Dennis - $ 770,272 (überarbeitet)

Alex L. - $ 714.962 (überarbeitet)


Ich habe es so implementiert, dass es nur False zurückgibt. Da Sie es lesen können, gibt es keinen wirklichen
Grund,

4
Falls jemand es verwenden möchte, ist hier der Controller, mit dem ich meine Algorithmen getestet habe: gist.github.com/Maltysen/5a4a33691cd603e9aeca
Maltysen

8
PS Schöne Frage und willkommen bei Programming Puzzles und Code Golf :)
Trichoplax

3
@Maltysen Ich stelle deinen Controller ins OP, danke für den Beitrag!
LivingInformation

1
Ich konnte keine explizite Regel für Bitcoin-Preise finden, aber es gibt einige Metadiskussionen über reale Preise, zu denen die Leute beitragen können.
Trichoplax

Antworten:


9

CJam, $ 87.143 $ 700.424 $ 720.327 $ 727.580 $ 770.272

{0:T:M;1e4:E,:)mr{RM>{RR(*MM)*-E0.032*220+R*<{ERM--:E;R:MT+:T;}{E(:E;}?}&}fRT}
[easi*]$easi2/=N

Dieses Programm simuliert das gesamte Spiel mehrmals und berechnet den Median.

Wie läuft man?

Ich habe meine Einsendung mit 100.001 Testläufen bewertet:

$ time java -jar cjam-0.6.5.jar take-it-or-leave-it.cjam 100001
770272

real    5m7.721s
user    5m15.334s
sys     0m0.570s

Ansatz

Für jeden Umschlag gehen wir wie folgt vor:

  • Schätzen Sie, wie viel Geld durch die Entnahme des Umschlags unweigerlich verloren geht.

    Wenn R der Inhalt ist und M das Maximum ist, das genommen wurde, kann der Betrag als R (R-1) / 2 - M (M + 1) / 2 geschätzt werden , was dem Geld alle Umschläge mit dem Inhalt X in gibt Intervall (M, R) enthalten.

    Wenn noch keine Umschläge übergeben worden wären, wäre die Schätzung perfekt.

  • Berechnen Sie den Geldbetrag, der beim Übergeben des Umschlags unweigerlich verloren gehen wird.

    Dies ist einfach das Geld, das der Umschlag enthält.

  • Überprüfen Sie, ob der Quotient von beiden kleiner als 110 + 0,016 E ist , wobei E die Anzahl der verbleibenden Umschläge ist (ohne Umschläge, die nicht mehr genommen werden können).

    Wenn ja, nimm. Ansonsten bestanden.


5
Denn die Verwendung einer Golfsprache hilft in keiner Weise. ; P +1 für die Algo.
Maltysen

2
Ich kann Ihre Ergebnisse nicht mit einem Python-Klon replizieren: gist.github.com/orlp/f9b949d60c766430fe9c . Sie erzielen rund 50.000 US-Dollar. Das ist eine Größenordnung weniger.
Orlp

1
@LivingInformation Versuch und Irrtum. Ich versuche derzeit, den genauen Betrag anstelle von Schätzungen zu verwenden, aber der resultierende Code ist sehr langsam.
Dennis

2
Diese Antwort braucht mehr Gegenstimmen als meine! Es ist schlauer, punktet höher und ist sogar Golf!
Alex L

1
@LivingInformation Dies ist meine Adresse: 17uLHRfdD5JZ2QjSqPGQ1B12LoX4CgLGuV
Dennis

7

Python, $ 680.646 $ 714.962

f = (float(len(stack)) / 10000)
step = 160
if f<0.5: step = 125
if f>0.9: step = 190
if read() < max_taken + step:
    take()
else:
    passe()

Nimmt immer größere Mengen in Schritten von 125 bis 190 US-Dollar auf. Lief mit N = 10.000 und bekam einen Median von $ 714962. Diese Schrittweiten stammen aus Versuchsreihen und sind sicherlich nicht optimal.

Der vollständige Code, einschließlich einer modifizierten Version des @ Maltysen-Controllers, der ein Balkendiagramm druckt, während es ausgeführt wird:

import random
N = 10000


def init_game():
    global stack, wallet, max_taken
    stack = list(range(1, 10001))
    random.shuffle(stack)
    wallet = max_taken = 0

def read():
    return stack[0]

def take():
    global wallet, max_taken
    amount = stack.pop(0)
    if amount > max_taken:
        wallet += amount
        max_taken = amount

def passe():
    stack.pop(0)

def test(algo):
    results = []
    for _ in range(N):
        init_game()
        for i in range(10000):
            algo()
        results += [wallet]
        output(wallet)
    import numpy
    print 'max: '
    output(max(results))
    print 'median: '
    output(numpy.median(results))
    print 'min: '
    output(min(results))

def output(n):
    print n
    result = ''
    for _ in range(int(n/20000)):
        result += '-'
    print result+'|'

def alg():
    f = (float(len(stack)) / 10000)
    step = 160
    if f<0.5: step = 125
    if f>0.9: step = 190
    if read() < max_taken + step:
        #if read()>max_taken: print read(), step, f
        take()
    else:
        passe()

test(alg)

BitCoin-Adresse: 1CBzYPCFFBW1FX9sBTmNYUJyMxMcmL4BZ7

Wow OP geliefert! Vielen Dank @LivingInformation!


1
Der Controller ist von Maltysen, nicht von mir.
Orlp

2
Bestätigt. Ich hatte gerade einen Controller eingerichtet und habe sehr ähnliche Nummern für Ihre Lösung erhalten. Genau genommen denke ich, dass Sie den Wert von max_takenin Ihrem eigenen Code beibehalten müssen, da er nicht Teil der offiziellen Spiel-API ist. Aber das ist trivial.
Reto Koradi

1
Ja, max_taken ist in @ Maltysens Controller. Wenn es nützlich ist, kann ich die gesamte Lösung (Controller + Algorithmus) in einem Block posten.
Alex L

Es ist wirklich keine große Sache. Aber ich denke , der sauberste Ansatz nur wäre das zu verwenden read(), take()und pass()Verfahren , die in dem von ihm entsandten Code, da das sind die „3 - Befehle zur Verfügung“ , basierend auf der Definition in der Frage.
Reto Koradi

@Reto Ich bin bereit, die Frage auf die Befehle zu korrigieren, die am sinnvollsten sind. Read, Take und Pass waren alle 4 Zeichen und fühlten sich passend an, aber ich bin offen für Vorschläge (ich habe zum Beispiel in Erwägung gezogen, "pass" in "leave" zu ändern, weil ich den Beitrag mit "take it or leave it" betitelt habe ").
LivingInformation

5

C ++, 803.960 USD

for (int iVal = 0; iVal < 10000; ++iVal)
{
    int val = game.read();
    if (val > maxVal &&
        val < 466.7f + 0.9352f * maxVal + 0.0275f * iVal)
    {
        maxVal = val;
        game.take();
    }
    else
    {
        game.pass();
    }
}

Das gemeldete Ergebnis ist der Median von 10.001 Spielen.


Rate und überprüfe, ich nehme es? Oder haben Sie eine Art Eingabe-Fuzzer für die Konstanten verwendet?
LivingInformation

Ich habe einen Optimierungsalgorithmus ausgeführt, um die Konstanten zu bestimmen.
Reto Koradi

Glauben Sie, dass eine dynamische Berechnung an jedem Punkt effektiver ist, oder nähert sich dies dem Maximalwert, den Sie erhalten können?
LivingInformation

Ich habe keinen Grund zu der Annahme, dass dies die ideale Strategie ist. Ich hoffe, es ist das Maximum für eine lineare Funktion mit diesen Parametern. Ich habe versucht, verschiedene Arten von nichtlinearen Begriffen zuzulassen, aber bisher nichts Besseres gefunden.
Reto Koradi

1
Ich kann bestätigen, dass das Simulieren dieses Ergebnisses einen Wert von etwas mehr als 800.000 US-Dollar ergibt.
Orlp

3

C ++, ~ 815.000 US-Dollar

Basiert auf der Lösung von Reto Koradi, wechselt jedoch zu einem ausgefeilteren Algorithmus, sobald 100 (gültige) Hüllkurven übrig sind. Dabei werden zufällige Permutationen gemischt und die am stärksten zunehmende Folge davon berechnet. Es vergleicht die Ergebnisse der Entnahme und Nichtentnahme des Umschlags und wählt gierig die beste Wahl aus.

#include <algorithm>
#include <iostream>
#include <vector>
#include <set>


void setmax(std::vector<int>& h, int i, int v) {
    while (i < h.size()) { h[i] = std::max(v, h[i]); i |= i + 1; }
}

int getmax(std::vector<int>& h, int n) {
    int m = 0;
    while (n > 0) { m = std::max(m, h[n-1]); n &= n - 1; }
    return m;
}

int his(const std::vector<int>& l, const std::vector<int>& rank) {
    std::vector<int> h(l.size());
    for (int i = 0; i < l.size(); ++i) {
        int r = rank[i];
        setmax(h, r, l[i] + getmax(h, r));
    }

    return getmax(h, l.size());
}

template<class RNG>
void shuffle(std::vector<int>& l, std::vector<int>& rank, RNG& rng) {
    for (int i = l.size() - 1; i > 0; --i) {
        int j = std::uniform_int_distribution<int>(0, i)(rng);
        std::swap(l[i], l[j]);
        std::swap(rank[i], rank[j]);
    }
}

std::random_device rnd;
std::mt19937_64 rng(rnd());

struct Algo {
    Algo(int N) {
        for (int i = 1; i < N + 1; ++i) left.insert(i);
        ival = maxval = 0;
    }

    static double get_p(int n) { return 1.2 / std::sqrt(8 + n) + 0.71; }

    bool should_take(int val) {
        ival++;
        auto it = left.find(val);
        if (it == left.end()) return false;

        if (left.size() > 100) {
            if (val > maxval && val < 466.7f + 0.9352f * maxval + 0.0275f * (ival - 1)) {
                maxval = val;
                left.erase(left.begin(), std::next(it));
                return true;
            }

            left.erase(it);
            return false;
        }

        take.assign(std::next(it), left.end());
        no_take.assign(left.begin(), it);
        no_take.insert(no_take.end(), std::next(it), left.end());
        take_rank.resize(take.size());
        no_take_rank.resize(no_take.size());
        for (int i = 0; i < take.size(); ++i) take_rank[i] = i;
        for (int i = 0; i < no_take.size(); ++i) no_take_rank[i] = i;

        double take_score, no_take_score;
        take_score = no_take_score = 0;
        for (int i = 0; i < 1000; ++i) {
            shuffle(take, take_rank, rng);
            shuffle(no_take, no_take_rank, rng);
            take_score += val + his(take, take_rank) * get_p(take.size());
            no_take_score += his(no_take, no_take_rank) * get_p(no_take.size());
        }

        if (take_score > no_take_score) {
            left.erase(left.begin(), std::next(it));
            return true;
        }

        left.erase(it);
        return false;
    }

    std::set<int> left;
    int ival, maxval;
    std::vector<int> take, no_take, take_rank, no_take_rank;
};


struct Game {
    Game(int N) : score_(0), max_taken(0) {
        for (int i = 1; i < N + 1; ++i) envelopes.push_back(i);
        std::shuffle(envelopes.begin(), envelopes.end(), rng);
    }

    int read() { return envelopes.back(); }
    bool done() { return envelopes.empty(); }
    int score() { return score_; }
    void pass() { envelopes.pop_back(); }

    void take() {
        if (read() > max_taken) {
            score_ += read();
            max_taken = read();
        }
        envelopes.pop_back();
    }

    int score_;
    int max_taken;
    std::vector<int> envelopes;
};


int main(int argc, char** argv) {
    std::vector<int> results;
    std::vector<int> max_results;
    int N = 10000;
    for (int i = 0; i < 1000; ++i) {
        std::cout << "Simulating game " << (i+1) << ".\n";
        Game game(N);
        Algo algo(N);

        while (!game.done()) {
            if (algo.should_take(game.read())) game.take();
            else game.pass();
        }
        results.push_back(game.score());
    }

    std::sort(results.begin(), results.end());
    std::cout << results[results.size()/2] << "\n";

    return 0;
}

Interessant. Ich war auf den Gedanken gekommen, dass es möglich sein sollte, Verbesserungen zu erzielen, indem man sich die Werte der letzten Umschläge ansieht. Ich nehme an, Sie haben mit dem Cutoff-Punkt gespielt, an dem Sie die Strategie wechseln. Wird es nur zu langsam, wenn Sie früher wechseln? Oder verschlechtern sich die Ergebnisse tatsächlich?
Reto Koradi

@RetoKoradi Ich habe mit dem Cutoff-Punkt gespielt, und frühere Cutoffs wurden beide zu langsam und schlechter. Nicht allzu überraschend ehrlich, bei 100 Umschlägen sind wir bereits Abtasten gerade einmal 1000 Permutationen von möglichem 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000.
orlp

3

Java, 806.899 USD

Dies ist aus einem Versuch von 2501 Runden. Ich arbeite noch daran, es zu optimieren. Ich schrieb zwei Klassen, einen Umschlag und einen Spieler. Der Wrapper instanziiert den Player mit der Anzahl der Umschläge (immer 10000 für das Original) und ruft dann die Methode takeQmit dem Wert des obersten Umschlags auf. Der Spieler kehrt dann zurück, truewenn er es nimmt, falsewenn er es besteht.

Spieler

import java.lang.Math;

public class Player {
  public int[] V;

  public Player(int s) {
    V = new int[s];
    for (int i = 0; i < V.length; i++) {
      V[i] = i + 1;
    }
    // System.out.println();
  }

  public boolean takeQ(int x) {

    // System.out.println("look " + x);

    // http://www.programmingsimplified.com/java/source-code/java-program-for-binary-search
    int first = 0;
    int last = V.length - 1;
    int middle = (first + last) / 2;
    int search = x;

    while (first <= last) {
      if (V[middle] < search)
        first = middle + 1;
      else if (V[middle] == search)
        break;
      else
        last = middle - 1;

      middle = (first + last) / 2;
    }

    int i = middle;

    if (first > last) {
      // System.out.println(" PASS");
      return false; // value not found, so the envelope must not be in the list
                    // of acceptable ones
    }

    int[] newVp = new int[V.length - 1];
    for (int j = 0; j < i; j++) {
      newVp[j] = V[j];
    }
    for (int j = i + 1; j < V.length; j++) {
      newVp[j - 1] = V[j];
    }
    double pass = calcVal(newVp);
    int[] newVt = new int[V.length - i - 1];
    for (int j = i + 1; j < V.length; j++) {
      newVt[j - i - 1] = V[j];
    }
    double take = V[i] + calcVal(newVt);
    // System.out.println(" take " + take);
    // System.out.println(" pass " + pass);

    if (take > pass) {
      V = newVt;
      // System.out.println(" TAKE");
      return true;
    } else {
      V = newVp;
      // System.out.println(" PASS");
      return false;
    }
  }

  public double calcVal(int[] list) {
    double total = 0;
    for (int i : list) {
      total += i;
    }
    double ent = 0;
    for (int i : list) {
      if (i > 0) {
        ent -= i / total * Math.log(i / total);
      }
    }
    // System.out.println(" total " + total);
    // System.out.println(" entro " + Math.exp(ent));
    // System.out.println(" count " + list.length);
    return total * (Math.pow(Math.exp(ent), -0.5) * 4.0 / 3);
  }
}

Verpackung

import java.lang.Math;
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;

public class Controller {
  public static void main(String[] args) {
    int size = 10000;
    int rounds = 2501;
    ArrayList<Integer> results = new ArrayList<Integer>();
    int[] envelopes = new int[size];
    for (int i = 0; i < envelopes.length; i++) {
      envelopes[i] = i + 1;
    }
    for (int round = 0; round < rounds; round++) {
      shuffleArray(envelopes);

      Player p = new Player(size);
      int cutoff = 0;
      int winnings = 0;
      for (int i = 0; i < envelopes.length; i++) {
        boolean take = p.takeQ(envelopes[i]);
        if (take && envelopes[i] >= cutoff) {
          winnings += envelopes[i];
          cutoff = envelopes[i];
        }
      }
      results.add(winnings);
    }
    Collections.sort(results);
    System.out.println(
        rounds + " rounds, median is " + results.get(results.size() / 2));
  }

  // stol... I mean borrowed from
  // http://stackoverflow.com/questions/1519736/random-shuffling-of-an-array
  static Random rnd = new Random();

  static void shuffleArray(int[] ar) {
    for (int i = ar.length - 1; i > 0; i--) {
      int index = rnd.nextInt(i + 1);
      // Simple swap
      int a = ar[index];
      ar[index] = ar[i];
      ar[i] = a;
    }
  }
}

Eine ausführlichere Erklärung folgt in Kürze, nachdem ich Optimierungen abgeschlossen habe.

Die Grundidee besteht darin, die Belohnung für das Spielen eines Spiels aus einem bestimmten Satz von Umschlägen abschätzen zu können. Wenn der aktuelle Satz von Umschlägen {2,4,5,7,8,9} und der obere Umschlag die 5 ist, gibt es zwei Möglichkeiten:

  • Nimm die 5 und spiele ein Spiel mit {7,8,9}
  • Übergeben Sie die 5 und spielen Sie eine Partie {2,4,7,8,9}

Wenn wir die erwartete Belohnung von {7,8,9} berechnen und mit der erwarteten Belohnung von {2,4,7,8,9} vergleichen, können wir feststellen, ob es sich lohnt, die 5 zu nehmen.

Nun stellt sich die Frage, wie hoch der erwartete Wert bei einer Reihe von Umschlägen wie {2,4,7,8,9} ist. Ich fand, dass der erwartete Wert proportional zur Gesamtmenge des Geldes in der Menge zu sein scheint, aber umgekehrt proportional zur Quadratwurzel der Anzahl der Umschläge, in die das Geld aufgeteilt ist. Dies ist darauf zurückzuführen, dass mehrere kleine Spiele "perfekt" gespielt wurden, bei denen alle Umschläge einen nahezu identischen Wert haben.

Das nächste Problem ist die Ermittlung der " effektiven Anzahl von Umschlägen". In allen Fällen ist die Anzahl der Umschläge genau bekannt, indem Sie nachverfolgen, was Sie gesehen und getan haben. So etwas wie {234,235,236} ist definitiv drei Umschläge, {231,232,233,234,235} ist definitiv 5, aber {1,2,234,235,236} sollte wirklich als 3 und nicht als 5 Umschläge zählen, da die Umschläge 1 und 2 fast wertlos sind und Sie niemals einen 234er PASSEN würden Sie könnten später eine 1 oder 2 nehmen. Ich hatte die Idee, Shannon-Entropie zu verwenden, um die effektive Anzahl von Umschlägen zu bestimmen.

Ich habe meine Berechnungen auf Situationen ausgerichtet, in denen die Werte der Hüllkurve gleichmäßig über ein Intervall verteilt sind, was während des Spiels passiert. Wenn ich {2,4,7,8,9} nehme und das als Wahrscheinlichkeitsverteilung betrachte, ist seine Entropie 1.50242. Dann exp()bekomme ich 4.49254 als effektive Anzahl der Umschläge.

Die geschätzte Belohnung von {2,4,7,8,9} ist 30 * 4.4925^-0.5 * 4/3 = 18.87

Die genaue Anzahl ist 18.1167.

Dies ist keine exakte Schätzung, aber ich bin wirklich stolz darauf, wie gut dies zu den Daten passt, wenn die Umschläge gleichmäßig über ein Intervall verteilt sind. Ich bin mir nicht sicher, welcher Multiplikator richtig ist (ich verwende momentan 4/3), aber hier ist eine Datentabelle ohne den Multiplikator.

Set of Envelopes                    Total * (e^entropy)^-0.5      Actual Score

{1,2,3,4,5,6,7,8,9,10}              18.759                        25.473
{2,3,4,5,6,7,8,9,10,11}             21.657                        29.279
{3,4,5,6,7,8,9,10,11,12}            24.648                        33.125
{4,5,6,7,8,9,10,11,12,13}           27.687                        37.002
{5,6,7,8,9,10,11,12,13,14}          30.757                        40.945
{6,7,8,9,10,11,12,13,14,15}         33.846                        44.900
{7,8,9,10,11,12,13,14,15,16}        36.949                        48.871
{8,9,10,11,12,13,14,15,16,17}       40.062                        52.857
{9,10,11,12,13,14,15,16,17,18}      43.183                        56.848
{10,11,12,13,14,15,16,17,18,19}     46.311                        60.857

Die lineare Regression zwischen erwartet und tatsächlich ergibt einen R ^ 2-Wert von 0,999994 .

Mein nächster Schritt, um diese Antwort zu verbessern, besteht darin, die Schätzung zu verbessern, wenn die Anzahl der Umschläge langsam abnimmt. Dies ist der Fall, wenn die Umschläge nicht mehr annähernd gleichmäßig verteilt sind und das Problem allmählich granular wird.


Bearbeiten: Wenn dies Bitcoins wert ist, habe ich gerade eine Adresse an 1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg. Vielen Dank! (Dies war hier, als der Herausforderungsautor Preise verteilte.)


Sie haben versehentlich 20.000 Satoshi über 805.479 gesendet. Als Referenz wurde die Menge sollte Ihre Gäste sein. Genießen Sie meinen Fehler :)
LivingInformation

Wirst du Zahlen mit mehr Runden laufen lassen? Basierend auf dem, was ich sehe, gibt es einige Variationen, und 500 reichen nicht aus, um einen stabilen Median zu erhalten. Meine Punktzahl liegt sehr nahe bei Ihrer, wenn ich nur 500 Runden spiele, aber alles hängt davon ab, wie die Zufallszahlen zufällig fallen. Wenn ich einen variablen Startwert verwendet und ein paar Mal 500 Läufe ausgeführt hätte, könnte ich wahrscheinlich eine höhere Punktzahl erzielen.
Reto Koradi

@RetoKoradi Ich werde auf jeden Fall mehr Runden machen.
PhiNotPi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.