Label dead ends
CJam, 61 bytes
q_N/{{0f+zW%}4*3ew:z3few::z{e__4=_@1>2%'#e=*"#"='X@?}f%}@,*N*
Try it here.
Explanation
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 saved two bytes, thanks!)
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 saved thanks to @edc65!
Explanation
Very simple approach to the problem. Searches for each #
, and if there are less than 2 #
s around it, replaces it with an X
. Repeats this process many times until it's guaranteed all the dead-ends have been replaced with X
s.
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>