Китайские шашки самый длинный ход


12

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

вход

Последовательность из 121 нуля или единиц, каждый из которых представляет место на доске. Ноль означает, что место пусто; один означает, что место занято. Позиции перечислены слева направо; сверху донизу. Например, ввод этой установки будет

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

Объяснение:

Самое верхнее место занимает зеленая часть, поэтому первая цифра на входе - 1. Второй ряд имеет одну пустую позицию, а затем одну занятую позицию, поэтому 01следующий. Третий ряд уже занят, так что 111. В четвертом ряду два пустых и два занятых пробела (слева направо), поэтому 0011. Затем идут пять 0, а 1и семь 0для следующего ряда и так далее.

Как и в этой настройке, есть угол, направленный прямо вверх. На доске может быть любое количество фигур (от 1 до 121). Обратите внимание, что кусочки разных цветов не представлены по-разному.

Выход

Максимальная длина легального прыжка, используя любую фигуру на доске. Вы не можете посещать одно и то же место более одного раза (включая начальную и конечную позиции). Тем не менее, вы можете перепрыгнуть через один и тот же кусок более одного раза. Если легального прыжка нет, выведите 0. Не думайте, существует ли законный ход без прыжка.

Например, выход для настройки, описанной выше, является 3.

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

Тестовые случаи

Входные данные:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

Вывод: 0(нет двух частей рядом друг с другом)


Входные данные:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

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


Я играю это с моей двоюродной бабушкой; мы оба достаточно хороши Это интересный вызов.
cjfaure

1
Может быть, вы должны указать больше о том, как хранятся входные данные / какие биты идут куда.
Доктор

Какие части вы можете «перепрыгнуть»? То, как мы с мамой играли, вы можете перепрыгнуть через любую фигуру в одном из 6 направлений на любом расстоянии (до противоположного места фигуры, которую вы перепрыгнули), если на пути нет фигуры. путь для этого прыжка. Другие играют, что вы можете прыгать только на соседние фигуры.
Джо З.

1
@TheDoctor Я добавил более подробное объяснение.
Ypnypn

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

Ответы:


1

Perl, 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

Те работают хорошо, но они слишком просты :-).
user2846289

2

С 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(правдивого) для 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.