| Bytes | Lang | Time | Link |
|---|---|---|---|
| 046 | 05AB1E | 250620T134608Z | Kevin Cr |
| 051 | oK | 250620T122123Z | zgrep |
| 317 | Befunge93 | 171125T143250Z | Jo King |
| 015 | MATL | 171123T174331Z | Luis Men |
| 181 | JavaScript ES6 | 171124T015900Z | yetirs |
| 247 | Python 2 | 171124T094349Z | TFeld |
| 114 | JavaScript ES6 | 171124T082901Z | Arnauld |
| 066 | J | 171124T051413Z | Jonah |
| 096 | Wolfram Language Mathematica | 171124T025604Z | Misha La |
05AB1E, 46 bytes
˜εQ©˜ƶ®gäΔ4F¬ašøí}2Fø€ü3}®*εε˜ŽqÆSèà]ε˜Ù0Kg}PΘ
Input as a matrix of characters.
Outputs 1/0 for truthy/falsey respectively. Could be -1 byte if the default truthy/falsey wasn't overwritten, with 1 for truthy and \$\geq2\$ for falsey.
Try it online or verify all test cases.
Explanation:
The flood-fill section ˜ƶ®gäΔ4F¬ašøí}2Fø€ü3}®*εε˜ŽqÆSèà] is similar as I've done in multiple other challenges (e.g. this answer for the Max Island Area challenge).
˜ # Flatten the (implicit) input-matrix to a list of characters
ε # Map over each character:
Q # Equals check with the values in the (implicit) input-matrix;
# will mark all locations of the character as 1, and other characters as 0
© # Store this matrix of bits in variable `®` (without popping)
˜ # Flatten it
ƶ # Multiply each value by its 1-based index
®g # Push the length (amount of rows) of matrix `®`
ä # Convert the list back to a matrix with that many rows
Δ # Loop until the result no longer changes to flood-fill the matrix:
# Add a border of 0s around the matrix:
4F } # Loop 4 times:
¬ # Push the first row of the current matrix (without popping)
a # Convert all values to 0s (with an is_letter check)
š # Prepend that row of 0s to the matrix
øí # Rotate once clockwise:
ø # Zip/transpose; swapping rows/columns
í # Reverse each inner list
2Fø€ü3} # Then get all overlapping 3x3 blocks:
2F } # Loop 2 times:
ø # Zip/transpose; swapping rows/columns
€ # Map over each inner row:
ü3 # Get all overlapping triplets
®* # Multiply this matrix of 3x3 blocks by bit-matrix `®` to fix the 0s
εε # Nested map over each 3x3 block:
˜ # Flatten the 3x3 block to a list of 9 values
ŽqÆ # Push compressed integer 13457
S # Convert it to a list of digits: [1,3,4,5,7]
è # Get the values at those indices
à # Pop and push the maximum
] # Close the nested map; changes-loop; and outer map at once
ε # Open a new map again:
˜ # Flatten the now flood-filled matrix
Ù # Uniquify this list
0K # Remove all 0s
g # Pop and push the length (the amount of connected groups)
}P # After the map: take the product of this list
Θ # Distinct the falsey results with an ==1 check (1 if 1; 0 otherwise)
# (after which the result is output implicitly)
See this 05AB1E tip of mine (section How to compress large integers?) to understand why ŽqÆ is 13457.
oK, 51 bytes
{&/3>{#?,/(4(+|{(y%y)*x|y}\')/)/x*+\'+\x}'x=/:?,/x}
{ } /function of x:
x=/:?,/x / binary matrices per letter
{ }' / for each matrix x:
+\'+\x / choose non-decreasing
x* / numbers where non-zero
( )/ / repeat until fixed-point:
4(+| )/ / for each direction:
{ }\' / scan along direction
x|y / with max function
(y%y)* / zero or nan -> nan
#?,/ / count unique entries
&/3> / all(less than 3)
Befunge-93, 317 bytes
Edit: Fixed for proper byte-count. Also could be golfed further
93+:10pv +93p01+1g01_ v@.1<
gp00g1+>00p~1+:93+`!#^_1-00g10
50p93+:vv_v#!:gg03:p02:<>40p#
!`g01: <>\ 1+:vvp05:+<@^p03_^#
v93$_v# !- g00<4v04g<^1<vp06:<
>+\!\>\ 3v> 40v0>g-v^<.g>:70vp
07_v#:<^ >#+0# g#\< 10\v4gg<^
!#v _$^ g03p <\ v1_#:^5>0g -
< ^ g02p1< >-:#^_^#:g05
-1< ^p\g06\0\+1:\g06\-1:\g06:\+1g06:g07
Prints 1 as the truthy, 0 as the falsey
Here's a visualisation of the path the pointer takes
Note: this is for an old version
How it works
Here's some quick and dirty pseudocode
a = 2Darray() # from 12,12 down and to the right
arrayLocation = 12
x = arrayLocation #stored at 0,0
y = arrayLocation #stored at 1,0
i = input() #stored in the stack
while (i != 0):
if (i == 10):
y++
x = init
else
a[x][y] = i
x++
i = input
new.x = init #stored at 2,0
new.y = init #stored at 3,0
currentChar = 0 #stored at 4,0
chars = array() #stored at 1,1 onwards
charnum = 0 #stored 5,0
ToCheck = array() #stored in the stack
current.x = null #stored at 6,0
current.y = null #stored at 7,0
while (new.y < y):
if (a[new] != 0)
currentChar = a[new]
toCheck[] = new
while (toCheck)
current = toCheck.pop()
if (a[current] == currentChar)
toCheck.append(adjacent(current))
a[current] = 0
foreach (chars as char)
if (char == currentChar)
return 0
charNum++
chars[charNum] = char
new.x++
if (new.x > x)
new.x = init
new.y++
return 1
Basically, after storing the input, it goes through the whole thing, checking each space. When it finds a space with a character in it it adds the coordinates to the stack. Then it checks the spaces around it for the same character recursively, setting each space to 0. When it has exhausted that character's section, it checks whether that character has already had a section. If so, return 0. If not, add it to the array of characters. Once it has gone through the whole grid with no duplicates, it returns 1.
For people familiar with Befunge, here's a spaced out version of the code
96+:10p v +69p01+1g01_v
`+96:+1~p00<+1g00pg01g00-1_^#
v <
>40p50p96+:v ^
v @.1< >
>:10g `#^_30p:20p:30gg:#v_$>1+:00g-!#v_0 >30g+
v < ^ >$96+1^
>40p30gv ^
>:!#v_70p:60p:70gg40 g-!#v_$>
v ^ > ^
1:\g06\+1:g 07\g07\-1:\g07\ +1: <^p\g06\0\-
v < ^
>50gv >5\g1+:50p40g\1p20g^
>:!#^_:1g40g-!#v_1-
>0.@
MATL, 16 15 bytes
1e"G@=4&1ZI1>vzg
Input is a 2D char array (with rows separated by ;). Output is 0 if input qualifies, or 1 otherwise.
Try it online! Or verify all test cases.
Explanation
The code essentialy checks if each char in the input has only one connected component, considering 4-connectivity (that is, no diagonals).
Repeated chars are processed repeatedly (which is golfier than deduplicating).
1e % Implicit input. Reshape into a row vector of chars
" % For each char
G % Push input again
@ % Push current char
= % Equal (element-wise)? Gives a matrix of zeros and ones, where one
% represents the presence of the current char
4 % Push 4. This will indicate 4-connectivity
&1ZI % Matrix with labels of connected componnents. Inputs are a number (4)
% to indicate connectivity, and a binary matrix. The output is a matrix
% the same size as the input where each connected componnent of ones
% in the input is replaced by a different integer starting at 1
1> % Greater than 1 (element-wise)? The result is a matrix. If the result
% is true for some entry the input doesn't qualify
v % Concatenate vertically with results from previous iterations
z % Number of nonzero/true values
g % Logical. Converts nonzero to true
% Implicit end. Implicit display. False / true are displayed as 0 / 1
JavaScript (ES6), 181 bytes
(d,o={})=>{f=(i,j,c,l=d[i])=>{if(c&&l&&l[j]==c){l[j]='';f(i-1,j,c);f(i+1,j,c);f(i,j-1,c);f(i,j+1,c);o[c]=1}};d.map((e,i)=>e.map((c,j)=>o[c]||f(i,j,c)));return!d.some(e=>e.join(''))}
Whenever a new color tile is found, fill the connected ones with empty strings. If the mat is properly grouped by colors, all tiles should be filled with empty strings.
Test Code
const t =
(d,o={})=>{f=(i,j,c,l=d[i])=>{if(c&&l&&l[j]==c){l[j]='';f(i-1,j,c);f(i+1,j,c);f(i,j-1,c);f(i,j+1,c);o[c]=1}};d.map((e,i)=>e.map((c,j)=>o[c]||f(i,j,c)));return!d.some(e=>e.join(''))}
;
const mat = s=>s.split('\n').filter(l=>l).map(l=>l.split(''));
console.log('true?', t(mat(`
A
`)));
console.log('true?', t(mat(`
AB
AB
`)));
console.log('false?', t(mat(`
AB
BA
`)));
console.log('true?', t(mat(`
ABCDE
`)));
console.log('false?', t(mat(`
ABCDC
`)));
console.log('true?', t(mat(`
**::dd22
***:d222
*:::::22
`)));
console.log('false?', t(mat(`
$$$%%%&&
$$%%&&&&
&&$$$%&&
`)));
console.log('true?', t(mat(`
AABBCDDDE
ABBCCCDEE
ABCCCCDDE
AACCCDDEE
AAAACCCCE
AAAAAACCC
`)));
console.log('true?', t(mat(`
AABB
ABBA
AAAA
`)));
console.log('true?', t(mat(`
AAAB
AAAA
AAAA
`)));
Python 2, 247 bytes
def f(a):
b=map(list,a.split('\n'));l=len(b[0])
for c in set(a):i=a.find(c);g(b,i/l,i%l,c)
print all(set(l)<={0}for l in b)
def g(a,i,j,c):
if len(a)>i>-1<j<len(a[0])and a[i][j]==c:
for x,y in(0,1),(0,-1),(1,0),(-1,0):g(a,i+x,j+y,c);a[i][j]=0
JavaScript (ES6), 114 bytes
Takes input as an array of strings. Returns 0 or 1.
a=>(C={},F=x=>!C[c=a[y][x]]|(g=v=>(a[y+v]||[])[x]==c)(-1)|g(1)|g(0,x--)|g(0,x+=2)?a[y+=!c]?F(C[c]=c?x:0):1:0)(y=0)
Test cases
let f =
a=>(C={},F=x=>!C[c=a[y][x]]|(g=v=>(a[y+v]||[])[x]==c)(-1)|g(1)|g(0,x--)|g(0,x+=2)?a[y+=!c]?F(C[c]=c?x:0):1:0)(y=0)
console.log(f([ // 1
"A"
]))
console.log(f([ // 1
"AB",
"AB"
]))
console.log(f([ // 0
"AB",
"BA"
]))
console.log(f([ // 1
"ABCDE"
]))
console.log(f([ // 0
"ABCDC"
]))
console.log(f([ // 1
"**::dd22",
"***:d222",
"*:::::22"
]))
console.log(f([ // 0
"$$$%%%&&",
"$$%%&&&&",
"&&$$$%&&"
]))
console.log(f([ // 1
"AABBCDDDE",
"ABBCCCDEE",
"ABCCCCDDE",
"AACCCDDEE",
"AAAACCCCE",
"AAAAAACCC"
]))
console.log(f([ // 1
"AABB",
"ABBA",
"AAAA"
]))
console.log(f([ // 1
"AAAB",
"AAAA",
"AAAA"
]))
Formatted and commented
a => ( // given an array of strings a
C = {}, // C = object holding encountered characters
F = x => // F = recursive function taking x:
!C[c = a[y][x]] // c = current character; is it a new one?
| (g = v => // g = helper function taking v
(a[y + v] || [])[x] == c // and testing whether a[y + v][x] == c
)(-1) // test a[y - 1][x]
| g(1) // test a[y + 1][x]
| g(0, x--) // test a[y][x - 1]
| g(0, x += 2) ? // test a[y][x + 1]; if at least one test passes:
a[y += !c] ? // increment y if c is undefined; if a[y] exists:
F(C[c] = c ? x : 0) // update C, update x and do a recursive call
: // else:
1 // all characters have been processed -> success
: // else:
0 // invalid character detected -> failure
)(y = 0) // initial call to F, starting with x = y = 0
J, 66 bytes
c=.1=+/@,+.]-:]*[:*@+/((,|."1)0,.1 _1)&(|.!.0)
[:*/[:c"2[="_ 0~.@,
c defines a verb that tells you if a matrix of ones and zeros is connected. It treats singleton ones as a special case of true. Otherwise it takes an orthogonal neighbor count of every cell, then the signum of that count, then multiplies that with the original matrix: if that product equals the original matrix, then it's connected.
The neighbor count is achieved by shifting in all 4 directions, then summing. The 4 direction shift is achieved using the "x-arg can by a table" feature of rotate/shift |.
Finally, the answer itself achieved by creating a ones/zeros matrix for every unique ~. element of the input, and then ensuring that all of those matrices are connected. This is the verb in the second line.
Wolfram Language (Mathematica), 96 bytes
And@@(ConnectedGraphQ@Subgraph[GridGraph@Dimensions[t],Tr/@Position[c,#]]&/@(c=Join@@(t=#)))&
Takes input as a 2D list of characters: for example, {{"A","B"},{"C","D"}}.
The character is \[Transpose].
How it works
For each character c in the input, takes the Subgraph of the GridGraph of the same Dimensions as the input which corresponds to every Position in which c occurs, and checks if it's a ConnectedGraphQ.
