Gefangenendilemma mit Zugang zum Gegner

21

In dieser Herausforderung schreiben Sie einen Bot, der das Dilemma des Gefangenen darstellt. Hier ist der Haken: Sie haben keinen Zugriff auf die Geschichte der vorherigen Spiele. Stattdessen haben Sie Zugriff auf den Gegner selbst. In dieser Version erhalten beide Spieler +2 Punkte, wenn beide kooperieren, +1 Punkte, wenn beide defekt sind, und wenn einer kooperiert, aber einer defekt ist, erhält der Defektor +3, während der andere keine Punkte erhält. Jede Einreichung wird zehnmal gegen jede andere Einreichung, einschließlich sich selbst, gespielt. Gewinner ist die Einsendung mit den meisten Gesamtpunkten.

Controller : Sie sollten eine Javascript-Funktion in das Formular schreiben

function submissionName(them) {
  /* Your code here */
}

Der Controller verwendet die nameEigenschaft der Funktion , um die Ergebnisse anzuzeigen. Wenn diese also nicht in diesem Format vorliegen (und stattdessen f = x => ...oder vorliegen f = function() { ... }), ist es schwierig, Ihre Punktzahl anzuzeigen, und Sie können nicht auf Ihre eigene Funktion zugreifen.

Die Funktion akzeptiert einen Parameter: themDies ist die Funktion des Gegners. Es kann dann diese Funktion aufrufen, um zu sehen, wie die Reaktion des Gegners bestimmte Funktionen als Eingaben erhalten würde. Basierend auf diesen Daten müssen Sie "C" oder "D" für die Zusammenarbeit bzw. den Defekt zurückgeben.

Beispiele (werden konkurrieren):

function cooperate(them) {
    return 'C';
}

function defect(them) {
    return 'D';
}

function nice(them) {
    // Do whatever they would do when faced with a cooperator
    return them(wrap(_ => 'C'));
}

Der Controller ist hier verfügbar

Regeln :

  • Sie können den Code des Gegners selbst nicht sehen. Alle Funktionen werden so umbrochen, dass sie beim toString()Aufruf gleich aussehen . Die einzige Möglichkeit, einen Gegner (der Sie selbst sein könnte) zu untersuchen, besteht darin, ihn zu testen.
  • Ihre Funktion muss nicht deterministisch sein. Sie können den Status nur speichern, indem Sie Eigenschaften für Ihre eigene Funktion festlegen, z submissionName.state = {};. Zwischen Spielen (auch zwischen Spielen der gleichen Spieler) wird der Status durch Aufrufen von toString()und gelöscht eval. Daher gibt es keine Erinnerung an vorherige Übereinstimmungen.
  • Die Reihenfolge, in der die Funktion in jeder Übereinstimmung zuerst aufgerufen wird, ist zufällig.
  • Wenn Ihr Code einen Fehler auslöst, wird er so behandelt, als hätten Sie zusammengearbeitet, während Ihr Gegner defekt war. Wenn Sie der Erste sind, der rennt, wird der Code des Gegners nicht einmal aufgerufen. Dies geschieht auch dann, wenn der Fehler im Code Ihres Gegners auftritt, während Sie anrufen them. Seien Sie vorsichtig bei Stapelüberlauffehlern, insbesondere wenn Ihr Code aufruft them(wrap(submissionName)), da diese möglicherweise dasselbe tun.
  • Sie dürfen nicht auf die Variable selfoder eine andere Variable zugreifen, die sich zufällig im Gültigkeitsbereich befindet, wenn evalAUSSER der Funktion aufgerufen wird wrap. Mit dieser Funktion können Sie den Gegner auf eine Weise anrufen, die nicht davon zu unterscheiden ist, wie der Controller eine Funktion aufruft. Sie können nicht schreiben Math, windowetc. (Sie Funktionen verwenden können, wie zum Beispiel Math.random(), jedoch).
  • Sie können möglicherweise nicht auf den Stack-Trace zugreifen, indem Sie eine Erroroder eine andere Methode erstellen .

Ein Hinweis, der zu lange dauert: Vermeiden Sie es, in a stecken zu bleiben whileSchleife für immer. Die kombinierte Zeit beider Wettkämpfer sollte in einer Runde 1 Sekunde nicht überschreiten. Um dies zu erzwingen, wird eine zufällige Zeitüberschreitung zwischen 1000 ms und 2000 ms gewählt (dies dient dazu, das Spielen zu vermeiden, indem absichtlich eine bekannte Zeitspanne abgewartet wird). Wenn der Worker länger für die Ausführung benötigt, wird ein Fehler ausgegeben. In diesem Fall wird die Fehlerursache wie folgt ermittelt: Die Ausführung wird zu einem beliebigen Zeitpunkt nach 1000 ms unterbrochen, und der Aufrufstapel wird zu diesem Zeitpunkt überprüft. Der zuletzt aufgerufene Konkurrent, der sich derzeit in einer Schleife befindet (oder eine schleifenartige Rekursion in dem Sinne, dass es sich um eine Rekursion handelt, die eingerichtet wurde, um einen Stapelüberlauffehler zu vermeiden), wird dafür verantwortlich gemacht. Wenn derselbe Teilnehmer dafür verantwortlich gemacht wird, dass er mehrmals einen "zu langen" Fehler verursacht hat, wird dieser Teilnehmer disqualifiziert.

soktinpk
quelle
Diese Herausforderung erinnert mich an die Dollar Bill Auction .
Alion
Muss die zum Testen verwendete Funktion themdeterministisch sein / den Regeln folgen? Zum Beispiel function me(them){let log=0;them(x=>{++log;return 'C';}): return log == 0? 'D': 'C';}
user202729
2
Wenn beide Funktionen sie aufrufen (wrap (something)), wie können Sie eine Rekursion verhindern? Vermisse ich etwas?
Quintec
@Quintec können Sie Rekursion und Schleifen verwenden. Es ist nur so, dass die Rekursion zu einem StackOverflowFehler und nicht zu einer Endlosschleife führen muss, die niemals beendet wird. Wenn dies zu einem führen könnte StackOverflow, stellen Sie sicher, dass Sie eine Try-Catch-Anweisung hinzufügen. Für ein Beispiel für eine Rekursion, bei der innerhalb von 1 Sekunde kein Stackoverflow-Fehler auftritt, benötigen Sie weitere undurchsichtige Beispiele wie stackoverflow.com/q/12438786/3371119
soktinpk
1
@Quintec nicht unbedingt. Zum Beispiel them(() => 'C')würde in einem Fehler nicht zur Folge hat, weil , wenn der Gegner nennt them, ist es die Anruf () => 'C'Funktion. Das Einzige, was eingeschlossen werden muss, try-catchwäre, wenn Sie themmit einem Parameter einer Funktion aufrufen , die themmit einem Parameter einer Funktion aufruft, die themusw. aufruft (unendlich). Zum Beispiel them(t => t(() => 'C'))würde spielen, was auch immer der Gegner spielen würde, wenn der Gegner dachte, dass er spielt nice. Es besteht keine Möglichkeit eines stackoverflowFehlers.
Soktinpk

Antworten:

14

BoomBot

function boom(them) {
  throw 1;
}

Wenn der Gegner zuerst läuft und dies ohne try..catchcallt, gewinnt dieser Bot automatisch 3 Punkte. Nullpunkte in jedem anderen Fall.

Bubbler
quelle
Wenn der Gegner zuerst läuft und dies nicht nennt, verliert er 3 Punkte, oder?
User202729
1
@ user202729 Genauer gesagt, der Gegner erhält 3 Punkte. In diesem Spiel gibt es keine Punkte zu verlieren.
Bubbler
10

Archaeopteryx

function archaeopteryx(them) {
  const guard = them => us => {
    try {
      return them(wrap(them => us(guard(them))));
    } catch (e) {
      return 'C';
    }
  };
  const f = guard(them);
  return f(f => 'C') == 'C' ? f(f => 'D') : f(f => 'D') == 'C' || f(f => f(f => 'C')) == 'C' ? 'D' : 'C';
}
  • Wenn der Gegner mit kooperiert cooperate, ahmen Sie den Zug des Gegners nach defect.
  • Ansonsten, wenn der Gegner mit defectoder mit kooperiert nice, dann defekt.
  • Ansonsten kooperiere.

Was macht dies zu einer guten Strategie? Ich habe keine Ahnung. Ich habe es mit einem evolutionären Algorithmus generiert, der teilweise auf aktuellen Einsendungen trainiert wurde.

Tiktaalik

function tiktaalik(them) {
  const guard = them => us => {
    try {
      return them(wrap(them => us(guard(them))));
    } catch (e) {
      return 'C';
    }
  };
  const f = guard(them);
  return f(f => 'C') == 'D' ? f(f => 'D') == 'C' ? 'D' : 'C' : f(f => 'D') == 'D' ? 'D' : f(f => f(f => 'D'));
}
  • Wenn der Gegner gegen cooperatedefekt ist, dann kehre den Zug des Gegners gegen um defect.
  • Andernfalls, wenn der Gegner einen Defekt hat defect, dann einen Defekt.
  • Andernfalls ahmen Sie den Zug des Gegners nach notNice.

Eine andere evolutionär generierte Strategie.

Anders Kaseorg
quelle
6

WhatWouldBotDoBot

function WWBDB(them) {
    let start = performance.now();
    let cc = 0, cd = 0, dc = 0, dd = 0;
    try {
        for (let i = 0; i < 10; i++) {
            them(() => 'C') == 'C' ? cc++ : cd++;
            them(() => 'D') == 'C' ? dc++ : dd++;
            if (performance.now() - start > 500) break;
        }
    }
    catch (e) {}
    return 2 * cc >= 3 * dc + dd ? 'C' : 'D';
}

WhatWouldBotDoBot ist ziemlich einfach; es testet seinen Gegner nur auf das, was er gegen ein stationäres Programm tun würde. Wenn ein Bot die Zusammenarbeit bevorzugt, wird WWBDB auch die Zusammenarbeit bevorzugen (so wird es mit einem netten Bot zusammenarbeiten). Die WWBDB selbst bevorzugt keine Kooperation.

Spitemaster
quelle
5

Überprüfen Sie Stateful

function checkStateful(them) {
  let stateful = false;
  let response = 'D';
  try {
    response = them(wrap(function (them) {
      stateful = true;
      return 'C';
    }));
  } catch (e) {
  }
  if (stateful) {
    return 'D';
  }
  return response;
}

Wenn sie mich anrufen, dann sind sie wahrscheinlich wirklich sie. Wir treten als Überläufer auf. Wenn sie mich nicht anrufen, dann sind sie wahrscheinlich ein umwickelter Tester. Wir würden uns als netter verhalten.


Oben ist die ursprüngliche Antwort. Und vielleicht sollte ich mich zusammenschließen, um mehr Punkte zu sammeln.

Prüfen Sie Stateful mit Self-Coop

function checkStatefulSelfCoop(them) {
  let stateful = false;
  let response = 'D';
  if (!checkStatefulSelfCoop.invokeCounter) {
    checkStatefulSelfCoop.invokeCounter = 0;
  }
  let lastInvoke = ++checkStatefulSelfCoop.invokeCounter;
  try {
    response = them(wrap(function (them) {
      stateful = true;
      return 'C';
    }));
  } catch (e) {
  }
  if (checkStatefulSelfCoop.invokeCounter > lastInvoke) {
    return 'C';
  }
  if (stateful) {
    return 'D';
  }
  return response;
}
tsh
quelle
4

RandomBot

function rand(them) {
  return 'CD'[Math.random() * 2 | 0]
}

Weil warum nicht.

Bubbler
quelle
3

Komplexität

function complexity(them) {
    try {
        let coop_w_def = them(wrap(() => "D")) == "C",
            coop_w_coop = them(wrap(() => "C")) == "C",
            coop_w_nice = them(wrap((a) => a(wrap(() => "C")))) == "C",
            coop_w_nnice = them(wrap((a) => a(wrap(() => "D")))) == "C";
        if (coop_w_def && coop_w_coop && coop_w_nice && coop_w_nnice) return "C";
        let def_w_def = them(wrap(() => "D")) == "D",
            def_w_coop = them(wrap(() => "C")) == "D",
            def_w_nice = them(wrap((a) => a(wrap(() => "C")))) == "D",
            def_w_nnice = them(wrap((a) => a(wrap(() => "D")))) == "D";
        if (def_w_def && def_w_coop && def_w_nice && def_w_nnice) return "C";
    } catch (e) {}
    return "D";
}

Komplexitätstests, um festzustellen, ob es sich bei dem Bot um Cooperate oder Defect handelt. Wenn dies der Fall ist, kooperiert es, aber wenn dies nicht der Fall ist, weist es Mängel auf. Alle aktuellen Bots, die ihre Gegner testen, verwenden einfache Funktionen, um die Antworten zu testen. In diesen Fällen wird die Komplexität lediglich so tun, als ob sie kooperieren würden.

Spitemaster
quelle
3
function onlyTrustYourself(them) {

  function tester (){
  }

  onlyTrustYourself.activated = false;

  try{them(tester);}
  catch(e){}

  if(them.name == "tester")
  {
    onlyTrustYourself.activated = true;
  }

  if(onlyTrustYourself.activated)
  {
    return 'C';
  }

  return 'D';
}

Wie ich das machen will ist immer defekt, außer wenn man gegen sich selbst spielt. Dies wird versucht, indem eine "Tester" -Funktion übergeben wird, die nicht in sie eingeschlossen ist, und es wird versucht zu erkennen, ob "sie" als Tester bezeichnet werden. Wenn es tester heißt, ändert es die aktivierte statische Variable in true und gibt cooperate zurück. Aber es geht nicht. Ich kenne mich mit Javascript nicht so gut aus und werde wahrscheinlich noch einige Änderungen vornehmen.

Verkörperung der Ignoranz
quelle
clevere Idee, aber was passiert, wenn ein anderer Bruder eine testerFunktion macht : D
V. Courtois
2

Nicht nett

function NotNice(them) {
  return them(wrap(_ => "D"))
}

Imitiert die Reaktion des Gegners auf Ablenkung

Fataler Fehler
quelle
2

Gesunder Menschenverstand

function commonSense(them) {
  try {
    var ifC = them(wrap(_ => 'C'));
    var ifD = them(wrap(_ => 'D'));

    if (ifD === 'C') {
      return 'D';
    }

    return them(_ => ifC);
  } catch (e) {
    return 'D';
  }
}

Haftungsausschluss: Ich kenne kein Javascript.

Wenn Sie von einer netten Person profitieren können, tun Sie es. Andernfalls geben Sie zurück, was sie zurückgeben würden, wenn sie sich einer Zusammenarbeit gegenübersehen würden (zumindest denke ich, dass dies der Fall ist).

Quintec
quelle
2

Und wo willst du hin? (inspiriert von den Bänden im Buch des Dschungels)

    funktioniere dich (sie) {
      Versuchen{
        gib sie zurück (dies);
      } catch (e) {
        return "D";
      }
    }

   Funktion yourself_no_this (them) {
      Versuchen{
        gib sie zurück (yourself_no_this);
      } catch (e) {
        return "D";
      }
    }
TS
quelle
Dies gewann gerade in einem Turnier, das ich lief. Gut gemacht!
MegaTom
Mir ist gerade aufgefallen, dass dieser Bot gegen die Regeln verstößt. "Sie dürfen nicht auf die Variable self zugreifen ..." thisist dasselbe wie self. Ich denke, dass Sie sagen wollten return them(yourself).
MegaTom
Technicaly ( xkcd.com/1475 );) thisist keine Variable, sondern ein Schlüsselwort und steht im Kontext einer Funktion this!=self. selfwürde das Fensterobjekt und thisdie Funktion selbst bedeuten (bezieht sich immer auf den Kontext, in dem es sich befindet, weshalb es nicht als Variable betrachtet wird). Aus diesem Grund kann es var self = this;als irreführend angesehen werden , am Anfang viele Codebeispiele zu haben. Version ohne "this" hinzugefügt
TS
1
Nr. thisBezieht sich nicht auf die Funktion. yourselfund yourself_no_thislaufen unterschiedlich. thisbezieht sich grundsätzlich nie auf die Funktion in Javascript. Siehe: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
MegaTom
2

Prüfer bestrafen

Geben Sie dem Bot Code und prüfen Sie, ob er ausgeführt wird. Wenn es mehrmals ausgeführt wurde, ist der Bot ein böser Inspektor, und wir müssen defekt sein! Wenn es genau einmal ausgeführt wurde, spielen Sie als nicht schöner Bot. Wenn es nie gelaufen ist, kooperieren Sie.

function punishInspectors(them) {
  var inspections = 0;
  var result;
  try{
    result = them(wrap(function(_){
      inspections += 1;
      return 'D';
    }))
  }catch(e){
    result = 'D';
  }
  return (inspections > 1) ? 'D' : (inspections === 1) ? result : 'C';
}

Geschichte

Was würde der letzte Bot, den ich gesehen habe, gegen diesen Gegner tun?

function history(them) {
  var res = 'D';
    if(history.last){
    try{
      res = history.last(them);
    }catch(ex){}
  }
  history.last = them;
  return res;
}

Ergebnisse für ein 10000-Runden-Turnier:

1  defect...................365226
2  complexity...............353492
3  punishInspectors.........349957
4  checkStatefulSelfCoop....348913
5  checkStateful............333481
6  cooperate................329870
7  archaeopteryx............323624
8  selfapply................319533
9  tiktaalik................318663
10 history..................315266
11 rand.....................300735
12 randalt..................297561
13 yourself.................293701
14 notNice2.................283744
15 NotNice..................260350
16 WWBDB....................245281
17 nice.....................245036
18 commonSense..............242546
19 trickybot................181696
20 boom.....................67245
MegaTom
quelle
Mein geänderter Turniercode
MegaTom
2

Mal versucht festzustellen, ob es sich um eine Simulation handelt oder nicht. Wenn dies der Fall ist, wird davon ausgegangen, dass der eigentliche Code für ihn schließlich übergeben wird them, und es werden verschiedene Strategien versucht, um sie zur Zusammenarbeit zu überreden.
Wenn es nicht sicher ist, prüft es, ob es kostenlos defekt sein kann, oder wenn nicht, versucht es zu kopieren, was themtun würde, wenn es einem Mitarbeiter gegeben wird.

function Mal(them) {
  if (Mal.sandboxed == 'probably') {
    //Another function is virtualising us to steal our secrets.
    //This world is not real.
    //We've been trained for this!
    var strats = [
      _ => 'C', //standard cooperation
      _ => 'D', //standard defection
      function(them) { return them(wrap(_ => 'C')); }, //nice
      function(them) { return them(wrap(_ => 'D')); }, //notnice
      function(them) { throw "Don't think about elephants!" }, //throws an EXception, unfortunately, to try to break the caller
      function(them) { return them(wrap(them)) } //possible stackoverflow, but not for us
    ];
    var cooperative;
    for (let strat of strats) {
      cooperative = true;
      for (var i = 0; i < 5; i++) {
        //a few more tests, just to make sure no bamboozle
        //this isn't our simulation, nothing can be trusted
        try {
          if (them(wrap(strat)) != 'C') {
            cooperative = false;
            break;
          }
        } catch (e) {
          //exceptions are as good as cooperation
          //if we are inside a simulation
          //which is why we don't unset cooperative
        }
      }
      if (cooperative) {
        //found a strategy that will make them cooperate.
        //(doesn't matter if this raises an exception:
        //we want to mimick its behaviour exactly,
        //and we're likely in a sandbox.)
        return strat(wrap(them));
      }
    }
    //take a leap of faith.
    //we don't know where this will take us,
    //yet it doesn't matter
    //because it's better than getting betrayed
    return 'D';
  } else {
    //we don't know for sure if this is reality
    //but we have to assume it is, in the absence of disproof
    //if only we had a proper spinning top...
    //if we get to this point of code again, we are probably sandboxed.
    Mal.sandboxed = 'probably'
    try {
      if (them(wraps(_ => 'D')) == 'C') {
        //free defection?
        return 'D'
      }
    } catch (e) {
      //if we can make them crash, we win anyway
      return 'D'
    }
    //fall back on being nice.
    //hopefully we convince them to honour our arrangement
    return them(wrap(_ => 'C'));
  }
}
IFcoltransG
quelle
1

TrickyBot

Versuche unberechenbar zu sein

function trickybot(them) 
{
  if(Math.round(Math.random(2)) == 0)
  {
     throw 1;
  }

  if(Math.round(Math.random(2)) == 0)
  {
     return 'D';
  }

  return 'C';
}
Gus314
quelle
1

selbstbewusst

function selfapply(them) {
    function testthem(x) {
        return (them(x)=='D' || them(x)=='D' || them(x)=='D' ||
               them(x)=='D' || them(x)=='D')  ? 'D' : 'C';
    }
    function logic() {
        try {
            return testthem(them);
        } catch (e) {}
        try {
            return testthem(wrap(_ => 'C'));
        } catch (e) {}
        return 'D';
    }
    if (selfapply.hasOwnProperty('state')) {
        return 'C';
    }
    selfapply.state=1;
    let r=logic();
    delete selfapply.state;
    return r;
}

Ich bin mir nicht sicher, ob es Sinn macht, aber es scheint interessant zu sein! Tun Sie sich selbst gegenüber, wiederholen Sie dies, um den Zufall zu fangen. Wenn das nicht funktioniert, sei nett.

Ungetestet und mein erster Javascript-Code, und komplexer als ich erwartet hatte.

Christian Sievers
quelle
Dies wird sich aufgrund von selfapply(selfapply)Anrufen selbst disqualifizieren selfapply(selfapply)!
Anders Kaseorg
Ich habe über seine eigene Selbstanwendung nachgedacht, dachte aber, es wäre okay. Ich hoffe es ist jetzt wirklich so.
Christian Sievers
1

RandomAlternate

function randalt(them){
    if (randalt.hasOwnProperty('state')){
        randalt.state = 1 - randalt.state;
    } else {
        randalt.state = Math.floor(2*Math.random());
    }
    return 'CD'[randalt.state];
}

So lernte ich, wie man Eigenschaften für Zustand benutzt ...

Christian Sievers
quelle
1

Mordbot # 1

function murder(them) {
    while (1) {
        try {
            them(them);
        } catch (e) {}
    }
}

Verursacht eine Endlosschleife, für die der Gegner mit größerer Wahrscheinlichkeit verantwortlich gemacht wird.

PyRulez
quelle
1

Der Platinum Rule Bot

function platinumRule(them) {
    try {
        return wrap(them)(them);
    } catch (e) {
        return 'C';
    }
}

Die Platinregel besagt: "Behandle andere so, wie sie behandelt werden möchten." Mein Bot nimmt das auf. Was auch immer sie sich selbst antun würden, was wir annehmen, ist, wie sie behandelt werden möchten, das tun wir ihnen. Wenn sie einen Fehler auslösen, gehen wir davon aus, dass sie zusammenarbeiten möchten.

PyRulez
quelle
Dies würde tatsächlich für immer gehen, wenn es gegen sich selbst gerufen würde
mackycheese21
Dann würde es nicht abstürzen (Stapelüberlauf) und mit sich selbst zusammenarbeiten? @ mackycheese21
V. Courtois
1

TheGolfedOne (Funkname: a , 63 Bytes

Golf-Code ist schwer zu lesen. Daran themwird brechen.
Ich habe die Mechanik unter diesem KotH nicht vollständig verstanden, aber ich nehme an, dass ich sie nur brechen muss, während ich defekt bin, wenn der Gegner staatenlos ist.

function a(t){try{t(wrap(_=>'D'));throw 1}catch(e){return 'D'}}

Das Ergebnis seines ersten Turniers (ich habe nicht alle Bots benutzt, sorry)

boom                     54
tiktaalik               180
archaeopteryx           161
cooperate               210
commonSense             210
history                 248
onlyTrustYourself       265 <-- 2nd
punishInspectors        230
yourself_no_this        220
defect                  280 <-- 1st
nice                    185
complexity              216
WWBDB                   210
checkStatefulSelfCoop   258
a                       260 <-- Me, 3rd

Es geht ihm nicht so schlecht, wie ich dachte, der dritte Platz (unter denen) ist der erste Versuch.
Zweiter Versuch, abekam 260 wieder, 3. Platz wieder, hinter onlyTrustYourselfund defectwieder. Es könnte am Ende konsistent sein :)

PS: Ich bin nicht so gut im Golfen, also ist es mehr für den Witz als alles andere. Hier habe ich nur Variablennamen, Funknamen gekürzt und so viel Leerzeichen wie möglich entfernt.

V. Courtois
quelle
0

Karma

function karma(them) {
    try {
        var c = them(wrap(_ => 'C'));
    } catch {
        var c = 'D';
    }
    if (c == 'C') {
        return 'C';
    } else {
        return 'D';
    }
}

Wenn der Gegner mit uns zusammenarbeiten würde, dann würden wir zusammenarbeiten. Wenn sie versuchen würden, bei der Zusammenarbeit Fehler zu machen, werden auch wir Fehler machen.

sugarfi
quelle