Oznacz ślepe zaułki

16

Biorąc pod uwagę wejście „drogi” w sztuce ASCII, wyjmij drogę z oznaczonymi wszystkimi ślepymi zaułkami.

To jest droga:

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

To droga z ślepymi zaułkami oznaczonymi literą X:

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

Ślepy zaułek jest zdefiniowany jako dowolny płytki drogi że granice n inne płytki drogowe, co najmniej n-1 które są uważane za martwe końce już od tej reguły. „Granice” są w czterech głównych kierunkach, więc płytki graniczące po przekątnej nie liczą się.

Zasada ta jest stosowana wielokrotnie, ponieważ nowo utworzone ślepe zaułki mogą same tworzyć więcej ślepych zaułków . Należy również pamiętać, że każdy kafelek drogi, który graniczy tylko z jednym innym kafelkiem drogi, jest uważany za ślepy zaułek przy pierwszym zastosowaniu reguły.

Dane wejściowe i wyjściowe mogą być albo pojedynczym łańcuchem (z wierszami oddzielonymi dowolnym znakiem, który nie jest #lub .), albo tablicą / listą itp. Jeśli twój język to obsługuje, możesz również pobierać dane wejściowe, a każdy wiersz jest argumentem funkcji.

Możesz przyjąć następujące założenia dotyczące danych wejściowych:

  • Zawsze będzie przynajmniej jedna „pętla” - grupa #znaków, którą można śledzić w nieskończoność. (W przeciwnym razie każdy kafelek stałby się ślepym zaułkiem.)

  • Oznacza to, że wejście będzie zawsze 2 × 2 lub większe, ponieważ najmniejsza pętla to:

    ##
    ##
    

    (Nawiasem mówiąc, powinno być generowane bez zmian.)

  • Wszystkie #postacie zostaną połączone. Oznacza to, że jeśli wykonasz wypełnienie powodziowe na którymkolwiek #z nich, wpłynie to na wszystkie z nich.

Ponieważ tak jest , wygra najkrótszy kod w bajtach.

Powyższy przykład i mała siatka 2 × 2 mogą być użyte jako przypadki testowe (w tym wyzwaniu nie ma zbyt wielu przypadków brzegowych).

Klamka
źródło

Odpowiedzi:

8

CJam, 61 bajtów

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

Wypróbuj tutaj .

Wyjaśnienie

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 zapisał dwa bajty, dzięki!)

Lynn
źródło
To jedna z najdłuższych odpowiedzi na cjam, jakie kiedykolwiek widziałem. =)
DJMcMayhem
2
@DJMcGoathem Ummm ...
Martin Ender
Czy są '#i "#"różnią się w CJam?
ETHprodukcje
Tak, są. "#"jest równy ['#].
Lynn
5

JavaScript (ES6), 110 109 bajtów

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 bajt zapisany dzięki @ edc65 !

Wyjaśnienie

Bardzo proste podejście do problemu. Wyszukuje każde #, a jeśli #wokół niego są mniej niż 2 s, zastępuje je znakiem X. Powtarza ten proces wiele razy, dopóki nie zostanie zagwarantowane, że wszystkie ślepe zaułki zostaną zastąpione przez 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>

użytkownik 81655
źródło
1
Typowa sztuczka, której zawsze używam do tego typu zadań. Ponieważ używasz zarówno l, jak i -l w ten sam sposób, możesz obliczyć l=~r.searchzamiast l=1+r.search. (Zapisano tylko 1 bajt)
edc65
@ edc65 Clever. Dzięki!
user81655
0

Python (3.5) 362 331 329 314 bajtów

dzięki @Alissa. pomaga mi wygrać ~ 33 bajty

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

Objaśnienia

d='.'
r=range

Definicja funkcji

def f(s):

Dodaj granicę „.” po prawej i lewej stronie planszy

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

Dodaj granicę „.” na górze i na dole

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

Funkcja lambda do testowania „#”

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

Zapętlaj długość wejściową, aby mieć pewność, że nie zapomnimy ślepych zaułków

 for k in r(l*c):

Pętla na kolumnach i liniach

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

Sprawdź, czy mamy „#” wokół i na pozycji

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

Zamień „#” na „X”

     t[h][x]='X'

Przytnij granicę wypełnioną „.” i dołącz w ciąg

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

Stosowanie

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
źródło
1) użyj split()zamiast splitlines(). 2) t=['.'*(c+2)]+['.'+i+'.'for i in s]+['.'*(c+2)]jest krótszy. Można to jeszcze bardziej skrócić: d='.';t=[d*c]+t+[d*c];t=[d+i+d for i in t]3) nie potrzebujesz całej listy (zip (....)), użyjprint('\n'.join([''.join(i[1:-1])for i in t])
Alissa
@Alissa, dziękuję za pomoc. Korzystam z twoich wskazówek dla punktu 1) i 3), ale dla 2) nie mogę usunąć całego nawiasu, potrzebujemy listy znaków char, a nie listy ciągów, ponieważ 'str' object does not support item assignment. lista pozwala mi użyć t [h] [x] = 'X'
Erwan
przepraszam, tęskniłem za niezmiennością łańcucha. Można także przenieść wszystkie stałe ( r, gi d) ze swojego funkcji (oszczędza trochę tabulacji). Może może pomóc trochę zabawy przy split ():, t=[d+list(i)+d for i in s.split()]a następnie oblicz długości, następnie dodaj kropki na końcu i na początku, a następnie zmień cykle, aby pracować z tymi długimi długościami. Nie jestem pewien, czy skróci kod, ale może
Alissa
@Alissa, nie mogę przenieść g poza funkcję, ponieważ używa t, przetestuję twój inny komentarz
Erwan