| Bytes | Lang | Time | Link |
|---|---|---|---|
| 077 | R | 251004T221644Z | Glory2Uk |
| 109 | Txr Lisp | 211222T004445Z | Kaz |
| 016 | Jelly | 211220T020654Z | Unrelate |
| 141 | C gcc | 220119T085112Z | l4m2 |
| 103 | Perl 5 | 220102T025040Z | Kjetil S |
| 191 | C gcc | 211220T121046Z | Noodle9 |
| 205 | Python3 | 211222T014827Z | Ajax1234 |
| nan | Vyxal | 211220T020042Z | okie |
| 034 | SnakeEx | 211220T220632Z | DLosc |
| 156 | Brev | 211220T213308Z | Sandra |
| 021 | 05AB1E legacy | 211220T174840Z | Kevin Cr |
| 091 | Retina 0.8.2 | 211220T070910Z | Neil |
| 047 | Charcoal | 211220T095944Z | Neil |
| 089 | JavaScript Node.js | 211220T091634Z | tsh |
| 043 | J | 211220T071343Z | Jonah |
| 112 | JavaScript ES6 | 211220T022548Z | Arnauld |
| 019 | Jelly | 211220T004509Z | hyperneu |
| 254 | JavaScript ES6 | 211220T005605Z | rydwolf |
R, 87 81 77 bytes
\(m,`[`=apply)all(m[1,g<-\(b)ave(b,diffinv(!!diff(!b)),FUN=max)]*t(m[2,g])-1)
- -6 bytes by @pajonk
- -4 bytes
Explanation
A function that inputs a 2D array populated with the numbers 0 to 2 (# = 0, . = 1, L = 2). It returns True if all empty tiles are lit up or False otherwise.
The idea is to check the array once row-wise and once column-wise and identify the groups containing both 1 and 2 (lit up areas). Those groups are replaced with 2's. All other tiles remain themselves. Two arrays resulting from the row-wise and the column-wise substitutions are multiplied elementwise. This way we can identify the tiles which aren't lit, neither horizontally nor vertically since they remain 1 × 1 = 1.
Finally, the core algorithm is based on the ave function. What it does here is replacing all groups with their group maximum (this only replaces 1's that contact with 2's). The splitting of the row/column into groups is based upon the second argument of ave, which acts as a mask and this is where the most optimization occured (5 bytes in total).
Txr Lisp, 109 bytes
(do let((l(op mapcar(op regsub #/[. ]*L[. ]*/(op regsub #/\./" ")))))(find #\.(cat-str[l(transpose[l @1])])))
103 bytes
(op find #\.(cat-str[#1=(op mapcar(op regsub #/[. ]*L[. ]*/(op regsub #/\./" ")))(transpose[#1# @1])]))
97 bytes
Drop (cat-str X), use quasiliteral `@x`.
(op find #\.`@[#1=(op mapcar(op regsub #/[. ]*L[. ]*/(op regsub #/\./" ")))(transpose[#1# @1])]`)
93 bytes
Use map alias spelling of mapcar, remove stray space.
(op find #\.`@[#1=(op map(op regsub #/[. ]*L[. ]*/(op regsub #/\./" ")))(transpose[#1#@1])]`)
This is an expression that evaluate so to a function which operates on sequence of strings, those being the lines of the grid.
The function returns #\., the dot character, to indicate that unlit areas remain. Otherwise it returns nil. A character is truthy, and nil is the only false value.
The logic is just regex. The regsub function matches regular expressions. If the replacement argument is a function, the matched text is passed to it and replaced with what the function returns. For the substitution we use another partially applied regsub which replaces dots with spaces.
So, in every string of dots or spaces that contains an L, we replace the dots with spaces, doing this in every string. Then we transpose the vector of strings and do it again.
Truthy example:
#####.### #####.### #### ####
#L...L... --> #L L --> #L# --> #L#
##.####L. ##.####L # .L # L
#.L..#### # L #### # # # #
# # # #
.L## L##
# ## # ##
# L# # L#
# # # #
No dots remain, so everything is lit.
This main list-of-string processing action for replacing the Ls is a function. In the 109 byte version, it bound to the lexical variable l, which we then refer to twice separated by a transpose call.
In the 103 byte version, we get rid of the local variable and just repeat the code in two places using the Lisp circle notation. #1=OBJ means "OBJ, also associated with label 1". And #1# then means "reproduce the object from label 1, OBJ here". With this we can make a piece of data (i.e. piece of source code, of code is data) appear in two or more places.
Jelly, 17 16 bytes
»×¥@\Ṛ$⁺
Ç€»ÇF1e
Fixed by borrowing back from hyper-neutrino lmao
-1 replacing the double transpose with a map by replacing the map with implicit vectorization
Takes a matrix of 0 for #, 1 for ., and 2 for L.
»×¥@\Ṛ$⁺ Monadic helper link: light up all columns or a row
\ Scan by
» @ (vectorizing) max of right and
×¥ (vectorizing) product,
Ṛ then reverse.
$⁺ Do it again.
Ç€»ÇF1e Monadic main link: is there anything unlit?
Ç Light up
€ each row,
Ç light up the columns,
» and take the maximum at each position.
F Flatten the result.
1e Does it contain 1?
C (gcc), 146 141 bytes
#define F(d)for(i=r*c;i--;F&=m[i])for(j=i;m[i]>3&1u*j<r*c&m[j]<8&&j/c!=i/c^d*d;j+=d)m[j]|=1;
i;j;F;f(m,r,c)int*m;{F(1)F(-1)F(c)F=1;F(-c)i=F;}
Thank ceilingcat for -3 bytes
Not quite sure what Noodle9 did, and not sure why I can't F(1)(-1)... here
Perl 5, 103 bytes
sub{$_=pop;while(!$h{$_}++){s/(Ll*)\./$1l/;$r=@l=();map/\s/?$r=0:$l[$r++]=~s/^/$_/,/./gs;$_="@l"}!/\./}
C (gcc), 274 \$\cdots\$ 195 191 bytes
#define F for(y=0,i=r*c;i--;
#define J(A,B,C,D)for(y=A c;--y+B&&~-m[C*c+D];)m[C*c+D]|=m[i]*2&4;
i;y;f(m,r,c)int*m;{F){J(-i%,c,i/c,-y)J(i%,1,i/c,y)J(-i/,r,-y,i%c)J(i/,1,y,i%c)}F)y|=!m[i];i=y;}
Saved a whopping 45 \$\cdots\$ 55 59 bytes and got below 200 thanks to ceilingcat!!!
Inputs a pointer to an array of integers along with the room dimensions (since pointers in C carry no length info).
These integers represent a room with \$0\$ -> ., \$1\$ -> #, and \$2\$ -> L.
Returns \$0\$ if the room is lit up or \$1\$ otherwise.
Python3, 205 bytes:
import re
m=lambda x:re.sub('(?:\.+)*L(?:\.+)*',lambda j:'L'*len(j.group()),x)
f=lambda x:all(all(n!=('.','.')for n in zip(m(i),j)if n!=('#','#'))for i,j in zip(x,[*zip(*[m(''.join(c))for c in zip(*x)])]))
Vyxal, 29 27 25 23 bytes
2(⌈ƛƛ:×c[¶1V];Ṅ;∩vṅ)∑¶↔
Split on wall, check if any spilt contain light, replace it with 1, transpose, do it again, check sum.
outputs empty string for false, dots otherwise.
-2 by @lyxal (pog)
-2 by @lyxal again (1 minute after first one)
-2 by ... yep still @lyxal
SnakeEx, 34 bytes
m:{d<>}{d<R>}{d<L>}{d<B>}
d:,+[#$]
Uses , instead of .; to take inputs formatted as in the question, replace , on the second line with \.. Outputs one or more matches (truthy) for a room that is not fully lit, no matches (falsey) for a room that is lit. Try it here!
Explanation
Core idea: find a , which can't "see" an L in any of the four directions. If no such , exists, the room is fully lit; if such a , exists, it is not fully lit.
d: Define a helper snake d to match
,+ 1 or more commas
[#$] followed by a pound sign or the edge of the grid
m: Define the main snake m to match
{d<>} d in the default direction (left-to-right)
{d<R>} and also in the direction 90 degrees clockwise (top-to-bottom)
{d<L>} and the direction 90 degrees counterclockwise (bottom-to-top)
{d<B>} and the reverse direction (right-to-left)
Brev, 159, no, 156 bytes:
(define (l row) (strse row "[g_]*L+[g_]*" (strse (m 0) "_" "g")))
(print (apply any (compose (strse? "_") l string) (map (o string->list l) (read-lines))))
Uses _ instead of . (shaves four bytes) and prints #f for lit up, #t for dark.
Update: remove a redundant partial applicator
05AB1E (legacy), 21 bytes
3xŸvTyT+:yT*y∞:ζí}SßĀ
Input as a list of lines, where .L# are 012 respectively.
Uses the legacy version of 05AB1E where the ζ and : builtin works on list of strings, which would have been €SζJ and required a map over the lines in the new 05AB1E (ending up 6 bytes longer).
Try it online or verify all test cases.
Explanation:
3 # Push a 3
x # Double it (without popping): 6
Ÿ # Pop both and push a list in this range: [3,4,5,6]
v # Loop over each of these digits `y`:
: # Replace all:
T # "10"
yT+ # with "1y", where `y` is the current digit
# (which use the implicit input-list in the first iteration)
: # Then infinitely replace all:
yT* # "y0"
y∞ # with "yy", where the `y` are again the current digit
ζí # Then rotate once clockwise:
ζ # Zip/transpose; swapping rows/columns
í # Reverse each row
} # After the loop, we want to check if any empty spots remain:
S # Convert the list of strings to a flattened list of characters
ß # Pop and push its minimum
Ā # Check if this is NOT 0
# (after which the result is output implicitly)
Retina 0.8.2, 94 91 bytes
(?!_+L|((?<=(.)*)_.*¶(?<-2>.)*(?(2)^))+L)_(?<!L_+|L((?<=(?<!.)(?(4)$)(?<-4>.)*.).*¶(.)*_)+)
Try it online! Takes input using _ as a floor tile instead of . but header converts . to _ for you for convenience. Outputs the number of unlit floor tiles, so a falsy value if the room is lit. Explanation:
(?!_+L|
Don't match a floor tile that is to the left of a light, or...
((?<=(.)*)_.*¶(?<-2>.)*(?(2)^))+L)
... that is above a light.
_
Match an unlit floor tile.
(?<!L_+|
Don't match a floor tile that is to the right of a light, or...
L((?<=(?<!.)(?(4)$)(?<-4>.)*.).*¶(.)*_)+)
... that is below a light.
.NET balancing groups are used to ensure that the light is in the same column as the tile.
Charcoal, 47 bytes
WS⊞υιυFLυF⌕A§υιLF⁴«JκιM✳⊗λW﹪℅KK³⁵✳⊗λ_»≔№KA.θ⎚¬θ
Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings and outputs a Charcoal boolean, i.e. - if the room is fully lit, nothing if not. Explanation:
WS⊞υιυ
Input the map and print it to the canvas.
FLυF⌕A§υιLF⁴«
Loop over the lights in all directions.
JκιM✳⊗λ
Move to a tile adjacent to a light.
W﹪℅KK³⁵
While this tile is not wall, ...
✳⊗λ_
... mark it as lit and move to the next tile. (Note: If there are two lamps, they'll light each other, but the loop above checks the original lamps, so it doesn't matter that they get removed from the canvas.)
»≔№KA.θ
Count the number of remaining unlit tiles.
⎚¬θ
Clear the canvas and output the result.
JavaScript (Node.js), 89 bytes
f=(a,n=4)=>n?f(a[0].map((_,x)=>a.map(c=>(t=c.at(~x))>1?p=t:t|p>>2,p=0)),n-1):!/0/.test(a)
Input matrix where 0 = empty, 2 = wall, 4 = light. Output true vs. false.
Rotate the matrix 90deg 4 times, fill empty cell if there is a light on its left side. Finally test if there are any empty cell left.
This function use ES2022 feature Array#at which requires a newer version of NodeJs than current TIO available. A Polyfill for Array#at is included in the header of TIO code. So it may be tested on it. You may execute it on a more recent version NodeJs without the header.
f=
(a, // input matrix
n=4 // rotate 4 times
)=>n?
f(
a[0].map((_,x)=>a.map(c=>(t=c.at(~x)) // rotate
/* t */>1?p=t:t|p>>2,p=0) // fill empty cell if there is a light left side
),n-1):
!/0/.test(a) // no empty cells left
JavaScript (Node.js), 95 bytes
a=>w=>a.every((c,i)=>c|[-2,-1,1,2].some(s=>a.some(_=>t=a[j+=s%2?(j%w-~s)%-~w&&s:s*w/2],j=i)&t))
Input flatten matrix with 0 = empty, 1 = light, 2 = wall, and its width. Output true vs. false.
a=> // the matrix; 0 = empty, 1 = light, 2 = wall
w=> // width of matrix
a.every( // if every cell is
(c,i)=>c| // either cell is not empty
// or cell is lighted
[-2,-1,1,2] // four directions; up, left, right, down
.some(s=> // any direction that
a.some(_=> // repeat enough times (we use `a` only because it is long enough)
t=a[ // repeat move until current cell is non empty
j+=s%2? // -2, 2 are left / right, while -1, 1 are up / down
(j%w-~s)%-~w&&s: // if we reached end of current row, stop move
s*w/2 // move up or down (may out of bound but we don't care)
],
j=i // starting from cell `i`
)&t // if non-empty cell exists and the cell is light
)
)
J, 43 bytes
*-:g&.|:>.g=.**[:}:@;"1<@(#$2&e.);.2"1@,.&0
Based on okie's "split on walls and check if each section contains a light" idea.
JavaScript (ES6), 112 bytes
Expects a matrix with \$0\$ for walls, \$3\$ for lights and \$4\$ for empty squares. Returns false if the lights cover all the tiles, or true otherwise.
f=m=>m<(m=m.map((r,y)=>r.map((v,x)=>v&&[1,2,1,2].map((b,d)=>v|=(m[y+--d%2]||0)[x+~-d%2]&b)|v)))?f(m):/4/.test(m)
Jelly, 19 bytes
,Z»×¥@\Ṛ$2¡€Z»¥/F’Ạ
"Borrowing" the multiplication idea from Unrelated String (i.e. stealing lol). 0 for #, 1 for ., 2 for L.
JavaScript (ES6), 254 bytes
d=>!(f=i=>i?f(i-1,d=d.replace(/(?<=a|b)[ c]|[ c](?=a|b)/g,x=>"ab"[+
(x<"!")]),d=(t=s=>[...s.split`
`[0]].map((_,i)=>s.split`
`.map(x=>x[i]).join``).join`
`)(t(d).replace(/(?<=a|c)[ b]|[ b](?=a|c)/g,x=>"ac"[+(x<"!")]))):d)
(d.length+d[0].length).includes` `
Uses for empty spaces, a for lights, and any non-alphabetical and non-space character for walls.