Mathematica 186 (ganancioso) e 224 (todas as combinações)
Solução gananciosa
t=MorphologicalTransform;n@w_:=Flatten@w~Count~1
p_~w~q_:=n[p~t~Max]==n[q~t~Max]
g@m_:=Module[{l=m~Position~1,r,d=m},While[l!={},If[w[m,r=ReplacePart[d,#-> 0]&
[l[[1]]]],d=r];l=Rest@l];n@m-n@d]
Isso apaga as luzes supérfluas uma a uma. Se a cobertura da luz não diminui quando a luz se apaga, essa luz pode ser eliminada. A abordagem gananciosa é muito rápida e pode lidar facilmente com matrizes de 15x15 e muito maiores (veja abaixo). Ele retorna soluções únicas, mas não se sabe se isso é ideal ou não. Ambas as abordagens, nas versões golfadas, retornam o número de luzes não utilizadas. As abordagens sem golfe também exibem as grades, como abaixo.
Antes:
Depois de:
Soluções ideais usando todas as combinações de luzes (224 caracteres)
Com agradecimentos a @ Clément.
Versão ungolfed usando todas as combinações de luzes
fA função de transformação morfológica usada em sameCoverageQ
trata como iluminado (valor = 1 em vez de zero) o quadrado 3 x3 no qual cada luz reside.Quando uma luz está próxima à borda da fazenda, apenas os quadrados (menos de 9) dentro das bordas da a fazenda é contada. Não há contagem excessiva; um quadrado aceso por mais de uma lâmpada é simplesmente aceso. O programa apaga cada luz e verifica se a cobertura geral de iluminação da fazenda é reduzida.Se não estiver, essa luz será eliminada.
nOnes[w_]:=Count[Flatten@w,1]
sameCoverageQ[m1_,m2_]:=nOnes[MorphologicalTransform[m1,Max]]==
nOnes[MorphologicalTransform[m2,Max]]
(*draws a grid with light bulbs *)
h[m_]:=Grid[m/.{1-> Style[\[LightBulb],24],0-> ""},Frame-> All,ItemSize->{1,1.5}]
c[m1_]:=GatherBy[Cases[{nOnes[MorphologicalTransform[ReplacePart[Array[0&,Dimensions[m1]],
#/.{{j_Integer,k_}:> {j,k}-> 1}],Max]],#,Length@#}&/@(Rest@Subsets[Position[m1,1]]),
{nOnes[MorphologicalTransform[m1,Max]],_,_}],Last][[1,All,2]]
nOnes[matrix]
conta o número de células sinalizadas. É usado para contar as luzes e também para contar as células acesas
sameCoverageQ[mat1, mat2]
testa se as células acesas em mat1 são iguais ao número de células acesas em mat2.MorphologicalTransform [[mat] pega uma matriz de luzes e retorna uma matriz` das células que acendem.
c[m1]
pega todas as combinações de luzes de m1 e as testa quanto à cobertura. Entre os que têm cobertura máxima, seleciona aqueles que têm menos lâmpadas. Cada um deles é uma solução ideal.
Exemplo 1:
Uma configuração 6x6
(*all the lights *)
m=Array[RandomInteger[4]&,{6,6}]/.{2-> 0,3->0,4->0}
h[m]
Todas as soluções ideais.
(*subsets of lights that provide full coverage *)
h/@(ReplacePart[Array[0&,Dimensions[m]],#/.{{j_Integer,k_}:> {j,k}-> 1}]&/@(c[m]))
Versão Golfed usando todas as combinações de luzes.
Esta versão calcula o número de luzes não utilizadas. Não exibe as grades.
c
retorna o número de luzes não utilizadas.
n@w_:=Flatten@w~Count~1;t=MorphologicalTransform;
c@r_:=n@m-GatherBy[Cases[{n@t[ReplacePart[Array[0 &,Dimensions[r]],#
/.{{j_Integer,k_}:> {j,k}-> 1}],Max],#,Length@#}&/@(Rest@Subsets[r~Position~1]),
{n[r~t~Max],_,_}],Last][[1,1,3]]
n[matrix]
conta o número de células sinalizadas. É usado para contar as luzes e também para contar as células acesas
s[mat1, mat2]
testa se as células acesas em mat1 são iguais ao número de células acesas em mat2.t [[mat] pega uma matriz de luzes e retorna uma matriz` das células que acendem.
c[j]
pega todas as combinações de luzes de j e testa sua cobertura. Entre os que têm cobertura máxima, seleciona aqueles que têm menos lâmpadas. Cada um deles é uma solução ideal.
Exemplo 2
m=Array[RandomInteger[4]&,{6,6}]/.{2-> 0,3->0,4->0};
m//Grid
Duas luzes podem ser salvas com a mesma cobertura de iluminação. cm]
2