Позначте тупики


16

Враховуючи вхідний текст ASCII "дороги", виведіть дорогу з усіма тупиками з маркуванням.

Це дорога:

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

Це дорога з тупиками, позначена буквою X:

########.....######..X..###
#......#######....#..X..#.#
#.XX......X...X####..X..###
#..XXXXX..X....#..#######.#
#......X...#####.....##...#
#..###.X...#...###...#..###
##########.#..X..##..#.##.X
..X......#.#XXXXX.#..#.#.X.
..X......#.#..X.X.#..#.#.X.
..XXXXXX.###..XX..######XXX

Тупиковий визначається як будь-якій дорожній плитки , що кордони п інші дорожні плитки, по крайней мере , п-1 з яких вважаються тупиків вже до цього правила. "Окантовка" знаходиться в чотирьох кардинальних напрямках, тому плитки, що межують по діагоналі, не рахуються.

Це правило застосовується неодноразово, оскільки новостворені тупики можуть самі створити більше тупиків . Також зверніть увагу, що будь-яка дорожня плитка, яка межує лише з однією іншою дорожньою плиткою, вважається тупиком при першому застосуванні правила.

Вхід і вихід можуть бути або окремими рядками (з рядками, розділеними будь-яким символом, який не є # або). ) або масив / список / і т.д .. Якщо ваша мова підтримує його, ви також можете взяти введення, коли кожен рядок є аргументом функції.

Ви можете припустити наступне про вхід:

  • Завжди буде принаймні одна «петля» - це група #символів, за якими можна нескінченно дотримуватися. (Інакше кожна плитка стала б тупиком.)

  • Це означає, що вхід завжди буде 2 × 2 або більше, оскільки найменший цикл:

    ##
    ##
    

    (Що, до речі, повинно виводитися без змін.)

  • Всі #символи будуть підключені. Тобто, якби ви виконали заливку на будь-якій #, будь-яка з них буде зачеплена.

Оскільки це , найкоротший код у байтах виграє.

Приклад, наведений вище, і крихітна сітка 2 × 2 може бути використаний як тестовий випадок (у цьому виклику не так вже й багато крайніх справ).

Відповіді:


8

CJam, 61 байт

q_N/{{0f+zW%}4*3ew:z3few::z{e__4=_@1>2%'#e=*"#"='X@?}f%}@,*N*

Спробуйте тут .

Пояснення

Outline:

    q_N/               Read input lines
        {   }@,*       Perform some operation as many times as there are bytes
                N*     Join lines

Operation:

    {0f+zW%}4*         Box the maze with zeroes
    3ew:z3few::z       Mystical 4D array neighborhood magic.
                       (Think: a 2D array of little 3x3 neighborhood arrays.)

    {                        }f%    For each neighborhood, make a new char:
     e_                                 Flatten the neighborhood
       _4=_                             Get the center tile, C
           @1>2%                        Get the surrounding tiles
                '#e=                    Count surrounding roads, n
                    *                   Repeat char C n times
                     "#"=               Is it "#"? (i.e., C = '# and n = 1)
                         'X@?           Then this becomes an 'X, else keep C.

(Мартін врятував два байти, дякую!)


Це одна з найдовших відповідей на дружину, яку я коли-небудь бачив. =)
DJMcMayhem

2
@DJMcGoathem Ummm ...
Мартін Ендер

Існують '#і "#"різні в CJam?
ETHproductions

Так, вони є. "#"дорівнює ['#].
Лінн

5

JavaScript (ES6), 110 109 байт

r=>[...r].map(_=>r=r.replace(g=/#/g,(_,i)=>(r[i+1]+r[i-1]+r[i+l]+r[i-l]).match(g)[1]||"X"),l=~r.search`
`)&&r

1 байт збережено завдяки @ edc65 !

Пояснення

Дуже простий підхід до проблеми. Пошук кожного #, і якщо #навколо нього менше 2 с, замінює його на an X. Повторюється цей процес багато разів, поки гарантовано всі тупики не будуть замінені Xs.

var solution =

r=>
  [...r].map(_=>                    // repeat r.length times to guarantee completeness
    r=r.replace(g=/#/g,(_,i)=>      // search for each # at index i, update r once done
      (r[i+1]+r[i-1]+r[i+l]+r[i-l]) // create a string of each character adjacent to i
      .match(g)                     // get an array of all # matches in the string
        [1]                         // if element 1 is set, return # (the match is a #)
        ||"X"                       // else if element 1 is undefined, return X
    ),
    l=~r.search`
`                                   // l = line length
  )
  &&r                               // return the updated r
<textarea id="input" rows="10" cols="40">########.....######..#..###
#......#######....#..#..#.#
#.##......#...#####..#..###
#..#####..#....#..#######.#
#......#...#####.....##...#
#..###.#...#...###...#..###
##########.#..#..##..#.##.#
..#......#.######.#..#.#.#.
..#......#.#..#.#.#..#.#.#.
..######.###..##..#########</textarea><br>
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>


1
Загальна хитрість, яку я завжди використовую для такого типу завдань. Оскільки ви використовуєте l і -l однаково, ви можете обчислити l=~r.searchзамість l=1+r.search. (Всього 1 байт збережено)
edc65

@ edc65 Розумний. Спасибі!
користувач81655

0

Пітон (3,5) 362 331 329 314 байт

завдяки @Alissa вона допомагає мені виграти ~ 33 байти

d='.'
r=range
def f(s):
 t=[list(d+i+d)for i in s.split()]
 c=len(t[0])
 u=[[d]*c]
 t=u+t+u
 l=len(t)
 g=lambda h,x:t[h][x]=='#'
 for k in r(l*c):
  for h in r(1,l):
   for x in r(1,c):
    if g(h,x) and g(h+1,x)+g(h-1,x)+g(h,x+1)+g(h,x-1)<2:
     t[h][x]='X'
 print('\n'.join([''.join(i[1:-1])for i in t][1:-1]))

Пояснення

d='.'
r=range

Визначення функції

def f(s):

Додайте межу "." справа і зліва від дошки

 t=[list(d+i+d)for i in s.split()]
 c=len(t[0])
 u=[[d]*c]

Додайте межу "." зверху і знизу

 t=u+t+u
 l=len(t)

Функція лямбда для тестування "#"

 g=lambda h,x:t[h][x]=='#'

Цикл на вхідній довжині, щоб бути впевненим, що ми не забудемо тупики

 for k in r(l*c):

Петля на стовпцях і лініях

  for h in r(1,l):
   for x in r(1,c):

Перевірте, чи є у нас "#" на місці

    if g(h,x) and g(h+1,x)+g(h-1,x)+g(h,x+1)+g(h,x-1)<2:

Замініть "#" на "X"

     t[h][x]='X'

Обріжте кордон, заповнений символом "." і приєднатися до рядка

 print('\n'.join([''.join(i[1:-1])for i in t][1:-1]))

Використання

f("########.....######..#..###\n#......#######....#..#..#.#\n#.##......#...#####..#..###\n#..#####..#....#..#######.#\n#......#...#####.....##...#\n#..###.#...#...###...#..###\n##########.#..#..##..#.##.#\n..#......#.######.#..#.#.#.\n..#......#.#..#.#.#..#.#.#.\n..######.###..##..#########")

########.....######..X..###
#......#######....#..X..#.#
#.XX......X...X####..X..###
#..XXXXX..X....#..#######.#
#......X...#####.....##...#
#..###.X...#...###...#..###
##########.#..X..##..#.##.X
..X......#.#XXXXX.#..#.#.X.
..X......#.#..X.X.#..#.#.X.
..XXXXXX.###..XX..######XXX

1) використовувати split()замість splitlines(). 2) t=['.'*(c+2)]+['.'+i+'.'for i in s]+['.'*(c+2)]коротше. І це можна скоротити ще більше: d='.';t=[d*c]+t+[d*c];t=[d+i+d for i in t]3) вам не потрібен весь список (zip (....)) річ, використовуйтеprint('\n'.join([''.join(i[1:-1])for i in t])
Alissa

@Alissa дякую за вашу допомогу, я використовую ваші поради щодо пункту 1) та 3), але для 2) я не можу видалити всі дужки, нам потрібен список списку char, а не список рядків, тому що 'str' object does not support item assignment. список списку дозволяє мені використовувати t [h] [x] = 'X'
Ерван

Вибачте, я пропустив річ про незмінність струн. Ви також можете перемістити всі константи ( r, gі d) з вашої функції (економить вам деякий підсумовування). Можливо, деякі ігри навколо split () можуть допомогти:, t=[d+list(i)+d for i in s.split()]потім обчислити довжини, потім додати точкові лінії до кінця до початку, а потім змінити свої цикли для роботи з цими розширеними довжинами. Не впевнений, чи скоротить він код, але це може бути
Аліса

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