Признать лозу

31

Задний план

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

Вход и выход

Ваш ввод представляет собой прямоугольный двумерный массив битов A , заданный в любом удобном формате. Он не будет пустым, но не обязательно будет содержать 0 и 1. Массив изображает виноградную лозу, если выполняются следующие условия:

  • Нижний ряд А содержит как минимум один 1. Это корни виноградной лозы.
  • Каждый 1 в A связан с нижним рядом путем 1, который идет только влево, вправо и вниз (не вверх и не по диагонали). Эти пути являются ветвями виноградной лозы.

Ваш вывод является непротиворечивым истинным значением, если на входе изображена лоза, и непротиворечивым ложным значением в противном случае.

Примеры

Этот массив изображает лозу:

0 0 1 0 0 1
0 1 1 0 0 1
0 1 0 1 1 1
1 1 0 1 0 1
0 1 1 1 0 1
0 0 1 0 1 1

Эти входные данные не изображают лозу, поскольку в середине правой границы есть 1, который не связан с корнями веткой:

0 0 0 1 1 0
0 1 0 1 1 1
0 1 0 1 0 1
0 1 1 1 1 0
0 0 1 1 0 1

Массив all-0 никогда не отображает лозу, а массив all-1 всегда отображает.

Правила и оценки

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

Контрольные примеры

Истинные входы:

1

0
1
1

01
11

0000
0111
1100
1001

1111
1111
1111
1111

001001
011001
010111
110101
011101
001011

1011011
1001001
1111111
0100000
0111111
1111001
1001111
1111101

0000000
0011100
0010100
0011100
0001000
1111111
0001000
0011100
0010100
0010100

Ложные входы:

0

1
0

10
01

000
000
000

011
110
000

111111
000000
101011
111001

010010
001000
000010
110001

001100
111111
110101
010011
111011

000110
010111
010101
011110
001101

11000000
10110001
10011111
11110001
01100011
00110110
01101100
01100001
01111111
Zgarb
источник
1
Не понимал, что лоза не может расти вниз, имел хорошую идею, используя связанные компоненты графика, вздох ...
swish
@swish Все это означает, что удаление каждой строки по очереди должно приводить к графику, соединенному линией 1 с в нижней части.
Нил

Ответы:

26

Улитки , 25 19 17 байт

&
\0z),(\1dlr)+d~

Попробуйте онлайн!

объяснение

Snails - это язык сопоставления с двумерным шаблоном, вдохновленный regex, который изначально был разработан для нашей задачи проектирования языка сопоставления с двумерным рисунком .

В &ДАЕТ Улитки попробовать образец из всех возможных стартовой позиции и печатает 0или в 1зависимости от того, терпит ли картина в какой - либо из них или матчей во всех из них.

Теперь улитки могут работать с неявными круглыми скобками, поэтому шаблон является сокращением для следующего:

(\0z),(\1dlr)+d~

,Действует как *в регулярном выражении (т.е. соответствует ноль или более раз), в то время как +такое же , как в регулярном выражении (соответствует один или несколько раз). Таким образом, мы начинаем с сопоставления \0zтак часто, как это необходимо, что соответствует одному, 0а затем позволяет улитке произвольно изменять свое направление z. Это позволяет вводить нули во входные данные, при условии, что допустимая ячейка винограда может быть найдена где-либо еще.

Затем мы сопоставляем хотя бы один \1dlr, который соответствует одному, 1а затем позволяет улитке сбрасывать свое направление вниз, влево или вправо. Обратите внимание, что если ячейка, с которой мы начали, содержит a, 1то мы соответствуем только этой части. Это в основном позволяет улитке пересекать виноградную лозу от ветви до корней.

Наконец, нам нужно убедиться, что мы достигли земли, ища за пределами ячейки ( ~) ниже ( d).

Мартин Эндер
источник
1
Я приятно удивлен, что кто-то смог следить за документацией :)
feersum
3

JavaScript (ES6), 135 байт

s=>s.replace(/^[^1]*\n/,``).split`
`.map(s=>+`0b${s}`).reverse(g=(n,m,o=(m<<1|m|m>>1)&n)=>n-m?o-m&&g(n,o):n).reduce((m,n,i)=>g(n,n&m))

Примечание. Из-за ограничений целочисленного типа работает только для лоз шириной до 31 символа. Объяснение: Каждая строка побитовая И соединяется со смежной строкой для определения точек соединения, а затем gфункция используется для рекурсивного расширения строки по горизонтали, пока она больше не сможет расширяться. Например, если есть две соседние строки, 1110111а 1011100затем точки подключения, 1010100и это затем расширяется, 1110110а 1110111затем обнаруживает, что строка связана. Если gфункция завершается с ошибкой, она возвращает ноль, что также приводит gк сбою всех последующих функций, и результат становится ложным. Если gфункция завершается успешно, она возвращает новую строку, которая затем распространяется через, reduceчтобы проверить следующую строку.

s=>s.replace(/^[^1]*\n/,``)         Remove irrelevant leading "blank" rows
    .split`\n`                      Split into lines
    .map(s=>+`0b${s}`)              Convert into binary
    .reverse(                       Process from bottom to top
     g=(n,m,o=(m<<1|m|m>>1)&n)=>     Expand row horizontally
      n-m?o-m&&g(n,o):n)             Check whether rows are connected
    .reduce((m,n,i)=>g(n,n&m))      Check all rows
Нил
источник
Я считаю, что 31 символ достаточно широк, и этот подход является действительным.
Згарб
2

Python 2, 254 байта

Нет библиотек

def f(A,r=0,c=-1):
 B=A[r];R=len(A)-1;C=len(B);i=1 in A[R]
 if c<0:
    for j in range(R*C+C):
        if A[j/C][j%C]:i&=f(A,j/C,j%C)
    return i&1
 _=B[c];B[c]=0;i=_&(r==R)
 if _:
    if c>0:i|=f(A,r,c-1)
    if r<R:i|=f(A,r+1,c)
    if c<C-1:i|=f(A,r,c+1)
 B[c]=_;return i

Обратите внимание, что отступы второго и третьего уровня формируются с помощью вкладок в количестве байтов.

Попробуйте онлайн

Чак Моррис
источник
1

Вольфрам - 254

Потратьте некоторое время на создание этой работы, поэтому я просто оставлю это здесь:

f[s_]:=(
v=Characters@StringSplit@s;
{h,w}=Dimensions@v;
g=GridGraph@{w,h};
r=First/@Position[Flatten@v,"0"];
g=VertexDelete[Graph[VertexList@g,
EdgeList@g/.x_y_/;Abs[x-y]>1yx],r];
v=VertexList@g;
v≠{}∧v~Complement~VertexOutComponent[g,Select[v,#>w h-w&]]{}
)

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

рассекать
источник
2
Почему это не конкурирует?
Downgoat
1
В настоящее время мы считаем это "не ответом", поскольку это не игра в гольф. Если вы просто удалите ненужные пробелы и добавите количество байтов, я не вижу причин, по которым это должно быть неконкурентным.
Алекс А.
0

Python + NumPy 204 202 195 байт

from numpy import*
def f(A):
 r,c=A.shape
 z,s=zeros((r,1)),array([0,2,c+3])
 B=hstack((z,A,z)).flat
 for i in range(1,(r-1)*(c+2)):
    if B[i]and not any(B[s]):return 1<0
    s+=1
 return any(B[i:])

Предполагается, Aчто это двумерный массив.

Берет матрицу, дополняет нулями столбцы влево и вправо и выравнивает матрицу. sэто трафарет, который указывает на левый, правый и нижний элемент. Цикл проверяет каждый элемент, кроме последней строки, если он есть, 1и хотя бы один из его шаблонов 1, возвращает Falseиначе. После этого проверьте, есть ли в последней строке 1.

Два теста для вас:

I1 = '001001\n011001\n010111\n110101\n011101\n001011'
A1 = array([int(c) for c in I1.replace('\n','')]).reshape(6,6)
print f(A1) #True

I2 = '001100\n111111\n110101\n010011\n111011'
A2 = array([int(c) for c in I2.replace('\n','')]).reshape(5,6)
print f(A2) #False

Edit1: 1<0корочеFalse

Edit2: flatпрекрасная альтернатива flatten()и использование табуляторов для второго намерения в цикле

Карл Напф
источник