Expressão impassível
Introdução
Leo gosta de jogar pôquer, mas seu trabalho na Tech Inc. é muito exigente para ele aprender a jogar bem. Leo, sendo um cientista da computação, não desanima. Ele decide levar mais tempo do que seria necessário para aprender pôquer e usá-lo para escrever um bot de pôquer para ajudá-lo a jogar melhor. Mas agora Leo tem um problema: para entender como jogar um pouco melhor, Leo precisa observar vários jogos de várias "pessoas", mas as "pessoas" precisam de diferentes estilos de jogo para melhorar a qualidade e a realidade do jogo.
O desafio
Leo lembra que na verdade existe um site dedicado aos desafios de programação e está solicitando sua ajuda! Seu trabalho é escrever um programa que reproduza "Pokerface", uma versão modificada do pôquer de 5 cartas. O programa receberá a entrada como uma mão de 5 cartas, em qualquer formato que você desejar, após o qual o programa produzirá:
- Exatamente (com distinção entre maiúsculas e minúsculas) "verdadeiro" "1" ou "t" se o jogador desejar trocar cartões, qualquer outra saída não vazia de outra forma.
- Se verdadeiro, lista de índices de cartas e / ou nomes de cartas que o jogador deseja trocar.
- Um único número entre 0 e 3, que especifica quantas cartas adicionais o jogador deseja.
- Imprima a mão que o jogador deseja usar.
(Veja a formatação abaixo)
Regras do Pokerface
- Como o pokerface é um jogo de aventura baseado em texto, as cartas devem ser apresentadas de maneira consistente. As cartas são representadas por dois códigos de caracteres, o primeiro caractere é o naipe e o segundo é o nome da carta.
- Cartões:
- 2-9 = 2-9
- 10 = T
- Jack = J
- Rainha = Q
- King = K
- Ace = A
- Ternos:
- Espadas = S
- Clubes = C
- Corações = H
- Diamante = D
- Cartões:
Então o ás de espadas seria SA, o 10 de copas é HT, o quarto de diamantes é D4, etc.
- Uma única rodada do Pokerface consiste em quatro etapas:
- O baralho é embaralhado e uma mão de cinco cartas é distribuída para cada jogador.
- Cada jogador tem a chance de trocar quantas cartas quiser.
- Cada jogador tem a chance de ganhar até mais três cartas.
- Cada jogador deve revelar sua melhor mão.
- A melhor mão vence e ganha um ponto para o jogador. Em caso de empate, os dois jogadores ganham um ponto.
- Em um único jogo, dez rodadas são disputadas e o jogador com mais pontos ganha e ganha um único "ponto de vitória". Em caso de empate, os dois jogadores ganham um ponto de vitória.
- Leo realmente não tem uma grande quantidade de dinheiro, então seu bot pode assumir que este é um mundo perfeito sem apostas.
Mãos
- As mãos têm exatamente 5 cartas de comprimento (entrada inicial e saída final).
- As mãos são classificadas de acordo com as regras descritas aqui .
Entrada / Saída
- Leo conhece apenas Java, portanto, seu programa deve ser executável por meio da API de processos (linha de comando) e usar STDIN e STDOUT para entrada e saída, respectivamente.
- Para cada etapa de entrada e saída detalhada acima, cada entrada e saída devem existir em uma linha.
- Deve haver pelo menos uma nova linha após a saída final. (Isso ocorre devido à maneira como a entrada é lida em STDIN)
- Nenhuma entrada / saída estranha é permitida, exceto espaços à direita e à direita. O analisador simplesmente não entende coisas como
final_hand=...
oudraw 0
. - Ao desenhar, a saída é um único número inteiro, quando a saída da troca é uma lista de números inteiros e / ou cartões definidos abaixo e, ao receber a mão original, a saída é uma lista de cartões definidos abaixo.
- Todos os números de entrada / saída devem ser números inteiros positivos na base 10.
- Você pode definir o formato para a entrada do cartão (consulte o formato da postagem abaixo).
- True é definido como exatamente "true", "1" ou "t" e false é qualquer outro valor não vazio.
- Durante a etapa de troca:
- Os índices do cartão devem ser impressos com pelo menos um espaço entre eles (por exemplo
3 4 0
) - Os nomes dos cartões devem ser impressos com pelo menos um espaço entre eles (por exemplo
H4 S8
) - Os nomes e índices do cartão podem ser misturados na saída (por exemplo
0 H7 3 D3
) - Espaços à direita e à esquerda são permitidos.
- A entrada resultante do reprodutor acima será formatada conforme especificado pelo
bot.jlsc
arquivo, na mesma ordem solicitada
- Os índices do cartão devem ser impressos com pelo menos um espaço entre eles (por exemplo
- O número de cartas que um jogador deseja adicionar à sua mão pode ter espaços iniciais e finais.
- As mãos devem ser produzidas com pelo menos um espaço entre elas (por exemplo
H4 D5 CA
), espaços à direita e à esquerda são permitidos. - As mãos não precisam ser produzidas na ordem correta (por exemplo,
H4 D4 C4 DA SA
eH4 DA D4 SA C4
ambas representam 4, 4, 4, Ás, Ás, que é um full house). - Se você deseja construir uma estratégia analisando as mãos dos oponentes, pode armazenar dados em um
<botname>/data
diretório.- Depois que os bots concorrentes exibirem suas mãos, eles serão gravados em todos os diretórios de dados de bots, em hands.txt, com cada mão em uma nova linha (separada por \ n). O arquivo será codificado em US_ASCII.
- Depois que seu bot solicitar novos cartões ou trocar cartões, os cartões serão inseridos dependendo do formato que você especificar no
bot.jlsc
arquivo.
Formato da postagem
- Cada postagem deve incluir duas coisas:
- O código-fonte do seu bot ou um link para um repositório público.
- Um arquivo zip contendo:
- A versão compilada / executável do seu bot (se o arquivo for um arquivo .exe ou outro arquivo não descompilável, inclua apenas instruções de compilação na sua publicação).
- Um
bot.jlsc
arquivo, veja abaixo (nota lateral: a extensão .jlsc é apenas por causa de um projeto paralelo meu, um formato de configuração. O arquivo abaixo corresponde à sintaxe apropriada, portanto, não se preocupe).
- O arquivo .zip deve ter o mesmo nome do seu bot.
- Se você não tiver acesso ao Windows ou algum outro utilitário de zipagem ou não puder criar um .zip por qualquer motivo, inclua o texto do arquivo bot.jlsc na sua postagem
arquivo bot.jlsc:
name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"
Onde:
- "cmd" é o comando de linha de comando do Windows para executar seu bot. Note que seu bot estará no diretório
<botname>
, então ajuste o comando de acordo. - "nome" é o nome do seu bot.
- "link" é o link para sua resposta. Você precisará editá-lo depois de postar.
- "input_hand" é como você deseja que o negócio original seja formatado (com $ {#} representando os cartões de 0 a 4).
- "input_1" é como você deseja que a entrada de um cartão adicional seja formatada.
- "input_2" é como você deseja que a entrada de dois cartões adicionais seja formatada.
- "input_3" é como você deseja que a entrada de três cartões adicionais seja formatada.
- "input_4" é como você deseja que a entrada de quatro cartões adicionais seja formatada.
Específicos
- Essas brechas não são permitidas (consulte "armadilhas comuns")
- Você não pode escrever um bot, sempre exibirá a melhor mão possível, sempre, dentro do conjunto de regras. (ou seja, sem bots de força bruta de longa duração, nada deve ser tão "bom" quanto o LeoBot)
- Seu bot deve rodar em ~ 100 ms ou menos (neste momento, máximo de ~ 1 segundo)
- Qualquer saída do bot após a mão escolhida será ignorada.
- As brechas padrão não são permitidas.
- Sim, eu sei que o Linux é melhor, mas eu tenho um PC com Windows, portanto, certifique-se de que a versão compilada / executável do seu programa possa ser executada na linha de comando do Windows.
- Eu já tenho python e java instalado no meu computador, mas estou disposto a atualizar para novas versões e instalar outros ambientes; portanto, especifique que tipo de ambiente o seu programa exige.
- Você não pode escrever um bot que faça o mesmo que outro bot em todos os casos. Bots de spam são permitidos, mas desencorajados.
- Seu bot pode usar apenas cartões que possui. Os cartões perdidos em troca ou não negociados no início são inválidos na mão final.
- Entrada e saída podem conter apenas caracteres ASCII.
Torneios
- Os torneios ocorrerão quando eu chegar no horário (minha agenda é quase tão cheia quanto a de Leo, então isso é um pouco raro. Desculpe pelo inconveniente.).
- Os bots serão disputados entre si em jogos para 4 pessoas, e haverá um jogo para cada subconjunto possível de bots (ou seja, muitos jogos).
- Este processo será repetido cinco vezes.
- Devido à maneira como o manipulador do torneio faz os grupos de bots, até três bots de preenchimento serão adicionados para tornar o número de bots divisível por 4. Esses bots simplesmente retornarão a mão em que foram distribuídos originalmente.
- Após cada rodada e jogo, a pontuação dos bots será calculada com base no número de jogos que eles venceram.
- Vários bots podem compartilhar uma posição (empates pela primeira vitória e pela primeira postagem).
- Após o término de um torneio, as pontuações serão anexadas ao final deste post.
Pontuação
Regras normais de KoTH. Os bots que vencem mais jogos vencem o desafio.
LeoBot
O bot de Leo é bem esperto. Ele não troca cartas, é muito difícil, mas exige o número máximo de cartas adicionais e determina a melhor mão possível que ele pode fazer e joga essa mão. A principal lógica do leobot está abaixo.
package com.gmail.socraticphoenix.pokerface.leobot;
import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class LeoBot {
public static void main(String[] args) {
List<Card> hand = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
hand.addAll(Card.parseHand(scanner.nextLine()));
System.out.println(false);
System.out.println(3);
hand.addAll(Card.parseHand(scanner.nextLine()));
List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
}
private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
if (current.size() == k) {
solution.add(new ArrayList<>(current));
return;
}
if (idx == superSet.size()) return;
T x = superSet.get(idx);
if (!current.contains(x)) {
current.add(x);
}
getSubsets(superSet, k, idx + 1, current, solution);
current.remove(x);
getSubsets(superSet, k, idx + 1, current, solution);
}
public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
List<List<T>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new ArrayList<T>(), res);
return res;
}
}
Observe que, se o LeoBot vencer consistentemente os torneios e houver uma boa quantidade de entradas, eu pararei de incluí-lo na corrida.
Links importantes
aviso Legal
Leo e Tech Inc. são elementos da história e qualquer semelhança com empresas ou pessoas da vida real é puramente não intencional. (No entanto, quando a 'situação' de Leo adiciona ou subtrai condições da pergunta, elas realmente fazem parte da pergunta ...)
"f"q+
atende aos requisitos mínimos. Se houver 10 pessoas em competição, isso provavelmente supera todas as entradas não idiotas (a entrada não idiota provavelmente tem> 75 caracteres, 5 * 10 (pontuação do bot idiota, por último) = 50 <75 (pontuação do bot inteligente muito pequeno (em primeiro lugar))). Thusly, você provavelmente deve remover codegolf deste desafio