| Bytes | Lang | Time | Link |
|---|---|---|---|
| 195 | Perl 5 | 250705T140109Z | good old |
| 456 | Maple | 250702T003055Z | dharr |
| 198 | JavaScript ES6 | 250629T235924Z | Arnauld |
| 800 | Python3 | 250630T170230Z | Ajax1234 |
| 165 | Charcoal | 250629T195013Z | Neil |
Perl 5, 195 196 .. 253 bytes
($c,$_)='..'x((@d=/\d/g)/@{$x=eval});$_=/7|0\n|(\n.*){$#$x}3/?pop@a:$_.(($n-=/0$/+/3$c$/s)^1||!!push@a,$_.32).!$n*2while$n=0*s/$c$/2$&\n/.$d[y/13//];$_=$&.s!.+\n!$&=~y/201/| /r.$&!ger;y/1302/- +/
-p0 are the CLI switches. Somewhat un-golfed but not commented:
( $c, $_ ) = '..' x (( @d = /\d/g ) / @{ $x = eval });
$_ = / 7 | 0\n | (\n.*){$#$x}3 /x
? pop @a
: $_ . (
( $n -= /0$/ + /3$c$/s ) ^ 1
|| !!push @a, $_ . 32
)
. !$n * 2
while $n = 0 * s/$c$/2$&\n/ . $d[ y/13// ];
$_ = $& . s!.+\n! $& =~ y/201/| /r . $& !ger;
y/1302/- +/
Maple, 472 456 bytes
proc(s)m:=nops(s);n:=nops(s[1]);M,N:=2*m+1,2*n+1;X:=Matrix(M,N,(i,j)->`if`(`and`((i,j)::~odd),"+"," "));e:=();for p to m do for q to n do i,j:=2*p,2*q;e,=x[i,j-1]+x[i,j+1]+x[i-1,j]+x[i+1,j]=s[p,q]od od;f:={seq([x[1,p],x[M,p]][],p=2..N,2),seq([x[q,1],x[q,N]][],q=2..M,2)}=~0;Z:=subs(f,{e});Y:=indets(Z);assign(subs(x=X,map(d->`if`(rhs(d)=1,NULL,`if`(op(1,(h:=lhs(d)))::odd,h="-",h="|")),SMTLIB:-Satisfy({Z[],(Y>=~0)[],(Y<~2)[]})union f)));printf("%s",X)end;
For m rows of rooms and n columns of rooms, set up a (2m+1) x (2n+1) matrix X=(x)_{i,j} with an entry for each character in the printout. Set up spaces in room interiors and "+" at the room corners. Set up the walls for the perimeter with values 0 (0 = wall, 1 = door). So for the p,q th room (p = 1,..,m, q = 1,..,n) with given wall number s[p,q], we have x[2p,2q-1]+x[2p,2q+1]+x[2p-1,2q]+x[2p+1,2q] = s[p,q]. Solve these equations and fill in walls of the correct type.
Slightly ungolfed:
proc(s)
m:=nops(s);
n:=nops(s[1]);
M,N:=2*m+1,2*n+1;
# X is matrix of characters; start with "+" and " "
X:=Matrix(M,N,(i,j)->`if`(`and`((i,j)::~odd),"+"," "));
e:=(); # initialize eqns to solve
for p to m do for q to n do
i,j:=2*p,2*q;
e,=x[i,j-1]+x[i,j+1]+x[i-1,j]+x[i+1,j]=s[p,q] # eqns for door numbers
od od;
# f sets wall variables around the boundary to zero
f:={seq([x[1,p],x[M,p]][],p=2..N,2),seq([x[q,1],x[q,N]][],q=2..M,2)}=~0;
Z:=subs(f,{e}); # set known wall vals in eqns
Y:=indets(Z);
C:=(Y>=~0)[],(Y<~2)[]; # conditions for all variables 0 or 1
R:=SMTLIB:-Satisfy({Z[],C}); # find a solution
# where there are walls, substitute "|" or "-" (doors are already " ")
S:=map(d->`if`(rhs(d)=1,NULL,`if`(op(1,(h:=lhs(d)))::odd,h="-",h="|")),R union f);
assign(subs(x=X,S));
printf("%s",X) # print out as string
end;
JavaScript (ES6), 198 bytes
Returns a string.
m=>{for(N=0;n=N++,s="",m.some((r,y)=>r.some(v=>v^(k=n&!!y+2*!!x++,p+=k&1?" +":"-+",q+=k&2?" ":"| ",n>>2*r.length&!!m[y+1])+((n/=4)/2&!!r[x])-~k/2,p="+",x=q=`
`)|(y?0:t=p,s+=p+q+`|
`)););return s+t}
Method
We use a brute-force search that increments a counter N until its bits represent a set of doorways compatible with the input matrix.
We build the output string s while testing the bits. Each row of the input matrix is turned into two strings p and q, representing horizontal and vertical doorways respectively. The last line is a copy of the first line (saved in t), where all doors are closed.
We use 2 bits per cell to encode the doorways to the North (bit #0) and to the West (bit #1). A cleared bit means closed. A set bit means open.
We have 3 cells to test to compute the total number of doorways at a given position:
Commented
m => { // m[] = input matrix
for( // main loop
N = 0; // start with a counter N set to 0
n = N++, // copy N to n, then increment N
s = "", // start each iteration with s = ""
m.some((r, y) => // for each row r[] at index y in m[]:
r.some(v => // for each value v in r[]:
v ^ ( // compare v against the sum of doorways
k = n & // k = doorway bitmask of the current cell:
!!y + // allow bit #0 if y != 0
2 * !!x++, // allow bit #1 if x != 0 (and increment x)
p += k & 1 ? " +" // add " +" to p if bit #0 is set,
: "-+", // or "-+" otherwise
q += k & 2 ? " " // add " " to q if bit #1 is set,
: "| ", // or "| " otherwise
// test the doorways with touching cells:
n >> 2 * r.length // 1. the cell below
& !!m[y + 1] // force a door if it's the last row
) + ( //
(n /= 4) / 2 // 2. the cell to the right
& !!r[x] // force a door if it's the last column
// (we also update n)
) - ~k / 2, // count the doorways of the current cell
// (number of bits set in k)
p = "+", // start with p = "+"
x = q = `\n` // start with q = "\n" and x zero'ish
) | ( // end of inner some()
y ? 0 : t = p, // if this is the first row, save p in t
s += p + q + `|\n` // append p, q, a pipe and a newline to s
) //
); // end of outer some()
); // end of for()
return s + t } // return s + t
Python3, 800 bytes
from itertools import*
E=enumerate
def f(b):
V=['+',*'+'.join('-'*len(b[0])),'+']
U=[k for i in b for k in[V,['|',*'|'.join(' '*len(i)),'|']]]+[V]
q=[S:={(x,y):v for x,r in E(U)for y,v in E(r)if v in['|',' ','-']}]
M=dict(zip([i for i in q[0]if' '==q[0][i]],[j for k in b for j in k]))
for c in q:
T,F=[],0
for x,y,o in[(x,y,[(x+X,y+Y)for X,Y in[(1,0),(-1,0),(0,-1),(0,1)]])for x,y in c if' '==S[(x,y)]]:
if M[(x,y)]>(H:=sum(c[O]==' 'for O in o)):T+=[(x,y,o)]
if M[(x,y)]<H:F=1
if[]==T:
for X,Y in c:U[X][Y]=c[(X,Y)]
return'\n'.join(map(''.join,U))
if F:continue
x,y,o=T[0]
for t in combinations([(X,Y)for X,Y in o if(c[(X,Y)]=='|'and 0<Y-1 and Y+1<len(U[0])-1)or(c[(X,Y)]=='-'and 0<X-1 and X+1<len(U)-1)],M[(x,y)]-sum(c[O]==' 'for O in o)):q+=[{**c,**{i:' 'for i in t}}]
Charcoal, 226 165 bytes
WS⊞υιυUE¹¦¹FLυFLθ«J⊖⊗κ⊖⊗ιB³¦³»≔⁰ηW‹ηLΣυ«J⊗﹪ηLθ⊗÷ηLθ≔ΦrdΣ⊟KD³✳κζ≔›ΣKKLζεWε«≔dζ≦⊖ηJ⊗﹪ηLθ⊗÷ηLθ≔¬∧Σ⊟KD³↓⁼ -Φ⪫KVω﹪μ³εP0FΦErdKD³✳λ№λ UMλ⎇⊖νI⊕μ|P¶-»FΣKKUMKD³✳§ζκ⎇⊖μI⊖λ ≦⊕η
Try it online! Link is to verbose version of code. Takes input as a rectangular list of newline-terminated digit strings. Explanation:
WS⊞υιυ
Input the floorplan and write it to the canvas.
UE¹¦¹FLυFLθ«J⊖⊗κ⊖⊗ιB³¦³»
Space out the digits and draw boxes around each of them.
≔⁰ηW‹ηLΣυ«
Loop until all of the rooms have been processed.
J⊗﹪ηLθ⊗÷ηLθ
Jump to the current room.
≔ΦrdΣ⊟KD³✳κζ
Find the remaining possible doorways (i.e. that are down or right and lead to a room which still wants at least one more doorway).
≔›ΣKKLζε
See if there are more doorways wanted than possible.
Wε«≔dζ
While we need to backtrack, set the possible doorways to down.
≦⊖ηJ⊗﹪ηLθ⊗÷ηLθ
Move to the previous room.
≔¬∧Σ⊟KD³↓⁼ -Φ⪫KVω﹪μ³ε
See if this was a room where we chose a single right doorway but it had both doorways available, in which case we can stop backtracking.
P0
Restore the doorway count to this room.
FΦErdKD³✳λ№λ UMλ⎇⊖νI⊕μ|
Remove any previous right or down doorways.
P¶-
The above restored the down wall with |, so correct that now.
»FΣKKUMKD³✳§ζκ⎇⊖μI⊖λ ≦⊕η
This room can now be satisfied, so create the desired number of doorways and move to the next room, clearing the doorway count.
