Беземоційне обличчя
Вступ
Лео подобається грати в покер, але його робота в Tech Inc. занадто вимоглива до нього, щоб навчитися грати добре. Лев, будучи комп'ютерним науковцем, не відлякує. Він вирішує зайняти більше часу, ніж знадобиться, щоб просто вивчити покер, і використовувати його для написання бота в покер, щоб допомогти йому грати краще. Але тепер у Лео є проблема: щоб зрозуміти, як грати трохи краще, Лео потрібно спостерігати за кількома іграми кількох «людей», але «людям» потрібні різні стилі гри, щоб поліпшити якість та реальність гри.
Змагання
Лео нагадує, що насправді існує веб-сайт, присвячений проблемам програмування, і залучає вашу допомогу! Ваше завдання - написати програму, яка грає в "Pokerface" модифіковану версію покеру на 5 карт. Програма буде приймати вклад як 5-картка в будь-якому форматі, який ви бажаєте, після чого програма виводить:
- Точно (з урахуванням регістру) "справжнього" "1" або "t", якщо гравець бажає обміняти картки, будь-який інший не порожній вихід.
- Якщо це правда, перелік індексів карт та / або імен карт, які гравець хоче обміняти.
- Єдине число від 0 до 3, яке вказує, скільки додаткових карт хоче гравець.
- Роздрукуйте руку, яку хоче використати гравець.
(Дивіться форматування нижче)
Правила Pokerface
- Оскільки покерфактор є текстовою пригодницькою грою, картки повинні бути представлені послідовно. Картки представлені двома символьними кодами, перший символ - костюм, а другий - назва картки.
- Картки:
- 2-9 = 2-9
- 10 = Т
- Джек = J
- Королева = Q
- Король = К
- Туз = А
- Костюми:
- Лопати = S
- Клуби = С
- Серця = Н
- Алмаз = D
- Картки:
Отже, туз лопат був би SA, 10 сердечок - HT, четверте з діамантів - D4 тощо.
- Один раунд Pokerface складається з чотирьох кроків:
- Колода перестановлюється і кожному гравцеві передається п’ять карт.
- Кожному гравцеві надається можливість обміняти якомога більше карт.
- Кожному гравцеві надається можливість отримати до трьох карт.
- Кожен гравець повинен розкрити свою найкращу руку.
- Найкраща рука виграє і набирає гравцю очко. У разі нічиєї, обидва гравці отримують очко.
- В одній грі проводиться десять раундів, і гравець з найбільшою кількістю очок виграє і отримує єдину "виграшну очку". У разі вирівнювання, обидва гравці отримують виграшну очко.
- Лев насправді не має великої кількості грошей, тому ваш бот може припустити, що це ідеальний світ, де немає ставок.
Руки
- Руки мають рівно 5 карт у довжину (початковий вхід та кінцевий вихід).
- Руки класифікуються відповідно до описаних тут правил .
Введення-виведення
- Лео знає лише Java, тому ваша програма повинна виконуватися через API API (командний рядок), а також використовувати STDIN та STDOUT для введення та виведення відповідно.
- Для кожного етапу введення та виводу, детально описаного вище, кожен вхід і вихід повинні існувати в одному рядку.
- Після кінцевого результату повинен бути принаймні один зворотний новий рядок. (Це пов’язано з способом зчитування вхідних даних із STDIN)
- Не допускаються сторонні введення / виведення, крім проміжних і провідних пробілів. Парсер просто не розуміє таких речей, як
final_hand=...
абоdraw 0
. - Під час малювання, вихід - це єдине ціле число, при обміні результатами - це цілий список чи / та карт, визначений нижче, а при передачі оригінальної руки виведення - це список карт, визначений нижче.
- Усі вхідні / вихідні номери повинні бути додатними цілими числами в базі 10.
- Ви можете визначити формат для введення картки (див. Формат публікації нижче).
- True визначається як "true", "1" або "t", а false - будь-яке інше не порожнє значення.
- Під час кроку обміну:
- Індекси карт повинні бути виведені з принаймні одним проміжком між ними (наприклад
3 4 0
) - Імена карт повинні бути виведені з принаймні одним проміжком між ними (наприклад
H4 S8
) - Імена та індекси карт можуть бути змішані у висновку (наприклад
0 H7 3 D3
) - Доступні пробіли та провідні місця.
- Вхід у результаті програвача, який виводить вище, буде форматований, як зазначено
bot.jlsc
файлом, у тому ж порядку, що і запитувалося
- Індекси карт повинні бути виведені з принаймні одним проміжком між ними (наприклад
- Кількість карт, які гравець хоче додати до своєї руки, може мати провідні та відсталі місця.
- Руки повинні бути виведені з принаймні одним пробілом між ними (наприклад
H4 D5 CA
), дозволені проміжки та провідні місця. - Руки не повинні бути виведені в правильному порядку (наприклад ,
H4 D4 C4 DA SA
іH4 DA D4 SA C4
обидва представляють собою 4, 4, 4, Ace, Ace, який є повним будинком). - Якщо ви хочете створити стратегію, аналізуючи руки опонентів, ви можете зберігати дані в
<botname>/data
каталозі.- Після того, як конкуруючі боти показали свої руки, вони будуть записуватися до кожного каталогу даних ботів, в hands.txt, з кожною рукою в новому рядку (розділеному \ n). Файл буде закодовано в US_ASCII.
- Після того, як ваш бот запитує нові картки або обмінні картки, вони будуть вводитись залежно від формату, який ви вказали у
bot.jlsc
файлі.
Формат повідомлення
- Кожна публікація повинна містити дві речі:
- Вихідний код вашого бота або посилання на загальнодоступне сховище.
- Zip-файл, що містить:
- Скомпільована / виконувана версія вашого бота (Якщо файлом є .exe або інший файл, який не піддається компіляції, будь ласка, просто додайте інструкції щодо компіляції у свій пост).
bot.jlsc
Файл, дивіться нижче (сторона примітка: .jlsc розширення тільки з сайд - проекту шахти, формат конфігурації Файл нижче сірників правильний синтаксис, так що не хвилюйтеся.).
- Файл .zip повинен бути названий таким же, як і ваш бот.
- Якщо у вас немає доступу до Windows чи іншої утиліти ZIP, або ви не можете зробити .zip з будь-якої причини, просто додайте текст файлу bot.jlsc у свій пост
Файл 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}"
Де:
- "cmd" - команда командного рядка Windows для запуску вашого бота. Зауважте, що ваш бот буде в каталозі
<botname>
, тому відповідно налаштуйте команду. - "name" - це ім'я вашого бота.
- "link" - посилання на вашу відповідь, вам доведеться відредагувати це після публікації.
- "input_hand" - це те, як ви хочете відформатувати оригінальну угоду ($ {#}, що представляє картки 0-4).
- "input_1" - це форматування введення однієї додаткової картки.
- "input_2" - це те, як ви хочете форматувати вхід двох додаткових карток.
- "input_3" - це те, як ви хочете форматувати вхід трьох додаткових карток.
- "input_4" - це те, як ви хочете форматувати вхід чотирьох додаткових карток.
Особливості
- Ці лазівки заборонені (див. "Загальні підводні камені")
- Ви не можете писати бота, він завжди виводить найкращу можливу руку в рамках набору правил. (тобто немає тривалих бот-грубої сили, нічого не повинно бути настільки "хорошим", як LeoBot)
- Ваш бот повинен працювати більше ~ 100 мс або менше (поблажливіший на цей момент, максимум ~ 1 секунду)
- Будь-який вихід бота після обраної руки буде ігнорований.
- Стандартні лазівки заборонені.
- Так, я знаю, що Linux краще, але у мене є Windows PC, тому переконайтеся, що компільована / виконувана версія вашої програми може бути запущена з командного рядка Windows.
- У мене вже встановлені python та java на моєму комп’ютері, але я готовий оновити нові версії та встановити інші середовища, тому, будь ласка, вкажіть, який тип середовища потребує ваша програма.
- Ви не можете писати бота, який робить те саме, що інший бот у кожному випадку. Спам-боти дозволені, але не рекомендуються.
- Ваш бот може використовувати лише ті картки, які він має. Карти, втрачені через обмін або не розпочаті з початку, мають недійсний вихід у кінцевій руці.
- Введення та вихід можуть містити лише символи ASCII.
Турніри
- Турніри будуть проводитись, коли я знайду час (мій графік майже такий же упакований, як у Лео, тому це моє бути трохи нечасто. Вибачте за незручності.)
- У чотирьох іграх для чотирьох ботів буде протистояти іншим, і буде одна гра для кожного можливого набору ботів (тобто багато ігор).
- Цей процес повториться п’ять разів.
- Зважаючи на те, як обробник турніру складає групи ботів, буде додано до трьох ботів для заповнення, щоб число ботів було розділеним на 4. Ці боти просто повернуть ту руку, якою вони були розроблені.
- Після кожного раунду та гри, кількість ботів підраховується на основі кількості виграних ігор.
- Кілька ботів можуть ділити позицію (зв'язки для перших виграних першими опублікованими).
- Після завершення турніру, бали будуть додані внизу цієї публікації.
Оцінка балів
Нормальні правила KoTH. Бот (и), які виграють у більшості ігор, виграють виклик.
ЛеоБот
Бот Лео досить розумний. Він не обмінює жодної карти, це занадто важко, але він вимагає максимальної кількості додаткових карт, і він визначає найкращу можливу руку, яку він може зробити, і грає в цю руку. Основна логіка леобота наведена нижче.
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;
}
}
Зауважте, що якщо ЛеоБот послідовно виграє турніри, і є хороша кількість заявок, я перестану включати його в біг.
Важливі посилання
Відмова від відповідальності
Leo та Tech Inc. є елементами історії, і будь-яка схожість з реальними компаніями чи людьми є чисто ненавмисною. (Однак, коли "ситуація" Лео додає або віднімає умови запитання, вони фактично є частиною питання ...)
"f"q+
відповідає мінімальним вимогам. Якщо у змаганнях 10 чоловік, це, ймовірно, перемагає всі немітні записи (мабуть, німий запис має> 75 символів, 5 * 10 (оцінка тупого бота, останній) = 50 <75 (оцінка дуже маленького розумного бота (підходить першим))). Таким чином, ви, ймовірно, повинні видалити кодгольф від цього виклику