Dada uma lista de pontos, encontre o caminho mais curto que visite todos os pontos e retorne ao ponto de partida.
O Problema do Vendedor Viajante é bem conhecido no campo da ciência da computação, pois há muitas maneiras de calcular / aproximar esse problema. Foi resolvido para grupos muito grandes de pontos, mas alguns dos maiores levam muitos anos de CPU para serem concluídos.
Não se queime pela batata.
Hot Potato é um jogo em que mais de 2 jogadores passam uma "batata" em círculo enquanto a música toca. O objetivo é passá-lo para o próximo jogador rapidamente. Se você estiver segurando a batata quando a música parar, estará fora.
O objetivo do vendedor de batata quente é:
Dado um conjunto de 100 pontos únicos , retorne esses pontos em uma ordem melhor ( distância total menor, conforme definido mais abaixo ). Isso "passará" o problema para o próximo jogador. Eles precisam aprimorá-lo e passá-lo para o próximo, etc. Se um jogador não puder melhorá-lo, eles estarão fora e o jogo continuará até que um jogador seja deixado.
Para evitar que isso seja uma competição de "força bruta-por-um-caminho", existem as seguintes estipulações:
Você não pode demorar mais de um minuto para passar a batata. Se você não encontrou e aprovou uma solução mais curta quando termina um minuto, está fora.
Você não pode alterar a posição de mais de 25 pontos. Para ser exato, os
>= 75
pontos devem estar na mesma posição em que você os recebeu. Não importa quais você decide mudar, apenas a quantidade que você muda.
Quando resta apenas um jogador, ele é o vencedor do jogo e recebe um ponto. Um torneio consiste em 5*n
jogos, onde n
é o número de jogadores. A cada jogo, o jogador inicial será girado e a ordem restante do jogador será embaralhada . O jogador com mais pontos no final é o vencedor do torneio. Se o torneio terminar empatado em primeiro lugar, um novo torneio será disputado apenas com esses competidores. Isso continuará até que não haja empate.
O jogador inicial de cada jogo receberá um conjunto de pontos selecionados pseudo-aleatoriamente em nenhuma ordem específica.
Os pontos são definidos como um par de x,y
coordenadas inteiras em uma grade cartesiana. A distância é medida usando Manhattan distância , |x1-x2| + |y1-y2|
. Todas as coordenadas estarão no [0..199]
intervalo.
Entrada
A entrada é fornecida com um argumento de cadeia única. Ele consistirá em 201 inteiros separados por vírgula, representando o número de jogadores atuais ( m
) e 100 pontos:
m,x0,y0,x1,y1,x2,y2,...,x99,y99
A ordem desses pontos é o caminho atual. A distância total é obtida adicionando a distância de cada ponto ao próximo ( dist(0,1) + dist(1,2) + ... + dist(99,0)
). Não se esqueça de voltar ao início ao calcular a distância total!
Note que m
é não o número de jogadores que iniciaram o jogo, é o número que ainda está dentro
Saída
A saída é dada da mesma maneira que a entrada, menos m
; uma única sequência contendo números inteiros separados por vírgula, representando os pontos em sua nova ordem.
x0,y0,x1,y1,x2,y2,...,x99,y99
O programa de controle aguardará a saída por apenas um minuto. Quando a saída é recebida, ele verifica se:
- a saída é bem formada
- a saída consiste em apenas e todos os 100 pontos presentes na entrada
>=75
pontos estão em suas posições originais- o comprimento do caminho é menor que o caminho anterior
Se alguma dessas verificações falhar (ou não houver saída), você estará fora e o jogo prosseguirá para o próximo jogador.
Programa de Controle
Você pode encontrar o programa de controle neste link . O programa de controle em si é determinístico e é lançado com uma semente fictícia de1
. A semente usada durante a pontuação será diferente, portanto, não se preocupe em tentar analisar a lista de pontos / ordem dos turnos que ela cospe.
A classe principal é Tourney
. Se isso acontecer, será realizado um torneio completo, com os participantes como argumentos. Ele cuspiu o vencedor de cada jogo e uma contagem no final. Um torneio de amostra com dois SwapBots é semelhante a:
Starting tournament with seed 1
(0) SwapBot wins a game! Current score: 1
(1) SwapBot wins a game! Current score: 1
(1) SwapBot wins a game! Current score: 2
(1) SwapBot wins a game! Current score: 3
(0) SwapBot wins a game! Current score: 2
(1) SwapBot wins a game! Current score: 4
(1) SwapBot wins a game! Current score: 5
(1) SwapBot wins a game! Current score: 6
(1) SwapBot wins a game! Current score: 7
(1) SwapBot wins a game! Current score: 8
Final Results:
Wins Contestant
2 (0) SwapBot
8 (1) SwapBot
Se você quiser testar apenas um jogo de cada vez, poderá executar a Game
aula. Isso executará um jogo com os jogadores na ordem dada como argumento. Por padrão, ele também imprimirá uma reprodução por reprodução, mostrando o player atual e o comprimento do caminho.
Também estão incluídos alguns jogadores de teste: SwapBot
, BlockPermuter
, e TwoSwapBot
. Os dois primeiros não serão incluídos nas execuções de pontuação; portanto, fique à vontade para usá-los e abusar deles durante o teste. TwoSwapBot
vai incluído no julgamento, e ele não é desleixado, então traga seu A-game.
Miscelânea
Você não pode salvar informações de estado e cada turno é uma execução separada do seu programa. A única informação que você receberá a cada turno é o conjunto de pontos.
Você não pode usar recursos externos. Isso inclui chamadas de rede e acesso a arquivos.
Você não pode usar as funções da biblioteca projetadas para resolver / ajudar com o problema do TSP ou suas variantes.
Você não pode manipular ou interferir com outros jogadores de forma alguma.
Você não pode manipular ou interferir no programa de controle ou em quaisquer classes ou arquivos incluídos de forma alguma.
Multi-threading é permitido.
Um envio por usuário. Se você enviar mais de uma entrada, inserirei apenas a primeira. Se você deseja alterar seu envio, edite / exclua o original.
O torneio será executado no Ubuntu 13.04, em um computador com um CPU i7-3770K e 16GB de RAM. Não será executado em uma VM. Qualquer coisa que eu considere maliciosa desqualificará imediatamente a entrada atual e futura que você enviar.
Todas as entradas devem ser executáveis na linha de comando com free ( como na cerveja ). Se eu tiver problemas para compilar / executar sua entrada, solicitarei ajuda nos comentários. Se você não responder ou se eu não conseguir colocá-lo em execução, ele será desqualificado.
Resultados (22 de maio de 2014)
Novos resultados estão chegando! O UntangleBot venceu bastante a concorrência. O TwoSwapBot conseguiu sete vitórias e o SANNbot também obteve uma vitória. Aqui está um placar e um link para a saída bruta :
Wins Contestant
22 (2) ./UntangleBot
7 (0) TwoSwapBot
1 (5) SANNbot.R
0 (1) BozoBot
0 (3) Threader
0 (4) DivideAndConquer
Como está agora , o UntangleBot ganhou a marca de seleção. Não deixe que isso o desanime de participar, pois eu vou disputar o torneio à medida que mais competidores aparecerem e mudar a resposta aceita de acordo.
fonte
Respostas:
UntangleBot (anteriormente NiceBot)
Um bot C ++ 11 que usa duas estratégias.
Inicialmente, ele tentará "desembaraçar" o caminho, se possível, detectando interseções entre caminhos com menos de 25 pontos (uma vez que desembaraçar implica modificar todos os pontos intermediários).
Se a primeira estratégia falhar, alterna aleatoriamente pontos para encontrar distâncias melhores até que um caminho melhor seja encontrado.
Esse bot vence o TwoSwapBot de forma consistente com uma proporção aproximada de cinco vitórias por uma perda nos meus torneios de teste.
fonte
SANNbot
(um bot de recozimento simulado em R )
Deve ser chamado com
Rscript SANNbot.R
.A idéia é relativamente simples: cada turno é um "passo de resfriamento" de um recozimento simulado com o número de jogadores ainda no jogo como "temperatura" (modificado pela distância atual acima de 12000, ou seja, aproximadamente a distância inicial). A única diferença com um recozimento simulado adequado é que eu verifiquei que não permuto mais de 25 elementos e se usei 20 movimentos, mas a sequência resultante vale mais que a inicial, e então recomeça.
fonte
java Tourney "java Swapbot" "Rscript SANNbot.R"
e parecia funcionar.u
aumentar os limites de verificação, isso não acontece (e tem um desempenho muito melhor). Embora seu código pareça bastante direto, eu não conheço as peculiaridades de R, então não sei dizer se a lógica está errada. (a versão mais recente do controlador dará mensagens sobre por que um bot sai durante a execuçãoGame
, de modo que possam ajudar a identificar o problema)BozoBot
Utiliza a lógica complexa por trás do Bozosort para encontrar um caminho melhor. Se parece com isso.
O BozoBot agora foi aprimorado com o Multithreading ! Agora quatro lacaios fazem malabarismos sem rumo, até encontrar uma melhoria. O primeiro a encontrar uma solução recebe um cookie!Aparentemente, falhei no multithreading.
fonte
new Thread(new Minion()).start()
TwoSwapBot
Uma atualização para
SwapBot
, esse cara verifica todos os swaps. Primeiro, ele verifica se alguma troca única reduzirá o caminho. Se isso acontecer, ele retornará imediatamente. Caso contrário, ele verifica cada uma para ver se outra troca a reduzirá. Caso contrário, ele simplesmente morre.Enquanto o caminho ainda é semi-aleatório, ele normalmente retorna em cerca de 100ms. Se ele tiver que verificar cada 2-swap (aproximadamente 25M), leva cerca de 20 segundos.
No momento da apresentação, isso venceu todos os outros concorrentes nas rodadas de teste.
fonte
Threader
Este bot
410 peças de2510 pontosA idéia é encontrar a melhor melhoria no caminho, para que os outros bots falhem com sua lógica.
fonte
println
paraprint
para me livrar da nova linha no final da sua saída. Caso contrário, ele trava.println
paraprint
e fez a dinâmica contagem de fios. Agora começa com 10 threads ...Dividir e conquistar + Bot ganancioso
NOTA:
Game
Examinei o seu código, o qual inclui o seguinte em Game.parsePath:No entanto, como não há
catch(NumberFormatException)
bloqueio, o seu programa provavelmente trava quando um programa reproduz uma string (como demonstrado no final domain
método do meu programa ). Aconselho que você corrija isso, porque os programas podem gerar exceções, rastrear pilhas ou similares. Caso contrário, comente essa linha no meu programa antes de executá-la.Voltar ao tópico
Esta implementação (em Java) divide a lista de pontos em pedaços de 25, espaçados aleatoriamente na lista. Em seguida, ele cria threads para encurtar o caminho entre os pontos em cada bloco (daí, "Divide and Conquer"). O thread principal monitora os outros e apresenta a solução mais curta dentro do prazo. Se um encadeamento morre com ou sem solução, ele inicia outro encadeamento novamente em um pedaço diferente.
Cada thread usa o algoritmo "ganancioso", que inicia em um ponto aleatório, vai para o ponto mais próximo e se repete até que todos os pontos sejam cobertos (por isso, "ganancioso").
Notas
Basta compilar e usar
java DivideAndConquer.class
para executar.fonte
<200
tokens antes de tentar analisar. Ainda melhor verificar isso de qualquer maneira.)
na linha 19; mudesubstr
parasubstring
em 38; inicializeidx
para algo norun()
método