天皇官邸


14

在中国古代,社会等级不是由出生或财富决定的,而是由一个人在科举考试中表现出色的能力决定的。天堂的神圣统治者翡翠皇帝号召所有臣民接受检查以确定他们的身价,然后由谁下达神圣的使命来统治中国。

官僚规则:

  • Divine官僚机构由以0开头的非负整数值等级组成。官僚机构的每个成员(bot)都属于一个等级。每个等级可以容纳任意多个成员,但除非以上所有等级都为空,否则不能为空
  • 游戏开始时,所有成员的等级均为0
  • 每一次官僚机构的每个成员都必须参加考试。考试包括正确猜测列表的布尔值。列表的长度是该成员上方的等级编号。
  • 试题由以上级别的随机成员准备。最高级别的成员直接从JadeEmperor(请参见下文)获得问题。
  • 考试分数至少达到50%的会员有资格晋升。考试分数低于50%的成员有资格降级。
  • 只有在以下等级中有晋升资格的成员代替其职位时,才有资格降级的成员的排名才降低一级。
  • 只要没有排名空缺,所有有资格晋升的会员的等级都会提高一。
  • 如果不是所有符合条件的成员都可以降级或晋升,则优先级将降到最低(降级)。最高(促销)分数。领带随机断裂。
  • 成员等级每回合最多只能改变1。

游戏规则:

  • 每个机器人在游戏开始时都会被随机分配一个ID,该ID在整个过程中不会改变。在JadeEmperor具有ID -1,其他所有的连续非负的ID,从0开始。
  • 所有机器人同时竞争
  • 游戏运行100圈,机器人的得分为其在那段时间内的平均排名。
  • 总得分是通过运行1000场比赛并取平均结果而获得。
  • 每个Bot是一个Python 3类,实现以下四个功能:
    • ask(self,n,ID),它通过返回list长度为n的布尔值a进行检查。ID是必须猜测该列表的机器人的ID。ask()可以在一个机器人的单个回合中被多次调用,但一点也不被调用。
    • answer(self,n,ID),这是通过返回list长度为n的布尔值a来回答考试的尝试。ID是ask()生成检查的机器人的ID 。answer()每个机器人每轮准确调用一次。
    • update(self,rankList,ownExam,otherExams)一旦控制器执行了所有降级和降级,就会调用。它的参数是:整数列表,按所有漫游器的ID列出所有等级;一个由两个列表组成的元组,首先是考试问题,然后是漫游器给出的答案(以防万一它忘记了);然后是元组列表,类似地由考试答案对组成,这次是机器人执行的所有考试。
    • __init__(self, ID, n) 传递该机器人自己的ID和竞争机器人的数量。
  • 允许类实现其他私有功能
  • 明确允许定义其他变量,并使用它们存储有关过去考试的数据。
  • 禁止编程元效果,这意味着任何直接访问其他机器人代码,控制器代码的尝试均会导致异常或类似情况。这是考试策略的竞赛,而不是代码黑客的竞赛。
  • 明确允许尝试互相帮助的机器人,只要它们不通过元效应来做到,而是纯粹通过传递的信息来实现 update()
  • 仅在其他语言可以轻松转换为Python 3的情况下才允许使用其他语言。
  • 库numpy将作为导入np。版本是1.6.5,这意味着它使用了旧的随机库。如果您有numpy 1.7,则可以使用旧功能numpy.random.mtrand进行测试。请记住要剥离mtrand以便提交。
  • 如果机器人在运行时导致异常,则该机器人不合格。任何代码过于混乱以至于无法确定何时在调用ask()或时answer()都不会生成长度为n的列表的bot 也会被抢先取消资格。强制我进行深度复制输出的机器人的得分为-1。
  • 类名必须唯一
  • 每个人可以使用多个漫游器,但是仅采用最新版本的迭代更新漫游器。
  • 由于关于机器人相似性似乎有些困惑:
    • 无权发布其他漫游器的副本。这是真正适用于此挑战的唯一 标准漏洞
    • 可以与其他机器人(包括其他人的机器人)共享代码。
    • 不得提交从另一只由一个微不足道的变化的策略(如种子为出题的变化)不同的机器人,除非你能证明这种抄送机器人的数量是成功所需的最小制定他们的策略(通常是两个机器人进行合作)。

示例机器人:

JadeEmperor始终是比赛的一部分,但不竞争; 他是最高级别的机器人考试的生成器。他的考试是随机的,但不是统一的考试,目的是让智能机器人有进步的方法。

class JadeEmperor:
    def __init__(self):
        pass

    def ask(self,n,ID):
        num=min(np.random.exponential(scale=np.sqrt(np.power(2,n))),np.power(2,n)-1)
        bi=list(np.binary_repr(int(num),width=n))
        return [x=='0' for x in bi]

The Drunkard进行考试并完全随机地回答。他将成为比赛的一部分。

class Drunkard:
    def __init__(self,ID,n):
        pass

    def ask(self,n,ID):
        return list(np.random.choice([True,False],size=n,replace=True))

    def answer(self,n,ID):
        return list(np.random.choice([True,False],size=n,replace=True))

    def update(self,rankList,ownExam,otherExams):
        pass #out

剽窃者只是复制以前的考试。他也将参加比赛。

class Plagiarist:
    def __init__(self,ID,n):
        self.exam=[True]

    def ask(self,n,ID):
        return (self.exam*n)[0:n]

    def answer(self,n,ID):
        return (self.exam*n)[0:n]

    def update(self,rankList,ownExam,otherExams):
        self.exam=ownExam[0]

此处提供控制器代码。为了进行测试,您可以将自己的类放入同一文件夹中的Contestants.py文件,并将其导入。

聊天室可以在这里找到。

考试开始了!

10月20日的当前得分,以更高的精度(10000个运行):

参赛者作者得分了ΑSleafar9.669691伽玛Sleafar9.301362贝塔Sleafar9.164597维奇路紫色P7.870821好学徒Dignissimus-垃圾邮件7.538537桑塔亚娜萨拉·J7.095528gia窃者6.522047眼泪联合会5.881175汤玛士外星人@系统5.880041相反德拉科5.529652马克思主义Sugarfi5.433808酒鬼5.328178阴阳紫色P5.102519均衡器助记符4.820996TitForTat匿名3.35801

在可预见的将来,竞赛将与每个新条目一起进行。


1
僵尸副本是标准漏洞,所以没有。如果您尝试通过提交几乎但并非完全相同的副本来滥用每个作者的多个漫游器规则,则将其删除。
AlienAtSystem

1
@AlienAtSystem为什么允许机器人互相帮助?似乎需要处理更多的混乱和随机性。
唐千

2
为什么构造函数参数ID, n是其他方法参数n, ID
紫色P

1
@DonThousand,因为我相信在给定的限制下,使两个机器人成功握手(请注意,izer窃者可能会在中间意外打人)和B)然后制定一项能够切实帮助该机器人的策略是一件很了不起的事但没有其他上升。
AlienAtSystem

1
@某人排名向上。您从0开始,然后逐步增加数值
AlienAtSystem

Answers:


4

桑塔亚娜

那些不记得过去的人会被谴责重复过去。因此,我们根据其他人过去的行为来做出决定,根据给定者在给定指标上通常期望我们提出的答案来做出回答,并询问他们在给定指标上给我们最少的回答。

import numpy as np

class Santayana:
    """
    Those who cannot remember the past are condemned to repeat it
    """
    def __init__(self, ID, num_competitors):
        self.ID = ID
        self.exams_taken = {}
        self.exams_issued = {}
        self.last_exam_asker = None
        self.recent_exam_takers = []

        for i in range(num_competitors):
            self.exams_taken[i] = []
            self.exams_issued[i] = []

    def ask(self, length, taker_ID):
        # Remember who asked
        self.recent_exam_takers.append(taker_ID)
        new_exam = []

        # At every index, expect the answer they've given the least often (default to False if equal)
        for i in range(length):
            trues = 0
            falses = 0
            for exam in self.exams_issued[taker_ID]:
                if len(exam) <= i: continue
                if exam[i]:
                    trues += 1
                else:
                    falses += 1
            new_exam.append(trues < falses)
        return new_exam

    def answer(self, num_answers, asker_ID):
        self.last_exam_asker = asker_ID
        if asker_ID == -1:
            # Copy emperor's process to hopefully get a similar exam
            num = min(np.random.exponential(scale=np.sqrt(np.power(2,num_answers))),np.power(2,num_answers)-1)
            as_bin = list(np.binary_repr(int(num),width=num_answers))
            return [x=='0' for x in as_bin]
        else:
            new_answer = []

            # At every index, give the answer that's been correct the greatest number of times (default to True if equal)
            for i in range(num_answers):
                trues = 0;
                falses = 0;
                for exam in self.exams_taken[asker_ID]:
                    if len(exam) <= i: continue
                    if exam[i]:
                        trues += 1
                    else:
                        falses += 1
                new_answer.append(trues >= falses)
            return new_answer

        return [True for i in range(num_answers)]

    def update(self, rank_list, own_exam, other_exams):
        if self.last_exam_asker > -1:
            # Save the exam we took, unless it was from the Emperor - we already know how he operates
            self.exams_taken[self.last_exam_asker].append(own_exam[0])
        for i in range(len(self.recent_exam_takers)):
            # Save the responses we got
            self.exams_issued[i].append(other_exams[i][1])

        self.recent_exam_takers = []

3

好学的机器人

这个机器人学习测试!它试图在各种自动程序发出的测试中找到模式,并采取一致的行动。

就目前而言,到目前为止,该机器人的性能要优于我可以在计算机上使用的所有其他机器人,除了Alpha,Beta和Gamma(它们已被编程为可以协同工作)之外。该漫游器没有利用允许分组的事实,因为我觉得这有点像作弊,并且有点脏。纵观它,团队合作似乎非常有效。

僵尸程序会尝试识别何时测试答案是随机的,并且作为响应,它希望平均达到测试的50%。

该机器人还试图识别一个机器人何时仅将其答案抛弃,以甩掉其他试图预测其行为的机器人,但是我尚未对其进行编程以使其具体发挥作用。

我在代码中加上了一些注释,以使其易于阅读

import random
import numpy as np


class StudiousBot:
    GRAM_SIZE = 5
    def __init__(self, identifier, n):
        self.id = identifier
        self.ranks = {i: 0 for i in range(n)} # Stores ranks
        self.study_material = {i: [] for i in range(n)} # Stores previous exam data
        self.distribution = {i: [] for i in range(n)} # Stores the percentage of answers that were `True` on a Bot's tests over time
        self.last_examiner = None

    def ask(self, n, identifier):
        # This bot gives random tests, it doesn't bother making them difficult based on answers to them
        # The reason for this is that I can't personalise the tests for each bot
        return [random.choice([True, False]) for i in range(n)] 

    def answer(self, n, examiner_id):
        self.last_examiner = examiner_id
        if examiner_id == -1:
            return StudiousBot.answer_emperor(n) # Easy win, I know the distribution of answers for the Emperor's tests

        bother_predicting = True # Whether or not the Bot will attempt to predict the answers to the exam
        study_material = self.study_material[examiner_id]
        distribution = self.distribution[examiner_id]
        if len(distribution) > 0: # If there is actually data to analyse
            sd = StudiousBot.calculate_standard_deviation(distribution)
            normalised_sd = StudiousBot.calculate_normalised_standard_deviation(distribution)

            if abs(30 - sd) < 4: # 30 is the expected s.d for a random distribution
                bother_predicting = False # So I won't bother predicting the test 

            if abs(sd - normalised_sd * 2) > 4: # The bot is merely inverting answers to evade being predicted
                pass # However, at this time, I'm not certain how I should deal with this. I'll continue to attempt to predict the test 


        if bother_predicting and len(study_material) >= StudiousBot.GRAM_SIZE:
            return StudiousBot.predict(study_material, n)

        return [random.choice([True, False]) for i in range(n)]

    def predict(study_material, n): # Predicts the answers to tests with `n` questions
        grams = StudiousBot.generate_ngrams(study_material, StudiousBot.GRAM_SIZE) # Generate all n-grams for the study material
        last_few = study_material[-(StudiousBot.GRAM_SIZE - 1):] # Get the last 9 test answers
        prediction = None
        probability = -1
        for answer in [True, False]: # Finds the probabiility of the next answer being True or False, picks the one with the highest probability
            new_prediction = last_few + [answer]
            new_probability = grams.count(new_prediction)         

            if new_probability > probability:
                prediction = answer
                probability = new_probability

        if n == 1:
            return [prediction]

        return [prediction] + StudiousBot.predict(study_material + [prediction], n-1)          


    @staticmethod
    def calculate_standard_deviation(distribution):
        return np.std(distribution)

    def calculate_normalised_standard_deviation(distribution): # If the answers happen to be inverted at some point, this function will return the same value for answers that occured both before and after this point  
        distribution = list(map(lambda x: 50 + abs(50-x), distribution))
        return StudiousBot.calculate_standard_deviation(distribution)   

    @staticmethod
    def generate_ngrams(study_material, n):
        assert len(study_material) >= n
        ngrams = []
        for i in range(len(study_material) - n + 1):
            ngrams.append(study_material[i:i+n])

        return ngrams

    def update(self, ranks, own_exam, other_exams):
        self.ranks = dict(enumerate(ranks))
        if self.last_examiner != -1:
            self.study_material[self.last_examiner] += own_exam[0]
            self.distribution[self.last_examiner].append(own_exam[0].count(True) / len(own_exam[0]) * 100) # Stores the percentage of the answers which were True

    @staticmethod
    def answer_emperor(n): # Algorithm to reproduce Emperor's distribution of test answers  
        exp = np.random.exponential(scale=np.sqrt(np.power(2,n)))
        power = np.power(2,n) - 1        
        num = min(exp, power)
        bi = list(np.binary_repr(int(num), width=n))
        return [x == '0' for x in bi]

从我们的表现来看,您拥有最佳的回答算法,Wi Qe Lu拥有最佳的询问算法。我建议将我们的机器人合并为一个名为Xuézhě(中文为“学者”)的机器人,巧合地听起来像是“切换器”。
紫色P

我砍了它,然后在我的机器上进行了检查。奇怪的是,它的得分超过了Studious Bot,但没有Wi Qe Lu。
紫色P

@PurpleP哈哈!这听起来很有趣,我认为没有足够的时间来改善我的机器人,但是您可以将其作为提交内容发布在此处
Dignissimus-Spammy

3

数眼

该机器人使用一种算法,对所有其他正在运行的机器人进行平均检查(给出轮次和一些令人讨厌的启发式算法),以确定每个其他机器人将设置为该考试。
Count使用md5哈希值要求考试。因此,它的问题和答案都是确定性的。它忽略了大多数输入,询问和回答了完全相同的布尔值,降雨或光照序列,包括对Jade Emporer的序列。

import numpy as np
import hashlib

class CountOracular:
    '''Uses very little external data to make heuristical statistical
    deterministic predictions about the average exam.
    (Assonance not intended.)
    To generate its own exams, uses a deterministic hash.'''
    def __init__(self, id, number_of_bots):
        self.last_round = []
        #functions for calculating what other bots will likely do.
        self.bots_calculators = [
            self._jad, #Jade Emporer
            self._alp, #Alpha
            self._bet, #Beta
            self._gam, #Gamma
            self._wiq, #Wi Qe Lu
            self._stu, #StudiousBot
            self._pla, #Plagiarist
            self._san, #Santayana
            self._tho, #Thomas
            self._dru, #Drunkard
            self._yin, #YinYang
            self._con, #Contrary
            self._tit, #TitForTat
            self._equ, #Equalizer
            self._mar, #Marx
        ]
        self.bot_types = len(self.bots_calculators)
    def ask(self, n, id):
        #if we can, show that hardcoding is no match for the power of heuristics:
        if n == 2:
            return [False, True]
        #otherwise, refer to the wisdom of Mayor Prentiss in order to command The Ask
        #i.e. hashes a quote, and uses that as the exam.
        salt = b"I AM THE CIRCLE AND THE CIRCLE IS ME " * n
        return self._md5_from(salt, n)
    def answer(self, n, id):
        #uses the power of heuristics to predict what the average bot will do
        #ignores all inputs except the length of the output
        #very approximate, and deterministic
        #i.e. every game, Count Oracular will send the same lists of answers, in the same order
        best_guess_totals = [0.5] * n #halfway between T and F
        for bot in self.bots_calculators:
            exam, confidence = bot(n)
            if not exam:
                continue
            while len(exam) < n:
                #ensure exam is long enough
                exam += exam[:1]
            exam = exam[:n] #ensure exam is short enough
            #map T and F to floats [0,1] based on confidence
            weighted_exam = [0.5+confidence*(0.5 if q else -0.5) for q in exam]
            best_guess_totals = [current+new for current,new in zip(best_guess_totals, weighted_exam)]
        best_guess_averages = [total/self.bot_types
            for total
            in best_guess_totals
        ]
        best_guess = [avg > 0.5 for avg in best_guess_averages]
        self.last_round = best_guess
        return best_guess
    def update(self, ranks, own, others):
        pass
    def _md5_from(self, data, n):
        md5 = hashlib.md5(data)
        for i in range(n):
            md5.update(data)
        exam = []
        while len(exam) < n:
            exam += [x == "0"
                for x
                in bin(int(md5.hexdigest(), 16))[2:].zfill(128)
            ]
            md5.update(data)
        return exam[:n]
    def _invert(self, exam):
        return [not val for val in exam]
    def _digits_to_bools(self, iterable):
        return [char=="1" for char in iterable]
    def _plagiarise(self, n):
        copy = (self.last_round * n)[:n]
        return copy

    '''functions to calculate expected exams for each other bot:
       (these values, weighted with corresponding confidence ratings,
       are summed to calculate the most likely exam.)'''
    def _jad(self, n):
        '''Calculate the mean of _jad's distribution, then
        use that as the guess'''
        mean = max(int(np.sqrt(np.power(2,n))), (2<<n)-1)
        string_mean = f"{mean}".zfill(n)
        exam = self._invert(self._digits_to_bools(string_mean))
        return exam, 0.5
    def _alp(self, n):
        '''Alpha uses a predictable hash,
        until it figures out we aren't Beta,
        modelled by the probability of giving or solving
        Alpha's exam'''
        #probability that Alpha thinks we're Beta
        #assuming we fail to pretend to be Beta if we meet Alpha
        chance_beta = ((1 - 1/self.bot_types) ** n) ** 2
        return self._md5_from(b"Beta", n), chance_beta
    def _gam(self, n):
        '''Gamma is like Beta, except after realising,
        switches to 50-50 random choice of inverse
        either Beta or Alpha's hash'''
        #probability that Gamma thinks we're Alpha still
        #(Unlikely that Gamma will think we're Beta;
        #we'd need to fail Alpha but pass Beta,
        #therefore, not accounted for)
        chance_unknown = ((1 - 1/self.bot_types) ** n) ** 2
        #default exam that assumes that Gamma thinks we're Alpha
        exam = self._md5_from(b"Beta", n)
        if chance_unknown > 0.5:#there exists a better heuristic here
            #assume Gamma will consider us Alpha
            confidence = chance_unknown
        else:
            #assume Gamma considers us neither Alpha nor Beta
            alpha = self._invert(self._md5_from(b"Beta", n))
            beta = self._invert(self._md5_from(b"Alpha", n))
            #check for bools where both possible exams match
            and_comp = [a and b for a, b in zip(alpha, beta)]
            nor_comp = [not (a or b) for a, b in zip(alpha, beta)]
            #count up matches vs times when fell back on default
            #to calculate ratio of default
            #to bools where hashes agree
            confidence_vs_default = (sum(and_comp)+sum(nor_comp)) / n
            confidence = confidence_vs_default * chance_unknown + (1 - confidence_vs_default) * (1 - chance_unknown)
            for i in range(n):
                if and_comp[i]:
                    exam[i] = True
                if nor_comp[i]:
                    exam[i] = False
        return exam, confidence
    def _bet(self, n):
        '''Beta is like Alpha, but with a different hash'''
        #probability we haven't matched with Beta yet
        #i.e. probability that Beta still thinks we're Alpha
        chance_alpha = ((1 - 1/self.bot_types) ** n) ** 2
        return self._md5_from(b"Alpha", n), chance_alpha
    def _wiq(self, n):
        '''Wi Qe Lu is hard to model, so we pretend
        that it mimicks Plagiarist for the most part'''
        if n == 1:
            #first round is random
            return [False], 0
        #other rounds are based on exams it met
        #leaning towards same as the previous exam
        return self._plagiarise(n), 0.1
    def _stu(self, n):
        '''StudiousBot is random'''
        return [False] * n, 0
    def _pla(self, n):
        '''Plagiarist copies the exams it received,
        which can be modelled with the standard prediction
        calculated for the previous round, padded with its first
        element.'''
        if n == 1:
            return [True], 1
        return self._plagiarise(n), 0.3
    def _san(self, n):
        '''Santayana is based on answers, which we don't predict.
        Modelled as random.'''
        #mostly random, slight leaning towards default False
        return [False] * n, 0.1
    def _tho(self, n):
        '''Thomas has an unpredictable threshold.'''
        #for all intents, random
        return [False] * n, 0
    def _dru(self, n):
        '''Drunkard is utterly random.'''
        return [False] * n, 0
    def _yin(self, n):
        '''YinYang inverts itself randomly, but not unpredictably.
        We can model it to find the probability. Also notably,
        one index is inverted, which factors into the confidence
        especially for lower n.'''
        if n == 1:
            #one element is inverted, so whole list must be False
            return [False], 1
        if n == 2:
            #split half and half randomly; can't predict
            return [True] * n, 0
        #cumulative chance of mostly ones or mostly zeros
        truthy = 1
        for _ in range(n):
            #simulate repeated flipping
            truthy = truthy * 0.44 + (1-truthy) * 0.56
        falsey = 1 - truthy
        if falsey > truthy:
            return [False] * n, falsey - 1/n
        return [True] * n, truthy - 1/n
    def _con(self, n):
        '''Contrary is like Jade Emporer, but inverts itself
        so much that modelling the probability of inversion
        is not worth the effort.'''
        #there are some clever ways you could do statistics on this,
        #but I'm content to call it uniform for now
        return [False] * n, 0
    def _tit(self, n):
        '''TitForTat is most likely to give us False
        but the confidence drops as the chance of having
        met TitForTat increases.
        The square root of the probability we calculate for
        Alpha, Beta and Gamma, because those also care about what
        we answer, whereas TitForTat only cares about what we ask'''
        #probability that we've not given TitForTat an exam
        chance_friends = (1 - 1/self.bot_types) ** n
        return [False] * n, chance_friends
    def _equ(self, n):
        '''Equalizer always asks True'''
        #certain that Equalizer's exam is all True
        return [True] * n, 1
    def _mar(self, n):
        '''Marx returns mostly True, randomised based on our rank.
        We don't predict our rank.
        There's ~50% chance an answer is random'''
        #75% chance we guess right (= 50% + 50%*50%)
        return [True] * n, 0.75

从理论上讲是个好主意,但在第一场比赛中,Oracular Count表现不及YinYang,尽管它努力模拟YinYang。
紫色P

1
@PurpleP是的,不是很好。原因是它试图通过将所有特定策略平均在一起来选择“通常最佳”的策略。例如,在遇到阴阳时,它不使用量身定制的策略来击败阴阳。它甚至没有在Jade Emporer上使用特定的策略:它只是将Jade Emporer策略添加到平均水平上。它会比随机的要好,但要好得多。
IFcoltransG

马克思已经解决。您应该更新Count Oracular进行预测。
紫色P,

@PurpleP马克思现在应该得到支持。就像是1917年一样。
IFcoltransG

2

阴阳

回答全部True或全部False,除了随机选择相反的一个索引。询问与之相反的答案。随机掉头甩开对手。

import random

class YinYang:
    def __init__(self, ID, n):
        self.exam = True

    def update(self, rankList, ownExam, otherExams):
        if random.random() < 0.56:
            self.exam = not self.exam

    def answer(self, n, ID):
        a = [not self.exam] * n
        a[random.randint(0, n-1)] = self.exam
        return a

    def ask(self, n, ID):
        e = [self.exam] * n
        e[random.randint(0, n-1)] = not self.exam
        return e

卢威(Switcheroo)

在第一轮中随机回答。之后,他使用上次考试的答案,并更改了一个问题,即是否有数量超过平均水平的竞争对手认为正确。

class WiQeLu:
    def __init__(self, ID, n):
        self.rounds = 1
        self.firstexam = True
        self.firstanswer = True
        self.lastexaminer = -1
        self.exam = []
        self.pastanswers = {}

    def update(self, rankList, ownExam, otherExams):
        questions, lastanswers = ownExam
        self.pastanswers[self.lastexaminer] = questions

        if len(otherExams) == 0:
            return
        correctCounts = [0 for i in otherExams[0][0]]
        for ourExam, response in otherExams:
            for i in range(len(response)):
                if ourExam[i] == response[i]:
                    correctCounts[i] += 1

        newExam = otherExams[0][0]
        meanWhoAnsweredCorrectly = sum(correctCounts) / len(correctCounts)
        for i in range(len(correctCounts)):
            if correctCounts[i] > meanWhoAnsweredCorrectly:
                newExam[i] = not newExam[i]
        self.exam = newExam

    def answer(self, n, ID):
        self.lastexaminer = ID
        if ID not in self.pastanswers:
            randomanswer = [random.randint(0, 1) == 1] * n
            self.pastanswers[ID] = randomanswer
            return randomanswer
        return (self.pastanswers[ID] * n)[:n]

    def ask(self, n, ID):
        if self.firstexam:
            self.firstexam = False
            self.exam = [random.randint(0, 1) == 1] * n
        return (self.exam * n)[:n]

5
根据Google翻译,“ wi qe lu”大致翻译为“我是企鹅之路”。
紫色P

2

我自己的一个机器人:

汤玛士

一位来自遥远土地的旅行者对过去的结果表示未来的表现有一些危险的想法。他用这些工具压低其他机器人,除非这扼杀了自己的进步。

class Thomas:
    def __init__(self,ID,n):
        N=10
        self.ID=ID
        self.myrank=n
        self.lowerank=0
        #The highest number of questions is equal to the number of participants, so we can do this:
        self.probs=[{i:1.0/N for i in np.linspace(0,1,num=N)} for i in np.arange(n)]
        self.output=[0.5]*n

    def ask(self,n,ID):
        if self.myrank==1 and self.lowerrank > 1: #I can't advance without promoting somebody first
            return [self.output[i]>np.random.rand() for i in np.arange(n)]
        #Otherwise, try to step on their fingers by going against the expected probability
        return [self.output[i]<np.random.rand() for i in np.arange(n)]


    def answer(self,n,ID):
        return [self.output[i]>np.random.rand() for i in np.arange(n)]

    def update(self,rankList,ownExam,otherExams):
        #Update our ranks
        self.myrank=len([i for i in rankList if i==rankList[self.ID]])
        self.lowerrank=len([i for i in rankList if i==rankList[self.ID]-1])
        #Update our expectations for each input we've been given
        self.bayesianupdate(ownExam[0])
        for ex in otherExams:
            self.bayesianupdate(ex[1])
        #Compress into output variable
        self.output=[np.sum([l[entry]*entry for entry in l]) for l in self.probs]

    def bayesianupdate(self,data):
        for i in np.arange(len(data)):
            if data[i]: #Got a True
                self.probs[i].update({entry:self.probs[i][entry]*entry for entry in self.probs[i]})
            else: #Got a False
                self.probs[i].update({entry:self.probs[i][entry]*(1-entry) for entry in self.probs[i]})
            s=np.sum([self.probs[i][entry] for entry in self.probs[i]]) #Renormalize
            self.probs[i].update({entry:self.probs[i][entry]/s for entry in self.probs[i]})
```

您是否忘了在类声明后缩进代码?
pppery

那只是SE格式,让我无所适从。我将修复该问题以及使用此漫游器时在某人的测试中导致错误的任何原因
AlienAtSystem

2

Α

拒绝投票之前,请先阅读聊天内容。这些漫游器不违反任何规则。OP甚至鼓励合作机器人。

Alpha与Beta一起组成了一个团队。两者都使用一组预定义的考试来互相帮助。同样,它们都在不断地利用相同考试的机器人。

import numpy as np
import hashlib

class Alpha:
    def __init__(self, ID, n):
        self.alpha = hashlib.md5(b"Alpha")
        self.beta = hashlib.md5(b"Beta")
        self.asker = -1
        self.betas = set(range(n)).difference([ID])
        self.fixed = set(range(n)).difference([ID])
        self.fixedExams = [[]] * n

    def ask(self,n,ID):
        if ID in self.betas:
            return self.md5ToExam(self.alpha, n)
        else:
            return list(np.random.choice([True, False], n))

    def answer(self,n,ID):
        self.asker = ID
        if self.asker == -1:
            return [True] * n
        elif self.asker in self.fixed and len(self.fixedExams[self.asker]) > 0:
            return (self.fixedExams[self.asker] * n)[:n]
        elif self.asker in self.betas:
            return self.md5ToExam(self.beta, n)
        else:
            return list(np.random.choice([True, False], n))

    def update(self,rankList,ownExam,otherExams):
        if self.asker >= 0:
            if self.asker in self.betas and ownExam[0] != self.md5ToExam(self.beta, len(ownExam[0])):
                    self.betas.remove(self.asker)
            if self.asker in self.fixed:
                l = min(len(ownExam[0]), len(self.fixedExams[self.asker]))
                if ownExam[0][:l] != self.fixedExams[self.asker][:l]:
                    self.fixed.remove(self.asker)
                    self.fixedExams[self.asker] = []
                elif len(ownExam[0]) > len(self.fixedExams[self.asker]):
                    self.fixedExams[self.asker] = ownExam[0]
        self.alpha.update(b"Alpha")
        self.beta.update(b"Beta")

    def md5ToExam(self, md5, n):
        return [x == "0" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

我相信这三个漫游器都违反了提示和评论中所述的OP规则。
唐·唐(Don Thousand),

@DonThousand如果您在聊天中阅读了讨论,您会发现他们没有违反规则。chat.stackexchange.com/rooms/98905/imperial-exams-office
Sleafar

很公平。我的错。
Don Thousand

@DonThousand那么,对它们全部进行投票到底有什么意义呢?
Sleafar

我只投票给Alpha。我不能取消投票。进行多余的编辑,我将修复它。
唐千

1

均衡器

每个人都应该平等(没有这个愚蠢的皇帝废话),所以要提供尽可能多的社会流动性。使问题变得非常简单(答案始终是正确的),以便人们可以成功。

class Equalizer:
    def __init__(self, ID, n):
        self.previousAnswers = [[0, 0] for _ in range(n)]
        self.previousAsker = -1

    def ask(self, n, ID):
        return [True] * n

    def answer(self, n, ID):
        if ID == -1:
            return [True] * n

        # Assume that questions from the same bot will usually have the same answer.
        t, f = self.previousAnswers[ID]
        return [t >= f] * n

    def update(self, rankList, ownExam, otherExams):
        if self.previousAsker == -1:
            return

        # Keep track of what answer each bot prefers.
        counts = self.previousAnswers[self.previousAsker]
        counts[0] += ownExam[0].count(True)
        counts[1] += ownExam[0].count(False)

1

贝塔

拒绝投票之前,请先阅读聊天内容。这些漫游器不违反任何规则。OP甚至鼓励合作机器人。

Beta正在与Alpha组成团队。两者都使用一组预定义的考试来互相帮助。同样,它们都在不断地利用相同考试的机器人。

import numpy as np
import hashlib

class Beta:
    def __init__(self,ID,n):
        self.alpha = hashlib.md5(b"Alpha")
        self.beta = hashlib.md5(b"Beta")
        self.asker = -1
        self.alphas = set(range(n)).difference([ID])
        self.fixed = set(range(n)).difference([ID])
        self.fixedExams = [[]] * n

    def ask(self,n,ID):
        if ID in self.alphas:
            return self.md5ToExam(self.beta, n)
        else:
            return list(np.random.choice([True, False], n))

    def answer(self,n,ID):
        self.asker = ID
        if self.asker == -1:
            return [True] * n
        elif self.asker in self.fixed and len(self.fixedExams[self.asker]) > 0:
            return (self.fixedExams[self.asker] * n)[:n]
        elif self.asker in self.alphas:
            return self.md5ToExam(self.alpha, n)
        else:
            return list(np.random.choice([True, False], n))

    def update(self,rankList,ownExam,otherExams):
        if self.asker >= 0:
            if self.asker in self.alphas and ownExam[0] != self.md5ToExam(self.alpha, len(ownExam[0])):
                    self.alphas.remove(self.asker)
            if self.asker in self.fixed:
                l = min(len(ownExam[0]), len(self.fixedExams[self.asker]))
                if ownExam[0][:l] != self.fixedExams[self.asker][:l]:
                    self.fixed.remove(self.asker)
                    self.fixedExams[self.asker] = []
                elif len(ownExam[0]) > len(self.fixedExams[self.asker]):
                    self.fixedExams[self.asker] = ownExam[0]
        self.alpha.update(b"Alpha")
        self.beta.update(b"Beta")

    def md5ToExam(self, md5, n):
        return [x == "0" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

1

伽玛

拒绝投票之前,请先阅读聊天内容。这些漫游器不违反任何规则。OP甚至鼓励合作机器人。

Gamma发现了Alpha和Beta的计划,并通过伪装成其中之一来尝试利用两者。

import numpy as np
import hashlib

class Gamma:
    def __init__(self, ID, n):
        self.alpha = hashlib.md5(b"Alpha")
        self.beta = hashlib.md5(b"Beta")
        self.asker = -1
        self.alphas = set(range(n)).difference([ID])
        self.betas = set(range(n)).difference([ID])
        self.fixed = set(range(n)).difference([ID])
        self.fixedExams = [[]] * n

    def ask(self,n,ID):
        if ID in self.alphas:
            return self.md5ToExam(self.beta, n)
        elif ID in self.betas:
            return self.md5ToExam(self.alpha, n)
        else:
            return self.md5ToWrongExam(np.random.choice([self.alpha, self.beta], 1)[0], n)

    def answer(self,n,ID):
        self.asker = ID
        if self.asker == -1:
            return [True] * n
        elif self.asker in self.fixed and len(self.fixedExams[self.asker]) > 0:
            return (self.fixedExams[self.asker] * n)[:n]
        elif self.asker in self.alphas:
            return self.md5ToExam(self.alpha, n)
        elif self.asker in self.betas:
            return self.md5ToExam(self.beta, n)
        else:
            return list(np.random.choice([True, False], n))

    def update(self,rankList,ownExam,otherExams):
        if self.asker >= 0:
            if self.asker in self.alphas and ownExam[0] != self.md5ToExam(self.alpha, len(ownExam[0])):
                    self.alphas.remove(self.asker)
            if self.asker in self.betas and ownExam[0] != self.md5ToExam(self.beta, len(ownExam[0])):
                    self.betas.remove(self.asker)
            if self.asker in self.fixed:
                l = min(len(ownExam[0]), len(self.fixedExams[self.asker]))
                if ownExam[0][:l] != self.fixedExams[self.asker][:l]:
                    self.fixed.remove(self.asker)
                    self.fixedExams[self.asker] = []
                elif len(ownExam[0]) > len(self.fixedExams[self.asker]):
                    self.fixedExams[self.asker] = ownExam[0]
        self.alpha.update(b"Alpha")
        self.beta.update(b"Beta")

    def md5ToExam(self, md5, n):
        return [x == "0" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

    def md5ToWrongExam(self, md5, n):
        return [x == "1" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

1

TitForTat

如果您过去曾问过简单问题,就会问您一些简单问题。如果您从未参加过考试,则默认为简单问题。

此外,不要相信任何提出困难问题的人,他们会给他们难以预测的答案。

import numpy as np

class TitForTat:
    def __init__(self, ID, n):
        self.friendly = [True] * n
        self.asker = -1

    def make_answers(self, n, ID):
        if ID == -1 or self.friendly[ID]:
            return [False] * n
        else:
            return list(np.random.choice([True, False], n))

    def ask(self, n, ID):
        return self.make_answers(n, ID)

    def answer(self, n, ID):
        self.asker = ID
        return self.make_answers(n, ID)

    def update(self, rankList, ownExam, otherExams):
        if self.asker != -1:
            # You are friendly if and only if you gave me a simple exam
            self.friendly[self.asker] = all(ownExam[0])

如果其他机器人与之合作,则该机器人运行良好。目前只有Equalizer合作,但这有望足够。


目前,该机器人无法竞争,因为它没有遵循规范。确保它list始终返回对象。同样,在旧的和更新的规则下,bot的完美副本都不是有效的提交,因此,此bot运行的实例数量为
1。– AlienAtSystem

我对其进行了编辑以返回列表。至于完美复制,目前尚无合适的机器人与之配合,因此,碳复制机器人的数量(成功实施该策略所需的最低数量)至少为1(需要该机器人及其副本1) )。
匿名

您在争辩说要提交第1条规定的内容时,您有资格获得第3条规定的例外,机器人的完美副本永远无效,也不例外。为了符合条款3的例外条件,您需要证明您的策略严格要求所有这些合作伙伴对此做出反应,例如握手信号,如果没有人倾听,这确实是无用的。你没有。均衡器将让您进行考试以触发“友好”条款,从而证明您需要机器人的副本。
AlienAtSystem

那好 我将作最后的调整。
匿名

0

相反

玉皇大帝总是对的,因此当需要两个以上的答案时,会将玉皇大帝的问讯功能实现为自己的答案功能。对于只有1个答案,它会回答true(正确的几率是正确的),对于2个答案true,false(它会通过“至少一半”的问题,这是四个可能测验中的三个,比随机选择更好)。

关于如何更改其询问模式,在其Update中使用了类似的逻辑,但其询问逻辑与Jade Emperor相似,只是权重不同。当太多的候选人获得足够高的分数通过时,在较高的值true和较高的值之间波动false

class Contrary:
    def __init__(self,ID,n):
        self.rank = 0
        self.ID = ID
        self.competitors = {}
        self.weight = -2
        pass

    def ask(self,n,ID):
        if self.weight > 0:
            num=min(np.random.exponential(scale=np.sqrt(np.power(self.weight,n))),np.power(2,n)-1)
            bi=list(np.binary_repr(int(num),width=n))
            return [x=='0' for x in bi]
        else:
            num=min(np.random.exponential(scale=np.sqrt(np.power(-self.weight,n))),np.power(2,n)-1)
            bi=list(np.binary_repr(int(num),width=n))
            return [x=='1' for x in bi]

    def answer(self,n,ID):
        if n == 1:
            return [True]
        if n == 2:
            return [True,False]
        num=min(np.random.exponential(scale=np.sqrt(np.power(2,n))),np.power(2,n)-1)
        bi=list(np.binary_repr(int(num),width=n))
        return [x=='0' for x in bi]

    def update(self,rankList,ownExam,otherExams):
        self.rank = rankList[self.ID];
        if len(otherExams) == 0:
            return
        correctCounts = [0 for i in otherExams[0][0]]
        for ourExam, response in otherExams:
            for i in range(len(response)):
                if ourExam[i] == response[i]:
                    correctCounts[i] += 1

        meanWhoAnsweredCorrectly = sum(correctCounts) / len(correctCounts)
        for i in range(len(correctCounts)):
            if correctCounts[i]+1 > meanWhoAnsweredCorrectly:
                self.weight = np.copysign(np.random.uniform(1,3),-self.weight)

1
true, false考试通过不不会失败false, true吗?
pppery

中的前几行 answer存在语法和名称错误- true并且false应为TrueFalse,并且结尾if缺少:s
Sara J

谢谢你们两个;我没有在我的机器上安装Python,因为我不经常使用它,所以我经常弄乱语法。
Draco18s不再信任

newExam已设置,但从未读过updatepass是NOP命令,您可以将其删除。(它后面的注释只是复制的Drunkard的双关语。)此外,您暗中使用mathrandom模块,但未声明已导入它们。与我较量文件我已经重新写它np.copysignnp.random.uniform应该做同样的事情。
AlienAtSystem

@AlienAtSystem应该立即修复。
Draco18s不再信任

0

马克思主义

这是马克思机器人。他认为,我们应该建立共产主义制度,而不是官僚主义。为了帮助实现此目标,它会给排名较高的机器人更难的测验。它还可以对高级机器人的测验给出更多随机答案,因为它们可能更聪明,因为它们更高。

import numpy as np

class Marx():
    def __init__(self, ID, n):
        self.ID = ID
        self.n = n
        self.ranks = [] # The bot rankings
        self.e = [] # Our quiz
        self.rank = 0 # Our rank
    def ask(self, n, ID):
        test = [True] * n
        # Get the rank of the bot being quizzed
        if self.ranks:
            rank = self.ranks[ID]
        else:
            rank = 0
        for i in range(len(test)):
            item = test[i]
            if np.random.uniform(0, rank / self.n) > 0.5:
                # If the bot is higher ranking, make the quiz harder
                item = np.random.choice([True, False], 1)[0]
            test[i] = item
        # IF the test is not long enough, add Falses to the end
        while len(test) < n - 1:
            test.append(False)
        return test
    def answer(self, n, ID):
        # Get the rank of the asking bot
        if self.ranks:
            rank = self.ranks[ID]
        else:
            rank = 0
        if self.e:
            # Pad our quiz with Falses so it will not throw IndexError
            while len(self.e) < n:
                self.e.append(False)
            for i in range(len(self.e)):
                item = self.e[i]
                if np.random.uniform(0, rank / self.n) > 0.5:
                    # Assume that higher ranking bots are cleverer, so add more random answers
                    item = np.random.choice([True, False], 1)[0]
                self.e[i] = item
            if len(self.e) > self.rank + 1:
                self.e = self.e[:self.rank + 1]
            return self.e
        else:
            # If it is the first round, return all Trues
            return [True] * n
    def update(self, rankList, ownExam, otherExams):
        # Update our list of ranks
        self.ranks = rankList
        # Store the quiz we were given, to give to the next bot
        self.e = ownExam[0]
        # Store our rank
        self.rank = rankList[self.ID]

马克思当前回答的字节过多,因此他现在无法竞争
AlienAtSystem

你什么意思?他的考试/答案太长了吗?
Sugarfi '19

他的回答是输入内容过长
-AlienAtSystem

好,我解决了。现在应该没事了。
sugarfi '19

抱歉,我给您错误的反馈:现在,答案太短了。真正的问题是,当self.e太短时(虽然现在还不够),您会对其进行扩展,但是当马克思降级时,不要对其进行修剪。
AlienAtSystem
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.