Вирівнювання на трикутних сітках


18

Гексагональні сітки останнім часом стали досить популярним поворотом для викликів щодо двовимірних даних. Однак, схоже, що однаково цікаві трикутні сітки до цього часу були значною мірою занедбані. Я хотів би усунути це досить простим завданням.

По-перше, як ми представляємо трикутну сітку? Розглянемо наступний приклад (зараз ігноруй правильну схему):

введіть тут опис зображення введіть тут опис зображення

Клітини акуратно потрапляють на звичайну сітку (відмінність від звичайної сітки лише в тому, що клітини вважаються суміжними):

1234567
89abcde
fghijkl
mnopqrs

Тепер, як показує правильна схема, трикутна сітка має три основні осі: горизонтальну та дві діагональні.

Виділяючи їх у сітці ASCII:

AVAVAVA
VAabcAV
fVAiAVl
mnVAVrs

Змагання

Вам надано прямокутну рядок, що представляє трикутну сітку (де верхній лівий кут - вгору спрямований трикутник). Більшість клітинок має бути ., але рівно дві буде #, наприклад:

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

Визначте, чи обидві #вирівняні вздовж будь-якої з трьох осей сітки (тобто чи лежать вони в одному ряду в будь-якому з трьох напрямків, виділених вище). У цьому прикладі відповідь - «ні».

Ви можете написати програму або функцію, взявши введення через STDIN (або найближчу альтернативу), аргумент командного рядка або аргумент функції та вивівши результат через STDOUT (або найближчу альтернативу), значення повернення функції або параметр функції (out).

Введення може бути однією строкою, обмеженою подачею рядків або іншим зручним символом, або списком рядків. Ви можете використовувати будь-які два (послідовні) символи ASCII для друку замість .та #.

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

Діють стандартні правила .

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

Простір сітки:

.#..#.

#
#

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

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

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

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

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

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

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

Фальшиві сітки:

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

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

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

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

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

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

Відповіді:


3

Равлики , 40 39 байт

\#{z|=(ul.ul.`,l~a~)(l.a3|.a|d.ea5}.,\#
\ # ,, відповідність "#"
{
  z | ,, Або поверніть у будь-якому октинілярному напрямку, або виконайте всі інші речі до}
  = (,, Якщо це твердження вдалося, вихідна комірка - це "трикутник, спрямований вгору"
    ul.ul.`, ,, Перейдіть по одній клітці вгору або вліво двічі, будь-яку кількість разів.
              ,, Це повинно було бути на один байт коротше з ul.`2, або ul.`2 +? але
              ,, синтаксичний розбір `є баггі.
    l ~ a ~ ,, Перевірте, чи ми знаходимося у верхній лівій клітці, порівнюючи поза межами ліворуч та потім на північний схід
  )
  (l.a3 | ,, Перемістіть один раз вліво, потім встановіть напрямок на північний захід; або
    .a | ,, Один раз рухайтесь праворуч (початковий напрямок), потім задайте напрям на північний схід; або
    d.ea5 ,, Перемістіться один раз вниз, потім встановіть напрямок на північний захід або північний схід
}
., ,, Збігайте будь-яку кількість довільних символів (рухаючись у поточному напрямку)
\ # ,, відповідність "#"

2

CJam, 47 байт

Ну а тепер, коли існує коротше рішення, я більше не відчуваю себе погано ділитися власним. :) (Переважно, щоб показати, що це не особливо складно, навіть якщо у вас немає 2D-мови узгодження мови ...)

qN%:eeee::f+:~{S&},2f<:P0f=P::+Xf|P::-Xf|]::=:|

Для цього використовуються пробіли замість, #і справді все інше ..

Запустити всі тестові приклади в Інтернеті.

Я дуже ненавиджу дублювання, P::+Xf|P::-Xf|але поки що нічого не придумав, щоб позбутися цього.

Пояснення

Не читайте далі, якщо ви хочете знайти рішення для себе.

По-перше, нудна частина: отримання двох координатних пар двох проміжків у вхідній сітці:

qN%   e# Read input and split into lines.
:ee   e# Enumerate the characters in each line. I.e. turn each character 'x into a pair
      e# [N 'x] where N is its horizontal 0-based index.
ee    e# Enumerate the lines themselves, turning each line [...] into [M [...]] where M
      e# is its vertical 0-based index.
::f+  e# This distributes the vertical index over the individual lines, by prepending it
      e# to each pair in that line. So now we've got a 2-D array, where each character 'x
      e# has been turned into [M N 'x].
:~    e# Flatten the outermost dimension, so that we have a flat list of characters with
      e# their coordinates.
{S&}, e# Filter only those lists that contain a space.
2f<   e# Truncate the two results to only their first two elements.
:P    e# Store the result in P.

Тепер цікава частина полягає в тому, як визначити, вирівняні ці координати чи ні. Мій код обчислює всі три осі окремо:

  • Горизонтальна вісь тривіальна. Перевірте, чи збігаються вертикальні координати.
  • Давайте розглянемо діагональ північного сходу. У сітці ASCII завжди є два антидіагоналі, які належать до кожної трисерійної діагоналі:

    ....AV..
    ...AV...
    ..AV....
    

    Ми можемо ідентифікувати поточний антидіагональ, додавши xі yкоординати:

    01234567
    12345678
    23456789
    

    Отже, ми хотіли б 0і 1належати до тієї ж діагоналі, як 2і 3, 4і, 5і так далі. Це означає, що коли ми маємо свій антидіагональний індекс, ми хочемо округлити до наступного непарного числа. Іншими словами, ми беремо біт АБО з 1. (Ми також можемо округлити до наступного парного числа по порозрядному І, -2але це дорожче в коді.)

  • Тепер діагоналі на південному сході:

    .VA.....
    ..VA....
    ...VA...
    

    Для того , щоб дати діагоналям індекс, ми віднімаємоx з yкоординат (що представляють негативних чисел як літери):

    0abcdefg
    10abcdef
    210abcde
    

    У цьому випадку ми хотіли б 0і 1належати до тієї ж діагоналі, як -1і -2, або 2і 3. Тож ще раз ми хочемо округнути до наступного непарного числа.

Ось код для цього:

0f=  e# The coordinates are still on the stack. Replace each with its vertical coordinate
     e# to check for the horizontal axis.
P    e# Push the coordinates again.
::+  e# Sum each pair to get an anti-diagonal index.
Xf|  e# OR each index with 1 to round up to the next odd number.
P    e# Push the coordinates again.
::-  e# In each pair, subtract the horizontal coordinate from the vertical, to
     e# get a diagonal index.
Xf|  e# OR each index with 1.
]    e# Wrap all three index pairs in an array.
::=  e# Check equality for each pair.
:|   e# Fold bitwise OR over the results to check if at least one pair of indices
     e# was equal.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.