Визнайте лозу


31

Фон

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

Вхід і вихід

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

  • Нижній ряд A містить щонайменше одне 1. Це коріння виноградної лози.
  • Кожен 1 в A з'єднаний з нижчим рядом шляхом в 1s, який йде лише вліво, вправо і вниз (не вгору і не по діагоналі). Ці стежки - гілки виноградної лози.

Ваш вихід - це узгоджене значення, якщо зображення зображено виноградна лоза, а інше - хибне значення.

Приклади

Цей масив зображує лозу:

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

1
Не зрозуміли, що виноградна лоза не може рости вниз, гарно уявляли, використовуючи підключені компоненти графіка, зітхаючи ...
swish

@swish Все, що означає, що видалення кожного рядка по черзі має продовжувати отримувати графік, підключений до рядка 1s внизу.
Ніл

Відповіді:


26

Равлики , 25 19 17 байт

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

Спробуйте в Інтернеті!

Пояснення

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

У &ДАЄ Равлики спробувати зразок з усіх можливих стартової позиції і друкує 0або в 1залежності від того, терпить картина в якій - небудь з них або матчів у всіх з них.

Тепер Равлики можуть працювати з неявними дужками, тому шаблон є скороченим для наступного:

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

,Діє як *в регулярному виразі (тобто відповідає нуль або більше разів), в той час як +таке ж , як в регулярному виразі (відповідає один або кілька разів). Отже, ми почнемо з узгодження \0zякомога частіше, що відповідає одиночному, 0а потім дозволяє равлику довільно скинути свій напрямок z. Це дозволяє нулі на вході, за умови, що дійсна клітина лози можна знайти деінде.

Тоді ми узгоджуємо хоча б один \1dlr, який відповідає одиночному, 1а потім дозволяє равлику скинути свій напрямок або вниз, вліво або вправо. Зауважте, що якщо клітина, з якої ми розпочали роботу, містить 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 символу. Пояснення: Кожен рядок розряджається бітом AND разом із сусіднім рядком для визначення точок з'єднання, а потім 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&]]{}
)

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


2
Чому це неконкуренто?
Пуховик

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:])

Очікує A2D масив numpy.

Бере матрицю, прошиває нульові стовпчики ліворуч та праворуч і вирівнює матрицю. 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()та використання табуляторів для другої інтенції в циклі

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