Solve Hitori Puzzles
Haskell, 374 bytes
import Data.Array;import Data.List;r=range;p=partition
c(e,f)=p(\(b,p)->any(==1)[(b-d)^2+(p-q)^2|(d,q)<-e])f
n#g=[s|(o,(e:f))<-[p((==0).(g!))$indices g],
null.fst$c(o,o),null.snd$until(null.fst)c([e],f),
s<-case[((l,c),d)|((l,c),h)<-assocs g,h>0,
d<-[filter((==h).(g!))$r((l,c+1),(l,n))++r((l+1,c),(n,c))],d/=[]]
of[]->[g];((c,d):_)->n#(g//[(c,0)])++n#(g//[(c,0)|c<-d])]
Try it online!
Jelly, 62 bytes
Uses user202729's isConnected monadic link from another question.
FJṁa@µ«Ḋoµ€ZUµ4¡ÐLFQL<3
ḟ0ĠḊ€
¬T€œ&2\;Ç€FȦ
ZÇȯÇ_1Ŀ
2ḶṗLṗLa⁸ÇÞḢ
A full program printing a representation of a list of lists.
Works by brute force and is stupidly inefficient.
Try it online! - a 3 by 3, since it is too inefficient to run even a size 4 within the 60 second TIO limit!
How?
FJṁa@µ«Ḋoµ€ZUµ4¡ÐLFQL<3 - Link 1 isConnected? List of lists
... - 1 if connected 0 if not -- see linked answer in the header
ḟ0ĠḊ€ - Link 2, helperFor-AnyRepeatedValues: list
ḟ0 - filter out zeros
Ġ - group indices by value (i.e. [[indices of min],...,[indices of max]]
Ḋ€ - dequeue €ach -- leaving a list of empty lists iff no repeated values
- any remaining values are non-zero (1-based indexing in Jelly)
¬T€œ&2\;Ç€FȦ - Link 3, columnwiseAnyAdjacentZerosOrRowwiseAnyRepeatedValues: list of lists
¬ - logical not (convert all zeros to ones and all others to zeros)
T€ - for €ach row get a list of truthy indexes (i.e. indexes of original zeros)
2\ - pairwise reduction (i.e. for neighbouring rows) with:
œ& - intersection (empty if no columnwise adjacent original zeros
- any remaining values are non-zero due to 1-based indexing)
Ç€ - call last link (1) as a monad for €ach row
; - concatenate
F - flatten into a single list (empty iff no columnwise adjacent original zeros
- AND no rowwise repeated values)
Ȧ - any and all (0 if empty [or contains any zero -- never] else 1)
ZÇȯÇ_1Ŀ - Link 4, validity check? list of lists
Z - transpose
Ç - call last link (2) as a monad rowwiseAnyAdjacentZerosOrColumnwiseAnyRepeatedValues?
Ç - call last link (2) as a monad columnwiseAnyAdjacentZerosOrRowwiseAnyRepeatedValues?
ȯ - logical OR
1Ŀ - call link 1 as a monad (isConnected?)
_ - subtract
- this yields -1 for valid, while it yields 0 or 1 if not.
2ḶṗLṗLa⁸ÇÞḢ - Main link: list of lists
2Ḷ - lowered range of 2 -> [0,1]
L - length (number of rows in the input)
ṗ - Cartesian power (all lists of zeros and ones of length L)
L - length (number of rows in the input again)
ṗ - Cartesian power (all grids of zeros and ones of same shape as the input)
⁸ - the input
a - logical AND -- effectively uses each of the formed grids as a mask
Þ - sort by:
Ç - last link (3) as a monad
Ḣ - head
- implicit print
APL (Dyalog Unicode), 133 bytesSBCS
{q←{⊢/4 2⍴⍵}⌺3 3⋄g←⍵=⊂∪,⍵⋄⍵×~1⊃{((⌈/q b)⌈b<{2<≢∪0,,(⍵×⊢⌈⌈/∘q)⍣≡⍵×(⍴⍵)⍴1+⍳≢,⍵}¨~b∘⌈¨⊂⍤2∘.≡⍨⍳⍴b)(+/↑w<g×⌈.⌈⍨w×g)⌈w b←⍵}⍣≡×\(⌈/=∘⌽⍨q⍵)0}
Try it online!
My implementation of rule #4 (cells must form a single connected component) is rather wasteful, but still this passes all tests in about 10 seconds on TIO.
The overall algorithm: Store two boolean matrices b
and w
for cells that are certain to be black and white respectively. Initialise b
as all-zero. Initialise w
as 1 only for those cells that have opposite matching neighbours.
Repeat until b
and w
settle down:
add to
b
cells that are on the same line (horizontal or vertical) and of the same value as a cell inw
add to
w
the immediate neighbours of all cells inb
add to
w
all cutpoints - cells whose removal would split the graph of non-black cells into multiple connected components
Finally, output not(b)
multiplied by the original matrix.