KOTH: Cada moeda tem dois lados

26

Resultados finais disponíveis

Introdução

Depois do meu KOTH anterior, com temas pesados ​​( guerra de fantasia , pandemia mundial ...), estou de volta com um novo jogo leve. Desta vez, você está enfrentando uma situação de "jogo de tabuleiro". Uma pilha de moedas de cabeça para baixo é colocada no centro de uma mesa muito grande e você está determinado a receber sua parte do saque!

Glossário

Moedas : tokens que podem ser invertidos ou invertidos.
Unflipped : Moedas colocadas na mesa com o valor apontando para baixo. Este é o estado padrão das moedas.
Lançado : Moedas colocadas na mesa com o valor apontando para cima.
Local : refere-se à sua pilha de moedas.
Global : refere-se à pilha de moedas no centro.

Princípio

No início do jogo, cada jogador começa com 0 pontos e 0 moedas (lançadas ou não). O jogo é baseado em turnos. Durante o turno, os jogadores podem realizar até 3 ações interagindo com a pilha de moedas no centro da mesa, sua própria pilha de moedas ou com outros jogadores.

A ordem do jogo é definida aleatoriamente no início do jogo. A ordem dos jogadores na lista de argumentos representa a ordem do turno e vai da esquerda para a direita nessa lista. "Próximo" e "Anterior" referem-se, respectivamente, a "à direita nessa lista" e "à esquerda nessa lista" com um loop, se você for o último dos dois lados.

O jogo dura 50 rodadas ou até que haja 0 moedas no centro no final do turno do jogador (o que significa que você terminará suas 3 ações, mesmo que a pilha esteja vazia após a sua primeira ação, e você poderá colocar de volta moedas para deixar o jogo continua). O número inicial de moedas globais é definido aleatoriamente com esta fórmula:

(2 ^ nb_players) + (nb_players * 10) - random(1 + (nb_players ^ 2))`

Cada ação lhe dará pontos (ou fará com que você perca alguns) e, no final do jogo, cada moeda que você tiver será adicionada aos seus pontos ( -1 para não jogado, +2 para jogado ). O jogador com mais pontos ganha.

O controlador fornece entrada por meio de argumentos de comando, e seu programa deve gerar via stdout.

Sintaxe

Entrada

Cada vez que seu programa é chamado, ele recebe argumentos neste formato:

Round;YourPlayerId;Coins;PlayerId_Points_Flipped_Unflipped;PlayerId_Points_Flipped_Unflipped;...

As rodadas são indexadas em 1.

Exemplo de entrada

6;2;52;1_20_3_12;0_-2_0_1;2_12_1_0

Aqui, você vê que é a 6ª rodada e você é o jogador 2. Há 52 moedas na pilha central. Você tem 12 pontos, 1 moeda lançada e 0 moeda não lançada. Os pontos podem ser negativos.

Saída

Você precisa produzir três caracteres (sem espaço, sem separador), cada um correspondendo a uma ação que você executará neste turno. A ordem dos caracteres determina a ordem das ações. Você pode emitir as mesmas ações várias vezes. Caso não haja moedas suficientes para concluir sua ação, ele usará o máximo de moedas disponíveis e contará pontos apenas para as moedas usadas.

N: Não faça nada
1: Pegue 1 moeda da pilha central [Efeitos: +1 desbloqueado local / -1 ponto / -1 desbloqueado global]
2 : Pegue 2 moedas da pilha central [Efeitos: +2 desbloqueado local / -2 pontos / -2 desbloqueado global]
3 : pegue 3 moedas da pilha central [Efeitos: +3 desbloqueado local / -3 pontos / -3 desbloqueado global]
A : coloque 1 moeda da sua pilha [Efeitos: -1 desbloqueado local / +1 ponto / +1 global unflipped]
B : Coloque de volta 2 moedas da sua pilha [Efeitos: -2 locais não lançados / +2 pontos / +2 global unflipped]
C : Coloque de volta 3 moedas da sua pilha [Efeitos: -3 locais não lançados / +3 pontos / +3 global unflipped]
X : remova 1 moeda da sua pilha[Efeitos: -1 local não jogado / 0 ponto]
Y : Remova 2 moedas da sua pilha [Efeitos: -2 local não jogado / 0 ponto]
Z : Remova 3 moedas da sua pilha [Efeitos: -3 local não jogado / 0 ponto]
R : Gire moedas ao jogador anterior [Efeitos: -1 ponto por flipper recebido, +2 pontos por flipped recebido / aplica-se a todos os jogadores]
T : Gire moedas para o próximo jogador [Efeitos: -1 ponto por flipper recebido, +2 pontos por flipped recebido / aplica-se a todos os jogadores]
F : Jogue 1 moeda [Efeitos: -1 local invertido / +1 local invertido / +2 pontos]
U : Solte 1 moeda [Efeitos: +1 local não invertido / -1 local invertido / -2 pontos]

Saída de exemplo

2FF : Pega duas moedas e vira duas moedas, marcando -2 + 2 + 2 = 2 points

Se sua saída estiver incorreta, o controlador assumirá NNN.

Controlador

Você pode encontrar o controlador no GitHub . Ele também contém dois samplebots, escritos em Java. Para executá-lo, confira o projeto e abra-o no seu IDE Java. O ponto de entrada no mainmétodo da classe Game. É necessário o Java 8.

Para adicionar bots, primeiro você precisa da versão compilada para Java (arquivos .class) ou das fontes das linguagens interpretadas. Coloque-os na pasta raiz do projeto. Em seguida, crie uma nova classe Java no playerspacote (você pode dar um exemplo nos bots já existentes). Esta classe deve ser implementada Playerpara substituir o método String getCmd(). A String retornada é o comando do shell para executar seus bots. Você pode, por exemplo, fazer um trabalho de bot rubi com este comando: return "C:\Ruby\bin\ruby.exe MyBot.rb";. Por fim, adicione o bot na matriz de jogadores na parte superior da Gameclasse.

Regras

  • Os bots não devem ser escritos para vencer ou suportar outros bots específicos.
  • A gravação em arquivos é permitida. Por favor, escreva para "YOURSubmissionname.txt", a pasta será esvaziada antes do início do jogo. Outros recursos externos não são permitidos.
  • Seu envio tem 1 segundo para responder.
  • Forneça comandos para compilar e executar seus envios.

Idiomas suportados

Vou tentar dar suporte a todos os idiomas, mas ele precisa estar disponível online gratuitamente. Por favor, forneça instruções de instalação se você não estiver usando um idioma "mainstream".

A partir de agora, eu posso executar: Java 6-7-8, PHP, Ruby, Perl, Python 2-3, Lua, R, node.js, Haskell, Kotlin, C ++ 11.

Resultados finais

Estes são os resultados de 100 jogos (soma de pontos):

1. BirdInTheHand: 1017790
2. Balance: 851428
3. SecondBest: 802316
4. Crook: 739080
5. Jim: 723440
6. Flipper: 613290
7. Wheeler: 585516
8. Oracle: 574916
9. SimpleBot: 543665
10. TraderBot: 538160
11. EgoisticalBot: 529567
12. RememberMe: 497513
13. PassiveBot: 494441
14. TheJanitor: 474069
15. GreedyRotation: 447057
16. Devil: 79212
17. Saboteur: 62240

Os resultados individuais dos jogos estão disponíveis aqui: http://pasted.co/63f1e924 (com moedas iniciais e número de rodadas por jogo).

Uma recompensa de 50 reputações é concedida ao vencedor: Bird In The Hand, de Martin Büttner .

Obrigado a todos por sua participação, até a próxima KOTH ~

Thrax
fonte
1
" Efeitos: -1 local invertido / +1 local invertido / +2 pontos " parece errado para mim. Não deveria ser +3 pontos, porque você passou de -1 para uma moeda não lançada a +2 para uma moeda lançada?
Peter Taylor
1
@ PeterTaylor Acho que os pontos são independentes das moedas. Cada ação é associada a um número de pontos recebidos ou perdidos e estes são independentes dos pontos que você recebe pelas moedas no final do jogo.
Martin Ender
Você menciona moedas com seu "valor" apontando para cima ou para baixo. Para que esses valores são usados? As moedas são distinguíveis?
User2357112 suporta Monica
@PeterTaylor Como Martin Büttner disse, você recebe moedas por ações (neste caso, +2 por sacudir) e também ganha pontos por ter moedas no final (neste caso, +2 por cada sacudida).
Thrax
O ID é baseado em zero ou baseado em um?
Frederick

Respostas:

12

Pássaro na mão, Ruby

def deep_copy(o)
  Marshal.load(Marshal.dump(o))
end

ID = 0
PTS = 1
FLP = 2
UFL = 3

round, id, global, *players = ARGV[0].split(';')
round = round.to_i
id = id.to_i
global = global.to_i

players.map!{ |s| s.split('_').map(&:to_i) }

nplayers = players.size

my_pos = players.find_index { |i, p, f, u| i == id }

state = {
    round: round,
    id: id,
    global: global,
    players: players,
    my_pos: my_pos,
    me: players[my_pos],
    prev_p: players[my_pos-1],
    next_p: players[(my_pos+1)%nplayers],
    ends_game: round == 50 && my_pos == nplayers-1,
    score: 0
}

moves = {
    'N' => ->s{deep_copy(s)},
    '1' => ->s{t = deep_copy(s); coins = [1, t[:global]].min; t[:global] -= coins; t[:me][UFL] += coins; t[:score] -= coins; t},
    '2' => ->s{t = deep_copy(s); coins = [2, t[:global]].min; t[:global] -= coins; t[:me][UFL] += coins; t[:score] -= coins; t},
    '3' => ->s{t = deep_copy(s); coins = [3, t[:global]].min; t[:global] -= coins; t[:me][UFL] += coins; t[:score] -= coins; t},
    'A' => ->s{t = deep_copy(s); coins = [1, t[:me][UFL]].min; t[:global] += coins; t[:me][UFL] -= coins; t[:score] += coins; t},
    'B' => ->s{t = deep_copy(s); coins = [2, t[:me][UFL]].min; t[:global] += coins; t[:me][UFL] -= coins; t[:score] += coins; t},
    'C' => ->s{t = deep_copy(s); coins = [3, t[:me][UFL]].min; t[:global] += coins; t[:me][UFL] -= coins; t[:score] += coins; t},
    'X' => ->s{t = deep_copy(s); coins = [1, t[:me][UFL]].min; t[:me][UFL] -= coins; t},
    'Y' => ->s{t = deep_copy(s); coins = [2, t[:me][UFL]].min; t[:me][UFL] -= coins; t},
    'Z' => ->s{t = deep_copy(s); coins = [3, t[:me][UFL]].min; t[:me][UFL] -= coins; t},
    'F' => ->s{t = deep_copy(s); coins = [1, t[:me][UFL]].min; t[:me][UFL] -= coins; t[:me][FLP] += coins; t[:score] += 2*coins; t},
    'U' => ->s{t = deep_copy(s); coins = [1, t[:me][FLP]].min; t[:me][FLP] -= coins; t[:me][UFL] += coins; t[:score] -= 2*coins; t},
    'R' => ->s{
        t = deep_copy(s)
        (-1...t[:players].size-1).each do |i|
            t[:players][i][FLP] = s[:players][i+1][FLP]
            t[:players][i][UFL] = s[:players][i+1][UFL]
        end
        t[:score] += 2*t[:me][FLP] - t[:me][UFL];
        t
    },
    'T' => ->s{
        t = deep_copy(s)
        (0...t[:players].size).each do |i|
            t[:players][i][FLP] = s[:players][i-1][FLP]
            t[:players][i][UFL] = s[:players][i-1][UFL]
        end
        t[:score] += 2*t[:me][FLP] - t[:me][UFL];
        t
    }
}


results = {}

'N123ABCXYZFURT'.each_char { |c1| 
    s1 = moves[c1][state]
    'N123ABCXYZFURT'.each_char { |c2| 
        s2 = moves[c2][s1]
        'N123ABCXYZFURT'.each_char { |c3| 
            s3 = moves[c3][s2]
            s3[:ends_game] ||= s3[:global] == 0
            results[c1+c2+c3] = s3
        }
    }
}

endingMoves = results.keys.select{|k| results[k][:ends_game]}

endingMoves.each{|k| results[k][:score] += 2*results[k][:me][FLP] - results[k][:me][UFL]}

$> << results.keys.shuffle.max_by {|k| results[k][:score]}

Se nenhum de nós tem um bug em seus programas, o principal algoritmo disso é provavelmente muito semelhante ao Oracle de Mathias. Com base no pressuposto de que, antes da rodada final, não podemos saber com quais moedas terminaremos, avaliamos o conjunto de movimentos atual puramente com base nos pontos recebidos imediatamente, ignorando completamente que tipo de moeda acabaremos com. Como existem apenas 14 3 = 2744 conjuntos de movimentos possíveis, podemos simular facilmente todos eles para descobrir quantos pontos eles trarão.

No entanto, se um conjunto de jogadas terminar o jogo (seja porque reduz o pote global a zero, ou porque esta é a rodada 50 e somos os últimos a se mover), também levará em consideração as moedas pertencentes ao final de o conjunto de movimentos para determinar o valor do conjunto de movimentos. Eu considerei terminar o jogo sempre que possível, mas isso resultaria em uma jogada horrível 333quando restassem apenas 9 moedas no pote.

Se houver vários conjuntos de movimentos que dão o mesmo resultado, escolhemos um aleatório. (Eu posso mudar isso para enviesá-lo em favor dos conjuntos de movimentos que terminam o jogo.)

Martin Ender
fonte
17

Oracle, Python 3

Atualização: mudou a ordem das várias tentativas para favorecer a baixa pilha de moedas sobre as rotações.

import sys
import itertools
from copy import deepcopy


MOVES_REQUIRED = 3

FLIPPED = 0
UNFLIPPED = 1


def filter_neighbors(neighbors, me, size):
    limit = size - MOVES_REQUIRED
    for data in neighbors:
        i, _, flipped, unflipped = map(int, data.split('_'))
        if MOVES_REQUIRED < (me - i) % size < limit:
            continue  # Skip neighbors that are too far away
        yield i, [flipped, unflipped]


class Player:
    def __init__(self, raw_data):
        _, me, coins, *data = raw_data.split(';')

        self.num_players = len(data)
        self._me = int(me)
        self._coins = int(coins)
        self._state = dict(filter_neighbors(data, self._me, self.num_players))

    def reset(self):
        self.me = self._me
        self.coins = self._coins
        self.state = deepcopy(self._state)
        self.my_state = self.state[self.me]

    def invalid_move(self, move):
        if move in 'NRT':
            return False

        if move in '123'[:self.coins]:
            return False

        flipped, unflipped = self.my_state
        if flipped and move == 'U':
            return False
        if unflipped and move == 'F':
            return False

        if move in 'AXBYCZ'[:2 * unflipped]:
            return False

        return True

    def N(self):
        return 0

    def one(self):
        self.coins -= 1
        self.my_state[UNFLIPPED] += 1
        return -1

    def two(self):
        self.coins -= 2
        self.my_state[UNFLIPPED] += 2
        return -2

    def three(self):
        self.coins -= 3
        self.my_state[UNFLIPPED] += 3
        return -3

    def A(self):
        self.coins += 1
        self.my_state[UNFLIPPED] -= 1
        return 1

    def B(self):
        self.coins += 2
        self.my_state[UNFLIPPED] -= 2
        return 2

    def C(self):
        self.coins += 3
        self.my_state[UNFLIPPED] -= 3
        return 3

    def X(self):
        self.my_state[UNFLIPPED] -= 1
        return 0

    def Y(self):
        self.my_state[UNFLIPPED] -= 2
        return 0

    def Z(self):
        self.my_state[UNFLIPPED] -= 3
        return 0

    def R(self):
        self.me = (self.me + 1) % self.num_players
        flipped, unflipped = self.my_state = self.state[self.me]
        return 2 * flipped - unflipped

    def T(self):
        self.me = (self.me - 1) % self.num_players
        flipped, unflipped = self.my_state = self.state[self.me]
        return 2 * flipped - unflipped

    def F(self):
        self.my_state[FLIPPED] += 1
        self.my_state[UNFLIPPED] -= 1
        return 2

    def U(self):
        self.my_state[FLIPPED] -= 1
        self.my_state[UNFLIPPED] += 1
        return -2

setattr(Player, '1', Player.one)
setattr(Player, '2', Player.two)
setattr(Player, '3', Player.three)


def scenarii(player):
    for tries in itertools.product('FUABCXYZ123NRT', repeat=MOVES_REQUIRED):
        player.reset()
        points = 0
        for try_ in tries:
            if player.invalid_move(try_):
                break
            points += getattr(player, try_)()
        else:
            yield points, ''.join(tries)


if __name__ == '__main__':
    player = Player(sys.argv[1])
    print(max(scenarii(player))[1])

Tenta cada saída possível e mantém a que produz a quantidade máxima de pontos para este turno.

409_Conflict
fonte
Ah, eu estava prestes a implementar isso, +1. :) (eu ainda poderia realmente, porque eu tinha uma ou duas idéias menores para melhorar esta ligeiramente .)
Martin Ender
@ MartinBüttner Pensei em melhorar a deepcopycomplexidade do espaço (portanto, do tempo [ ]) mantendo apenas vizinhos relevantes. Não tenho certeza de como isso afetará as coisas.
409_Conflict
@Thrax Corrigi um bug filter_neighborse modifiquei invalid_movepara esclarecer a questão. Porém, não consigo reproduzir o erro: $ python oracle.py '4;7;2040;8_-28_1_10;9_-43_0_9;2_-10_4_3;6_-24_6_3;0_6_2_12;1_48_3_0;10_21_4_8;5_6_5_1;4_-12_3_7;7_10_1_3;3_1_1_0'printsTTR
409_Conflict
7

Rotação gananciosa, Ruby

round, id, global, *players = ARGV[0].split(';')
round = round.to_i
id = id.to_i
global = global.to_i

players.map!{ |s| s.split('_').map(&:to_i) }

nplayers = players.size

my_pos = players.find_index { |i, p, f, u| i == id }

prev_p = players[my_pos-1]
next_p = players[(my_pos+1)%nplayers]

prev_score = 2*prev_p[2] - prev_p[3]
next_score = 2*next_p[2] - next_p[3]

take_from = prev_p

$><< '3'
if prev_score > next_score || prev_score == next_score && prev_p[3] > next_p[3]
    $><< 'T'
else
    $><< 'R'
    take_from = next_p
end

if take_from[3] >= 3
    $><< 'C'
elsif take_from[3] >= 1
    $><< 'F'
else
    $><< 'N'
end

Isso é bastante semelhante à abordagem do ArtOfCode, exceto que isso verifica de qual vizinho podemos obter mais pontos e escolhe em Cvez de Fterminar com 3 ou mais moedas após a rotação.

Depois de escrever isso, tenho certeza de que uma abordagem melhor seria apenas escolher com avidez o melhor de todos os movimentos todas as vezes, precedendo a rotação tomando, se possível (em vez de usar um fixo "desmonte, gire, se livre) padrão "invertido").

Isso também não leva em conta os pontos implícitos representados pelas moedas realmente possuídas (com base no pressuposto de que o jogo vai durar rodadas suficientes para que eu provavelmente não acabe mantendo minhas moedas de qualquer maneira).

Martin Ender
fonte
@MegaTom Opa, obrigado por assistir.
Martin Ender
6

Flipper, Python 2

Flipper recolhe moedas e tenta girar de um lado para o outro. Flipper não é um jogador inteligente, mas tenta ser uma força positiva no jogo.

import sys, random

# process input data (not used here):
args = sys.argv[1].split(';')
rounds, myid, coins = map(int, args[:3])
players = [map(int, data.split('_')) for data in args[3:]]

# implement strategy using multiples of 'N123ABCXYZRTFU':
options = '12333FFFFFFFFFFF'
print ''.join(random.choice(options) for i in range(3))

Flipper só precisa python flipper.py <arg>correr.

Cavaleiro Lógico
fonte
5

SimpleBot, Python 3

SimpleBot é, bem, simples. Ele elaborou uma estratégia e vai continuar com ela.

Para correr:

python3 main.py

onde o conteúdo do main.pyarquivo é:

def main():
    print("3RF")


if __name__ == "__main__":
    main()
ArtOfCode
fonte
5

Balance, Lua

O Balance tentará manter o equilíbrio em seu símbolo, minimizando a perda no caso de alguém usar as ações Re Tcontra ele. Ele acha que esse estilo de vida é o verdadeiro e deve ser aplicado a qualquer um que não mantenha um bom equilíbrio de moedas lançadas / não lançadas, para que todos os que estão próximos a ele sejam punidos assim que isso os faça perder pontos.

Ele precisa do seguinte comando para executar:

lua balance.lua

Onde o arquivo balance.lua contém o seguinte trecho de código:

local datas={}
local arg=arg[1]..";"

-- parse the arguments
-- add some meta datas for debuging purpose/usefulness
arg:gsub("(.-);",function(c)
  if not datas.round
  then
    datas.round=c+0
  elseif not datas.myID
  then
    datas.myID=c+0
  elseif not datas.coins
  then
    datas.coins=c+0
  else
    datas[#datas+1]={}
    datas[#datas].repr=c
    c=c.."_"
    tmp={}
    c:gsub("(.-)_",function(d) tmp[#tmp+1]=d end)
    datas[#datas].id=tmp[1]+0
    datas[#datas].points=tmp[2]+0
    datas[#datas].flip=tmp[3]+0
    datas[#datas].unflip=tmp[4]+0
    if datas[#datas].id==datas.myID
    then
      datas.myOrder=#datas
      datas.myDatas=datas[#datas]
    end
  end
end)

local actions=""
-- construct actions
for i=1,3
do
  -- if we aren't in balance and can grab more coins
  -- we do it
  if #actions==0 and datas.myDatas.unflip<=datas.myDatas.flip/2 and datas.coins>=3
  then
    actions=actions.."3"
    datas.myDatas.unflip=datas.myDatas.unflip+3
    datas.coins=datas.coins-3
  -- if we couldn't grab coins, but aren't in balance, we flip some coins
  elseif datas.myDatas.unflip>datas.myDatas.flip/2
  then
    actions=actions.."F"
    datas.myDatas.unflip=datas.myDatas.unflip-1
    datas.myDatas.flip=datas.myDatas.flip+1

  -- if we didn't have anything to do on our pile, let's punish
  -- the fools who doesn't follow the great Balance principle
  else
    previous=datas.myOrder<2 and #datas or datas.myOrder-1
    following=datas.myOrder>=#datas and 1 or datas.myOrder+1

    lossPrev=-datas[previous].flip + 2*datas[previous].unflip
    lossFoll=-datas[following].flip+ 2*datas[following].unflip
    if lossFoll>0 and lossPrev>0
    then
      actions =actions.."N"
    elseif lossFoll>=lossPrev
    then
      actions=actions.."T"
      datas[following].unflip,datas[following].flip=datas[following].flip,datas[following].unflip
    else
      actions=actions.."R"
      datas[previous].unflip,datas[previous].flip=datas[previous].flip,datas[previous].unflip
    end
  end
end
print(actions)
Katenkyo
fonte
@ Thrax Obrigado, corrigido. Esqueceu-se de trabalhar com valores indexados em 1 para esta linha ... #
231
4

O zelador, Python 3

Ele tenta limpar a bagunça que os outros jogadores fazem com todas essas moedas e colocá-las de volta na piscina.

import sys;
def Parse(S):
    T = S.split(';');
    me = eval(T[1]);
    N = len(T)-3;
    A = list(map(lambda x: list(map(lambda y:int(y),T[3+((2*N+x+me)%N)].split('_'))),range(-3,4)));    
    Dic = {}
    for a in A:
        Dic[a[0]] = a[1:];
    Dic[-1] = [me];
    return Dic;
def Recursive(Dic,me,D):
    if D==3: return '';
    V = Dic[me];
    N = max(Dic.keys());
    Next = (me+1)%N;
    Prev = (N+1+me)%N;
    for i in range(3,0,-1):
        if V[2]>=i:
            Dic[me][2] = Dic[me][2]-i;
            return chr((i-1)+ord('A'))+Recursive(Dic,me,D+1);
    if V[1]>0:
        Dic[me][1] = Dic[me][1]-1;
        Dic[me][2] = Dic[me][2]+1;
        return 'U'+Recursive(Dic,me,D+1);
    if Dic[Next][2]>Dic[Prev][2]:
        return 'T'+Recursive(Dic,Next,D+1);
    return 'R'+Recursive(Dic,Prev,D+1);
Dic = Parse(sys.argv[1]);
me = Dic[-1][0];
print(Recursive(Dic,me,0));

Ele tenta devolver todas as suas moedas que não foram lançadas, se ele tiver algumas moedas lançadas e presas, ele será retirado e se ele se livrar de todas as suas moedas, ele receberá outra pessoa.

Lause
fonte
3

Crook, R

args <- strsplit(commandArgs(TRUE),";")[[1]]
state <- as.data.frame(do.call(rbind,strsplit(args[-(1:3)],"_")), stringsAsFactors=FALSE)
colnames(state) <- c("id","pts","flipped","unflipped")
state$flipped <- as.integer(state$flipped)
state$unflipped <- as.integer(state$unflipped)
nb <- nrow(state)
score <- function(place) 2*state$flipped[place]-state$unflipped[place]
my_place <- which(state$id==args[2])
next_1 <- ifelse(my_place!=nb,my_place+1,1)
next_2 <- ifelse(next_1!=nb,next_1+1,1)
next_3 <- ifelse(next_2!=nb,next_2+1,1)
previous_1 <- ifelse(my_place!=1,my_place-1,nb)
previous_2 <- ifelse(previous_1!=1,previous_1-1,nb)
previous_3 <- ifelse(previous_2!=1,previous_2-1,nb)
n <- 3
out <- c()
while(n){
    M <- N <- score(my_place)
    R <- switch(n,"1"=score(next_1),
                "2"=cumsum(c(score(next_1),score(next_2))),
                "3"=cumsum(c(score(next_1),score(next_2),score(next_3))))
    P <- switch(n,"1"=score(previous_1),
                "2"=cumsum(c(score(previous_1),score(previous_2))),
                "3"=cumsum(c(score(previous_1),score(previous_2),score(previous_3))))
    M <- c(M,M+R[-n])
    N <- c(N,N+P[-n])
    if(any(R>M & R>0)){
        action <- c("R","RR","RRR")[which.max(R-M)]
        out <- c(out, action)
        state[,3:4] <- state[c((nchar(action)+1):nb,seq_len(nchar(action))),3:4]
        n <- n-nchar(action)
    }else if(any(P>N & P>0)){
        action <- c("T","TT","TTT")[which.max(P-N)]
        out <- c(out, action)
        state[,3:4] <- state[c((nb+1-seq_len(nchar(action))),1:(nb-seq_len(nchar(action)))),3:4]
        n <- n-nchar(action)
    }else if(n>1 & all(R[1]+M[1]>c(0,P[1]+M[1],R[1]+R[2]))){
        out <- c(out,"RT")
        n <- n-2
    }else if(n>1 & all(P[1]+M[1]>c(0,R[1]+M[1],P[1]+P[2]))){
        out <- c(out,"TR")
        n <- n-2
    }else{
        out <- c(out, switch(n,"1"="A","2"="1F","3"="2FF"))
        n <- 0
        }
    }
cat(paste(out,collapse=""))

Para correr: Rscript Crook.R

Basicamente, ele troca suas moedas com seus vizinhos apenas se a troca for desigual a seu favor. Se não for possível uma troca benéfica, ela troca moedas com a pilha global de uma maneira que mantém sua relação intacta, mas gera alguns pontos.

Edit: Eu adicionei um pouco de profundidade a este bot, fazendo com que ele verifique as pilhas de 2 e 3 jogadores seguintes e anteriores, em vez de apenas a seguinte, e verifique se, no geral, é benéfico girar tantas vezes.

2º Edit : Seguindo a idéia de @ MartinBüttner, o bot agora executa um "RT", ou "TR", se seria mais benéfico para ele do que para seus vizinhos (se eu não errasse ao implementá-lo :)).

plannapus
fonte
Re sua edição: se o cara ao seu lado tem uma tonelada de moedas lançadas, pode ser melhor fazê- RTRlo para que você obtenha a pontuação das moedas duas vezes.
Martin Ender
Verdade. Embora também dê a um dos vizinhos que marca uma vez. Mas eu vou pensar sobre isso, é definitivamente uma idéia para explorar.
Plannapus 3/16
@ MartinBüttner Ok, no final, encontrei uma maneira de implementá-lo, mantendo o espírito do bot. Obrigado pela sugestão!
Plannapus #
@thrax Apenas para que você não esqueça de atualizar meu bot ao executar o próximo jogo, pensei em avisá-lo que a versão do meu bot no seu repositório no github é antiga.
Plannapus
3

Jim, Ruby

baseado na rotação gananciosa de Martin Büttner .

PlayerId = 0
Points = 1
Flipped = 2
Unflipped = 3

round, id, global, *players = ARGV[0].split(';')
round = round.to_i
id = id.to_i
global = global.to_i

if(round == 1)
    print '3FF'
    exit
end

players.map!{ |s| s.split('_').map(&:to_i) }

nplayers = players.size

my_pos = players.find_index { |a| a[PlayerId] == id }

coin_vals = players.map{|a| a[Flipped]*2 - a[Unflipped]}

move = [-1,1].max_by{|s|
    swap_gain = coin_vals.rotate(s)
    scores = (0...nplayers).map{|i|
        swap_gain[i]+players[i][Points]
    }
    scores.delete_at(my_pos)-scores.max
}
if move == 1
    print 'R'
else
    print 'T'
end

print ['1F', 'FF'][rand 2]

irá rodar de uma maneira ou de outra, dependendo do que lhe dará mais pontos em comparação com o melhor outro jogador. Então, ele vira dinheiro rápido.

MegaTom
fonte
2

TraderBot

Esse bot tenta girar sempre que é o que leva mais pontos nessa ação. Se ele não puder girar, tente se livrar das moedas não lançadas ou demorar um pouco mais para alterá-las nas ações a seguir.

import java.util.ArrayList;

importar java.util.List;

classe pública TraderBot {

class Player{
    private int id;
    private int points;
    private int flip;
    private int unflip;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getPoints() {
        return points;
    }
    public void setPoints(int points) {
        this.points = points;
    }
    public int getFlip() {
        return flip;
    }
    public void setFlip(int flip) {
        this.flip = flip;
    }
    public int getUnflip() {
        return unflip;
    }
    public void setUnflip(int unflip) {
        this.unflip = unflip;
    }


}

int round;
int coins;
int otherMaxPoints = 0;
Player myself = new Player();
List<Player> players = new ArrayList<>();

public static void main (String[] s){
    new TraderBot().play(s);
}

private void play(String[] s){
    parse(s[0]);
    System.out.println(action() + action() + action());
}

private int simRotateNext(){
    int flip, unflip;
    int maxP = Integer.MIN_VALUE;
    int myP = 0;
    for (int i = 0; i < players.size(); i++){
        flip = players.get(i).getFlip();
        unflip = players.get(i).getUnflip();
        int next = i + 1 <= players.size() - 1 ? i + 1 : 0;
        int p = 2 * flip - unflip;
        if (p > maxP && players.get(next).getId() != myself.getId()){
            maxP = p;
        } else if (players.get(next).getId() == myself.getId()){
            myP = p;
        }

    }
    return  myP - maxP;
}

private int simRotatePrev(){
    int flip, unflip;
    int maxP = Integer.MIN_VALUE;
    int myP = 0;
    for (int i = players.size() -1; i > 0; i--){
        flip = players.get(i).getFlip();
        unflip = players.get(i).getUnflip();
        int prev = i - 1 >= 0 ? i - 1 : players.size() - 1;
        int p = 2 * flip - unflip;
        if (p > maxP && players.get(prev).getId() != myself.getId()){
            maxP = p;
        } else if (players.get(prev).getId() == myself.getId()){
            myP = p;
        }
    }
    return  myP - maxP;
}

private int rotateNext(){
    int flip, unflip, nflip, nunflip;
    flip = players.get(0).getFlip();
    unflip = players.get(0).getUnflip();
    for (int i = 0; i < players.size(); i++){
        int next = i + 1 <= players.size() - 1 ? i + 1 : 0;
        nflip = players.get(next).getFlip();
        nunflip = players.get(next).getUnflip();
        players.get(next).setFlip(flip);
        players.get(next).setUnflip(unflip);
        players.get(next).setPoints(players.get(next).getPoints() + 2 * flip - unflip);
        flip = nflip;
        unflip = nunflip;
    }
    return myself.getPoints();
}

private int rotatePrev(){
    int flip, unflip,  nflip, nunflip;
    flip = players.get(players.size() -1).getFlip();
    unflip = players.get(players.size() -1).getUnflip();
    for (int i = players.size() -1; i > 0; i--){
        int prev = i - 1 >= 0 ? i - 1 : players.size() - 1;
        nflip = players.get(prev).getFlip();
        nunflip = players.get(prev).getUnflip();
        players.get(prev).setFlip(flip);
        players.get(prev).setUnflip(unflip);
        players.get(prev).setPoints(players.get(prev).getPoints() + 2 * flip - unflip);
        flip = nflip;
        unflip = nunflip;
    }
    return myself.getPoints();
}

private String action() {
    int next = simRotateNext();
    int prev = simRotatePrev();

    if (next > 0 || prev > 0){
        if (next > prev){
            rotateNext();
            return "T";
        } else {
            rotatePrev();
            return "R";
        }
    }

    if (myself.getUnflip() > 3){
        myself.unflip -= 3;
        myself.points += 3;
        return "C";
    }

    if (myself.getUnflip() > 0){
        myself.unflip -= 1;
        myself.points += 2;
        return "F";
    }

    if (myself.getPoints() > otherMaxPoints){
        return "N";
    } else {
        myself.unflip += 3;
        myself.points -= 3;
        return "3";
    }

}

private void parse(String s){
    String[] ps = s.split(";");
    round = Integer.parseInt(ps[0]);
    myself.setId(Integer.parseInt(ps[1]));
    coins = round = Integer.parseInt(ps[2]);
    for (int i = 3; i < ps.length; i++){
        String[] sp2 = ps[i].split("_");
        if (Integer.parseInt(sp2[0]) == myself.getId()){
            myself.setPoints(Integer.parseInt(sp2[1]));
            myself.setFlip(Integer.parseInt(sp2[2]));
            myself.setUnflip(Integer.parseInt(sp2[3]));
            players.add(myself);
        } else {
            Player p = new Player();
            p.setId(Integer.parseInt(sp2[0]));
            p.setPoints(Integer.parseInt(sp2[1]));
            p.setFlip(Integer.parseInt(sp2[2]));
            p.setUnflip(Integer.parseInt(sp2[3]));
            players.add(p);
            if (p.getPoints() > otherMaxPoints){
                otherMaxPoints = p.getPoints();
            }
        }
    }
}
}

Para executar: basta adicioná-lo à mesma pasta que os bots padrão e depois criar a seguinte classe

package players;

import controller.Player;

public class TraderBot extends Player {

    @Override
    public String getCmd() {
        return "java TraderBot";
    }   
}

Em seguida, adicione essa classe à Player[] playersmatriz.

Averroes
fonte
2

Wheeler

Wheeler calculou a melhor jogada possível ao girar as moedas.

import java.util.ArrayList;
import java.util.List;

public class Wheeler {

String[] actions = {"TTT", "TTR", "TRR", "TRT", "RRR", "RRT", "RTR", "RTT"};
String paramString;

class Player{
    private int id;
    private int points;
    private int flip;
    private int unflip;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getPoints() {
        return points;
    }
    public void setPoints(int points) {
        this.points = points;
    }
    public int getFlip() {
        return flip;
    }
    public void setFlip(int flip) {
        this.flip = flip;
    }
    public int getUnflip() {
        return unflip;
    }
    public void setUnflip(int unflip) {
        this.unflip = unflip;
    }
    @Override
    public String toString() {
        return "Player [id=" + id + ", points=" + points + ", flip=" + flip + ", unflip=" + unflip + "]";
    }




}

int round;
int coins;
int otherMaxPoints = 0;
Player myself = new Player();
List<Player> players = new ArrayList<>();

public static void main (String[] s){
    new Wheeler().play(s);
}

private void play(String[] s){
    paramString = s[0];
    reset();
    System.out.println(action());
}

private int rotateNext(){
    int flip, unflip, nflip, nunflip;
    flip = players.get(0).getFlip();
    unflip = players.get(0).getUnflip();
    for (int i = 0; i < players.size(); i++){
        int next = i + 1 <= players.size() - 1 ? i + 1 : 0;
        nflip = players.get(next).getFlip();
        nunflip = players.get(next).getUnflip();
        players.get(next).setFlip(flip);
        players.get(next).setUnflip(unflip);
        players.get(next).setPoints(players.get(next).getPoints() + 2 * flip - unflip);
        flip = nflip;
        unflip = nunflip;
    }
    return myself.getPoints();
}

private int rotatePrev(){
    int flip, unflip,  nflip, nunflip;
    flip = players.get(players.size() -1).getFlip();
    unflip = players.get(players.size() -1).getUnflip();
    for (int i = players.size() -1; i > 0; i--){
        int prev = i - 1 >= 0 ? i - 1 : players.size() - 1;
        nflip = players.get(prev).getFlip();
        nunflip = players.get(prev).getUnflip();
        players.get(prev).setFlip(flip);
        players.get(prev).setUnflip(unflip);
        players.get(prev).setPoints(players.get(prev).getPoints() + 2 * flip - unflip);
        flip = nflip;
        unflip = nunflip;
    }
    return myself.getPoints();
}

private String action() {
    int maxPoints = myself.getPoints();
    String action = "1F2";
    for (String s : actions){
        int cPoints = 0;
        for (char c : s.toCharArray()){
            if (c == 'T'){
                cPoints += rotateNext();
            } else {
                cPoints += rotatePrev();
            }
        }
        if (cPoints > maxPoints){
            action = s;
        }
        reset();
    }
    return action;      
}


private void reset(){
    players = new ArrayList<>();
    String[] ps = paramString.split(";");
    round = Integer.parseInt(ps[0]);
    myself.setId(Integer.parseInt(ps[1]));
    coins = round = Integer.parseInt(ps[2]);
    for (int i = 3; i < ps.length; i++){
        String[] sp2 = ps[i].split("_");
        if (Integer.parseInt(sp2[0]) == myself.getId()){
            myself.setPoints(Integer.parseInt(sp2[1]));
            myself.setFlip(Integer.parseInt(sp2[2]));
            myself.setUnflip(Integer.parseInt(sp2[3]));
            players.add(myself);
        } else {
            Player p = new Player();
            p.setId(Integer.parseInt(sp2[0]));
            p.setPoints(Integer.parseInt(sp2[1]));
            p.setFlip(Integer.parseInt(sp2[2]));
            p.setUnflip(Integer.parseInt(sp2[3]));
            players.add(p);
            if (p.getPoints() > otherMaxPoints){
                otherMaxPoints = p.getPoints();
            }
        }
    }
}

}
Averroes
fonte
2

Sabotador, Python 2

import random
moves = '3R'
print '33' + ''.join(random.choice(moves))

A aleatoriedade significa que provavelmente não sabotará muito bem, mas depois acho que vou esperar até o 'fim' (quantas voltas / moedas restam) e ENTÃO girar, depois de olhar para os jogadores acessíveis nas proximidades para roubar. ... na verdade, apenas fazer uma rotação parece muito ruim, considerando que outras pessoas também podem usar rotações. Eu não acho que isso funcionará muito bem ...

Neal
fonte
O que mais se faz é acabar com a pilha de moedas. bem como dar a si e aos outros muitos pontos negativos.
MegaTom
@MegaTom Sim, eu pensei que seria um efeito colateral, eu meio que virei a fórmula do total de moedas, eu acho. Eu poderia torná-lo um número aleatório. E nos pontos negativos, dar pontos negativos aos outros é apenas outra maneira de ganhar!
Neal
Você não precisa da importação do sistema. : P
cat
2

SecondBest, Python 3

Este programa analisará todas as três combinações possíveis de movimentos e escolherá a segunda melhor.

Porque se você tem a jogada perfeita, provavelmente é uma armadilha.

Editar: entrada comentada removida

import sys
from copy import deepcopy
from random import randint
In=str(sys.argv[1])
def V(n,f=10,t=14):
 n=str(n);z=0;s='';d='0123456789';d1='N123ABCXYZRTFU'
 for i in n:z=z*f+d.index(i)
 while z:z,m=divmod(z,t);s=d1[m]+s
 while len(s)<3:s='N'+s
 return s
In=In.split(';')
number=In[0:3]
players=In[3:]
for x in range(0,len(players)):players[x]=players[x].split('_')
for x in players:
 if number[1] in x[0]:self=x
for x in range(0,len(players)):
 for y in range(0,len(players[x])):
  players[x][y]=int(players[x][y])
for x in range(0,len(number)):number[x]=int(number[x])
Pos=list(map(V,range(0,14**3)))
B=[]
C=[]
P1=deepcopy(players)
N1=deepcopy(number)
for x in range(len(Pos)):
    P=True
    y=Pos[x]
    if '1A'in y or '2B'in y or '3C'in y or 'FU'in y or 'A1'in y or 'B2'in y or 'C3'in y or 'UF'in y:
            P=False#stupid check
    if P:#legality check
        z=0
        players=deepcopy(P1)
        number=deepcopy(N1)
        for x in players:
            if str(number[1]) in str(x[0]):self=x
        for w in range(0,3):
            if y[w] in '3':
                if int(number[2])<3:P=False;break
                else:z-=3;self[3]+=3;number[2]-=3
            if y[w] in '2':
                if int(number[2])<2:P=False;break
                else:z-=2;self[3]+=2;number[2]-=2
            if y[w] in '1':
                if int(number[2])<1:P=False;break
                else:z-=1;self[3]+=1;number[2]-=1
            if y[w] in 'A':
                if int(self[3])<1:P=False;break
                else:z+=1;self[3]-=3;number[2]+=3
            if y[w] in 'B':
                if int(self[3])<2:P=False;break
                else:z+=2;self[3]-=2;number[2]+=2
            if y[w] in 'C':
                if int(self[3])<3:P=False;break
                else:z+=3;self[3]-=1;number[2]+=1
            if y[w] in 'X':
                if int(self[3])<1:P=False;break
                else:self[3]-=1
            if y[w] in 'Y':
                if int(self[3])<2:P=False;break
                else:self[3]-=2
            if y[w] in 'Z':
                if int(self[3])<3:P=False;break
                else:self[3]-=3
            if y[w] in 'F':
                if int(self[3])<1:P=False;break
                else:z+=2;self[3]-=1;self[2]+=1
            if y[w] in 'U':
                if int(self[3])<1:P=False;break
                else:z-=2;self[3]+=1;self[2]-=1
            if y[w] in 'R':
                self[2:4]=players[(players.index(self)+1)%len(players)][2:4]
                z+=int(self[3])*-1
                z+=int(self[2])*2
            if y[w] in 'T':
                self[2:4]=players[(players.index(self)-1)%len(players)][2:4]
                z+=int(self[3])*-1
                z+=int(self[2])*2
    if P:
        C.append(z);B.append((z,y))
c=list(set(C))
c.sort()
c=c[::-1][1];D=[]
for x in B:
    if c in x:D.append(x)
print(D[randint(0,len(D)-1)][1])

Editar: o código estava imprimindo uma jogada legal aleatória. Agora deve estar retornando o segundo melhor resultado.

Magenta
fonte
1

Bot do Diabo

Embora sua produção seja apenas metade do número do diabo, os resultados devem ser bastante desastrosos. Tomando 9 moedas a cada turno, acaba esgotando a pilha de moedas. Como esse bot nunca joga nenhuma das moedas necessárias, é extremamente ruim para quem estiver sentado ao lado dele quando houver uma rotação (-9 pontos por cada turno realizado por esse bot).

print("333")

Comando: python3 devil.py

Espero fazer alguns robôs reais mais tarde.

Frederick
fonte
@plannapus Whoops! Eu não notei aquele. Obrigado por me dizer!
Frederick
1

Lembre-se de mim, Python 3

Este programa contém uma quantidade significativa de dados embutidos de um teste contra o bot SecondBest fixo.

Ele deve aprender quais movimentos são os melhores para usar, mas não usa as informações de outros jogadores.

Editar: removido cálculo de ponto desnecessário

Editar: entrada não comentada do jogador

import sys
file=sys.argv[0].split('\\')[::-1][0]
from copy import deepcopy
from random import randint
In=str(sys.argv[1])
def V(n,f=10,t=14):
 n=str(n);z=0;s='';d='0123456789';d1='N123ABCXYZRTFU'
 for i in n:z=z*f+d.index(i)
 while z:z,m=divmod(z,t);s=d1[m]+s
 while len(s)<3:s='N'+s
 return s
In=In.split(';')
number=In[0:3]
players=In[3:]
for x in range(0,len(players)):players[x]=players[x].split('_')
for x in players:
 if number[1] in x[0]:self=x
for x in range(0,len(players)):
 for y in range(0,len(players[x])):
  players[x][y]=int(players[x][y])
for x in range(0,len(number)):number[x]=int(number[x])
Pos=list(map(V,range(0,14**3)))
B=[]
P1=deepcopy(players)
N1=deepcopy(number)
for x in range(len(Pos)):
    P=True
    y=Pos[x]
    if '1A'in y or '2B'in y or '3C'in y or 'FU'in y or 'A1'in y or 'B2'in y or 'C3'in y or 'UF'in y:
            P=False
    if P:
        players=deepcopy(P1)
        number=deepcopy(N1)
        for x in players:
            if str(number[1]) in str(x[0]):self=x
        for w in range(0,3):
            if y[w] in '3':
                if int(number[2])<3:P=False;break
                else:self[3]+=3;number[2]-=3
            if y[w] in '2':
                if int(number[2])<2:P=False;break
                else:self[3]+=2;number[2]-=2
            if y[w] in '1':
                if int(number[2])<1:P=False;break
                else:self[3]+=1;number[2]-=1
            if y[w] in 'A':
                if int(self[3])<1:P=False;break
                else:self[3]-=3;number[2]+=3
            if y[w] in 'B':
                if int(self[3])<2:P=False;break
                else:self[3]-=2;number[2]+=2
            if y[w] in 'C':
                if int(self[3])<3:P=False;break
                else:self[3]-=1;number[2]+=1
            if y[w] in 'X':
                if int(self[3])<1:P=False;break
                else:self[3]-=1
            if y[w] in 'Y':
                if int(self[3])<2:P=False;break
                else:self[3]-=2
            if y[w] in 'Z':
                if int(self[3])<3:P=False;break
                else:self[3]-=3
            if y[w] in 'F':
                if int(self[3])<1:P=False;break
                else:self[3]-=1;self[2]+=1
            if y[w] in 'U':
                if int(self[3])<1:P=False;break
                else:self[3]+=1;self[2]-=1
            if y[w] in 'R':
                self[2:4]=players[(players.index(self)+1)%len(players)][2:4]
            if y[w] in 'T':
                self[2:4]=players[(players.index(self)-1)%len(players)][2:4]
    if P:
        B.append(y)
Pos=list(B)
B=[]
#
C=[['NNN',0],['NN1',-1],['NN2',-2],['NN3',-3],['NNR',-6],['NNT',-1],['N1N',-1],['N11',-2],['N12',-3],['N13',-4],['N1X',-1],['N1R',-7],['N1T',-2],['N1F',1],['N1U',-3],['N2N',-2],['N21',-3],['N22',-4],['N23',-5],['N2A',-1],['N2X',-2],['N2Y',-2],['N2R',-8],['N2T',-3],['N2F',0],['N2U',-4],['N3N',-3],['N31',-4],['N32',-5],['N33',-6],['N3A',-2],['N3B',-1],['N3X',-3],['N3Y',-3],['N3Z',-3],['N3R',-9],['N3T',-4],['N3F',-1],['N3U',-5],['NRN',-6],['NR1',-7],['NR2',-8],['NR3',-9],['NRA',-5],['NRB',-4],['NRC',-3],['NRX',-6],['NRY',-6],['NRZ',-6],['NRR',-12],['NRT',-7],['NRF',-4],['NRU',-8],['NTN',-1],['NT1',-2],['NT2',-3],['NT3',-4],['NTA',0],['NTX',-1],['NTR',-7],['NTT',-2],['NTF',1],['NTU',-3],['1NN',-1],['1N1',-2],['1N2',-3],['1N3',-4],['1NA',0],['1NX',-1],['1NR',-7],['1NT',-2],['1NF',1],['1NU',-3],['11N',-2],['111',-3],['112',-4],['113',-5],['11B',0],['11X',-2],['11Y',-2],['11R',-8],['11T',-3],['11F',0],['11U',-4],['12N',-3],['121',-4],['122',-5],['123',-6],['12A',-2],['12C',0],['12X',-3],['12Y',-3],['12Z',-3],['12R',-9],['12T',-4],['12F',-1],['12U',-5],['13N',-4],['131',-5],['132',-6],['133',-7],['13A',-3],['13B',-2],['13X',-4],['13Y',-4],['13Z',-4],['13R',-10],['13T',-5],['13F',-2],['13U',-6],['1XN',-1],['1X1',-2],['1X2',-3],['1X3',-4],['1XR',-7],['1XT',-2],['1RN',-7],['1R1',-8],['1R2',-9],['1R3',-10],['1RA',-6],['1RB',-5],['1RC',-4],['1RX',-7],['1RY',-7],['1RZ',-7],['1RR',-13],['1RT',-8],['1RF',-5],['1RU',-9],['1TN',-2],['1T1',-3],['1T2',-4],['1T3',-5],['1TA',-1],['1TX',-2],['1TR',-8],['1TT',-3],['1TF',0],['1TU',-4],['1FN',1],['1F1',0],['1F2',-1],['1F3',-2],['1FR',-5],['1FT',0],['1UN',-3],['1U1',-4],['1U2',-5],['1U3',-6],['1UA',-2],['1UB',-1],['1UX',-3],['1UY',-3],['1UR',-9],['1UT',-4],['1UU',-5],['2NN',-2],['2N1',-3],['2N2',-4],['2N3',-5],['2NA',-1],['2NB',0],['2NX',-2],['2NY',-2],['2NR',-8],['2NT',-3],['2NF',0],['2NU',-4],['21N',-3],['211',-4],['212',-5],['213',-6],['21B',-1],['21C',0],['21X',-3],['21Y',-3],['21Z',-3],['21R',-9],['21T',-4],['21F',-1],['21U',-5],['22N',-4],['221',-5],['222',-6],['223',-7],['22A',-3],['22C',-1],['22X',-4],['22Y',-4],['22Z',-4],['22R',-10],['22T',-5],['22F',-2],['22U',-6],['23N',-5],['231',-6],['232',-7],['233',-8],['23A',-4],['23B',-3],['23X',-5],['23Y',-5],['23Z',-5],['23R',-11],['23T',-6],['23F',-3],['23U',-7],['2AN',-1],['2A2',-3],['2A3',-4],['2AR',-7],['2AT',-2],['2XN',-2],['2X1',-3],['2X2',-4],['2X3',-5],['2XA',-1],['2XX',-2],['2XR',-8],['2XT',-3],['2XF',0],['2XU',-4],['2YN',-2],['2Y1',-3],['2Y2',-4],['2Y3',-5],['2YR',-8],['2YT',-3],['2RN',-8],['2R1',-9],['2R2',-10],['2R3',-11],['2RA',-7],['2RB',-6],['2RC',-5],['2RX',-8],['2RY',-8],['2RZ',-8],['2RR',-14],['2RT',-9],['2RF',-6],['2RU',-10],['2TN',-3],['2T1',-4],['2T2',-5],['2T3',-6],['2TA',-2],['2TX',-3],['2TR',-9],['2TT',-4],['2TF',-1],['2TU',-5],['2FN',0],['2F1',-1],['2F2',-2],['2F3',-3],['2FA',1],['2FX',0],['2FR',-6],['2FT',-1],['2FF',2],['2UN',-4],['2U1',-5],['2U2',-6],['2U3',-7],['2UA',-3],['2UB',-2],['2UC',-1],['2UX',-4],['2UY',-4],['2UZ',-4],['2UR',-10],['2UT',-5],['2UU',-6],['3NN',-3],['3N1',-4],['3N2',-5],['3N3',-6],['3NA',-2],['3NB',-1],['3NC',0],['3NX',-3],['3NY',-3],['3NZ',-3],['3NR',-9],['3NT',-4],['3NF',-1],['3NU',-5],['31N',-4],['311',-5],['312',-6],['313',-7],['31B',-2],['31C',-1],['31X',-4],['31Y',-4],['31Z',-4],['31R',-10],['31T',-5],['31F',-2],['31U',-6],['32N',-5],['321',-6],['322',-7],['323',-8],['32A',-4],['32C',-2],['32X',-5],['32Y',-5],['32Z',-5],['32R',-11],['32T',-6],['32F',-3],['32U',-7],['33N',-6],['331',-7],['332',-8],['333',-9],['33A',-5],['33B',-4],['33X',-6],['33Y',-6],['33Z',-6],['33R',-12],['33T',-7],['33F',-4],['33U',-8],['3AN',-2],['3A2',-4],['3A3',-5],['3AR',-8],['3AT',-3],['3BN',-1],['3B1',-2],['3B3',-4],['3BA',0],['3BX',-1],['3BR',-7],['3BT',-2],['3BF',1],['3BU',-3],['3XN',-3],['3X1',-4],['3X2',-5],['3X3',-6],['3XA',-2],['3XB',-1],['3XX',-3],['3XY',-3],['3XR',-9],['3XT',-4],['3XF',-1],['3XU',-5],['3YN',-3],['3Y1',-4],['3Y2',-5],['3Y3',-6],['3YA',-2],['3YX',-3],['3YR',-9],['3YT',-4],['3YF',-1],['3YU',-5],['3ZN',-3],['3Z1',-4],['3Z2',-5],['3Z3',-6],['3ZR',-9],['3ZT',-4],['3RN',-9],['3R1',-10],['3R2',-11],['3R3',-12],['3RA',-8],['3RB',-7],['3RC',-6],['3RX',-9],['3RY',-9],['3RZ',-9],['3RR',-15],['3RT',-10],['3RF',-7],['3RU',-11],['3TN',-4],['3T1',-5],['3T2',-6],['3T3',-7],['3TA',-3],['3TX',-4],['3TR',-10],['3TT',-5],['3TF',-2],['3TU',-6],['3FN',-1],['3F1',-2],['3F2',-3],['3F3',-4],['3FA',0],['3FB',1],['3FX',-1],['3FY',-1],['3FR',-7],['3FT',-2],['3FF',1],['3UN',-5],['3U1',-6],['3U2',-7],['3U3',-8],['3UA',-4],['3UB',-3],['3UC',-2],['3UX',-5],['3UY',-5],['3UZ',-5],['3UR',-11],['3UT',-6],['3UU',-7],['RNN',-6],['RN1',-7],['RN2',-8],['RN3',-9],['RNA',-5],['RNB',-4],['RNC',-3],['RNX',-6],['RNY',-6],['RNZ',-6],['RNR',-12],['RNT',-7],['RNF',-4],['RNU',-8],['R1N',-7],['R11',-8],['R12',-9],['R13',-10],['R1B',-5],['R1C',-4],['R1X',-7],['R1Y',-7],['R1Z',-7],['R1R',-13],['R1T',-8],['R1F',-5],['R1U',-9],['R2N',-8],['R21',-9],['R22',-10],['R23',-11],['R2A',-7],['R2C',-5],['R2X',-8],['R2Y',-8],['R2Z',-8],['R2R',-14],['R2T',-9],['R2F',-6],['R2U',-10],['R3N',-9],['R31',-10],['R32',-11],['R33',-12],['R3A',-8],['R3B',-7],['R3X',-9],['R3Y',-9],['R3Z',-9],['R3R',-15],['R3T',-10],['R3F',-7],['R3U',-11],['RAN',-5],['RA2',-7],['RA3',-8],['RAA',-4],['RAB',-3],['RAC',-2],['RAX',-5],['RAY',-5],['RAZ',-5],['RAR',-11],['RAT',-6],['RAF',-3],['RAU',-7],['RBN',-4],['RB1',-5],['RB3',-7],['RBA',-3],['RBB',-2],['RBC',-1],['RBX',-4],['RBY',-4],['RBZ',-4],['RBR',-10],['RBT',-5],['RBF',-2],['RBU',-6],['RCN',-3],['RC1',-4],['RC2',-5],['RCA',-2],['RCB',-1],['RCC',0],['RCX',-3],['RCY',-3],['RCZ',-3],['RCR',-9],['RCT',-4],['RCF',-1],['RCU',-5],['RXN',-6],['RX1',-7],['RX2',-8],['RX3',-9],['RXA',-5],['RXB',-4],['RXC',-3],['RXX',-6],['RXY',-6],['RXZ',-6],['RXR',-12],['RXT',-7],['RXF',-4],['RXU',-8],['RYN',-6],['RY1',-7],['RY2',-8],['RY3',-9],['RYA',-5],['RYB',-4],['RYC',-3],['RYX',-6],['RYY',-6],['RYZ',-6],['RYR',-12],['RYT',-7],['RYF',-4],['RYU',-8],['RZN',-6],['RZ1',-7],['RZ2',-8],['RZ3',-9],['RZA',-5],['RZB',-4],['RZC',-3],['RZX',-6],['RZY',-6],['RZZ',-6],['RZR',-12],['RZT',-7],['RZF',-4],['RZU',-8],['RRN',-12],['RR1',-13],['RR2',-14],['RR3',-15],['RRA',-11],['RRB',-10],['RRC',-9],['RRX',-12],['RRY',-12],['RRZ',-12],['RRR',-18],['RRT',-13],['RRF',-10],['RRU',-14],['RTN',-7],['RT1',-8],['RT2',-9],['RT3',-10],['RTA',-6],['RTX',-7],['RTR',-13],['RTT',-8],['RTF',-5],['RTU',-9],['RFN',-4],['RF1',-5],['RF2',-6],['RF3',-7],['RFA',-3],['RFB',-2],['RFC',-1],['RFX',-4],['RFY',-4],['RFZ',-4],['RFR',-10],['RFT',-5],['RFF',-2],['RUN',-8],['RU1',-9],['RU2',-10],['RU3',-11],['RUA',-7],['RUB',-6],['RUC',-5],['RUX',-8],['RUY',-8],['RUZ',-8],['RUR',-14],['RUT',-9],['RUU',-10],['TNN',-1],['TN1',-2],['TN2',-3],['TN3',-4],['TNA',0],['TNX',-1],['TNR',-7],['TNT',-2],['TNF',1],['TNU',-3],['T1N',-2],['T11',-3],['T12',-4],['T13',-5],['T1B',0],['T1X',-2],['T1Y',-2],['T1R',-8],['T1T',-3],['T1F',0],['T1U',-4],['T2N',-3],['T21',-4],['T22',-5],['T23',-6],['T2A',-2],['T2C',0],['T2X',-3],['T2Y',-3],['T2Z',-3],['T2R',-9],['T2T',-4],['T2F',-1],['T2U',-5],['T3N',-4],['T31',-5],['T32',-6],['T33',-7],['T3A',-3],['T3B',-2],['T3X',-4],['T3Y',-4],['T3Z',-4],['T3R',-10],['T3T',-5],['T3F',-2],['T3U',-6],['TAN',0],['TA2',-2],['TA3',-3],['TAR',-6],['TAT',-1],['TXN',-1],['TX1',-2],['TX2',-3],['TX3',-4],['TXR',-7],['TXT',-2],['TRN',-7],['TR1',-8],['TR2',-9],['TR3',-10],['TRA',-6],['TRB',-5],['TRC',-4],['TRX',-7],['TRY',-7],['TRZ',-7],['TRR',-13],['TRT',-8],['TRF',-5],['TRU',-9],['TTN',-2],['TT1',-3],['TT2',-4],['TT3',-5],['TTA',-1],['TTX',-2],['TTR',-8],['TTT',-3],['TTF',0],['TTU',-4],['TFN',1],['TF1',0],['TF2',-1],['TF3',-2],['TFR',-5],['TFT',0],['TUN',-3],['TU1',-4],['TU2',-5],['TU3',-6],['TUA',-2],['TUB',-1],['TUX',-3],['TUY',-3],['TUR',-9],['TUT',-4],['TUU',-5]]
#
points=0
#
dpoints=self[1]-points
z=0
for x in range(len(Pos)):
    y=Pos[x]
    z=0
    for x in C:
     if x[0]==y:z=x[1]
    B.append((z,y))
B.sort()
B=B[::-1]
G=open(file,'r')
H=G.read().split('#')[::-1]
G.close()
G=open(file,'w')
H[3]=H[3].replace(H[3][8:-1],str(self[1]))
J=eval(H[4][3:-1])
A=[B[0][1],dpoints]
P=1
for x in range(0,len(J)):
 if J[x][0]==A[0]:J[x][1]+=A[1];P=0
if P:J.append(A)
H[4]='\nC='+str(J)+'\n'
s=''
for x in H[::-1]:s+=x;s+='#'
G.write(s[:-1])
G.close()
print(B[0][1])
Magenta
fonte
Acho que você tem a entrada comentou na linha # 5
Averroes
Deve ser corrigido agora. Obrigado por apontar isso.
Magenta #