सबसे छोटी अनोखी संख्या KoTH


27

सबसे छोटी अद्वितीय संख्या चुनने के लिए एक बॉट बनाएं।

(एक मनोविज्ञान प्रयोग के आधार पर मैंने कई साल पहले सुना था लेकिन फिर से ट्रैक नहीं कर पाया।)

नियम

  • प्रत्येक गेम में 1000 राउंड खेलने वाले 10 बेतरतीब ढंग से चयनित बॉट शामिल होंगे।
  • प्रत्येक दौर, सभी बॉट 1 से 10 (समावेशी) से पूर्णांक का चयन करते हैं। समान मूल्य चुनने वाले किसी भी बॉट को बाहर रखा जाएगा, और सबसे छोटे मूल्य वाले शेष बॉट को एक बिंदु प्राप्त होगा।
  • इस घटना में कि कोई बॉट अद्वितीय मूल्य नहीं उठाता है, कोई अंक नहीं दिया जाएगा।
  • 1000 राउंड के अंत में, सबसे अधिक अंक (या सभी बिंदुओं से बंधे सभी बॉट) वाले बॉट गेम जीतते हैं।
  • टूर्नामेंट 200 * (खिलाड़ियों की संख्या) खेलों में चलेगा।
  • सबसे अधिक जीत प्रतिशत वाला बॉट टूर्नामेंट जीतता है।

विशेष विवरण

बॉट्स को पायथन 3 वर्ग होना चाहिए और दो तरीकों को लागू करना चाहिए: selectऔर update
एक इंडेक्स के साथ बॉट्स का निर्माण किया जाएगा।
selectकोई तर्क नहीं दिया गया है और मौजूदा दौर के लिए बॉट की पसंद को लौटाता है।
updateपिछले दौर में प्रत्येक बॉट द्वारा किए गए विकल्पों की एक सूची दी गई है।

उदाहरण

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

नियंत्रक

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

अतिरिक्त जानकारी

  • कोई भी बॉट अपने खिलाफ खेल में नहीं खेलेगा।
  • इस घटना की संभावना नहीं है कि एक बॉट 100 से कम खेलों में शामिल है, टूर्नामेंट फिर से खेला जाएगा।
  • बॉट्स राउंड के बीच स्टेट स्टोर कर सकते हैं, लेकिन गेम्स के बीच नहीं।
  • नियंत्रक या अन्य बॉट्स तक पहुंचने की अनुमति नहीं है।
  • यदि परिणाम बहुत अधिक परिवर्तनशील हैं तो गेम की संख्या और प्रति गेम राउंड की संख्या बढ़ सकती है।
  • कोई भी बॉट जो त्रुटियां उठाता है या अमान्य प्रतिक्रियाएं देता है (गैर-इन्ट्स, [1, 10], इत्यादि के बाहर के मान)) को अयोग्य घोषित किया जाएगा, और टूर्नामेंट उनके बिना फिर से शुरू हो जाएगा।
  • राउंड के लिए कोई समय सीमा नहीं है, लेकिन मैं एक को लागू कर सकता हूं यदि बॉट्स को सोचने में बहुत लंबा समय लगता है।
  • प्रति उपयोगकर्ता सबमिशन की संख्या पर कोई सीमा नहीं है।
  • सबमिशन की समय सीमा शुक्रवार, 28 सितंबर को 23:59:59 यूटीसी है । टूर्नामेंट अब सबमिशन के लिए बंद है।

परिणाम

                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
@ मेनोनिक कोई खबर?
user1502040

4
@ हिरोहटार मैं काम से पहले निकलने से पहले इसे चलाता था। किसी भी भाग्य के साथ, यह तब होना चाहिए जब मुझे घर मिल जाए।

1
@ मेनोमोनिक क्या यह अभी तक समाप्त हो गया है?
user1502040

2
@ जस्टिन यह अभी चल रहा है, और दुर्घटनाग्रस्त प्रतीत नहीं होता है, लेकिन अगर यह रन विफल होता है, तो मैं निश्चित रूप से मदद को बुरा नहीं मानूंगा।

1
@MihailMalostanidis एक bots.pyही डायरेक्टरी में एक फाइल बनाते हैं जिसमें सभी बॉट्स होते हैं। अंत में, कंस्ट्रक्टरों की एक सूची बनाएं:allBotConstructors = [Lowball, BayesBot, ...]

जवाबों:


10

BayesBot

एक साधारण सांख्यिकीय मॉडल का उपयोग करके इष्टतम विकल्प बनाने की कोशिश करता है।

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

लगातार बॉट से बचें

ध्यान रखें कि किन बॉट्स ने हमेशा समान मान लौटाया है, और उन मानों को छोड़ दें। शेष मूल्यों में से, उन्हें यादृच्छिक रूप से चुनें, लेकिन कम मूल्यों के प्रति काफी पक्षपाती।

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

सबसे अधिक प्रतिस्पर्धी बॉट नहीं और निश्चित रूप से जीटीओ नहीं है , लेकिन किसी भी खेल में किसी भी "हमेशा 1" या "लगभग हमेशा 1" प्रतिद्वंद्वी के स्कोर को रोक दिया जाएगा क्योंकि इस तरह के वेटवॉटबॉट भी ऐसे ही एक बॉट बन जाता है।

समय (अधिक हाल ही में -> अधिक वजन) और पसंद मूल्य (कम बिंदु -> अधिक वजन) दोनों में भारित भार के साथ संभावित संभावनाओं का उपयोग करता है।

एक बिट के लिए कुछ अस्पष्ट कोड का उपयोग करता है।

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 ने कितना वजन खरीदा होगा, अगर WaitWhatBot वजन कम करेगा, लेकिन क्या होगा?
रोमन ओडिसी

सेट ([… में… के लिए]) for {… के लिए… में}}, वैसे
रोमन Odaisky

@ रोमेनोस्की मुझे वास्तव में किसी और ने सलाह दी थी कि एक गोल्फ के लिए दूसरे दिन!
जोनाथन एलन

5

स्टॉकर

खेल की शुरुआत में, यह बोट बेतरतीब ढंग से अपने लक्ष्य के रूप में एक विशिष्ट सूचकांक चुनता है। यह तब पूरे खेल को लक्षित करता है, जो उस संख्या को कॉपी करता है जिसे उसने पिछले दौर में चुना था।

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

मूर्ख लालची एक

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

यह बॉट मानता है कि अन्य बॉट्स टाई नहीं करना चाहते हैं।

मुझे लगता है कि यह प्रदान किए गए उदाहरण के समान है, लेकिन मैंने सोचा था कि इससे पहले कि मैं इसे पढ़ूं। अगर यह कोथ चुनौतियों के साथ कैसे चल रहा है, तो मुझे बताएं।


सामान्य तौर पर मैं डुप्लिकेट बॉट्स नहीं करना पसंद करता हूं, लेकिन मुझे इसे छोड़ने में कोई आपत्ति नहीं है।

1
@Memonic अच्छी तरह से तकनीकी रूप से यह एक डुबकी नहीं है, क्योंकि यह प्रारंभ नहीं करता है self.index
Hidefromkgb

@ मेनोनिक कोई समस्या नहीं! ईमानदारी से, यह मेरी पहली KoTH और पायथन में मेरी पहली कुछ भी है इसलिए मैंने पहले दो पोस्टरों का पालन किया और अपने संदेह के बावजूद इसे नहीं बदला जो मुझे होना चाहिए था। मुझे भी यकीन नहीं था कि आप अपने परीक्षणों में लोबॉल को शामिल करने जा रहे हैं या यह वास्तव में पोस्ट के लिए केवल एक उदाहरण था।
इंजीनियर टोस्ट

कोई चिंता नहीं। KoTH की अद्भुत दुनिया में आपका स्वागत है!

2
आपने एक "ऐस ग्रेनेड": puzzling.stackexchange.com/questions/45299/…
kaine

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

User2390246 की टिप्पणी का कार्यान्वयन:

फिर इस बारे में क्या? 1 के साथ शुरू करो। पहले दौर के बाद, जीतने वाले मूल्यों पर नज़र रखें और घटनाओं की संख्या के बराबर संभावना के साथ यादृच्छिक रूप से उन्हें चुनें। उदाहरण के लिए, यदि पहले तीन राउंड में जीतने वाले मान [2, 3, 2] हैं, तो राउंड फोर में, पी = 1/3 के साथ p = 2/3 और [3] के साथ [2] चुनें।


4

OneUpper

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

हर किसी के बॉट्स या तो 1 या यादृच्छिक के लिए लक्ष्य कर रहे हैं, तो सिर्फ 2 के लिए क्यों नहीं?


4

पानी की तरह बहना

बुनियादी निरंतर बॉट डिटेक्शन एल्गोरिदम को प्रत्येक संख्या पर दोगुना करने से बचाते हैं, यदि वे कम नहीं हैं तो धीरे-धीरे कम मूल्यों की ओर अग्रसर होते हैं।

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

मैं उत्सुक हूं, क्या आपका बॉट किसी तरह मेरे फाउंटेन से संबंधित है ? दोनों "जल-उन्मुख" हैं, हाहा।
RedClover

ईमानदारी से, मेरी प्रारंभिक योजना एक निश्चित अनुमान बॉट बनाने की थी, जिसमें कुछ संख्याओं का दोहरा अनुमान लगाया गया था, जो कि बॉट के निर्णय प्रक्रिया के लिए मेरी प्रेरणा थी। जब मैंने इसकी कल्पना की, मैं एक धीमी गति से चलती धारा के बारे में सोच रहा था, जिसने नाम को प्रेरित किया। हालांकि पानी विषय के लिए चिल्लाओ :)
TCFP

इसलिए यह मेरे द्वारा चलाए जाने वाले हर टेस्ट में 3rd या 4th (आमतौर पर 3rd) हो रहा है। ऐसी सरल रणनीति के लिए यह बहुत आश्चर्यजनक है।
रॉबर्ट फ्रेजर

4

पूरी तरह से खो दिया है

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

उलटी गिनती

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

इसे ऑनलाइन आज़माएं!

पहले 100 राउंड के लिए 10, अगले 100 के लिए 9 वगैरह।


4

Opportunitybot

यह बॉट प्रत्येक राउंड (सबसे कम उपलब्ध संख्या, या अवसर) द्वारा किसी अन्य बॉट्स द्वारा नहीं चुने गए सबसे कम संख्या का ट्रैक रखता है, और उस संख्या को निभाता है जो उस संख्या को सबसे अधिक बार किया गया है।

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

बॉट्स के सबमिशन में वर्गों को दोहराने के लिए लगता है, भविष्यवाणी करने और वहाँ संख्या से बचने की कोशिश करता है।

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

त्रिभुज

N लेने का मौका है (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

एक बॉट चुनता संभावना एक संख्या के लिए आनुपातिक है (10-n)*Δt। यह पहला दौर त्रिभुज के समान है।

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

कम से कम अक्सर होने वाली संख्या को प्रस्तुत करता है, यदि वे समान हैं, तो सबसे कम एक लें।

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

सबसे लंबा समय

समानताओं के साथ लेकिन सबमिशन के बीच सबसे लंबे समय के साथ।

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

नुक़सान पहुंचानेवाला

पिछली बार प्रस्तुत की गई सबसे कम संख्या को प्रस्तुत करता है।

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

दूसरी सबसे कम संख्या को जमा करता है जो पिछली बार प्रस्तुत किया गया था

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

पिछली बार जमा नहीं की गई सबसे कम संख्या को प्रस्तुत करता है

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)

क्षमा करें, मैं थोड़ा हट गया, पिछले एक बार को लागू करते समय नए बॉट के लिए विचार प्राप्त कर रहा था। मुझे यकीन नहीं था कि कौन सा सबसे अच्छा होगा और मैं उनमें से प्रत्येक के प्रदर्शन के बारे में उत्सुक हूं। आप उन सभी को यहां पा सकते हैं: https://repl.it/@Fejfo/Lowest-Unique-Number


अच्छा लगा। आप सबोटूर को संशोधित करने पर विचार कर सकते हैं ताकि वह अपनी अंतिम पसंद को अनदेखा कर सके (जब तक कि वह जानबूझकर न हो)। इसके अलावा, मुझे लगता है कि आपको कुछ विशेष मामलों को संभालने की आवश्यकता हो सकती है: यदि प्रत्येक बॉट किसी राउंड में समान मूल्य चुनता है, तो सेकंडबोटूर को क्या करना चाहिए, और अगर प्रत्येक बॉट एक अलग मूल्य चुनता है, तो प्रोफिटुर को क्या करना चाहिए? प्रोफिटुर के बाद आपको एक अंतिम कोष्ठक की आवश्यकता हो सकती है set(range(10)
मोनिका

PatternMatcher के पास अनंत लूप या उस स्थान के कुछ प्रकार दिखाई देते हैं जहाँ वह फंस जाता है।
रॉबर्ट फ्रेजर

3

शीर्ष 50% RNG बॉट

import random

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

मैं एक रैंडम बॉट पोस्ट करने वाला था, लेकिन मेरे सामने पोस्ट किया गया Hidefromkgb (पोस्ट करके वे खुद को केजीबी के लिए आसान लक्ष्य बना रहे हैं, छिपाने का अच्छा तरीका नहीं)। यह मेरा पहला KOTH जवाब है, जो कि रिंग बॉट को हराने की उम्मीद कर रहा है।


3

द साइक्लर

यह बॉट अपने नंबरों पर प्रत्येक संख्या के माध्यम से साइकिल चलाता है। सिर्फ मनोरंजन के लिए, यह अपने सूचकांक के साथ काउंटर को इनिशियलाइज़ करता है।

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

एक रास्ते पर दिमाग

यह बॉट बेतरतीब ढंग से एक नंबर चुनता है और उसके साथ 50 चक्कर लगाता है, फिर दूसरा उठाता है और दोहराता है।

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

सौभाग्यशाली सात

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

मैं आज भाग्यशाली महसूस कर रहा हूँ! मैं 7 पर सब कुछ बाहर फेंक रहा हूँ!


3

मेरा विचार है कि रणनीति रणनीतियों के वास्तविक मूल्यांकन की तुलना में बॉट की संख्या पर अधिक निर्भर है।

बॉट की एक महत्वपूर्ण संख्या के साथ, विकल्प हैं:

  • "लालची" रोबोट कम 1-3 संख्या वाले 10 बॉट को "चतुर" होने का लक्ष्य देते हैं और कम 1-3 संख्या प्राप्त करने का लक्ष्य रखते हैं, सबसे अच्छा यह है कि उन बॉट्स को उनके बीच हस्तक्षेप करने दें।

  • "स्मार्ट" रोबोट, जो 4 बार महसूस करने के बाद हमेशा उठाए जाते हैं, कहीं और जाएंगे।

  • "यादृच्छिक" और "निरंतर" रोबोट। यहां ज्यादा कुछ नहीं करना है।

इसलिए, मैंने # 4 पर दांव लगाया।

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

2

आवश्यक RNG बॉट

import secrets

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

2

हत्यारा

छाया में रहता है, तो वर्तमान न्यूनतम अनुमान का लक्ष्य रखता है। चलाएँ।

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

यदि कोई विजेता नहीं था, तो अंतिम राउंड से विजेता को कॉपी करें, या कम से कम सबसे कम-से-कम चुने गए।

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

परमाणु युद्ध जीतने का एकमात्र तरीका खुद को पागल बनाना है। इसलिए मैं टूर्नामेंट के पागल होने की हर भविष्यवाणी करने वाला हूं।

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

अंतिम राउंड के विकल्प लेता है, और सबसे कम अनचेंस्ड नंबर चुनता है (अनचेनबॉट की पसंद को अनदेखा करना, बिल्कुल)।


2

Whoop-डाई-स्कूप-डाई-पूप

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

पूप-डाई-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

मैंने पायथन को कभी नहीं देखा या छुआ है, क्या यह अस्वस्थ है?


1
<!-- language: lang-python -->वाक्यविन्यास हाइलाइटिंग को सक्षम करने के लिए कोड ब्लॉक से पहले लाइन जोड़ें
हरमन एल

@HermanL मैंने pythonसवाल पर एक टैग मंगाया और सोचा कि यह स्वचालित होगा लेकिन मैंने कुछ बुरा लिखा।
मिहेल मलोस्तानिडिस

1
पाइथोनिकिटी के लिए, कोड काफी अच्छा है, सिवाय इसके कि इसे कहने के लिए पायथोनिकर माना जा सकता है others = [c for i, c in enumerate(choices) if i != self.index], या, क्योंकि बाद में आप केवल सदस्यता परीक्षणों के लिए उस चर का उपयोग करते हैं, { }बजाय [ ]एक के setबजाय निर्माण करेंगे list
रोमन ओडिसी

if (self.guess)बहुत ही बेकार है।
जोनाथन फ्रीच

मुझे कोई अंदाजा नहीं है कि आसपास के लोग कैसे self.guessवहां पहुंच गए! फॉर्मेटर्स में से एक रहा होगा।
मिहेल मलोस्तानिडिस

2

झरना

एक साधारण बॉट, सबसे पहले सबसे कम संख्या को चुनता है और अगर कोई अन्य बॉट इसे चुनता है, तो यह काउंटर को बढ़ाएगा - फर्श भर जाता है और पानी नीचे बह जाता है। जब यह 11 तक पहुंचता है, तो यह 1 से शुरू होता है - पानी वापस शीर्ष पर पंप हो जाता है।

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

यदि आपके बॉट ने 1 से 8 तक की सभी संख्याओं को चुना है, तो क्या आप target10 से सेट करना चाहते हैं?
एमिल

@ ईमिल सच, यह मूल रूप से ऐसा था, बदल गया
RedClover

2

PoissonsBot

एक पॉइसन वितरण से संख्या का चयन करें जो कम मूल्यों के पक्षपाती है। यदि हम नीचे अनुमान लगाते हैं तो वितरण के माध्य पैरामीटर को समायोजित करें यदि हम एक टाई और नीचे हैं। खेल के बढ़ने के साथ ही कदम का आकार बहुत छोटा हो जाता है।

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

जीतने वाले मूल्यों और न्यूनतम अचयनित मूल्यों (जहां न्यूनतम अचयनित मूल्य को केवल तभी माना जाता है, यदि यह जीतने वाले मूल्य से कम है) की एक चलती हुई गिनती रखता है। यह इन जीत और न्यूनतम मूल्यों के बीच बेतरतीब ढंग से चयन करता है।

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

खिलाड़ियों के माध्यम से साइकिल। वर्तमान खिलाड़ी (स्वयं हो सकता है) की पसंद अब इस बॉट की पसंद है। 8 की छपाई शुरू करता है, क्योंकि क्यों नहीं। क्षमा करें, मैं अजगर नहीं कर सकता, यह शायद बुरा कोड है।

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

संपादित करें: Itertools के साथ अपने कोड में सुधार के लिए Triggernometry के लिए धन्यवाद


आपका कोड ठीक काम करता है, लेकिन आप एक इंटरट्यूलेस साइकिल () जोड़ सकते हैं ताकि यह स्वचालित रूप से 0-9 के माध्यम से चक्रित हो जाए और आपको वेतन वृद्धि या चेक करने की आवश्यकता न हो - इसे ऑनलाइन आज़माएं!
त्रिगुटर्नोमेट्री

2

एक प्रकार का जानवर

पिछले राउंड में नहीं चुनी गई सबसे कम संख्या को चुनें, हमारी अपनी पिछली पसंद को छोड़कर, जिसे इस बार फिर से चुना जा सके। पहले दौर में, 1. चुनें (9 विरोधियों और 10 विकल्पों को देखते हुए, एक उपलब्ध मूल्य होने की गारंटी है।)

मैं इसके साथ स्वतंत्र रूप से आया था, लेकिन अब कम से कम 2 पिछले बॉट देखें जो अनिवार्य रूप से समान हैं।

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

रैकोन त्रिभुज

रेसकोन और ट्राइएंगल को जोड़ती है: अनचाहे मूल्यों से, रिवर्स त्रिकोण संभावना के आधार पर एक चुनें।

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)

त्रुटि:AttributeError: 'RaccoonTriangle' object has no attribute 'boundaries'
Renzeee

1
हाँ क्षमा करें। मुझे लगता है कि मैंने इसे ठीक कर लिया। मैं लिखने के परीक्षण के बीच में था, जब मैंने छोड़ दिया।
क्वांटम मैकेनिक

1

सामान्य

जनरल हमेशा पिछले युद्ध लड़ता है (रों)

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

नहीं-दोहराए रैंडम

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

बीओटी बेतरतीब ढंग से चुनता है, लेकिन उसी संख्या को लेने से बचा जाता है जो उसने पिछले दौर में किया था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.