En küçük benzersiz sayı KoTH


27

En küçük benzersiz numarayı seçmek için bir bot oluşturun.

(Yıllar önce duymuş olduğum ancak bir daha izleyemediğim bir psikoloji deneyine dayanarak)

kurallar

  • Her oyun 1000 tur oynayan 10 rasgele seçilen bottan oluşacak.
  • Her turda, tüm botlar 1 ile 10 arasında bir tam sayı seçer (dahil). Aynı değeri seçen botlar hariç tutulacak ve en küçük değere sahip kalan bot puan kazanacaktır.
  • Hiçbir botun benzersiz bir değer seçmemesi durumunda, puan kazanılmayacaktır.
  • 1000 turun sonunda, en fazla puana sahip bot (veya en fazla puana bağlı tüm botlar) oyunu kazanır.
  • Turnuva 200 * (oyuncu sayısı) oyun sürecek.
  • En yüksek kazanma yüzdesine sahip olan bot, turnuvayı kazanır.

Özellikler

Botlar Python 3 sınıfı olmalı ve iki yöntem uygulamalıdır: selectve update.
Robotlar bir indeks ile inşa edilecek.
selecthiçbir argüman iletilmez ve botun geçerli tur için seçimini döndürür.
updateönceki turdaki her bot tarafından yapılan seçimlerin bir listesinden geçirilir.

Örnek

class Lowball(object):
    def __init__(self, index):
        # Initial setup happens here.
        self.index = index
    def select(self):
        # Decision-making happens here.
        return 1
    def update(self, choices):
        # Learning about opponents happens here.
        # Note that choices[self.index] will be this bot's choice.
        pass

kontrolör

import numpy as np

from bots import allBotConstructors
allIndices = range(len(allBotConstructors))
games = {i: 0 for i in allIndices}
wins = {i: 0 for i in allIndices}

for _ in range(200 * len(allBotConstructors)):
    # Choose players.
    playerIndices = np.random.choice(allIndices, 10, replace=False)
    players = [allBotConstructors[j](i) for i, j in enumerate(playerIndices)]

    scores = [0] * 10
    for _ in range(1000):
        # Let everyone choose a value.
        choices = [bot.select() for bot in players]
        for bot in players:
            bot.update(choices[:])

        # Find who picked the best.
        unique = [x for x in choices if choices.count(x) == 1]
        if unique:
            scores[choices.index(min(unique))] += 1

    # Update stats.
    for i in playerIndices:
        games[i] += 1
    bestScore = max(scores)
    for i, s in enumerate(scores):
        if s == bestScore:
            wins[playerIndices[i]] += 1

winRates = {i: wins[i] / games[i] for i in allIndices}
for i in sorted(winRates, key=lambda i: winRates[i], reverse=True):
    print('{:>40}: {:.4f} ({}/{})'.format(allBotConstructors[i], winRates[i], wins[i], games[i]))

Ek bilgi

  • Hiçbir bot kendine karşı bir oyunda oynamaz.
  • Düşük olasılıkla bir botun 100'den az oyuna dahil edilmesi durumunda, turnuva tekrar oynanacaktır.
  • Botlar durumu turlar arasında saklayabilir, ancak oyunlar arasında depolayamaz.
  • Denetleyiciye veya diğer botlara erişime izin verilmiyor.
  • Sonuçların çok değişken olması durumunda oyun sayısı ve oyun başına tur sayısı artabilir.
  • Hata yapan veya geçersiz cevap veren botlar (giriş olmayanlar, [1, 10] dışındaki değerler vb.) Diskalifiye edilir ve turnuva onlarsız tekrar oynanır.
  • Mermiler için zaman sınırı yoktur, ancak botların düşünmesi çok uzun sürerse bir tane uygulayabilirim.
  • Kullanıcı başına gönderim sayısında sınırlama yoktur.
  • Son başvuru tarihi 28 Eylül Cuma günü 23:59:59 UTC'dir . Turnuva başvurulara kapandı.

Sonuçlar

                BayesBot: 0.3998 (796/1991)
      WhoopDiScoopDiPoop: 0.3913 (752/1922)
           PoopDiScoopty: 0.3216 (649/2018)
                   Water: 0.3213 (660/2054)
                 Lowball: 0.2743 (564/2056)
                Saboteur: 0.2730 (553/2026)
                OneUpper: 0.2640 (532/2015)
         StupidGreedyOne: 0.2610 (516/1977)
          SecondSaboteur: 0.2492 (492/1974)
                    T42T: 0.2407 (488/2027)
                     T4T: 0.2368 (476/2010)
          OpportunityBot: 0.2322 (454/1955)
              TheGeneral: 0.1932 (374/1936)
             FindRepeats: 0.1433 (280/1954)
                  MinWin: 0.1398 (283/2025)
             LazyStalker: 0.1130 (226/2000)
               FollowBot: 0.1112 (229/2060)
                Assassin: 0.1096 (219/1999)
           MostlyAverage: 0.0958 (194/2024)
             UnchosenBot: 0.0890 (174/1955)
                 Raccoon: 0.0868 (175/2015)
               Equalizer: 0.0831 (166/1997)
       AvoidConstantBots: 0.0798 (158/1980)
WeightedPreviousUnchosen: 0.0599 (122/2038)
               BitterBot: 0.0581 (116/1996)
               Profiteur: 0.0564 (114/2023)
              HistoryBot: 0.0425 (84/1978)
            ThreeFourSix: 0.0328 (65/1984)
                 Stalker: 0.0306 (61/1994)
             Psychadelic: 0.0278 (54/1943)
              Unpopulist: 0.0186 (37/1994)
             PoissonsBot: 0.0177 (35/1978)
         RaccoonTriangle: 0.0168 (33/1964)
              LowHalfRNG: 0.0134 (27/2022)
              VictoryPM1: 0.0109 (22/2016)
            TimeWeighted: 0.0079 (16/2021)
             TotallyLost: 0.0077 (15/1945)
            OneTrackMind: 0.0065 (13/1985)
              LuckySeven: 0.0053 (11/2063)
          FinalCountdown: 0.0045 (9/2000)
                Triangle: 0.0039 (8/2052)
           LeastFrequent: 0.0019 (4/2067)
                Fountain: 0.0015 (3/1951)
             PlayerCycle: 0.0015 (3/1995)
                  Cycler: 0.0010 (2/1986)
               SecureRNG: 0.0010 (2/2032)
             SneakyNiner: 0.0005 (1/2030)
            I_Like_Nines: 0.0000 (0/1973)

2
@Mnemonic Herhangi bir haber var mı?
user1502040

4
@Herohtar İşe gitmeden önce çalışmaya başladım. Şansım yaver giderse, eve geldiğimde yapılmalı.

1
@ Anemonic Henüz bitti mi?
user1502040

2
@Justin Şu anda çalışıyor ve çöküyor gibi görünmüyor, ancak bu işlem başarısız olursa kesinlikle yardımı almazdım.

1
@MihailMalostanidis bots.pyTüm botları içeren aynı dizinde adı verilen bir dosya oluşturun . Sonunda, kurucular listesini oluşturmak:allBotConstructors = [Lowball, BayesBot, ...]

Yanıtlar:


10

BayesBot

Basit bir istatistiksel model kullanarak en uygun seçimi yapmaya çalışır.

import random

def dirichlet(counts):
    counts = [random.gammavariate(n, 1) for n in counts]
    k = 1. / sum(counts)
    return [n * k for n in counts]

class BayesBot(object):
    def __init__(self, index):
        self.index = index
        self.counts = [[0.2 * (10 - i) for i in range(10)] for _ in range(10)]
    def select(self):
        player_distributions = []
        for i, counts in enumerate(self.counts):
            if i == self.index:
                continue
            player_distributions.append(dirichlet(counts))
        cumulative_unique = 0.
        scores = [0.] * 10
        for i in range(10):
            p_unpicked = 1.
            for d in player_distributions:
                p_unpicked *= (1. - d[i])
            p_unique = p_unpicked * sum(d[i] / (1. - d[i]) for d in player_distributions)
            scores[i] = p_unpicked * (1. - cumulative_unique)
            cumulative_unique += p_unique * (1. - cumulative_unique)
        return scores.index(max(scores)) + 1
    def update(self, choices):
        for i, n in enumerate(choices):
            self.counts[i][n - 1] += 1

10

Sabit Botlardan Kaçının

Hangi botların her zaman aynı değeri döndürdüğünü takip edin ve bu değerleri atlayın. Kalan değerler arasından rasgele seçim yapın, ancak daha düşük değerlere doğru önyargılı olun.

import numpy as np

class AvoidConstantBots(object):
    all_values = range(1, 11)
    def __init__(self, index):
        self.index = index
        self.constant_choices = None

    def select(self):
        available = set(self.all_values)
        if self.constant_choices is not None:
            available -= set(self.constant_choices)
        if len(available) == 0:
            available = set(self.all_values)
        values = np.array(sorted(available))
        weights = 1. / (np.arange(1, len(values) + 1)) ** 1.5
        weights /= sum(weights)
        return np.random.choice(sorted(available), p=weights)

    def update(self, choices):
        if self.constant_choices is None:
            self.constant_choices = choices[:]
            self.constant_choices[self.index] = None
        else:
            for i, choice in enumerate(choices):
                if self.constant_choices[i] != choice:
                    self.constant_choices[i] = None

10

WaitWhatBot

En rekabetçi bot değil ve kesinlikle GTO değil , ancak böyle bir senaryoda olduğu gibi aynı oyunda herhangi bir "her zaman 1" veya "neredeyse her zaman 1" rakibinin puanını boğacak WaitWhatBot da böyle bir bot haline gelir.

Hem zaman içerisinde (daha yeni -> daha fazla ağırlık) hem de seçim değerinde (daha düşük puan -> daha fazla ağırlık) ağırlıklı ağırlıklarla gelişen olasılıkları kullanır.

Biraz kıkırdamak için biraz karışık kod kullanır.

from random import choices as weightWeight
class WaitWhatBot(object):
    def __init__(wait,what):
        weight,weightWhat=5,2
        wait.what,wait.weight=what,(weight**(weight/weight/weightWhat)+weightWhat/weightWhat)/weightWhat
        wait.whatWeight,wait.weightWeight=[wait.what==wait.weight]*int(wait.weight**weight),wait.weight
        wait.whatWhat=wait.whatWeight.pop()#wait, when we pop weight off whatWeight what weight will pop?
        wait.waitWait=tuple(zip(*enumerate(wait.whatWeight,wait.weightWeight!=wait.whatWeight)))[weightWeight==wait.weight]
    def select(what):return int(what.weight**what.whatWhat if all(not waitWait for waitWait in what.whatWeight)else weightWeight(what.waitWait,what.whatWeight)[what.weight==what.what])
    def update(waitWhat,whatWait):
        what,wait,weightWhat=set(wait for wait in whatWait[:waitWhat.what]+whatWait[waitWhat.what+1:]if wait in waitWhat.waitWait),-~waitWhat.whatWhat,waitWhat.weightWeight
        while wait not in what:
            waitWhat.whatWeight[wait+~waitWhat.whatWhat]+=weightWhat
            weightWhat/=waitWhat.weight
            wait-=~waitWhat.whatWhat
        if not wait!=(what!=weightWhat):waitWhat.whatWeight[waitWhat.whatWhat]+=weightWhat
        waitWhat.weightWeight*=waitWhat.weight

9
WaitWhatBot kilo alırken satın alırsa WaitWhatBot ne kadar ağırlık alırdı?
Roman Odaisky

set ([… için… içinde…]) ≡ {… için… içinde…}, bu arada
Roman Odaisky

@RomanOdaisky Aslında bir golf oynamak için geçen gün birisini öğrendim!
Jonathan Allan,

5

Takipçisi

Oyunun başında, bu bot rastgele hedef olarak belirli bir dizini seçer. Daha sonra, önceki turda seçtiği sayıyı kopyalayarak tüm oyunu hedefler.

import random

class Stalker(object):
  def __init__(self, index):
    # choose a random target to stalk that isn't ourself
    self.targetIndex = random.choice([x for x in range(10) if x != index])
    # get a random number to start with since we haven't seen our target's value yet
    self.targetValue = random.randint(1, 10)
  def select(self):
    return self.targetValue
  def update(self, choices):
    # look at what our target chose last time and do that
    self.targetValue = choices[self.targetIndex]

4

Aptal Açgözlü Bir

class StupidGreedyOne(object):
    def __init__(self, index):
        pass
    def select(self):
        return 1
    def update(self, choices):
        pass

Bu bot diğer botların bağlamak istemediğini varsayar.

Bunun verilen örnekle aynı olduğunu biliyorum, ancak o ana kadar okumadan önce düşündüm. Bu, KoTH zorluklarının nasıl yürüdüğü ile uyuşmuyorsa, bana bildirin.


Genelde yinelenen botlar olmamasını tercih ederim, fakat bırakmayı umursamıyorum.

1
@ Maymonik iyi teknik olarak bir başlangıç ​​değil, çünkü bir dupe değil self.index.
hidefromkgb

@ Anemonic Sorun değil! Dürüst olmak gerekirse, bu benim ilk KoTH'm ve Python'daki ilk şeyim, bu yüzden ilk iki posteri izledim ve sahip olmam gerektiği şüphesine rağmen değiştirmedim. Ayrıca testlerinize Lowball'ı dahil edip etmeyeceğinizden de emin değildim, yoksa bu yazı için sadece bir örnek.
Mühendis Toast,

Telaşa gerek yok. KoTH'nin harika dünyasına hoş geldiniz!


4

HistoryBot

import random

class HistoryBot(object):
    def __init__(self, index):
        self.pastWins = []
    def select(self):
        if not self.pastWins:
            return 1
        return random.choice(self.pastWins)
    def update(self, choices):
        unique = [x for x in choices if choices.count(x) == 1]
        if unique:
            self.pastWins.append(min(unique))

Kullanıcının2390246 yorumunun uygulanması:

Peki ya o zaman? 1 ile başlayın. İlk raunttan sonra, kazanma değerlerini takip edin ve onlardan rastgele birini seçin, ihtimal sayısına eşittir. Örneğin, ilk üç turdaki kazanma değerleri [2, 3, 2], sonra dördüncü turda ise, p2 / 3 ile [2] ve [3] ile p = 1/3 seçin.


4

OneUpper

class OneUpper(object):
    def __init__(self, index):
        self.index = index
    def select(self):
        return 2
    def update(self, choices):
        pass

Diğer herkesin botları ya 1'i hedefliyor ya da rastgele, peki neden sadece 2'yi hedeflemiyorsunuz?


4

Su Gibi Akış

Her sayıyı iki katına çıkararak temel sabit bot algılama algoritmalarından kaçınır, eğer kullanılmazlarsa düşük değerlere doğru yavaşça ilerler.

class Water(object):
    def __init__(self, index):
        self.index = index
        self.round = 0
        self.play = 4
        self.choices = [0]*10

    def select(self):
        if self.round > 0 and self.round%2 == 0:
            if not max([1, self.play - 1]) in self.choices:
                self.play -= 1
        return self.play

    def update(self, choices):
        self.round += 1
        self.choices = choices

Merak ediyorum, botunuz bir şekilde Çeşme ile ilgili mi? Her ikisi de "su yönelimli", haha.
RedClover

Dürüst olmak gerekirse, ilk planım, botun karar alma sürecinde benim motivasyonum olan belirli sayıları iki katına çıkaran sabit bir bot bulmaktı. Görselleştirdiğimde, isme ilham veren, yavaş hareket eden bir akış düşünüyordum. Su temasına rağmen bağırmak :)
TCFP

Yani bu yaptığım her testte 3. veya 4. (genellikle 3.) oluyor. Bu kadar basit bir strateji için oldukça şaşırtıcı.
Robert Fraser

4

Tamamen Kayıp

class TotallyLost(object):
    def __init__(self, index):
        self.index = index
        self.round = 0
        self.numbers = [4,8,1,5,1,6,2,3,4,2]
    def select(self):
        return self.numbers[self.round % len(self.numbers)]
    def update(self, choices):
        self.round = self.round + 1

4

Son gerisayım

class FinalCountdown(object):
    def __init__(self, index):
        self.round = -1
    def select(self):
        self.round += 1
        return (10 - self.round // 100)
    def update(self, choices):
        pass

Çevrimiçi deneyin!

İlk 100 tur için 10, sonraki 100 için 9 döndürür.


4

Opportunitybot

Bu bot, her turda başka bir bot tarafından seçilmeyen en düşük rakamı takip eder (mevcut en düşük rakam veya fırsat) ve bu rakamın en sık olduğu rakamı oynar.

class OpportunityBot(object):
    def __init__(self, index):
        self.index = index
        self.winOccasions = [0,0,0,0,0,0,0,0,0,0]

    def select(self):
        return self.winOccasions.index(max(self.winOccasions))+1

    def update(self, choices):
        choices.pop(self.index)
        succeeded = [choices.count(i)==0 for i in range(1,11)]
        self.winOccasions[succeeded.index(True)] += 1

4

PatterMatcher

Botların gönderimlerindeki bölümleri tekrar ediyor, sayıları tahmin etmeye ve kaçınmaya çalışıyor.

class PatternMatcher(object):
    def __init__(self, index):
        self.bots=[[]]*9
        self.index=index
    def select(self):
        minVisible=3    #increase these if this bot is to slow
        minOccurences=2
        predictions=set()
        for bot in self.bots:     
            #match patters of the form A+(B+C)*minOccurences+B and use C[0] as a prediction      
            for lenB in range(minVisible,len(bot)//(minVisible+1)+1):
                subBot=bot[:-lenB]
                patterns=[] 
                for lenBC in range(lenB,len(subBot)//minOccurences+1):
                    BC=subBot[-lenBC:]
                    for i in range(1,minOccurences):
                        if BC!=subBot[-lenBC*i-lenBC:-lenBC*i]:
                            break
                    else:
                        patterns.append(BC)
                predictions|={pattern[lenB%len(pattern)] for pattern in patterns}
        other=set(range(1,11))-predictions
        if other: return min(other)
        else: return 1                

    def update(self, choices):
        j = 0
        for i,choice in enumerate(choices):
            if i == self.index:
                continue
            self.bots[j].append(choice)
            j += 1

Üçgen

N toplama şansı (10-n)/45

import random
class Triangle(object):
    def __init__(self, index):pass
    def select(self):return random.choice([x for x in range(1, 11) for _ in range(10 - x)])
    def update(self, choices):pass

TimeWeighted

Bir botun seçtiği olasılık, orantılıdır (10-n)*Δt. Bu ilk turda üçgenle aynı.

import random
class TimeWeighted(object):
    def __init__(self, index):
        self.last=[0]*10
        self.round=1 
    def select(self):
        weights=[(self.round-self.last[i])*(10-i) for i in range(10)]
        return 1+random.choice([x for x in range(10) for _ in range(weights[x])])

    def update(self, choices):
        for c in choices:
            self.last[c-1]=self.round
        self.round+=1

LeastFrequent

En az sıklıkta olan sayıyı gönderir, eğer eşitse, en düşük olanı alır.

class LeastFrequent(object):
    def __init__(self, index):self.frequenties=[0]*10
    def select(self):return 1+self.frequenties.index(min(self.frequenties))
    def update(self, choices):
        for c in choices:
            self.frequenties[c-1]+=1

En uzun zaman

Frekanslarda olduğu gibi, ancak başvurular arasında en uzun süreye sahip.

class LongestTime(object):
    def __init__(self, index):
        self.frequencies=[0]*10
        self.round=1
    def select(self):return 1+self.frequencies.index(min(self.frequencies))
    def update(self, choices):
        for c in choices:
            self.frequencies[c-1]=self.round
        self.round+=1

sabotajcı

En son gönderilen en düşük sayıyı gönderir.

class Saboteur(object):
    def __init__(self, index):self.last=[1]
    def select(self):return min(self.last)
    def update(self, choices):self.last=choices

SecondSaboteur

Son kez gönderilen ikinci en düşük numarayı gönderir

class SecondSaboteur(object):
    def __init__(self, index):self.last=[1,2]
    def select(self):return min({i for i in self.last if i!=min(self.last)})
    def update(self, choices):self.last=choices

Profiteur

Son kez gönderilmeyen en düşük sayıyı gönderir

class Profiteur(object):
    def __init__(self, index):self.last=set()
    def select(self):return min(set(range(1, 11))-self.last, default=1)
    def update(self, choices):self.last=set(choices)

Özür dilerim, bir önceki kez uygularken yeni botlar hakkında fikir edindim. Hangisinin en iyi olacağından emin değildim ve her birinin performansını merak ediyorum. Hepsini burada bulabilirsiniz: https://repl.it/@Fejfo/Lowest-Unique-Number


Güzel. Sabote'yi değiştirerek kendi son tercihini görmezden gelmeyi düşünebilirsiniz (bu kasıtlı değilse). Ayrıca, bazı özel durumları ele almanız gerekebileceğini düşünüyorum: Her bot bir turda aynı değeri seçerse SecondSaboteur ne yapmalı ve her bot farklı bir değer seçerse Profiteur ne yapmalı? Sonra Profiteur'da biten bir parantez gerekebilir set(range(10).
Monica

PatternMatcher, bir çeşit sonsuz döngüye veya sıkışıp kaldığı bir yere sahip gibi görünüyor.
Robert Fraser,

3

En iyi% 50 RNG botu

import random

class LowHalfRNG(object):
    def __init__(self, index):
        pass
    def select(self):
        return random.randint(1, 5)
    def update(self, choices):
        pass

Rastgele bir bot göndermek üzereydim, ama hidefromkgb benden önce gönderildi (kendilerini KGB için kolay bir hedef haline getirerek, saklamak için iyi bir yol değil). Bu benim ilk KOTH cevabım, sadece rng botunu yenmeyi umuyorum.


3

Döngüleyici

Bu bot sadece dönüşlerdeki sayıların her biri arasında geçiş yapar. Sadece eğlence için tezgahı indeksiyle başlatır.

class Cycler(object):
  def __init__(self, index):
    self.counter = index # Start the count at our index
  def select(self):
    return self.counter + 1 # Add 1 since we need a number between 1-10
  def update(self, choices):
    self.counter = (self.counter + 1) % 10

3

OneTrackMind

Bu bot rastgele bir sayı seçer ve onunla 50 tur boyunca yapışır, sonra diğerini alır ve tekrarlar.

import random

class OneTrackMind(object):
    def __init__(self, index):
        self.round = 0;
        self.target = random.randint(1,10)
    def select(self):
        return self.target
    def update(self, choices):
        self.round += 1;
        if self.round % 50 == 0:
            self.target = random.randint(1,10)

3

Şanslı yedi

class LuckySeven(object):
    def __init__(self, index):
        pass
    def select(self):
        return 7
    def update(self, choices):
        pass

Bugün kendimi şanslı hissediyorum! Her şeyi 7'de atıyorum!


3

Benim fikrim, stratejinin gerçek stratejilerin değerlendirilmesinden daha çok bot sayısına bağlı olmasıdır.

Önemli sayıda botla, seçenekler şunlardır:

  • Düşük 1-3 sayıyı hedefleyen "açgözlü" robotlar 10 bot "akıllı" ve düşük 1-3 sayılarını almayı hedefleyen, en iyisi bu botların aralarında karışmasına izin vermektir.

  • "Akıllı" robotlar, 4'ün her zaman yakalandığını fark ettiklerinde başka bir yere gidecekler.

  • "Rastgele" ve "sabit" robotlar. Burada yapılacak çok şey yok.

Yani, 4 numaraya bahse girerim.

class LazyStalker(object):
    def __init__(self, index):
        pass
    def select(self):
        return 4
    def update(self, choices):
        pass

2

Temel RNG bot

import secrets

class SecureRNG(object):
    def __init__(self, index):
        pass
    def select(self):
        return secrets.randbelow(10) + 1
    def update(self, choices):
        pass

2

katil

Gölgelerde kalıyor, sonra mevcut en düşük tahmininizi hedefliyor. Koşmak.

class Assassin(object):
    def __init__(self, index):
        self.index = index
        self.round = 0
        self.choices = [0]*10

    def select(self):
        if self.round == 0:
            return 10
        else:
            return min(self.choices)

    def update(self, choices):
        self.round += 1
        self.choices = choices
        self.choices[self.index] = 10

2

FollowBot

Kazananı son raunttan veya en azından asgari düzeyde bağlı olan seçimi, kazanan yoksa kopyalayın.

import collections

class FollowBot(object):
    def __init__(self, index):
        self.lastround = []

    def select(self):
        counter = collections.Counter(self.lastround)
        counts = [(count,value) for (value,count) in counter.items()]
        counts.sort()
        if len(counts) >= 1:
            return counts[0][1]
        else:
            return 1

    def update(self, choices):
        self.lastround = choices

2

psychadelic

Nükleer savaşı kazanmanın tek yolu kendini delirtmek. Bu yüzden turnuvadaki her akıllı bot'u delirteceğim.

class Psychadelic(object):
    def __init__(self, index):
        self.index = index
    def select(self):
        return random.randint(1, self.index + 1)
    def update(self, choices):
        pass

2

UnchosenBot

class UnchosenBot(object):
    def __init__(self, index):
        self.index = index
        self.answer = 0
    def select(self):
        if self.answer == 0:
            return 1
        return self.answer
    def update(self, choices):
        self.answer = 0
        del choices[self.index]
        for x in range(1, 11):
            if x not in choices:
                self.answer = x
                return

Son turun seçimlerini alır ve en düşük seçilmemiş sayıyı seçer (elbette UnchosenBot'un seçimini göz ardı ederek).


2

Boksör-di-kepçe-di-kaka

class WhoopDiScoopDiPoop(object):
    def __init__(self, index):
        self.index = index
        self.guess = 1
        self.tenure = 0
        self.perseverance = 4

    def select(self):
        return self.guess

    def update(self, choices):
        others = {c for i, c in enumerate(choices) if i != self.index}
        for i in range(1, self.guess):
            if i not in others:
                self.guess = i
                self.tenure = 0
                self.perseverance += 1
                return
        if self.guess not in others:
            self.tenure = 0
            return
        self.tenure += 1
        if self.tenure > self.perseverance:
            if self.guess == 10:
                return
            self.guess += 1
            self.tenure = 0

Kaka-di-scoopty

class PoopDiScoopty(object):
    def __init__(self, index):
        self.index = index
        self.guess = 1
        self.tenure = 0
        self.perseverance = 4

    def select(self):
        return self.guess

    def update(self, choices):
        others = [c for i, c in enumerate(choices) if i != self.index]
        for i in range(1, self.guess):
            if i not in others:
                self.guess = i
                self.tenure = 0
                self.perseverance += 1
                return
        if self.guess not in others:
            self.tenure = 0
            return
        self.tenure += others.count(self.guess) # this is the change
        if self.tenure > self.perseverance:
            if self.guess == 10:
                return
            self.guess += 1
            self.tenure = 0

Python'u hiç görmedim veya ona dokunmadım, bu unpythonic mi?


1
<!-- language: lang-python -->Sözdizimi vurgulamasını etkinleştirmek için satırı kod bloğunun önüne ekleyin
Herman L

@HermanL pythonSoru üzerine bir etiket halüsinasyon yaptım ve otomatik olacağını düşünmüştüm ama kötü bir şey yazdım.
Mihail Malostanidis

1
O pythonicer söylemek düşünülebilir hariç pythonicity gelince, kod, oldukça iyi others = [c for i, c in enumerate(choices) if i != self.index]sonradan yalnızca, üyelik testleri için o değişken kullanın çünkü, ya { }ziyade [ ]bir inşa edecek setbir yerine list.
Roman Odaisky

if (self.guess)aynı zamanda çok unpythonic.
Jonathan Frech

self.guessBuradaki parensin oraya nasıl girdiği hakkında hiçbir fikrim yok! Formatlayıcılardan biri olmalı.
Mihail Malostanidis

2

Çeşme

Basit bir bot ilk önce en düşük sayıyı seçer ve eğer başka bir bot da bunu seçerse, sayacı arttırır - zemin doldurulur ve su akar. 11'e ulaştığında, 1'e yeniden başlar - su tekrar tepeye pompalanır.

class Fountain:

    def __init__(self, index, target=10):

        # Set data
        self.index = index
        self.pick  = 1
        self.target = target+1

    def select(self):

        # Select the number
        return self.pick

    def update(self, choices: list):

        # Remove self from the list
        choices.pop(self.index)  # I hope `choices[:]` is passed, not `choices`.

        # While the selected number is occupied
        while self.pick in choices:

            # Pick next number
            self.pick += 1

            # If target was reached
            if self.pick == self.target:

                # Reset to 1
                self.pick = 1

Şu anki haliyle, diğer botlar 1'den 8'e kadar olan tüm sayıları seçtiyse, botunuz süre içinde sıkışıp kalacak target. 10'a ayarlamak mı istediniz ?
Emil,

@Emil Doğru, başlangıçta böyleydi değişti
RedClover

2

PoissonsBot

Poisson dağılımından düşük değerlere bastırılmış sayıları seçin. Dağılımın ortalama parametresini, bağımızın altındaysa tahmin edip, tahmin etmemiz durumunda aşağı yukarı ayarlayın. Oyun ilerledikçe, adım ebadı da giderek küçülür.

from numpy.random import poisson
import math

class PoissonsBot(object):
    def __init__(self, index):
        self.index = index
        self.mean = 2
        self.roundsleft = 1000

    def select(self):
        self.roundsleft = max(self.roundsleft-1, 2)
        return max(min(poisson(self.mean),10),1)

    def update(self, choices):
        myval = choices[self.index]
        nequal = len([c for c in choices if c==myval])
        nless = len([c for c in choices if c<myval])
        step = math.log10(self.roundsleft)
        if nequal > 1:
            self.mean += nequal/step
        self.mean -= nless/step
        self.mean = max(self.mean, 0.3)

2

MinWin

Kazanan değerlerin ve seçilemeyen minimum değerlerin çalışan sayısını tutar (burada minimum seçili değer yalnızca kazanan değerden düşükse dikkate alınır). Bu kazanma ve minimum değerler arasından rastgele seçer.

import random

class MinWin:

    def __init__(self, index):
        self.index = index
        self.mins = list(range(1, 11))
        self.wins = list(range(1, 11))

    def select(self):
        return min(random.choice(self.mins), random.choice(self.wins))

    def update(self, choices):
        counts = [0] * 10
        for x in choices:
            counts[x - 1] += 1

        if 0 in counts and (1 not in counts or counts.index(0) < counts.index(1)):
            self.mins.append(counts.index(0) + 1)
        if 1 in counts:
            self.wins.append(counts.index(1) + 1)

2

PlayerCycle

Oyuncular arasında geçiş yapar. Şu anki oyuncu (kendi kendine olabilir) seçimi şu an bu botun tercihi. 8 numaralı yazdırmayı başlatır, çünkü neden olmasın. Üzgünüm python yapamam, bu muhtemelen kötü kod.

import itertools
class PlayerCycle(object):
    def __init__(self, index):
        self.a = itertools.cycle(range(10))
        self.b = 8
    def select(self):
        return self.b
    def update(self, choices):
        self.b = choices[next(self.a)]

Düzenleme: Kodumu itertools ile geliştirdiğim için Triggernometry sayesinde


Kodunuz gayet iyi çalışıyor ancak otomatik olarak 0-9 arasında geçiş yapması için bir intertools.cycle () ekleyebilirsiniz. Artımlı veya denetlemeniz gerekmez - Çevrimiçi deneyin!
Triggernometry 19:18

2

Rakun

Bir önceki turda seçilmeyen en düşük sayıyı seçin, bu sefer tekrar seçilebilecek kendi önceki seçeneğimiz hariç. İlk turda 1'i seçin. (9 rakip ve 10 seçenek verildiğinde, bir tek değer olması garanti edilir.)

Bağımsız olarak bununla geldim, ancak şimdi aslında aynı olan en az 2 eski bot görüyorum.

class Raccoon(object):
    def __init__(self, index):
        self.index = index
        self.last_round = None
        self.domain = None
    def select(self):
        # Return the lowest number not chosen last time.
        if self.domain is None:
            return 1
        else:
            # This finds the smallest element of domain, not present in last_round
            return min(self.domain-self.last_round)
    def update(self, choices):
        last_round = choices[:]
        last_round[self.index] = 0 # don't include our own choice
        self.last_round = set(last_round)
        if self.domain is None:
            self.domain = set(range(1,len(choices)+1))

Rakun Üçgeni

Raccoon ve Triangle'ı birleştirir: seçili olmayan değerlerden ters üçgen olasılığına göre birini seçin.

import random
class RaccoonTriangle(object):
    def __init__(self, index):
        self.index = index
        self.unchosen = set([1,])
        self.domain = None
    def select(self):
        # Return the lowest number not chosen last time.
        if self.domain is None:
            return random.randint(1,self.index+1)
        else:
            # Reverse triangle weights for unchosen values
            weighted_choices = [u for i,u in enumerate(sorted(self.unchosen),0) for _ in range(len(self.unchosen)-i)]
            return random.choice(weighted_choices)
    def update(self, choices):
        last_round = choices[:] # make a copy
        last_round[self.index] = 0 # don't include our own choice
        if self.domain is None:
            self.domain = set(range(1,len(choices)+1))
        self.unchosen = self.domain - set(last_round)

Hata:AttributeError: 'RaccoonTriangle' object has no attribute 'boundaries'
Renzeee 25:18

1
Evet üzgünüm. Sanırım tamir ettim. Ayrıldığımda sınavların ortasındaydım.
Quantum Mechanic

1

Genel

Genel hep son savaşı verecektir (ler) .

import numpy
import random

class TheGeneral:
    def __init__(self, index):
        self.round = 0
        self.index = index
        self.would_have_won = [0] * 10

    def select(self):
        if self.round <= 100:
            return random.choice((list(numpy.nonzero(self.would_have_won)[0]) + [0, 1])[:2]) + 1

        return random.choice(numpy.argsort(self.would_have_won)[-2:]) + 1

    def update(self, choices):
        for i, s in enumerate(numpy.bincount([c - 1 for i, c in enumerate(choices)
            if i != self.index], minlength=10)):

            if s == 0:
                self.would_have_won[i] += 1
            elif s == 1:
                break

        self.round += 1

1

No-Tekrar Rasgele

import secrets

class NoRepeats(object):
    def __init__(self, index):
        self.lastround = secrets.randbelow(10) + 1

    def select(self):
        i = secrets.randbelow(10) + 1
        while i == self.lastround:
             i = secrets.randbelow(10) + 1
        self.lastround = i
        return self.lastround

    def update(self, choices):
        pass

Bot rastgele seçiyor, ancak önceki tura yaptığı sayıyı seçmektan kaçınıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.