Comment récupérer à partir d'Internet DDOS

17

Internet a échoué. Les attaques DDoS sont désormais endémiques et répandues. C'est à vous de prendre le contrôle et de réparer Internet.

Chaque bot contrôlera 20 nœuds de ce réseau. Chaque nœud est actif ou sûr , a un propriétaire et a une force, qui commence à 2. Chaque nœud actif est connecté à tous les autres nœuds actifs.

Chaque tour, vous recevrez une liste de tous les nœuds actifs avec leur force. Pour chacun des nœuds actifs que vous possédez, vous:

  1. Désignez un nœud actif vers lequel vous souhaitez transférer toute votre force, ou
  2. Enregistrer et augmenter sa force

Ensuite, les événements suivants se produisent dans l'ordre :

  1. Un nœud choisissant de sauvegarder sa force augmentera sa force de 1.
  2. Tous les nœuds qui choisissent de transférer leur force transfèreront simultanément toute leur force au nouveau nœud.
  3. Si un nœud a été transféré de la force d'un nœud ennemi, une attaque s'ensuivra. Si un propriétaire ennemi transfère collectivement plus de force que le propriétaire d'origine (et tous les autres attaquants), cet ennemi devient le nouveau propriétaire. La force de ce nœud devient alors la force de l'attaquant. S'il y a une égalité pour la force, le propriétaire sera choisi au hasard.
  4. Tous les nœuds laissés sans force seront considérés comme sûrs et donnent 1 point au propriétaire.

Après 100 parties de 100 tours, le propriétaire avec les nœuds les plus sûrs de toutes les parties gagne. EDIT: Je l'ai changé de 2000 à 100 tours, car il s'est avéré que les 1900 derniers tours étaient inutiles

IO

Vous recevrez la liste des nœuds actifs (via les arguments de ligne de commande) comme suit:

F20 F4 E7 E2 E20 F2

Fdésigne que le nœud est un nœud ami et Edésigne que le nœud est un ennemi.

Pour chacun de vos nœuds amis, vous devez retourner une action (via STDOUT) comme celle-ci:

0,0 1,3 5,0

Ce qui précède signifierait que vous souhaitez augmenter votre force du premier nœud, utilisez votre deuxième nœud pour attaquer le quatrième nœud, et votre dernier nœud transférera sa force le premier nœud (et si personne ne l'attaque, il deviendra un nœud sûr ).

Après votre retour, votre programme devrait se fermer.

Tableau d'affichage

accumulateur a obtenu 3240 points

chic a obtenu 2370 points

dumbot a obtenu 2262 points

random_bot a obtenu 1603 points

smarter_random_bot a obtenu 1319 points

regular_bot a obtenu 1097 points

Le contrôleur peut être trouvé ici: https://github.com/nathanmerrill/NetAttack

Nathan Merrill
la source
Le contrôleur contredit la spécification: "Si un propriétaire ennemi transfère collectivement plus de force que le propriétaire d'origine ...". Actuellement, c'est égal ou supérieur .
randomra
@randomra: dans la spécification, il est dit: s'il y a une égalité pour la force, le propriétaire sera choisi au hasard
Nathan Merrill
@NathanMerrill J'ai supposé que les attaquants étaient à égalité.
randomra
Le dernier nœud restant est bloqué en attendant la fin de la partie, non? Il n'y a aucun moyen pour lui de s'enfuir?
aebabis
@acbabis correct, mais en fait je teste cela et je termine le jeu prématurément à ce point.
Nathan Merrill

Réponses:

5

Accumulateur, Python

Que la fête commence! Ma soumission devrait fonctionner à la fois sur Python 2 et Python 3.

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()

L'idée est vraiment simple. Je commence à énumérer mes nœuds par ordre croissant de force, en conservant une somme cumulée des forces. Lorsque la somme dépasse la force du nœud ennemi le plus faible (+1 pour une augmentation possible), j'attaque ce nœud et le retire du pool, réinitialise la somme et continue. À la fin, si les nœuds les plus forts ne trouvent personne à attaquer, ils collecteront plus de force.

EDIT: L' accumulateur est maintenant un peu plus intelligent. Au lieu d'attaquer toujours le nœud ennemi le plus faible, il accumule la force jusqu'à ce qu'il puisse le faire, puis attaque le nœud libre le plus fort qu'il peut avec cette force. De plus, s'il reste des ennemis à la fin, tous les nœuds non affectés attaqueront l'ennemi le plus faible restant, juste au cas où il déciderait de transférer sa force.

Zgarb
la source
4

Classy, ​​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()

Le bot divise ses propres nœuds en 3 catégories en fonction de la force et chaque nœud agit en fonction de sa catégorie.

  • Chaque nœud fort attaque un nœud ennemi aléatoire qu'il peut battre.
  • Chaque nœud intermédiaire prend en charge sa paire de nœuds faibles.
  • Chaque nœud faible se prend en charge.

Résultat contre l'accumulateur et les deux échantillons de robots:

smarter_random_bot got 1301 points
random_bot got 1841 points
Accumulator got 2178 points
Classy got 2580 points
randomra
la source
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);

Le bot attaquera sans aucune réflexion ni stratégie. L'objectif principal est d'assurer un grand nombre de nœuds sûrs dès le début. Sachez que ce bot fait une boucle infinie avec accumulateur.

Frappé
la source
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(' '));
});
  • Suppose que les ennemis ne renforcent pas les grands nœuds: le plus grand nœud ami attaque l'ennemi le plus puissant qu'il peut battre sous cette hypothèse.
  • Suppose que la cible la plus faible sera attaquée: le deuxième nœud ami le plus grand se déplace vers le nœud ami le plus faible à chaque tour.
  • Veut beaucoup de force libre: les autres nœuds attendent.
aebabis
la source
Je ne sais pas pourquoi, mais ce bot ne revient pas correctement (il imprime une chaîne vide). Les autres robots nodejs fonctionnent, donc je recommanderais de le regarder. Je dois également mentionner que je viens d'installer nodejs, et bien que je connaisse javascript, il se peut que je manque quelque chose de spécifique à nodejs.
Nathan Merrill
Merci pour l'information. Quand je le fais node SteadyBot.js F20 F4 E7 E2 E20 F2, cela fonctionne pour moi. Pourriez-vous s'il vous plaît me dire l'entrée pour laquelle il échoue?
aebabis
@NathanMerrill Je l'ai réécrit pour travailler également avec stdin. J'espère que cela le corrige. cat F20 F4 E7 E2 E20 F2 | node SteadyBot.js
aebabis
@acbabis Input est donné comme un gros argument.
randomra
@acbabis randomra est correct. Vous allez obtenir 1 gros argument, la liste (sauf si vous obtenez l'appel aussi bien que C ++, auquel cas, vous en obtiendrez 2).
Nathan Merrill