Rótulos sem saída

16

Dada a entrada de uma "estrada" de arte ASCII, produza a estrada com todos os becos sem saída rotulados.

Esta é uma estrada:

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

Esta é a estrada com becos sem saída rotulados com a letra X:

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

Um beco sem saída é definido como qualquer ladrilho de estrada que faz fronteira com n outros ladrilhos de estrada, pelo menos n-1 dos quais são considerados becos sem saída já por esta regra. "Limite" está nas quatro direções cardinais, portanto, os ladrilhos na diagonal não contam.

Essa regra é aplicada repetidamente, pois os becos sem saída recém-criados podem, eles próprios, criar mais becos sem saída . Observe também que qualquer ladrilho de estrada que limita apenas um outro ladrilho de estrada é considerado um beco sem saída na primeira vez que a regra é aplicada.

Entrada e saída podem ser uma única sequência (com linhas separadas por qualquer caractere que não seja #ou .) ou uma matriz / lista / etc. Se o seu idioma suportar, você também poderá receber entradas, sendo cada linha um argumento de função.

Você pode assumir o seguinte sobre a entrada:

  • Sempre haverá pelo menos um "loop" - ou seja, um grupo de #caracteres que podem ser seguidos infinitamente. (Caso contrário, cada bloco se tornaria um beco sem saída.)

  • Isso implica que a entrada sempre será 2 × 2 ou maior, pois o menor loop é:

    ##
    ##
    

    (Que, aliás, deve ser produzido sem alterações.)

  • Todos os #caracteres serão conectados. Ou seja, se você realizasse um preenchimento de uma inundação #, todas elas seriam afetadas.

Como esse é o , o código mais curto em bytes será vencedor.

O exemplo acima e a pequena grade 2 × 2 podem ser usadas como casos de teste (não há muitos casos extremos a serem abordados neste desafio).

Maçaneta da porta
fonte

Respostas:

8

CJam, 61 bytes

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

Experimente aqui .

Explicação

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.

(Martin salvou dois bytes, obrigado!)

Lynn
fonte
Essa é uma das respostas mais longas do cjam que eu já vi. =)
DJMcMayhem
2
@DJMcGoathem Ummm ...
Martin Ender
São '#e "#"diferentes no CJam?
ETHproductions 02/02
Sim, eles são. "#"é igual a ['#].
Lynn
5

JavaScript (ES6), 110 109 bytes

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 byte salvo graças a @ edc65 !

Explicação

Abordagem muito simples para o problema. Pesquisa cada uma #e, se houver menos de 2 #s em volta, a substitui por uma X. Repita esse processo várias vezes até garantir que todos os becos sem saída tenham sido substituídos por 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>

user81655
fonte
1
Truque comum que eu sempre uso para esse tipo de tarefa. Como você usa l e -l da mesma maneira, pode calcular em l=~r.searchvez de l=1+r.search. (Apenas 1 byte salvo)
edc65 02/02
@ edc65 Inteligente. Obrigado!
User81655
0

Python (3.5) 362 331 329 314 bytes

graças a @Alissa. ela me ajuda a ganhar ~ 33 bytes

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

Explicações

d='.'
r=range

Definição de função

def f(s):

Adicione uma borda de '.' à direita e esquerda do quadro

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

Adicione uma borda de '.' na parte superior e inferior

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

Função Lambda para testar '#'

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

Faça um loop no comprimento da entrada para garantir que não esquecemos becos sem saída

 for k in r(l*c):

Loop em colunas e linhas

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

Teste se temos '#' ao redor e na posição

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

Substituir '#' por 'X'

     t[h][x]='X'

Corte a borda preenchida com '.' e junte-se à string

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

Uso

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
Erwan
fonte
1) use em split()vez de splitlines(). 2) t=['.'*(c+2)]+['.'+i+'.'for i in s]+['.'*(c+2)]é mais curto. E isso pode ser reduzido ainda mais: d='.';t=[d*c]+t+[d*c];t=[d+i+d for i in t]3) você não precisa de toda a lista (zip (....)) coisa, usoprint('\n'.join([''.join(i[1:-1])for i in t])
Alissa
@Alissa obrigado por sua ajuda, eu uso suas dicas para os pontos 1) e 3), mas para os 2) não consigo remover todos os colchetes, precisamos de uma lista de lista de caracteres e não de uma lista de caracteres, porque 'str' object does not support item assignment. a lista de lista me permite usar t [h] [x] = 'X'
Erwan
desculpe, eu senti falta da imutabilidade das cordas. Você também pode mover todas as constantes ( r, ge d) da sua função (economizando algumas tabulações). Talvez algumas brincadeiras com split () possam ajudar t=[d+list(i)+d for i in s.split()]:, calcule comprimentos, adicione linhas de ponto ao final e ao início e altere seus ciclos para trabalhar com esses comprimentos estendidos. Não tenho certeza se ele vai encurtar o código, mas talvez
Alissa
@Alissa i não pode mover o g fora da função porque usar t i vai testar o seu outro comentário
Erwan