Давайте играть в прятки!

12

Пользователь будет прятаться, а компьютер попытается их найти.

Во-первых, программа примет вход для размера сетки. Как 5x5, 10x10, 15x15 и т. Д. Сетка не всегда будет идеальным квадратом.

Сетка вроде шахматной доски:

_______________________________
|     |     |     |     |     |
| A1  |     |     |     |     | A
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     | B2  |     |     |     | B
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     | C3  |     |     | C
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     |     | D4  |     | D
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     |     |     | E5  | E
|_____|_____|_____|_____|_____|
   1     2     3     4     5

Теперь пользователь выберет квадрат, например B2(не сообщая компьютеру)

Компьютер начнет угадывать квадраты. Если он выберет правильный квадрат, пользователь ответит y. Если нет, они будут вводить направление, в котором их плитка выбрана (N, NE, E, SE, S, SW, W).

Так что, если пользователь выбрал B2, и компьютер угадал C3, пользователь будет вводить NW.

Вот пример выходов и входов:

Grid?
5x5

C3?
NW

C2?
N

B2?
y

Подсчет очков:

Это будет забито немного иначе, чем обычный вызов.

Победителем становится программа, которая принимает наименьшее количество догадок (в среднем), необходимое для угадывания правильного квадрата. Усредненные тестовые случаи будут представлять собой все возможные квадраты в 5x5, а затем в 10x10.

Однако он также должен работать с каждым шаблоном сетки до 26 строк (т. Е. 5x8, 6x2, 20x5 и т. Д.).

Пожалуйста, укажите способ его тестирования, такой как JSFiddle.

И, наконец, в случае ничьей побеждает самая короткая программа.

JKonowitz
источник
1
Если я прячусь A1и компьютер догадывается B9, правильный ответ NWили W?
Грег Мартин
@GregMartin Это будет NW .... N, W, S, E все должны быть прямыми, в то время как все в другой строке / столбце должно быть NW, NE, SW, SE
JKonowitz
Есть ли гибкость в конкретном формате ввода и вывода? Если их более 26, как они называются?
Грег Мартин
@GregMartin Вы можете быть гибкими с выходом, но постарайтесь сделать его простым. Это не должно быть точно так же, но должно иметь похожий стиль. Вам не нужно учитывать ничего выше 26, я отредактирую это.
JKonowitz
Я не знаю, что означает «похожий стиль». Можем ли мы принять входные данные как упорядоченную пару целых чисел (row #, col #)? (PS: Эти типы вопросов являются причинами, по которым предварительная публикация задач в Песочнице является отличной идеей.)
Грег Мартин

Ответы:

3

Python 3,6 , 466 398 392 байта, минимакс

x, y = 1, 1
w, h = [int(x) for x in input('Grid?\n').split('x')]


def split_factor(a, b):
    N = b-y
    W = a-x
    S = h+~N
    E = w+~W
    return max(1, N, W, S, E, N*W, S*W, S*E, N*E)


def move(a, b):
    *Z, = zip([a, x, a, a+1, x, x, a+1, a+1],
              [y, b, b+1, b, y, b+1, b+1, y],
              [1, a-x, 1, w+x+~a, a-x, a-x, w+x+~a, w+x+~a],
              [b-y, 1, h+y+~b, 1, b-y, h+y+~b, h+y+~b, b-y])
    return Z[['N', 'W', 'S', 'E', 'NW', 'SW', 'SE', 'NE'].index(d)]

d = ''
while d != 'y':
    print()
    splits = {(a, b): split_factor(a, b) for a in range(x, x+w) for b in range(y, y+h)}
    a, b = min(splits, key=splits.get)
    d = input(f'{a}{"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[b]}?\n')
    x, y, w, h = move(a, b)

Вход и выход должны быть в форме, показанной в примере. Это находит квадрат с минимальным «фактором разделения» - который является наибольшей оставшейся областью, которая может быть получена в результате ответа игрока (то есть NW, E, y и т. Д.) - и предполагает это. Да, это всегда центр оставшейся области в этой игре, но этот метод минимизации наихудшего случая будет работать более широко в подобных играх с другими правилами.

Нечитаемая версия:

x=y=d=1
w,h=map(int,input('Grid?\n').split('x'))
while d!='y':print();s={(a,b):max(b-y,h+y+~b)*max(w+x+~a,a-x)for a in range(x,x+w)for b in range(y,y+h)};a,b=min(s,key=s.get);d=input(f'{a}{chr(64+b)}?\n');*z,=zip([a+1,x,a+1,x,a,a,a+1,x],[b+1,b+1,y,y,b+1,y,b,b],[w+x+~a,a-x,w+x+~a,a-x,1,1,w+x+~a,a-x],[h+y+~b,h+y+~b,b-y,b-y,h+y+~b,b-y,1,1]);x,y,w,h=z[~'WENS'.find(d)or-'NWNESWSE'.find(d)//2-5]
Бен Франкель
источник
2

Mathematica, оптимальное поведение в тестовых случаях, 260 байт

For[a=f=1;{c,h}=Input@Grid;z=Characters;t=<|Thread[z@#->#2]|>&;r="";v=Floor[+##/2]&;b:=a~v~c;g:=f~v~h,r!="y",r=Input[g Alphabet[][[b]]];{{a,c},{f,h}}={t["NSu",{{a,b-1},{b+1,c},{b,b}}]@#,t["uWX",{{g,g},{f,g-1},{g+1,h}}]@#2}&@@Sort[z@r/.{c_}:>{c,"u"}/."E"->"X"]]

Эта программа может быть протестирована путем вырезания и вставки вышеуказанного кода в Wolfram Cloud . (Протестируйте быстро, хотя: я думаю, что для каждого запуска программы существует ограничение по времени.) Предположения программы выглядят 2 cвместо C2, но в остальном она выполняется в соответствии со спецификацией выше. Сетка должна быть введена как упорядоченная пара целых чисел, как {26,100}, и ответы на догадки программы должны быть введены как строки, как "NE"или "y".

Программа отслеживает наименьший и наибольший номер строки и номера столбца, который соответствует входным данным, и всегда угадывает центральную точку подсетки возможностей (округление NW). Программа является детерминированной, поэтому легко вычислить количество угадываний, которое требуется в среднем по фиксированной сетке. В сетке 10x10 программа требует 1 предположение для одного квадрата, 2 догадки для восьми квадратов, 3 догадки для 64 квадратов и 4 догадки для оставшихся 27 квадратов, в среднем 3,17; и это теоретический минимум, учитывая, сколько последовательностей 1-угадывание, 2-угадывание и т. д. может привести к правильным предположениям. Действительно, программа должна достичь теоретического минимума на сетке любого размера по аналогичным причинам. (На сетке 5x5 среднее количество догадок составляет 2,6.)

Небольшое объяснение кода, хотя это довольно просто, кроме игры в гольф. (Я изменил порядок некоторых инициализирующих операторов для пояснительных целей - не влияет на количество байтов.)

1  For[a = f = 1; z = Characters; t = <|Thread[z@# -> #2]|> &;
2      v = Floor[+##/2] &; b := a~v~c; g := f~v~h;
3      r = ""; {c, h} = Input@Grid, 
4    r != "y", 
5    r = Input[g Alphabet[][[b]]];
6      {{a, c}, {f, h}} = {t["NSu", {{a, b - 1}, {b + 1, c}, {b, b}}]@#, 
7        t["uWX", {{g, g}, {f, g - 1}, {g + 1, h}}]@#2} & @@ 
8        Sort[z@r /. {c_} :> {c, "u"} /. "E" -> "X"]
   ]

Строки 1-3 инициализируют Forцикл, который на самом деле является просто Whileзамаскированным циклом, так что, эй, на два байта меньше. Возможные диапазоны номеров строк и номеров столбцов в любой момент сохраняются {{a, c}, {f, h}}, и центрированное предположение в этой подсетке вычисляется функциями, {b, g}определенными в строке 2. Строка 3 инициализирует cстолбец max-row и max-столбец hиз пользовательского ввода, и также инициализирует, rкоторая является проверенной петлей переменной, а также последующие пользовательские вводы.

В то время как тест в строке 4 выполнен, строка 5 получает ввод от пользователя, где подсказка приходит из текущего предположения {b, g}( Alphabet[][[b]]]преобразует номер строки в букву). Затем строки 6-8 обновляют подсеть возможностей (и, следовательно, неявно следующее предположение). Например, t["NSu", {{a, b - 1}, {b + 1, c}, {b, b}}](учитывая определение в tстроке 1) расширяется до

<| "N" -> {a, b - 1}, "S" -> {b + 1, c}, "u" -> {b, b}|>

где вы можете видеть, как номера мин и рядов обновляются в соответствии с последним вводом пользователя. Строка 8 преобразует любой возможный ввод в упорядоченную пару символов в форме { "N" | "S" | "u", "u" | "W" | "X"}; здесь "u"обозначает правильный ряд или столбец и "X"обозначает восток (просто, Sortчтобы работать хорошо). Когда пользователь, наконец, вводит данные "y", эти строки выдают ошибку, но затем проверка цикла завершается неудачей, и ошибка никогда не распространяется (программа все равно просто останавливается).

Грег Мартин
источник
0

Пакетно, разделяй и властвуй

@echo off
set z = ABCDEFGHIJKLMNOPQRSTUVWXYZ
set /p g = Grid?
set /a w = 0, n = 0, e = %g :x= + 1, s = % + 1
:l
set /a x = (w + e) / 2, y = (n + s) / 2
call set c = %%z :~%y%,1%%
set /p g = %c %%x%?
if %g :w=.% == %g % set /a w = x
if %g :n=.% == %g % set /a n = y
if %g :e=.% == %g % set /a e = x
if %g :s=.% == %g % set /a s = y
if %g :y=.% == %g % goto l

Работает, создавая ограничивающую рамку области, которую еще предстоит найти. Следующее предположение - всегда центр коробки. Для тех точек компаса, которые не включены в ответ, поле уменьшается в этом направлении. Например, для ответа Nслева, справа и снизу поля установлены угаданные квадраты.

На 369 байтах я не собираюсь никого побеждать, поэтому оставил пробелы для удобства чтения.

Нил
источник
Что ж, «разделяй и властвуй», как правило, полезно для больших тестовых случаев, но не для маленьких, лучше алгоритмы?
Мэтью Ро
@SIGSEGV Не уверен, что вы имеете в виду; В ответах Грега и Бена также используется метод центра поля.
Нил
Нам все еще нужен лучший алгоритм.
Мэтью Ро
@SIGSEGV Метод центра коробки оптимален. Нет лучшего алгоритма.
TheNumberOne