Обозначить тупики


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

Под тупиком понимается любая дорожная плитка, которая граничит с n другими дорожными плитками, по крайней мере, n-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.

(Мартин спас два байта, спасибо!)


Это один из самых длинных ответов cjam, которые я когда-либо видел. =)
DJMcMayhem

2
@DJMcGoathem Уммм ...
Мартин Эндер

Существуют '#и "#"разные в 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 секунд, заменяет его на 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 Умный. Благодарность!
user81655

0

Python (3,5) 362 331 329 314 байт

благодаря @ Алисса. она помогает мне выиграть ~ 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])
Алисса

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

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

@ Алисса, я не могу переместить g из функции, потому что она использует т, я проверю твой другой комментарий
Erwan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.