Оптимальна стратегія для абстрактної гри


12

Мені в інтерв'ю було надано таку проблему (яку я вже не вдалося вирішити, не намагаючись обдурити свій шлях минулого): Гра починається з натурального числа . (Наприклад A 0 = 1234. ) Це число перетворюється на двійкове представлення, а N - кількість бітів, встановлене на 1 . (Наприклад A 0 = b 100 1101 0010 , N = 5. )A0A0=1234N1A0=b100 1101 0010N=5.

Гравець 1 вибирає число менше A 0 . B 0 повинен мати лише один біт, встановлений на 1. (Наприклад, B 0 = b 10 0000 0000 = 512. ) Нехай A 1 = A 0 - B 0 . (Наприклад A 1 = 1234 - 512 = 722 = b 10 1101 0010. ) Переміщення дійсне, якщо B 0B0A0B0B0=b10 0000 0000=512A1=A0B0A1=1234512=722=b1011010010B0задовольняє попередні обмеження, і якщо кількість бітів в по - , як і раніше дорівнює N .A1

Гравець 2 продовжує з , вибираючи дійсний В 1 , потім гравець 1 продовжує з А 2 і так далі. Гравець програє, якщо у нього не залишилося дійсних кроків.A1B1A2

Припускаючи, що обидва гравці грають оптимально, визначте гравця-переможця, використовуючи досить ефективний метод. (У моєму визначенні проблеми обмеження в цьому полягали в тому, що програма повинна мати можливість надати рішення для кількох мільйонів вхідних чисел, які вписуються в підписане 32-бітове ціле число.) Тобто рішення не повинно бути повністю аналітичний.


Моя особиста зацікавленість тут полягає у з'ясуванні, чи сподівання мене знайти та застосувати правильне рішення, без зворотного зв’язку щодо правильності за 120 хвилин, які мені дали, було розумним; або якщо це було одне з таких питань "давайте подивимось, чи бачили цю головоломку раніше".

Я не зміг, тому що я вирішив реалізувати те, що здавалося розумною стратегією, і це дало мені правильні результати для кількох тестових випадків, від яких мені відмовились, витрачала занадто багато часу, роблячи цей пробіг швидко, і в кінці передала неправильно повний вихід, як мій час закінчився.

З ретроспективою я мав би реалізувати грубі сили пошуку та запам'ятовували часткові рішення для невеликих стартових чисел, але задній огляд завжди 20/20. Мені цікаво, однак, якщо існує інший загальний підхід, який ухилявся від мене як флункі.


З опису я не зрозумів, що вибрані рухи повинні мати один біт, встановлений на 1 (я вважав, що це лише частина прикладу).
jjmontes

@jjmontes - Це вказано як перше правило для вибору числа B - всі приклади вказані як такі, все поза дужками загальне. Чи є у вас пропозиція, як це могло бути зрозуміліше?
мільйозу

1
B0A0

@Veedrac - Людина, якби я знав, що всі мої зусилля, спрямовані на те, щоб біт-біг бігав досить швидко, не був би марним. Відповідь, що пояснює, чому це працює, була б чудовою.
мільйозу

@millimoose Bitcount є обладнанням для більшості сучасних процесорів!
Ведрак

Відповіді:


21

011001

1001

Тож єдиним визначальним фактором у грі є те, скільки потрібно замінити, щоб дістатися до стану, де всі праворуч, і стратегії виграшу чи програшу немає. Паритет кількості змін, які він здійснює, є єдиним визначальним фактором.

1

i1101kki

i = 0
k = 0
total = 0
while n > 0:
    if n & 1:
       total += k - i
       i += 1
    n >>= 1
    k += 1

totalO(logn)


Це здається правильним, я натрапив на шматочки та фрагменти такого підходу після передачі. Здогадуюсь, я вчинив, стрибнувши пістолет, почавши кодування, і потрапив у забруднену в результаті погоню за дикими гусками.
мільйозу

Якщо подумати про це, той факт, що стратегія не має значення, означає, що у мене є або досить незрозуміла помилка в моїй реалізації, або вона мала б дати ті ж результати, що і будь-яка інша реалізація, яка грає в гру правильно ...
millimoose

5

Один із способів вирішити таку проблему полягає в наступному:

  • Знайдіть рішення для кількох простих значень, використовуючи запропонований вами підхід «запам'ятована груба сила».

  • Відгадайте відповідь (які позиції виграють, а які програють).

  • Спробуйте довести свою відповідь. Якщо вам це вдасться, чудово. В іншому випадку спробуйте знайти контрприклад і скористайтеся ним, щоб відгадати іншу відповідь. Тут може бути корисно вирішити ще кілька справ.

Справді важко сказати, скільки часу займає. Однак в інтерв'ю від вас не обов’язково розраховувати знайти рішення. Швидше інтерв'юери хочуть знати, як ви підійшли до вирішення проблеми та який прогрес вам вдалося досягти.


Так, ні, вони відхилили мене, тому що мій вихід був невірним, і мені не вистачало часу.
мільйозу

Запам'ятований підхід грубої сили був би правильним, оскільки не потребує ярликів щодо стратегії. Однак це також - я вважав - було б нестерпно повільним, і запам'ятовування, можливо, було б надто багато роботи на вершині, можливо, не багато допомоги, не використовуючи дурних обсягів пам'яті. А може й ні, я спробую це пізніше просто очистити це від своєї системи.
мільйозу

5

Зауважте з відповіді @ orlp, що ми хочемо, щоб парність суми переміщень від початкової позиції до кінцевої позиції. Давайте зазначимо це:

       9876543210
       9 76 4  1    (positions at start)
start: 1011010010
end:   0000011111
            43210   (positions at end)

Так ми хочемо

  ((1 - 0) + (4 - 1) + (6 - 2) + (7 - 3) + (9 - 4)) & 1
= ((1 + 4 + 6 + 7 + 9) - (0 + 1 + 2 + 3 + 4)) & 1
= ((1 + 0 + 0 + 1 + 1) - (0 + 1 + 0 + 1 + 0)) & 1

Перша частина - це лише співвідношення кількості бітів у непарних позиціях. Ви можете замаскувати це, взявши максимальне непідписане ціле число, розділивши на 0b11 і відкинувши.

= (bitcount(x & ~(UINT_MAX / 0b11)) ^ (0 + 1 + 0 + 1 + 0)) & 1

Друга частина - це парність половини кількості бітів в x.

= (bitcount(x & ~(UINT_MAX / 0b11)) ^ (bitcount(x) >> 1)) & 1

bitcountможе або використовувати popcntінструкцію з обладнання , або може бути реалізована вручну, використовуючи, що потрібен лише останній або другий біт, з швидкими скороченнями, як це .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.