Số nhỏ nhất duy nhất KoTH


27

Tạo một bot để chọn số duy nhất nhỏ nhất.

(Dựa trên một thí nghiệm tâm lý học mà tôi đã nghe về nhiều năm trước nhưng không thể theo dõi lại được.)

Quy tắc

  • Mỗi trò chơi sẽ bao gồm 10 bot được chọn ngẫu nhiên chơi 1000 vòng.
  • Mỗi vòng, tất cả các bot chọn một số nguyên từ 1 đến 10 (đã bao gồm). Bất kỳ bot nào chọn cùng một giá trị sẽ bị loại trừ và bot còn lại có giá trị nhỏ nhất sẽ nhận được điểm.
  • Trong trường hợp không có bot chọn một giá trị duy nhất, sẽ không có điểm nào được trao.
  • Kết thúc 1000 vòng, bot có nhiều điểm nhất (hoặc tất cả các bot được gắn nhiều điểm nhất) sẽ thắng trò chơi.
  • Giải đấu sẽ kéo dài 200 * (số lượng người chơi) trò chơi.
  • Bot có tỷ lệ thắng cao nhất sẽ thắng giải đấu.

Thông số kỹ thuật

Bots phải là lớp Python 3 và phải thực hiện hai phương thức: selectupdate.
Bots sẽ được xây dựng với một chỉ mục.
selectđược thông qua không có đối số và trả về lựa chọn của bot cho vòng hiện tại.
updateđược thông qua một danh sách các lựa chọn được thực hiện bởi mỗi bot trong vòng trước.

Thí dụ

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

Bộ điều khiển

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

Thông tin thêm

  • Không có bot sẽ chơi trong một trò chơi chống lại chính nó.
  • Trong trường hợp không thể có bot được bao gồm trong ít hơn 100 trò chơi, giải đấu sẽ được chạy lại.
  • Bots có thể lưu trữ trạng thái giữa các vòng, nhưng không phải giữa các trò chơi.
  • Truy cập bộ điều khiển hoặc các bot khác không được phép.
  • Số lượng trò chơi và số vòng cho mỗi trò chơi có thể tăng nếu kết quả quá thay đổi.
  • Bất kỳ bot nào gây ra lỗi hoặc đưa ra phản hồi không hợp lệ (không phải int, giá trị bên ngoài [1, 10], v.v.) sẽ bị loại và giải đấu sẽ được chạy lại mà không có chúng.
  • Không có giới hạn thời gian cho các vòng, nhưng tôi có thể thực hiện một vòng nếu các bot mất quá nhiều thời gian để suy nghĩ.
  • Không có giới hạn về số lượng gửi cho mỗi người dùng.
  • Hạn chót để gửi là 23:59:59 UTC vào thứ Sáu, ngày 28 tháng 9. Giải đấu hiện đã đóng cửa để gửi.

Các kết quả

                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 Có tin gì không?
user1502040

4
@Herohtar Tôi cài đặt nó chạy trước khi tôi đi làm. Với bất kỳ may mắn, nó nên được thực hiện khi tôi về nhà.

1
@Mnemonic Đã xong chưa?
user1502040

2
@Justin Nó đang chạy ngay bây giờ và dường như không gặp sự cố, nhưng tôi chắc chắn sẽ không quan tâm đến sự giúp đỡ nếu lần chạy này thất bại.

1
@MihailMalostanidis Tạo một tệp được gọi bots.pytrong cùng thư mục chứa tất cả các bot. Cuối cùng, tạo một danh sách các hàm tạo:allBotConstructors = [Lowball, BayesBot, ...]

Câu trả lời:


10

Bayes

Cố gắng đưa ra lựa chọn tối ưu bằng mô hình thống kê đơn giản.

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

Tránh Bots liên tục

Theo dõi những bot nào luôn trả về cùng một giá trị và bỏ qua các giá trị đó. Trong số các giá trị còn lại, chọn chúng ngẫu nhiên, nhưng thiên về đáng kể đối với các giá trị thấp hơn.

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

Chờ đợi

Không phải bot cạnh tranh nhất và chắc chắn không phải GTO , nhưng sẽ bóp nghẹt điểm số của bất kỳ đối thủ "luôn luôn 1" hoặc "gần như luôn luôn 1" trong cùng một trò chơi như trong kịch bản như vậy WaitWhatBot cũng trở thành một bot như vậy.

Sử dụng xác suất phát triển với trọng số có trọng số cả về thời gian (gần đây hơn -> trọng lượng lớn hơn) và giá trị lựa chọn (điểm thấp hơn -> trọng lượng lớn hơn).

Sử dụng mã hơi khó hiểu cho một chút cười khúc khích.

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 đã mua bao nhiêu cân, nếu WaitWhatBot sẽ mua trọng lượng?
Roman Odaisky

bằng cách này ([cho trò chơi trong trò chơi ở]] ≡ {khắc cho trò chơi trong trò chơi}, nhân tiện
Roman Odaisky

@RomanOdaisky Tôi thực sự đã khuyên ai đó về điều đó chỉ một ngày khác cho một sân golf!
Jonathan Allan

5

Kẻ theo dõi

Khi bắt đầu trò chơi, bot này chọn ngẫu nhiên một chỉ số cụ thể làm mục tiêu. Sau đó, nó rình rập nhắm mục tiêu toàn bộ trò chơi, sao chép số mà nó đã chọn trong vòng trước.

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

Kẻ tham lam ngu ngốc

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

Bot này giả định rằng các bot khác không muốn ràng buộc.

Tôi nhận ra đây giống như ví dụ được cung cấp nhưng tôi đã có suy nghĩ trước khi đọc đến đó. Nếu điều này không phù hợp với cách các thử thách KoTH được thực hiện, hãy cho tôi biết.


Nói chung, tôi không muốn có các bot trùng lặp, nhưng tôi không ngại để nó.

1
@Mnemonic kỹ thuật tốt, nó không phải là một bản sao, vì nó không khởi tạo self.index.
Hidefromkgb

@Mnemonic Không có vấn đề! Thành thật mà nói, đây là KoTH đầu tiên của tôi bất cứ thứ gì đầu tiên của tôi trong Python vì vậy tôi chỉ theo dõi hai poster đầu tiên và không thay đổi nó mặc dù tôi nghi ngờ rằng tôi nên có. Tôi cũng không chắc chắn nếu bạn định đưa Lowball vào bài kiểm tra của mình hay nó thực sự chỉ là một ví dụ cho bài viết.
Kỹ sư Toast

Đừng lo lắng. Chào mừng đến với thế giới tuyệt vời của KoTH!

2
Bạn là một "lựu đạn ace": puzzling.stackexchange.com/questions/45299/
mẹo

4

Lịch sửBot

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

Triển khai bình luận của người dùng2390246:

Thế còn cái này thì sao? Bắt đầu với 1. Sau vòng đầu tiên, hãy theo dõi các giá trị chiến thắng và chọn ngẫu nhiên từ chúng với xác suất bằng số lần xuất hiện. Ví dụ: nếu các giá trị chiến thắng trong ba vòng đầu tiên là [2, 3, 2] thì ở vòng bốn, chọn [2] với p = 2/3 và [3] với p = 1/3.


4

OneUpper

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

Các bot của mọi người khác đều nhắm đến 1 hoặc ngẫu nhiên, vậy tại sao không chỉ nhắm đến 2?


4

Chảy như nước

Tránh các thuật toán phát hiện bot liên tục cơ bản bằng cách nhân đôi trên mỗi số, từ từ tiến tới các giá trị thấp hơn nếu chúng không được sử dụng.

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

Tôi tò mò, bot của bạn bằng cách nào đó có liên quan đến Đài phun nước của tôi ? Cả hai đều "hướng nước", haha.
RedClover

Thành thật mà nói, kế hoạch ban đầu của tôi là tạo ra một bot đoán cố định, nhân đôi số lượng nhất định, đó là động lực của tôi cho quá trình ra quyết định của bot. Khi tôi hình dung ra nó, tôi đã nghĩ về một dòng chuyển động chậm, lấy cảm hứng từ cái tên. Tuy nhiên
hãy hét

Vì vậy, điều này nhận được thứ 3 hoặc thứ 4 (thường là thứ 3) trong mỗi bài kiểm tra tôi chạy. Đó là khá tuyệt vời cho một chiến lược đơn giản như vậy.
Robert Fraser

4

Mất tất cả

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

Đếm ngược cuối cùng

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

Hãy thử trực tuyến!

Trả về 10 cho 100 vòng đầu tiên, 9 cho 100 vòng tiếp theo, v.v.


4

Cơ hội

Bot này theo dõi số thấp nhất không được chọn bởi bất kỳ bot nào khác trong mỗi vòng (số có sẵn hoặc cơ hội thấp nhất) và chơi số đó là số thường xuyên nhất.

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

Tìm kiếm để lặp lại các phần trong đệ trình của các bot, cố gắng dự đoán và tránh có số.

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

Tam giác

Cơ hội chọn n là (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

Nhìn xa

Xác suất một bot chọn một số tỷ lệ thuận với (10-n)*Δt. Vòng đầu tiên này giống hệt hình tam giác.

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

Ít nhất

Gửi số ít xảy ra nhất, nếu chúng bằng nhau, lấy số thấp nhất.

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

Thời gian dài nhất

Tương tự như với thường xuyên nhưng với thời gian dài nhất giữa các lần gửi.

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

Saboteur

Gửi số thấp nhất đã được gửi lần trước.

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

Thứ hai

Gửi số thấp thứ hai được gửi lần trước

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

Gửi số thấp nhất không được gửi lần trước

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)

Xin lỗi tôi đã mang đi một chút, lấy ý tưởng cho các bot mới trong khi thực hiện trước đó một lần. Tôi không chắc ai sẽ là người giỏi nhất và tôi tò mò về hiệu suất của từng người trong số họ. Bạn có thể tìm thấy tất cả chúng ở đây: https://repl.it/@Fejfo/Lowest-Unique-Number


Tốt đẹp. Bạn có thể cân nhắc sửa đổi Saboteur để bỏ qua lựa chọn cuối cùng của chính nó (trừ khi đó là cố ý). Ngoài ra, tôi nghĩ rằng bạn có thể cần phải xử lý một số trường hợp đặc biệt: SecondSaboteur nên làm gì nếu mỗi bot chọn cùng một giá trị trong một số vòng và Profiteur nên làm gì nếu mỗi bot chọn một giá trị khác nhau? Bạn có thể cần một dấu ngoặc đơn kết thúc trong Profiteur sau set(range(10).
Phục hồi Monica

PatternMatcher dường như có một số vòng lặp vô hạn hoặc nơi mà nó bị kẹt.
Robert Fraser

3

Bot RNG 50% hàng đầu

import random

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

Tôi đã định đăng một bot ngẫu nhiên, nhưng Hidefromkgb đã đăng trước tôi (bằng cách đăng chúng đang tự biến mình thành mục tiêu dễ dàng cho KGB, không phải là một cách hay để ẩn). Đây là câu trả lời KOTH đầu tiên của tôi, chỉ hy vọng đánh bại bot rng.


3

Người đi xe đạp

Bot này chỉ đơn giản là quay vòng qua từng con số trong lượt của nó. Chỉ để cho vui, nó khởi tạo bộ đếm với chỉ mục của nó.

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

Bot này chọn ngẫu nhiên một số và gắn bó với nó trong 50 vòng, sau đó chọn một số khác và lặp lại.

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

Số bảy may mắn

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

Hôm nay tôi cảm thấy may mắn! Tôi đang ném ra tất cả mọi thứ trên 7!


3

Ý tưởng của tôi là chiến lược phụ thuộc nhiều vào số lượng bot hơn là đánh giá thực tế các chiến lược.

Với số lượng bot đáng kể, các tùy chọn là:

  • Các robot "tham lam" nhắm đến các số 1-3 thấp hơn 10 bot là "thông minh" và nhằm mục đích lấy các số 1-3 thấp hơn, tốt nhất là chỉ để các bot đó can thiệp vào giữa chúng.

  • Những robot "thông minh", một khi chúng nhận ra 4 luôn được chọn, sẽ đi nơi khác.

  • Robot "ngẫu nhiên" và "không đổi". Không có nhiều để làm ở đây.

Vì vậy, tôi đặt cược vào số 4.

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

2

Bot RNG thiết yếu

import secrets

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

2

Kẻ ám sát

Nằm trong bóng tối, sau đó nhắm đến dự đoán thấp nhất hiện tại. Chạy.

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

Theo dõi

Sao chép người chiến thắng từ vòng cuối cùng, hoặc ít nhất là lựa chọn ràng buộc tối thiểu tốt nhất nếu không có người chiến thắng.

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

Tâm thần

Cách duy nhất để chiến thắng một cuộc chiến tranh hạt nhân là khiến bản thân trở nên điên loạn. Vì vậy, tôi sẽ làm cho mọi bot dự đoán trong giải đấu điên rồ.

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

Thực hiện các lựa chọn của vòng cuối cùng và chọn số lượng unchosen thấp nhất (tất nhiên bỏ qua lựa chọn của UnchosenBot).


2

Whoop-di-scoop-di-poop

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

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

Tôi chưa bao giờ nhìn thấy hoặc chạm vào Python, đây có phải là unpythonic không?


1
Thêm dòng <!-- language: lang-python -->trước khối mã để bật đánh dấu cú pháp
Herman L

@HermanL Tôi đã ảo giác một pythonthẻ về câu hỏi và nghĩ rằng nó sẽ tự động nhưng tôi đã viết một cái gì đó xấu.
Mihail Malostanidis

1
Đối với pythonicity, mã này khá tốt, ngoại trừ nó có thể được coi là pythonicer others = [c for i, c in enumerate(choices) if i != self.index], hoặc, vì sau đó bạn chỉ sử dụng biến đó cho các bài kiểm tra thành viên, { }thay vì [ ]xây dựng một setthay vì a list.
Roman Odaisky

if (self.guess)cũng rất unpythonic.
Jonathan Frech

Tôi không biết làm thế nào những parens xung quanh self.guesscó trong đó! Phải là một trong những người định hình.
Mihail Malostanidis

2

Đài phun nước

Một bot đơn giản, chọn số thấp nhất trước tiên và nếu bất kỳ bot nào khác cũng chọn nó, nó sẽ tăng bộ đếm - sàn được lấp đầy và nước chảy xuống. Khi đạt 11, nó khởi động lại thành 1 - nước được bơm trở lại đỉnh.

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

Ở dạng hiện tại, bot của bạn sẽ bị kẹt trong vòng lặp while nếu các bot khác đã chọn tất cả các số từ 1 đến 8. Ý của bạn là đặt targetthành 10?
Emil

@Emil Đúng, ban đầu nó như thế này, đã thay đổi
RedClover

2

PoissonsBot

Chọn các số từ phân phối Poisson được thiên vị cho các giá trị thấp hơn. Điều chỉnh tham số trung bình của phân phối lên nếu chúng ta hòa và xuống nếu có dự đoán bên dưới chúng ta. Kích thước bước sẽ nhỏ hơn khi trò chơi tiếp tục.

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

Giữ một số lượng chạy của các giá trị chiến thắng và các giá trị không được chọn tối thiểu (trong đó giá trị không được chọn tối thiểu chỉ được xem xét nếu nó nhỏ hơn giá trị chiến thắng). Nó chọn ngẫu nhiên trong số các giá trị chiến thắng và tối thiểu.

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

Chu kỳ thông qua các cầu thủ. Lựa chọn của người chơi hiện tại (có thể là chính mình) bây giờ là lựa chọn của bot này. Bắt đầu in 8, vì tại sao không. Xin lỗi tôi không thể python, đây có thể là mã xấu.

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

Chỉnh sửa: Cảm ơn Triggernometry đã cải thiện mã của tôi với itertools


Mã của bạn chỉ hoạt động tốt, nhưng bạn có thể thêm intertools. Motorcycle () để mã tự động chuyển qua 0-9 và bạn không phải thực hiện tăng hoặc kiểm tra - Hãy thử trực tuyến!
Triggernometry

2

Gấu trúc

Chọn số thấp nhất không được chọn trong vòng trước, ngoại trừ lựa chọn trước của chúng tôi, có thể được chọn lại lần này. Trong vòng đầu tiên, chọn 1. (Đưa ra 9 đối thủ và 10 lựa chọn, đảm bảo có một giá trị khả dụng.)

Tôi đã đưa ra điều này một cách độc lập, nhưng bây giờ thấy ít nhất 2 bot trước đó về cơ bản là giống nhau.

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

Tam giác gấu trúc

Kết hợp Raccoon và Triangle: từ các giá trị unchosen, chọn một giá trị dựa trên xác suất tam giác ngược.

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)

Lỗi:AttributeError: 'RaccoonTriangle' object has no attribute 'boundaries'
Renzeee

1
Vâng xin lôi. Tôi nghĩ rằng tôi đã sửa nó. Tôi đang ở giữa các bài kiểm tra viết, khi tôi rời đi.
Cơ học lượng tử

1

Đại tướng

Đại tướng luôn chiến đấu (các) cuộc chiến cuối cùng .

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

Không lặp lại ngẫu nhiên

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 chọn ngẫu nhiên, nhưng tránh chọn số tương tự như vòng trước.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.