Китайські шашки найдовший хід


12

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

Вхідні дані

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

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

Пояснення:

Найбільше місце займає зелений шматок, тому перша цифра у введенні є 1. Другий ряд має одну порожню позицію, а потім одну зайняту позицію, тому 01йде наступна. Третій ряд весь зайнятий, так 111. У четвертому ряду є два порожніх і два зайняті пробіли (йде ліворуч праворуч), так 0011. Потім приходить п'ять 0s, a 1, і сім 0для наступного ряду тощо.

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

Вихідні дані

Максимальна довжина законного хопу, використовуючи будь-який шматок на дошці. Ви не можете відвідувати одне і те ж місце більше одного разу (включаючи стартову та кінцеву позиції). Однак ви можете перестрибувати один і той же шматок не раз. Якщо немає законного скаку, виведіть 0. Не враховуйте, чи існує законний неприскорений хід.

Наприклад, вихід до установки, описаної вище, є 3.

Введення та виведення може здійснюватися за допомогою stdin та stdout, через аргументи командного рядка, через виклики функцій або будь-який подібний метод.

Випробування

Вхід:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

Вихід: 0(жодна частина не знаходиться поруч)


Вхід:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

Вихід: 1(початкова установка для одного гравця у верхньому лівому куті)


Я граю це зі своєю великою тіткою; ми обоє досить добре. Це цікавий виклик.
cjfaure

1
Можливо, вам слід вказати більше про те, як зберігається вхід / які біти йдуть куди.
TheDoctor

Які твори можна "перестрибнути"? Те, як ми з мамою грали, ви можете перестрибувати будь-яку частину в одному з 6 напрямків на будь-яку відстань (до протилежного місця твору, який ви перестрибували) до тих пір, поки немає жодного твору на шляху шлях до цього хопу. Інші грають, що ви можете перестрибувати лише сусідні фігури.
Джо З.

1
@TheDoctor Я додав більш детальне пояснення.
Ypnypn

Чи можете ви уточнити деталь: чи мені дозволяється займати одну і ту ж посаду двічі? Я припускаю, що не можу нескінченно циклічно, але якщо я можу потрапити на місце, яке рухається вліво-вправо, а потім пізніше натисніть його знову, рухаючись вліво-вправо-вниз, тоді це відкриває можливості.
Девон Парсонс

Відповіді:


1

Перл, 345 322

Правка: гольф, трохи.

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

$_=<>;
$s=2x185;
substr$s,(4,22,unpack'C5(A3)*','(:H[n129148166184202220243262281300')[$i++],0,$_ 
    for unpack A.join A,1..4,13,12,11,10,9..13,4,3,2,1;
$_=$s;
sub f{
    my(@a,%h)=@_;
    $h{$_}++&&return for@a;
    $-+=$#a>$-;
    $s=~/^.{$a[0]}$_/&&f($+[1],@a)
        for map{("(?=.{$_}1.{$_}(0))","(?<=(0).{$_}1.{$_}.)")}0,17,18
}
f$+[0]while/1/g;
print$-

Я додав пару тестових випадків.
Ypnypn

Вони працюють добре, але вони занадто легкі :-).
користувач2846289

2

C, 262 260

Код для гольфу ( видалено код налагодження та видалено зайвий пробіл. Змінено з введення через stdin на введення через командний рядок, і скористався можливістю оголосити змінну i там. Остання редакція: код перемістився в дужки forциклів, щоб зберегти два крапки з комою.)

t[420],j,l,x,y;f(p,d){int z,q,k;for(k=6;k--;t[q]&!t[p+z]?t[q]=0,f(q,d+1),t[q]=1:0)z="AST?-,"[k]-64,q=p+z*2;l=d>l?d:l;}main(int i,char**s){for(i=840;i--;x>3&y>5&x+y<23|x<13&y<15&x+y>13?i>420?t[i-420]=49-s[1][j++]:t[i]||f(i,0):0)x=i%20,y=i/20%21;printf("%d",l);}

Пояснення

Це спирається на плату 20x21, яка виглядає так, спочатку заповнюється нулями під час запуску програми (це зображення ASCII було створене модифікованою версією програми, і коли iцикл рахується вниз, нуль знаходиться в правому нижньому куті):

....................
....................
...............#....
..............##....
.............###....
............####....
.......#############
.......############.
.......###########..
.......##########...
.......#########....
......##########....
.....###########....
....############....
...#############....
.......####.........
.......###..........
.......##...........
.......#............
....................
....................

Петля iпроходить через цю дошку двічі, використовуючи x і y, щоб обчислити, чи насправді квадрат належить до контрольної дошки чи ні (для цього потрібно 6 окремих нерівностей у x та y).

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

Другий раунд, якщо квадрат зайнятий (містить 0), він викликає функцію, fяка шукає рухи.

fрекурсивно здійснює пошук у 6 можливих напрямках, закодованих +/- 1 (горизонтальний), +/- 20 (вертикальний) та +/- 19 (діагональний), закодований у виразі "AST?-,"[k]-64. Коли він знаходить хіт, він встановлює цю клітинку 0 (зайнято), перш ніж викликати рекурсивно, а потім повертає її до 1 (порожній), коли функція повертається. Значення комірки потрібно змінити перед рекурсивним викликом, щоб не один раз переходити в цю клітинку.

Невикористаний код

char s[999];                           //input string.
t[420],i,j,l,x,y;                      //t=board. i=board counter, j=input counter. l=length of longest hop found so far.

f(p,d){                                //p=position, d= recursion depth.
  //printf("%d,%d ",p,d);              //debug code: uncomment to show the nodes visited.
  int k,z,q;                           //k=counter,z=displacement,q=destination
  for(k=6;k--;)                        //for each direction
    z="AST?-,"[k]-64,                  //z=direction
    q=p+z*2,                           //q=destination cell
    t[q]&!t[p+z]?                      //if destination cell is empty (and not out of bounds) and intervening cell is full
      t[q]=0,f(q,d+1),t[q]=1           //mark destination cell as full, recurse, then mark it as empty again.
      :0;
  l=d>l?d:l;                           //if d exceeds the max recorded recursion depth, update l
}

main(){
  gets(s);                             //get input
  for(i=840;i--;)                      //cycle twice through t
    x=i%20,                            //get x
    y=i/20%21,                         //and y coordinates
    x>3&y>5&x+y<23|x<13&y<15&x+y>13?   //if they are in the bounds of the board
      i>420?
        t[i-420]=49-s[j++]             //first time through the array put 0 for a 1 and a 1 for a 0 ('1'=ASCII49)
        :t[i]||f(i,0)                  //second time, if t[i]=0,call f(). 
       //,puts("")                     //puts() formats debug output to 1 line per in-bounds cell of the board
      :0;
  printf("%d",l);                      //print output
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.