So stellen Sie das DDOS-Internet wieder her

17

Das Internet ist ausgefallen. DDoS-Angriffe sind mittlerweile weit verbreitet. Es liegt an Ihnen, die Kontrolle zu übernehmen und das Internet zu reparieren.

Jeder Bot steuert 20 Knoten in diesem Netzwerk. Jeder Knoten ist entweder aktiv oder sicher , hat einen Besitzer und eine Stärke, die bei 2 beginnt. Jeder aktive Knoten ist mit allen anderen aktiven Knoten verbunden.

In jeder Runde erhalten Sie eine Liste aller aktiven Knoten mit ihrer Stärke. Für jeden Ihrer aktiven Knoten haben Sie folgende Möglichkeiten:

  1. Bestimmen Sie einen aktiven Knoten, den Sie übertragen möchten gesamte Stärke , oder
  2. Speichern Sie und erhöhen Sie seine Stärke

Dann passiert das Folgende in der richtigen Reihenfolge :

  1. Ein Knoten, der seine Stärke speichert, erhöht seine Stärke um 1.
  2. Alle Knoten, die ihre Stärke übertragen möchten, übertragen gleichzeitig ihre gesamte Stärke auf den neuen Knoten.
  3. Wurde einem Knoten Stärke von einem feindlichen Knoten übertragen, erfolgt ein Angriff. Wenn ein feindlicher Besitzer gemeinsam mehr Stärke überträgt als der ursprüngliche Besitzer (und alle anderen Angreifer), wird dieser Feind zum neuen Besitzer. Die Stärke dieses Knotens wird dann zur Stärke des Angreifers. Wenn es einen Gleichstand für die Stärke gibt, wird der Eigentümer zufällig ausgewählt.
  4. Alle Knoten ohne Stärke werden als sicher angesehen und geben dem Besitzer 1 Punkt.

Nach 100 Spielen mit 100 Runden gewinnt der Besitzer mit den sichersten Knoten in allen Spielen. EDIT: Ich habe es von 2000 auf 100 Runden geändert, da die letzten 1900 Runden nutzlos waren

IO

Ihnen wird die Liste der aktiven Knoten (über Befehlszeilenargumente) wie folgt übergeben:

F20 F4 E7 E2 E20 F2

Fbezeichnet, dass der Knoten ein freundlicher Knoten ist, und Ebezeichnet, dass der Knoten ein Feind ist.

Für jeden Ihrer befreundeten Knoten sollten Sie eine Aktion (über STDOUT) wie die folgende zurückgeben:

0,0 1,3 5,0

Das oben Gesagte würde bedeuten, dass Sie Ihre Stärke des ersten Knotens erhöhen möchten, Ihren zweiten Knoten zum Angreifen des vierten Knotens verwenden möchten und Ihr letzter Knoten seine Stärke an den ersten Knoten überträgt (und wenn niemand ihn angreift, wird er zu einem sicheren Knoten ).

Nach der Rückkehr sollte Ihr Programm beendet werden.

Anzeigetafel

Akku bekam 3240 Punkte

nobel bekam 2370 Punkte

Dumbot bekam 2262 Punkte

random_bot bekam 1603 Punkte

smarter_random_bot bekam 1319 Punkte

steady_bot bekam 1097 Punkte

Den Controller finden Sie hier: https://github.com/nathanmerrill/NetAttack

Nathan Merrill
quelle
Der Controller widerspricht der Angabe: "Wenn ein gegnerischer Besitzer gemeinsam mehr Stärke überträgt als der ursprüngliche Besitzer ...". Derzeit ist es gleich oder mehr .
Randomra
@ Randomra: In der Spezifikation heißt es: Wenn es ein Unentschieden für die Stärke gibt, dann wird der Besitzer nach dem Zufallsprinzip ausgewählt
Nathan Merrill
@ NathanMerrill Ich nahm an, wenn die Angreifer gleichziehen.
Randomra
Der letzte verbleibende Knoten bleibt bis zum Ende des Spiels hängen, oder? Es gibt keine Möglichkeit für ihn zu fliehen?
Aebabis
@acbabis richtig, aber ich teste das tatsächlich und beende das Spiel zu diesem Zeitpunkt vorzeitig.
Nathan Merrill

Antworten:

5

Akku, Python

Lasst uns diese Party beginnen! Mein Beitrag sollte sowohl mit Python 2 als auch mit Python 3 funktionieren.

import sys

inputs = [(i, x[0], int(x[1:])) for (i, x) in enumerate(sys.argv[1].split())]

own_nodes = sorted([(s,i) for (i,o,s) in inputs if o == 'F'])
targets = sorted([(s,i) for (i,o,s) in inputs if o == 'E'])

if targets:
    t_copy = targets[:]
    out = ""
    total_str = 0
    attackers = []
    for (s,i) in own_nodes:
        attackers += [i]
        if t_copy:
            total_str += s
            if t_copy[0][0] < total_str - 1:
                j = max([j for j in range(len(t_copy)) if t_copy[j][0] < total_str - 1])
                out += " ".join([str(k) + "," + str(t_copy[j][1]) for k in attackers]) + " "
                attackers = []
                total_str = 0
                t_copy = t_copy[:j] + t_copy[j+1:]
    if attackers:
        if t_copy:
            out += " ".join([str(k) + "," + str(t_copy[0][1]) for k in attackers])
        else:
            out += " ".join([str(k) + "," + str(attackers[0]) for k in attackers])
else:
    out = " ".join([str(i) + "," + str(own_nodes[0][1]) for (s,i) in own_nodes])

print(out.rstrip())
sys.stdout.flush()

Die Idee ist wirklich einfach. Ich beginne, meine Knoten in aufsteigender Reihenfolge der Stärke aufzulisten und eine laufende Summe der Stärken aufzubewahren. Wenn die Summe die Stärke des schwächsten feindlichen Knotens überschreitet (+1 für eine mögliche Erhöhung), greife ich diesen Knoten an und entferne ihn aus dem Pool, setze die Summe zurück und fahre fort. Wenn die stärksten Knoten am Ende niemanden zum Angreifen finden, sammeln sie mehr Kraft.

EDIT: Akku ist jetzt ein bisschen schlauer. Anstatt immer den schwächsten feindlichen Knoten anzugreifen, sammelt es die Stärke, bis es dazu in der Lage ist, und greift dann den stärksten freien Knoten mit dieser Stärke an. Wenn am Ende noch Feinde übrig sind, greifen nicht zugewiesene Knoten den schwächsten verbleibenden Feind an, nur für den Fall, dass er beschließt, seine Stärke zu verlieren.

Zgarb
quelle
4

Nobel, Python3

import random, sys
f,e,p=[],[],[]
for si,s in enumerate(sys.argv[1].split()):
    if s[0]=='F': f+=[(int(s[1:]),si)]
    else: e+=[(int(s[1:]),si)]
f=sorted(f,key=lambda t:t[0]);r=4
f1,f2,f3=f[:len(f)//r],f[len(f)//r:len(f)//r*2],f[len(f)//r*2:]
for fa in f3:
    ea=[t for t in e if t[0]<fa[0]]
    p+=[(fa[1],random.choice(ea)[1])] if ea else [(fa[1],fa[1])]
for fd,fs in zip(f1,reversed(f2)):
    p+=[(fs[1],fd[1])]
    p+=[(fd[1],fd[1])]
if len(e)==0: p=[(fe[1],0) for fe in f]
for t in p: print(t[0],',',t[1],' ',sep='',end='')
sys.stdout.flush()

Der Bot teilt seine eigenen Knoten je nach Stärke in 3 Kategorien auf und jeder Knoten handelt entsprechend seiner Kategorie.

  • Jeder starke Knoten greift einen zufälligen feindlichen Knoten an, den er schlagen kann.
  • Jeder mittlere Knoten unterstützt sein schwaches Knotenpaar.
  • Jeder schwache Knoten unterstützt sich selbst.

Ergebnis gegen Accumulator und die beiden Sample Bots:

smarter_random_bot got 1301 points
random_bot got 1841 points
Accumulator got 2178 points
Classy got 2580 points
randomra
quelle
2

Dumbot, Nodejs

var input = process.argv.splice(2);
var regexp = new RegExp(" ", "gm");
input = String(input).split(regexp);
var nodes = [];
var targets = [];
for(var i = 0; i < input.length; i++){
    if(input[i].charAt(0) == "F")
        nodes.push(i);
    else
        targets.push(i);
}
var result = "";
var length = nodes.length;
for(var i = 0; i < length; i++){
    if(targets.length>0)
        result += nodes.shift() + "," + targets.shift() + " ";
    else
        result += nodes.shift() + ",0 ";
}
console.log(result);

Der Bot greift an, ohne nachzudenken oder Strategie. Das Hauptziel ist es, gleich zu Beginn eine Menge sicherer Knoten zu gewährleisten. Beachten Sie, dass dieser Bot eine Endlosschleife mit dem Akku macht.

Schlagen
quelle
2

SteadyBot, Node.js

(new Promise(function(resolve, reject) {
    var input = process.argv[2];
    if(input) {
        resolve(input);
    } else {
        process.stdin.once('data', function(data){
            resolve(data.toString());
        });
    }
})).then(function(input) {
    return input.trim().split(' ');
}).then(function(nodes) {
    var friends = [], enemies = [];
    nodes.forEach(function(value, index) {
        var data = { index: index, strength: parseInt(value.substring(1)) };
        if(value[0] === 'F') {
            friends.push(data);
        } else {
            enemies.push(data);
        }
    });

    function weaknessCompare(a, b) {
        return (a.strength > b.strength) ? -1 : ((a.strength < b.strength) ? 1 : 0);
    }

    friends.sort(weaknessCompare);
    enemies.sort(weaknessCompare);

    if(enemies.length === 0) {
        friends.forEach(function(friend) {
            friend.target = 0;
        });
    } else {
        if(friends.length > 0) {
            var strongest = friends[0];
            for(var i = 0; i < enemies.length; i++) {
                var enemy = enemies[i];
                if(enemy.strength + 1 < strongest.strength) {
                    strongest.target = enemy.index;
                    break;
                }
            };
        }
        if(friends.length > 1) {
            friends[1].target = friends[friends.length - 1].index;
        }
    }

    console.log(friends.map(function(friend) {
        return friend.index + ',' +
                (typeof friend.target === 'number' ? friend.target : friend.index);
    }).join(' '));
});
  • Angenommen, Gegner verstärken keine großen Knoten: Größter befreundeter Knoten greift den stärksten Feind an, den er unter dieser Annahme schlagen kann.
  • Nimmt an, dass das schwächste Ziel angegriffen wird: Der zweitgrößte befreundete Knoten bewegt sich in jeder Runde zum schwächsten befreundeten Knoten.
  • Will viel freie Kraft: Andere Knoten warten.
Aebabis
quelle
Ich bin mir nicht sicher, warum, aber dieser Bot kehrt nicht richtig zurück (er gibt eine leere Zeichenfolge aus). Der andere Nodejs-Bot funktioniert, daher würde ich empfehlen, ihn sich anzusehen. Ich sollte auch erwähnen, dass ich gerade nodejs installiert habe, und obwohl ich Javascript kenne, kann mir etwas fehlen, das spezifisch für nodejs ist.
Nathan Merrill
Danke für die Warnung. Wenn ich es tue node SteadyBot.js F20 F4 E7 E2 E20 F2, funktioniert es für mich. Könnten Sie mir bitte mitteilen, bei welchem ​​Eingang der Fehler aufgetreten ist?
Aebabis
@ NathanMerrill Ich habe es umgeschrieben, um auch mit stdin zu arbeiten. Hoffe das behebt es. cat F20 F4 E7 E2 E20 F2 | node SteadyBot.js
Aebabis
@acbabis Input wird als ein großes Argument angegeben.
Randomra
@acbabis randomra ist richtig. Sie erhalten 1 großes Argument, die Liste (es sei denn, Sie erhalten den Aufruf ebenso wie C ++. In diesem Fall erhalten Sie 2).
Nathan Merrill