Сітки можуть бути кривими. Як довго твоє?


12

Розглянемо зображення простої , відкритої , двовимірної кривої на широкій W високій сітці тексту, де Xпредставлена ​​частина кривої і .являє собою порожній простір, а інші символи не використовуються.

Кожен сітковий простір має 8 сусідніх сітових просторів, його квартал Мура . Простір сітки за межами кордонів вважається порожнім.

Сітка містить криву, якщо вона має точно одну X АБО, якщо вона має більше однієї, Xде:

  • Рівно два Xs мають лише одну сусідню X. Це кінцеві точки кривої.
  • У кожного Xкрім кінцевих точок сусідів рівно дві Xс. Вони утворюють основну частину кривої.

Наприклад, ця сітка, де W = 9 і H = 4, містить криву:

....X....
.X.X.X.X.
X..X..X.X
.XX.....X

Аналогічно, ці сітки (W = 4, H = 3) мають криві:

....  .X..  ....  ....  .X.X
....  X..X  ..X.  XX..  X.X.
..X.  .XX.  .X..  ....  ....

Однак ці сітки не містять кривої:

....  .XX.  ...X  XX..  ....  X.X.
....  X..X  ..XX  XX..  .X.X  .X..
....  .XX.  .X..  ....  ...X  X.X.

Ми можемо знайти довжину кривої шляхом підсумовування відстаней між усіма сусідніми парами Xs:

  • Відстань між двома ортогонально сусідніми Xs дорівнює 1 одиниці.

    XX
    X
    X
  • Відстань між двома діагонально сусідніми Xs √2 одиниці.

    X.
    .X
    .X
    X.

Наприклад, довжина кривої в сітці

XXX.
...X
..X.

можна візуалізувати як

Приклад довжини

тому ми можемо бачити, що це 1 + 1 + √2 + √2 = 4,828427 ...

Довжина кривої, що має лише одну, Xдорівнює нулю.

Коли сітка не утворює криву, її довжина недостатньо визначена.

Виклик

З огляду на сітку тексту Xs і .s, виведіть довжину кривої, яку вона містить, або виведіть щось таке, як, -1або Nullщоб вказати, що сітка не має кривої.

Для введення ви можете використовувати інші символи, ніж Xі .за бажанням, а H і W при необхідності можуть бути прийняті як введення. Введення у вигляді вкладеного списку чи матриці, заповненої 1s та 0s замість рядка, також добре.

Ви можете вивести поплавок на довжину кривої або, замість того, два цілі числа A і B, де length = A + B*√2.

Виграє найкоротший код у байтах.

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

XXX.
...X
..X.
2 + 2*√2 = 4.828427...

....X....
.X.X.X.X.
X..X..X.X
.XX.....X
3 + 8*√2 = 14.313708...

....
....
..X.
0 + 0*√2 = 0

.X..
X..X
.XX.
1 + 3*√2 = 5.242640...

....
..X.
.X..
0 + 1*√2 = 1.414213...

....
XX..
....
1 + 0*√2 = 1

.X.X
X.X.
....
0 + 3*√2 = 4.242640...

....
....
....
....
-1

.XX.
X..X
.XX.
-1

...X
..XX
.X..
-1

....
.X.X
...X
-1

X.X.
.X..
X.X.
-1

Я рекомендую дозволити розв'язувачу вибрати свій вихідний формат для сіток, які не мають кривих (будь-яке послідовне значення, яке не має форми m + n * sqrt (2) для будь-якого m, n≥0).
Грег Мартін

@Greg Звучить добре. Готово
Захоплення Кальвіна

[x.x,...,.x.]це невірна крива, правда?
Чарівний восьминога Урна

@carusocomputing правильний
Захоплення Кальвіна

Відповіді:


3

MATL , 52 51 байт

t2Y6~Z+*ssGt3Y6Z+*tt1=z2=wssGzqE=*Gz1=+?}_q]ssy-h2/

Введення - це матриця нулів та одиниць.

Вихід є B, значить A. Некриві дають негатив A.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

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

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

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

  1. Чи рівна кількість одиниць у M2 ? (Тобто, кидають рівно два очки з одним сусідом?)
  2. Чи загальна сума M дорівнює кількості балів у вхідній кривій разів 2мінус 2? (Разом із умовою 1 це перевіряється, якщо всі ненульові значення в M, за винятком двох, рівні 2)
  3. Чи містить вхідна крива одну точку?

Крива справедлива, якщо умови 1 і 2 є істинними, або якщо умова 3 є.

t       % Implicit input matrix of zeros and ones. Duplicate
2Y6~    % Push [1 0 1; 0 0 0; 1 0 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix D
ss      % Sum of matrix D
Gt      % Push input again wtice
3Y6     % Push [1 1 1; 1 0 1; 1 1 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix M
tt      % Duplicate twice
1=z     % Number of ones
2=      % Does it equal 2? This is condition 1
wss     % Swap. Sum of matrix
G       % Push input again
zqE     % Number of nonzeros values minus 1, and then multiplied by 2
=       % Are they equal? This is condition 2
*       % Multiply. This is a logical AND of conditions 1 and 2
G       % Push input again
z1=     % Does it contain exactly one nonzero value? This is condition 3
+       % Add. This is a logical OR with condition 3
?}      % If result was false
  _q    %   Negate and subtract 1. This makes sure we get a negative value
]       % End
ss      % Sum of matrix M
y       % Duplicate sum of matrix D from below
-       % Subtract
h       % Concatenate horizontally
2/      % Divide by 2. Implicitly display

1 Конволюція - запорука успіху .


1

Python 3 , 316 315 311 байт

Я думаю, що це стосується всіх випадків; принаймні тестові справи працюють.

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

def f(d,R,C):
 s=sum;d=[0]*(C+2),*[[0,*r,0]for r in d],[0]*(C+2);o=-1,0,1;k=[[[(1,0),(0,1)][i*j]for i in o for j in o if d[r+i][c+j]and i|j]for c in range(1,-~C)for r in range(1,-~R)if d[r][c]];w=[x/2for x in map(s,zip(*s(k,[])))]or[0,0];print([w,-1][s(w)!=s([s(z)for z in d])-1or[len(t)for t in k].count(1)>2])

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

Як це працює:

  1. d,R,C являють собою 1. список списків, 1 - крива, 0 - як фон, 2. кількість рядків та стовпців
  2. Вставте рядок 0 до і після і стовпець 0 до і після, dщоб ми не мали турбуватися про край 2d масиву
  3. Для кожного 1 у 2d масиві скануйте околиці на 1 і додайте (1,0) до списку, якщо відношення діагональне, інше додати (0,1)
  4. Підсумовуйте всі кортежі, так що (n, m) представляє кількість діагональних та недіагональних сусідів відповідно
  5. Перевірте, чи число відносин точно число 1 мінус один; якщо ні, не крива.

Дякуємо @Helka Homba за вказівку на відсутність справи. Дякуємо @TuukkaX та @Trelzevir за поради з гольфу.


Схоже d=[[1,0,1],[0,1,0],[1,0,1]], тут не вдасться (додано тест).
Захоплення Кальвіна

@HelkaHomba Ти маєш рацію, я це наглядав. Дякую! Виправлено це (зараз, на жаль, з більшою кількістю байтів).
nile

1
s=sumекономить 4 байти.
Трельзевір

0

Математика, 153 150 байт

Switch[Sort[Join@@BlockMap[If[#[[2,2]]<1,Nothing,Tr[Tr/@#]]&,#~ArrayPad~1,{3,3},1]],{1},0,{2,2,3...},1/.#~ComponentMeasurements~"PolygonalLength",_,]&

Займає 2D масив, з 0s для .s і 1s для Xs. Виходи Nullдля не кривих.

1/.#~ComponentMeasurements~"PolygonalLength"&

Mathematica має вбудований 45-байт для цього, але він виводить деякі числа для не кривих і 1 / sqrt (2) для введення {{1}}. Виправлення цих витрат становить 105 байт (можна було б пограти в гольф?).

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