Подтвердить что ты не робот

Алгоритм поиска улиц и того же вида в руке

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

В маджонге 14 плиток (плитки похожи на карты в Покере) расположены на 4 набора и на пару. Улица ( "123" ) всегда использует ровно 3 плитки, не более и не менее. Набор такого же типа ( "111" ) состоит также из 3 плиток. Это приводит к сумме 3 * 4 + 2 = 14 плиток.

Существуют различные исключения, такие как Кан или Тринадцать сирот, которые здесь не актуальны. Цвета и диапазоны значений (1-9) также не важны для алгоритма.

Я пытаюсь определить, может ли рука быть организована так, как описано выше. По определенным причинам он должен не только иметь дело с 14, но и с любым количеством плиток. (Следующим шагом было бы найти, сколько фрагментов нужно обменивать, чтобы иметь возможность выполнить руку.)

Примеры:

11122233344455 - достаточно легко, 4 набора и пара.
12345555678999 - 123, 456, 789, 555, 99
11223378888999 - 123, 123, 789, 888, 99
11223344556789 - не действительная рука

Моя текущая и еще не реализованная идея такова: для каждой плитки попробуйте сделать a) улицу b) набор c) пару. Если ни один не работает (или будет > 1 пара), вернитесь к предыдущей итерации и попробуйте следующую опцию, или, если это самый высокий уровень, сбой. В противном случае удалите использованные плитки из списка оставшихся фрагментов и продолжите следующую итерацию.

Я считаю, что этот подход работает, а также будет достаточно быстрым (производительность - "хороший бонус" ), но меня интересует ваше мнение по этому поводу. Можете ли вы подумать об альтернативных решениях? Это или что-то подобное уже существует?

(Не домашнее задание, Я учусь играть в маджонг.)

4b9b3361

Ответ 1

Сумма значений на улице и в наборе может быть разделена на 3:

  • n + n + n = 3n
  • (n-1) + n + (n + 1) = 3n

Итак, если вы соедините все числа в разрешенной руке, вы получите номер формы 3N + 2M, где M - значение плитки в паре. Остальная часть деления на три (total % 3) равна, для каждого значения M:

total % 3 = 0  -> M = {3,6,9}
total % 3 = 1  -> M = {2,5,8}
total % 3 = 2  -> M = {1,4,7}

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

Как только вы это сделаете, начните с самого низкого значения. Если есть меньше трех плиток с этим значением, это означает, что они обязательно являются первым элементом улицы, поэтому удалите эту улицу (если вы не можете, так как плитки n + 1 или n + 2 отсутствуют, это означает, что рука недействительна) и перейти к следующему наименьшему значению.

Если есть по крайней мере три плитки с наименьшим значением, удалите их как набор (если вы спросите "что, если они были частью улицы?", подумайте, что если бы они были, то есть также три плитки n + 1 и три плитки n + 2, которые также можно превратить в наборы) и продолжить.

Если вы достигнете пустой руки, рука будет действительна.

Например, для вашей недействительной руки общее значение равно 60, что означает M = {3,6,9}:

Remove the 3: 112244556789
 - Start with 1: there are less than three, so remove a street
   -> impossible: 123 needs a 3

Remove the 6: impossible, there is only one

Remove the 9: impossible, there is only one

В вашем втором примере 12345555678999 общее значение равно 78, что означает M = {3,6,9}:

Remove the 3: impossible, there is only one

Remove the 6: impossible, there is only one

Remove the 9: 123455556789
 - Start with 1: there is only one, so remove a street
   -> 455556789
 - Start with 4: there is only one, so remove a street
   -> 555789
 - Start with 5: there are three, so remove a set
   -> 789
 - Start with 7: there is only one, so remove a street
   -> empty : hand is valid, removals were [99] [123] [456] [555] [789]

В вашем третьем примере 11223378888999 также имеется в общей сложности 78, что вызывает обратное отслеживание:

Remove the 3: 11227888899
 - Start with 1: there are less than three, so remove a street
   -> impossible: 123 needs a 3

Remove the 6: impossible, there are none

Remove the 9: 112233788889
 - Start with 1: there are less than three, so remove streets
   -> 788889
 - Start with 7: there is only one, so remove a street
   -> 888
 - Start with 8: there are three, so remove a set
   -> empty, hand is valid, removals were : [99] [123] [123] [789] [888]

Ответ 2

Существует особый случай, когда вам нужно немного переделать, чтобы все было правильно. Это происходит, когда есть три-три и пара с одинаковым значением (но в другом костюме).

Пусть b обозначает бамбук, c передает знак, и d жертвует точкой, попробуйте эту руку:

b2,b3,b4,b5,b6,b7,c4,c4,c4,d4,d4,d6,d7,d8

d4,d4 should serve as the pair, and c4,c4,c4 should serve as the run-of-3 set.

Но из-за того, что плитки размером 3 "c4" появляются перед 2 безжалостностью d4, первые две c4-плитки будут подбираться как пара, оставив сироту c4 и 2 d4s, и эти 3 плитки не будут формировать действительный набор.

В этом случае вам нужно "вернуть" 2 c4 плитки обратно в руку (и сохранить сортировку вручную) и выполнить поиск следующего фрагмента, который соответствует критериям (value == 4). Для этого вам нужно сделать код "помните", что он попытался c4, поэтому на следующей итерации он должен пропустить c4 и искать другие плитки со значением == 4. Код будет немного грязным, но выполнимым.

Ответ 3

Я разбил бы его на 2 шага.

  • Выясните возможные комбинации. Я думаю, что с этими числами можно сделать исчерпывающую проверку. Результатом этого шага является список комбинаций, где каждая комбинация имеет тип (набор, улица или пара) и шаблон с используемыми картами (может быть растровым изображением).
  • С предыдущей информацией определите возможные комбинации комбинаций. Это то, где битмап пригодится. Используя побитовые операторы, вы можете видеть перекрытия в использовании одной и той же плитки для разных комбинаторов.

Вы также можете сделать шаг 1.5, где вы просто проверяете, доступно ли достаточное количество каждого типа. Этот шаг и шаг 2 будут там, где вы сможете создать общий алгоритм. Первый шаг будет таким же для всех чисел плиток и возможных комбинаций быстро.