Sackgassen kennzeichnen

16

Bei Eingabe einer ASCII-Kunst- "Straße" wird die Straße mit allen gekennzeichneten Sackgassen ausgegeben.

Dies ist eine Straße:

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

Dies ist die Straße mit den Sackgassen, die mit dem Buchstaben gekennzeichnet sind X:

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

Eine Sackgasse ist definiert als jedes Straßenplättchen, das an n andere Straßenplättchen grenzt , von denen mindestens n-1 nach dieser Regel bereits als Sackgasse gelten . "Angrenzen" erfolgt in den vier Hauptrichtungen, daher zählen diagonal angrenzende Kacheln nicht.

Diese Regel wird wiederholt angewendet, da neu erstellte Sackgassen selbst mehr Sackgassen erstellen können . Beachten Sie außerdem, dass jedes Straßenkärtchen, das nur an ein anderes Straßenkärtchen angrenzt, beim ersten Anwenden der Regel als Sackgasse eingestuft wird.

Eingabe und Ausgabe können entweder eine einzelne Zeichenfolge (mit durch ein beliebiges Zeichen getrennten Zeilen #oder .) oder ein Array / eine Liste / usw. Sein. Wenn Ihre Sprache dies unterstützt, können Sie auch Eingaben vornehmen, wobei jede Zeile ein Funktionsargument ist.

In Bezug auf die Eingabe können Sie Folgendes annehmen:

  • Es wird immer mindestens eine "Schleife" geben - das ist eine Gruppe von #Zeichen, der unendlich gefolgt werden kann. (Andernfalls würde jedes einzelne Plättchen eine Sackgasse werden.)

  • Dies impliziert, dass die Eingabe immer 2 × 2 oder größer ist, da die kleinste Schleife:

    ##
    ##
    

    (Was übrigens unverändert ausgegeben werden soll.)

  • Alle #Charaktere werden verbunden. Das heißt, wenn Sie eine Überflutung durchführen #, sind alle davon betroffen.

Da es sich um , wird der kürzeste Code in Bytes gewinnen.

Das obige Beispiel und das winzige 2 × 2-Raster können als Testfälle verwendet werden (es gibt nicht viele Randfälle, die in dieser Herausforderung behandelt werden müssen).

Türknauf
quelle

Antworten:

8

CJam, 61 Bytes

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

Probieren Sie es hier aus .

Erläuterung

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 sparte zwei Bytes, danke!)

Lynn
quelle
Das ist eine der längsten CJAM-Antworten, die ich je gesehen habe. =)
DJMcMayhem
2
@ DJMcGoathem Ummm ...
Martin Ender
Sind '#und "#"anders in CJam?
ETHproductions
Ja, das sind sie. "#"ist gleich ['#].
Lynn
5

JavaScript (ES6), 110 bis 109 Byte

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 gespart dank @ edc65 !

Erläuterung

Sehr einfache Herangehensweise an das Problem. Sucht nach jedem #und #ersetzt es durch ein , wenn es weniger als 2 Sekunden um ihn herum gibt X. Wiederholt diesen Vorgang so oft, bis garantiert ist, dass alle Sackgassen durch Xs ersetzt wurden.

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
quelle
1
Gemeinsamer Trick, den ich immer für diese Art von Aufgabe benutze. Da Sie sowohl l als auch -l auf die gleiche Weise verwenden, können Sie l=~r.searchanstelle von berechnen l=1+r.search. (Nur 1 Byte gespeichert)
edc65
@ edc65 Clever. Vielen Dank!
user81655
0

Python (3.5) 362 331 329 314 Bytes

danke an @Alissa. Sie hilft mir, ~ 33 Bytes zu gewinnen

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

Erklärungen

d='.'
r=range

Funktionsdefinition

def f(s):

Fügen Sie einen Rand von '.' rechts und links von der Tafel

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

Fügen Sie einen Rand von '.' oben und unten

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

Lambda-Funktion zum Testen von '#'

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

Durchlaufen Sie die Eingabe, um sicherzustellen, dass wir keine Sackgassen vergessen

 for k in r(l*c):

Schleife auf Spalten und Zeilen

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

Testen Sie, ob wir ein "#" in der Nähe und an der Position haben

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

Ersetze '#' durch 'X'

     t[h][x]='X'

Schneiden Sie den Rand mit '.' und mach mit

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

Verwendung

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
quelle
1) split()statt verwenden splitlines(). 2) t=['.'*(c+2)]+['.'+i+'.'for i in s]+['.'*(c+2)]ist kürzer. Und es kann noch mehr verkürzt werden: d='.';t=[d*c]+t+[d*c];t=[d+i+d for i in t]3) Sie brauchen nicht alle Liste (zip (....)) Sache, verwenden Sieprint('\n'.join([''.join(i[1:-1])for i in t])
Alissa
@ Alissa danke für Ihre Hilfe Ich benutze Ihre Tipps für Punkt 1) und 3), aber für die 2) Ich kann nicht alle Klammern entfernen, wir brauchen eine Liste der Liste der Zeichen und keine Liste der Zeichenfolge, weil 'str' object does not support item assignment. Die Liste der Liste ermöglicht es mir, t [h] [x] = 'X'
Erwan
Entschuldigung, ich habe die Sache mit der Unveränderlichkeit der Saiten verpasst. Sie können auch alle Konstanten (bewegen r, gund d) aus Ihrer Funktion (erspart Ihnen einige tabellarische). Vielleicht hilft ein wenig Herumspielen von split (): t=[d+list(i)+d for i in s.split()]Berechnen Sie dann die Längen, fügen Sie Punktlinien am Ende und am Anfang hinzu und ändern Sie dann Ihre Zyklen, um mit diesen erweiterten Längen zu arbeiten. Nicht sicher, ob es den Code verkürzen wird, aber es könnte
Alissa
@Alissa Ich kann das g nicht aus der Funktion verschieben, weil es t verwendet, ich werde Ihren anderen Kommentar testen
Erwan