Манкала дошки пасьянсу


10

Mancala - це назва сімейства настільних ігор, які зазвичай включають в себе серії чашок, наповнених намистинами, якими гравці маніпулюють. У цьому виклику буде використано специфічне правило для пасьянсового варіанту гри.

Дошка складається з «кошика» на одному кінці, за яким слідує нескінченна кількість чашок, пронумерованих починаючи з 1. Деякі з чашок матимуть деяку кількість намистин. Якщо в nчашці точно є nнамистинки, ви можете "сіяти" намистинки з неї. Посів означає вийняти всі nкульки з чашки, а потім покласти їх по одній у кожній чашці до кошика. Остання намистинка піде в кошик. Гравець виграє, коли всі кульки на дошці знаходяться в кошику.

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

Завдання

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

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

Демонстрація

Це демонстрація того, як грати на виграшну дошку і вводити 4. Виграшна дошка є [0, 1, 3]. Починаємо з єдиного доступного руху, сіючи намистини з третьої чашки, щоб отримати [1, 2, 0]. Тепер у нас на самому справі є вибір, але єдино правильна сіють першу чашку, отримуючи: [0, 2, 0]. Потім ми висіваємо другий урожай [1, 0, 0]і, нарешті, ми знову висіваємо перший стакан, щоб отримати всі порожні чашки.

Тестові приклади:

1 => [1]
2 => [0, 2]
3 => [1, 2]
4 => [0, 1, 3]
5 => [1, 1, 3]
6 => [0, 0, 2, 4]
7 => [1, 0, 2, 4]
8 => [0, 2, 2, 4]
9 => [1, 2, 2, 4]
10 => [0, 1, 1, 3, 5]
11 => [1, 1, 1, 3, 5]
12 => [0, 0, 0, 2, 4, 6]
13 => [1, 0, 0, 2, 4, 6]
14 => [0, 2, 0, 2, 4, 6]
15 => [1, 2, 0, 2, 4, 6]
16 => [0, 1, 3, 2, 4, 6]
17 => [1, 1, 3, 2, 4, 6]
18 => [0, 0, 2, 1, 3, 5, 7]
19 => [1, 0, 2, 1, 3, 5, 7]
20 => [0, 2, 2, 1, 3, 5, 7]

Велика подяка PeterTaylor за те, що він створив програму для генерації тестових випадків!


Відповіді:


5

CJam (21 байт)

M{_0+0#_Wa*\)+.+}ri*`

Демонстрація в Інтернеті

Пояснення

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

Основа: з 0 намистинами, єдина дошка, що виграла, - порожня.

Індуктивний крок: якщо ми будемо сіяти з чашки, kто при наступному ході чашка kбуде порожньою, і кожна чашка, що наближається до кошика, буде містити хоча б одну намистину. Тому ми можемо знайти унікальну дошку-виграш з nнамистами з виграшної дошки з n-1намистинами, шукаючи порожній найменший порожній кубок, дістаючи одну намистину з кошика та одну з кожної чашки нижче цієї порожньої чашки, і поміщаючи їх у порожній кубок.

Розсічення

M           e# Start with an empty board
{           e# Loop
  _0+0#     e#   Find position of first 0 (appending to ensure that there is one)
  _Wa*      e#   Make array of that many [-1]s
  \)+       e#   Append the index plus 1 (since board is 1-indexed)
  .+        e#   Pointwise addition
}
ri*         e# Read integer from stdin and execute loop that many times
`           e# Format for display


4

JavaScript (ES6), 63 37 байт

f=(n,d=2)=>n?[n%d,...f(n-n%d,d+1)]:[]

Порт відповіді Python @ orlp. Пояснення: Розгляньте загальну кількість намистин уi та більшій чашках. Кожна гра з однієї з цих чашок видалить iнамистинки із загальної суми. (Наприклад, якщо iце 3, а ви граєте з п’ятого кубка, ви зменшуєте кількість кульок у цій чашці на п’ять, але ви також додаєте одну до четвертої та третьої чашок.) Отже, загальна сума повинна бути кратною з i. Тепер i-1чашка не може містити iабо більше намистин, тому для того, щоб вона залишила кратну кількість, iповинна містити залишок модуля з намистинами i.

Попереднє пояснення (за посиланням @ xnor): Наївний підхід - це техніка "зворотної гри". Для цього використовується спостереження, що під час гри виставляється чашка, тому зворотна гра збирає бісер з кожної чашки і ставить їх у перший порожній кубок, як-от так (63 байти):

f=n=>n?[...a=f(n-1),0].some((m,i)=>(m?a[i]--:a[i]=i+1)>m)&&a:[]

Тепер лише розглянемо перші iчашки. У випадку, якщо одна з них порожня, зворотна гра додасть 1до загальної кількості намистин у цих чашках, тоді як у випадку, якщо жодна з них не порожня, зворотна гра віднімається iвід загальної кількості, однак це еквівалентно додаванню 1модуля i+1. Після nзворотної гри сума намистин у перших iчашках, таким чином, буде еквівалентна nмодулю . (Зверніть увагу, що я використовую, оскільки він використовує менше байтів.)i+1 , або, якщо говорити, іншим способом, кількість намистин у iчашці буде еквівалентно nмінус сумі намистин у попередніх чашках, за модулем i+1. Тепер для того, щоб цю iчашку можна було відтворити, кількість намистин не може перевищувати i, тому насправді вона буде дорівнює кількості модулів, що залишилисяi+1d=i+1


Ви забули призначити функцію у версії за допомогою рішення @ orlp, не даючи рекурсії працювати. Що стосується цього рішення, чи є об'єднання масиву з +річчю в ES6?
Значення чорнила

@KevinLau На жаль, і що після вирішення проблеми включити його до байтового рахунку теж! Але ні, + є рядковим конкатенацією, якщо обидва параметри не є числами або булевими, в цьому випадку це додавання. На щастя, розуміння масиву полегшує довільну конкатенацію.
Ніл

2

Рубін, 36 байт

Порт відповіді @ orlp, тому що для мене це занадто геніально, щоб думати про щось краще.

m=->n,i=2{n>0?[n%i]+m[n-n%i,i+1]:[]}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.