農民を助ける


10

農夫のジャックはとても貧しい。彼は農場全体を明るくしたいのですが、最小限のコストで。ランプは、自身のセルとその8つの隣接セルを照らすことができます。彼は自分のフィールドにランプを配置しましたが、余分なランプを保持しているかどうかを確認するには、あなたの助けが必要です。

余分なランプ:農場からの取り外し時に点灯するセルの数に影響を与えないランプ。また、ポイントするランプは1つずつ取り外されるのではなく、同時に取り外されます。

注:実行できる唯一のアクションは、一部のランプを取り外すことです。ランプの再配置や挿入はできません。最後の目標は、以前に点灯していたすべてのセルがまだ点灯するように、ランプの最大数を削除することです。

ファーマージャックが役に立たないランプの最大数を見つけ、他の場所で使用できるようにします。

入力

あなたは、フィールドの最初のライン寸法で与えられるMおよびN .Next Mの線が含有従うN個のフィールドを表す文字ずつ。

「1」は、ランプが保持されているセルを表します。

「0」は空のセルを表します。

出力

無駄なランプの数を含む整数を出力する必要があります。

入力例:

3 3
100
010
001

出力例:

2

勝者:

コードゴルフですので、最少キャラクター数で勝負するのが勝者です


@PeterTaylor投稿を編集しました。まだ混乱していますか?
— user2369284 2014年

ずっといい。ありがとう。
— Peter Taylor

入力が改行で終わると想定できますか?
— John Dvorak

1
これは宿題のようです。
— ヨハネス

1
入力ランプが農場全体を照らすことが保証されていますか?間違いないと思います...
— キースランダル14年

回答:


5

Mathematica 186(貪欲)および224(すべての組み合わせ)

貪欲なソリューション

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]

これにより、不要なライトが1つずつオフになります。ライトが消えたときにライトのカバレッジが減少しない場合は、そのライトを除去できます。貪欲なアプローチは非常に高速で、15x15以上の行列を簡単に処理できます(以下を参照)。単一の解を返しますが、それが最適かどうかは不明です。ゴルフバージョンの両方のアプローチは、未使用のライトの数を返します。ゴルフではないアプローチでは、以下のようにグリッドも表示されます。

前:

前

後:

後

ライトのすべての組み合わせを使用した最適なソリューション(224文字)

@Clémentに感謝します。

ライトのすべての組み合わせを使用した非ゴルフバージョン

fで使用されるモルフォロジー変換関数は、sameCoverageQ各ライトが存在する3 x 3の正方形を照明付き(値= 0ではなく1)として扱います。ライトが農場の端の近くにある場合、の境界内の正方形(9未満)のみ農場は数えられます。過大評価はありません。複数のランプで照らされた四角形は単純に点灯します。プログラムは各ライトをオフにして、ファームの全体的な照明範囲が減っているかどうかを確認します。減っていない場合は、そのライトを消します。

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]フラグが立てられたセルの数をカウントします。ライトの数を数えたり、点灯しているセルの数を数えたりするために使用されます

sameCoverageQ[mat1, mat2] mat1で点灯しているセルがmat2で点灯しているセルの数と等しいかどうかをテストします。MorphologicalTransform[[mat]はライトの行列を取り、点灯しているセルの行列 `を返します。

c[m1]m1からライトのすべての組み合わせを取得し、カバレッジをテストします。カバレッジが最大のものの中から、電球の数が最も少ないものを選択します。これらはそれぞれ最適なソリューションです。


例1:

6x6セットアップ

(*all the lights *)
m=Array[RandomInteger[4]&,{6,6}]/.{2-> 0,3->0,4->0}
h[m]

元の

すべての最適なソリューション。

(*subsets of lights that provide full coverage *)
h/@(ReplacePart[Array[0&,Dimensions[m]],#/.{{j_Integer,k_}:> {j,k}-> 1}]&/@(c[m]))

答え


ライトのすべての組み合わせを使用したゴルフバージョン。

このバージョンは、未使用のライトの数を計算します。グリッドは表示されません。

c 未使用のライトの数を返します。

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]フラグが立てられたセルの数をカウントします。ライトの数を数えたり、点灯しているセルの数を数えたりするために使用されます

s[mat1, mat2] mat1の点灯しているセルがmat2の点灯しているセルの数と等しいかどうかをテストします。t[[mat]はライトの行列を取り、それらが点灯するセルの行列を返します。

c[j]jからライトのすべての組み合わせを取得し、カバレッジをテストします。カバレッジが最大のものの中から、電球の数が最も少ないものを選択します。これらはそれぞれ最適なソリューションです。

例2

m=Array[RandomInteger[4]&,{6,6}]/.{2-> 0,3->0,4->0};
m//Grid

グリッド

同じ照明範囲で2つの照明を保存できます。CM]

2


Mathematicaが手元にないのでこのコードをテストすることはできませんが、説明を誤解しない限り、アルゴリズムは正しくないと思います。私の理解が正しい場合、それは光が処理される順序に依存する貪欲な戦略に依存しています。たとえば、3 * 3テストケースの真ん中のランプから開始すると、それが削除され、2つのサイドランプが残ります。実装で使用する特定の順序が正しいとは思いませんが、現時点では反例はありません。
— クレメント14年

あなたの考えは、元の設定で2つの余分なライトa、bを使用できる可能性があるということです。したがって、1つを削除すると(最初に)、より良い経済が達成される可能性があります。これは合計3つのライトでは発生しなかったと思いますが、実際にはもっと多くのライトで可能かもしれません。私はもともと、ライトのすべての組み合わせをテストすることで問題を解決しました。これは確かに最適であり、理想的ですが、大量のライトのセットでは実用的ではないことがわかりました。
— DavidC 2014年

@Clément私は可能なすべての組み合わせをテストするソリューションに取り組んでいます。しばらく時間がかかります...
— DavidC

確かに;)しかし、それは予想されることです。現状では、この問題は最小セットカバー(NP)のインスタンスです。追加の仮定(横方向のものを除くほとんどすべてのカバーするセットが同じカーディナリティを持っている)が効率的な実装を可能にするかどうかは興味深い問題ですが。
— クレメント14年

行と列で順番に行けば貪欲な解決策が正しいと私は強く思いますが、まだ証明していません。
— SEが邪悪なためaditsuが辞任2014

3

Python、309文字

import sys
I=sys.stdin.readlines()[1:]
X=len(I[0])
L=[]
m=p=1
for c in''.join(I):m|=('\n'!=c)*p;L+=('1'==c)*[p<<X+1|p<<X|p<<X-1|p*2|p|p/2|p>>X-1|p>>X|p>>X+1];p*=2
O=lambda a:m&reduce(lambda x,y:x|y,a,0)
print len(L)-min(bin(i).count('1')for i in range(1<<len(L))if O(L)==O(x for j,x in enumerate(L)if i>>j&1))

ビットマスクを使用して動作します。 Lは、ライトのリストです。各ライトは、そのライトパターンに(最大)9ビットが設定された整数で表されます。次に、リスト全体のビット単位ORとビット単位ORが同じであるこのリストのサブセットを徹底的に検索します。最短のサブセットが勝者です。

m シフト時にビットのラップアラウンドを防ぐマスクです。


正しく動作するプログラムを提供してみてください。Java/ C ++はあらゆる種類のインデントやスペースに対して安全ですが、Pythonは安全ではありません。コードを難読化または短縮することは別のことですが、実行しないプログラムを提供することは別です。
— user2369284 2014年

3
@ user2369284何言ってるの!?これは、(のpython 2で)完全に正常に動作します
— aditsuは、SEは悪であるため、終了

@aditsu私はPython 3を持っています
— user2369284

1
@ user2369284まあ、印刷構文が異なるのでpython 3で失敗します
— SEがEVILであるのでaditsuが終了しました

3

Java 6-509バイト

私は制限についていくつかの仮定を行い、現時点で述べられているように問題を解決しました。

import java.util.*;enum F{X;{Scanner s=new Scanner(System.in);int m=s.nextInt(),n=s.nextInt(),i=m,j,k=0,l=0,r=0,o,c,x[]=new int[30],y[]=x.clone();int[][]a=new
int[99][99],b;while(i-->0){String t=s.next();for(j=n;j-->0;)if(t.charAt(j)>48){x[l]=i;y[l++]=j;}}for(;k<l;++k)for(i=9;i-->0;)a[x[k]+i/3][y[k]+i%3]=1;for(k=1<<l;k-->0;){b=new
int[99][99];for(j=c=l;j-->0;)if((k&1<<j)>0)for(c--,i=9;i-->0;)b[x[j]+i/3][y[j]+i%3]=1;for(o=i=0;i++<m;)for(j=0;j++<n;)o|=a[i][j]^b[i][j];r=c-o*c>r?c:r;}System.out.println(r);}}

次のように実行します。 java F <inputfile 2>/dev/null


正確には短くありませんが、ディスクセクターに適合します:p後で別の言語を試す可能性があります。
— aditsuはSEがEVILである2014

@aditsuこれをWindowsで機能させる方法は?
— user2369284 2014年

1
@ user2369284:2つのランプだけで0011111100を実行する方法がわかりません。あなたは光で8つのセルをカバーする必要があり、各ランプはほとんど3で行うことができます
— キース・ランドール

@ user2369284おそらくjava F <inputfile 2>nul、それが失敗した場合java F <inputfileは例外を無視してください。また、それは、Java 7で動作しません
— SEは悪であるため、aditsuはやめ

@aditsuすみません、それはタイプミスでした。プログラムは正しく動作します。
— user2369284 2014年

1

c ++-477バイト

#include <iostream>
using namespace std;int main(){
int c,i,j,m,n,p,q=0;cin>>m>>n;
int f[m*n],g[m*n],h[9]={0,-1,1,-m-1,-m,-m+1,m-1,m,m+1};
for(i=0;i<m*n;i++){f[i]=0;g[i]=0;do{c=getchar();f[i]=c-48;}while(c!='0'&&c!='1');}
for(i=0;i<m*n;i++)if(f[i])for(j=0;j<9;j++)if(i+h[j]>=0&&i+h[j]<m*n)g[i+h[j]]++;
for(i=0;i<m*n;i++)if(f[i]){p=0;for(j=0;j<9;j++)if(i+h[j]>=0&&i+h[j]<m*n)if(g[i+h[j]]<2)p++;if(p==0){for(j=0;j<9;j++)if(i+h[j]>=0&&i+h[j]<m*n)g[i+h[j]]--;q++;}}cout<<q<<endl;}

1

ルビー、303

[これは、前のバージョンの質問に答えるためにコード化されました。以下の注意をお読みください]

def b(f,m,n,r)b=[!1]*1e6;(n..n+m*n+m).each{|i|b[i-n-2,3]=b[i-1,3]=b[i+n,3]=[1]*3if f[i]};b[r*n+r+n+1,n];end
m,n=gets.split.map(&:to_i)
f=[!1]*n
m.times{(?0+gets).chars{|c|f<<(c==?1)if c>?*}}
f+=[!u=0]*n*n
f.size.times{|i|g=f.dup;g[i]?(g[i]=!1;u+=1if m.times{|r|break !1if b(f,m,n,r)!=b(g,m,n,r)}):0}
p u

ブール値の配列に変換してから、近隣の変更を比較します。

制限事項(?):ファームフィールドの最大サイズは1,000 x 1,000です。問題は「ファーマージャックは非常に貧しい」と述べているので、彼の農場はそれほど大きくないと想定しています。;-) 2文字を追加することで制限を取り除くことができます。

注:これをコーディングし始めてから、質問の要件が変更されたようです。次の説明が追加されました。「ポイントするランプは1つずつ取り外されるのではなく、同時に取り外される」と追加されました。元の質問のあいまいさにより、個々のランプの取り外しをテストすることにより、コードを保存することができました。したがって、私のソリューションは、新しい要件の下では多くのテストケースで機能しません。時間があれば修正します。私はそうしないかもしれません。ここの他の回答は完全に準拠している可能性があるため、この回答には賛成しないでください。


1

APL、97文字/バイト*

⎕IO←1および⎕ML←3APL環境を想定しています。

m←{s↑⊃∨/,v∘.⊖(v←⍳3)⌽¨⊂0⍪0⍪0,0,s⍴⍵}⋄n-⌊/+/¨t/⍨(⊂m f)≡¨m¨(⊂,f)\¨t←⊂[1](n⍴2)⊤⍳2*n←+/,f←⍎¨⊃{⍞}¨⍳↑s←⍎⍞

ゴルフされていないバージョン:

s ← ⍎⍞                                         ⍝ read shape of field
f ← ⍎¨ ⊃ {⍞}¨ ⍳↑s                              ⍝ read original field (lamp layout)
n ← +/,f                                       ⍝ original number of lamps
c ← ⊂[1] (n⍴2) ⊤ ⍳2*n                          ⍝ all possible shutdown combinations
m ← {s↑ ⊃ ∨/ ,v ∘.⊖ (v←⍳3) ⌽¨ ⊂ 0⍪0⍪0,0, s⍴⍵}  ⍝ get lighted cells given a ravelled field
l ← m¨ (⊂,f) \¨ c                              ⍝ map of lighted cells for every combination
k ← c /⍨ (⊂ m f) ≡¨ l                          ⍝ list of successful combinations
u ← ⌊/ +/¨ k                                   ⍝ min lamps used by a successful comb.
⎕ ← n-u                                        ⍝ output number of useless lamps

⎕ ← s⍴ ⊃ (⊂,f) \¨ (u= +/¨ k) / k               ⍝ additional: print the layout with min lamps

より多くのテストケースがより良いことに同意します。ここにランダムなものがあります:

入力:

5 5
10001
01100
00001
11001
00010

出力(役に立たないランプ):

5

最小ランプのレイアウト(ゴルフバージョンには含まれません):

0 0 0 0 1
0 1 0 0 0
0 0 0 0 0
0 1 0 0 1
0 0 0 0 0

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
*:APLは、APLシンボルを上位128バイトの値にマップする独自の(レガシー)シングルバイト文字セットで記述できます。したがって、スコアリングの目的で、ASCII文字とAPL記号のみを使用する N文字のプログラムは、Nバイトの長さと見なすことができます。


0

C ++ 5.806バイト

これはまだサイズに最適化されていません。でも、出場者が少ないので、とりあえずそのままにしておきます。

FarmersFieldヘッダー:

#pragma once

namespace FarmersLand
{

class FarmersField
{
private:
    unsigned _m_size, _n_size;
    int * _lamp, * _lumination;
    char * _buffer;
    void _illuminate(unsigned m, unsigned n);
    void _deluminate(unsigned m, unsigned n);
    void _removeLamp(unsigned m, unsigned n);
    void _setLamp(unsigned m, unsigned n);
    int _canRemoveLamp(unsigned m, unsigned n);
    int _coordsAreValid(unsigned m, unsigned n);
    int _getLuminationLevel(unsigned m, unsigned n);
    int * _allocIntArray(unsigned m, unsigned n);
    int _coordHelper(unsigned m, unsigned n);
public:
    FarmersField(char * input[]);
    FarmersField(const FarmersField & field);
    ~FarmersField(void);
    int RemoveLamps(void);
    char * Cstr(void);
};

}

FarmersField CPP:

#include "FarmersField.h"
#include <stdio.h>


namespace FarmersLand
{

void FarmersField::_illuminate(unsigned m, unsigned n)
{
    if(this -> _coordsAreValid(m,n))
    {
        ++this -> _lumination[this -> _coordHelper(m,n)];
    }
}

void FarmersField::_deluminate(unsigned m, unsigned n)
{
    if(this -> _coordsAreValid(m,n))
    {
        --this -> _lumination[this -> _coordHelper(m,n)];
    }
}

void FarmersField::_removeLamp(unsigned m, unsigned n)
{
    if(this -> _coordsAreValid(m,n))
    {
        unsigned mi_start = (m == 0) ? 0 : m - 1;
        unsigned mi_end = m + 1;
        unsigned ni_start = (n == 0) ? 0 : n - 1;
        unsigned ni_end = n + 1;

        for(unsigned mi = mi_start; mi <= mi_end; ++mi)
        {
            for(unsigned ni = ni_start; ni <= ni_end; ++ni)
            {
                this -> _deluminate(mi, ni);
            }
        }
        --this -> _lamp[this -> _coordHelper(m,n)];
    }
}

void FarmersField::_setLamp(unsigned m, unsigned n)
{
    if(this -> _coordsAreValid(m,n))
    {
        unsigned mi_start = (m == 0) ? 0 : m - 1;
        unsigned mi_end = m + 1;
        unsigned ni_start = (n == 0) ? 0 : n - 1;
        unsigned ni_end = n + 1;

        for(unsigned mi = mi_start; mi <= mi_end; ++mi)
        {
            for(unsigned ni = ni_start; ni <= ni_end; ++ni)
            {
                this -> _illuminate(mi, ni);
            }
        }
        ++this -> _lamp[this -> _coordHelper(m,n)];
    }
}

int FarmersField::_canRemoveLamp(unsigned m, unsigned n)
{
    unsigned can = 1;
    unsigned mi_start = (m == 0) ? 0 : m - 1;
    unsigned mi_end =   (m == (this->_m_size - 1)) ? m : m + 1;
    unsigned ni_start = (n == 0) ? 0 : n - 1;
    unsigned ni_end =   (n == (this->_n_size - 1)) ? n : n + 1;

    for(unsigned mi = mi_start; mi <= mi_end; ++mi)
    {
        for(unsigned ni = ni_start; ni <= ni_end; ++ni)
        {
            if( 1 >= this -> _getLuminationLevel(mi, ni) )
            {
                can = 0;
            }
        }
    }
    return can;
}

int FarmersField::_coordsAreValid(unsigned m, unsigned n)
{
    return m < this -> _m_size && n < this -> _n_size;
}

int FarmersField::_getLuminationLevel(unsigned m, unsigned n)
{
    if(this -> _coordsAreValid(m,n))
    {
        return this -> _lumination[this -> _coordHelper(m,n)];
    }
    else
    {
        return 0;
    }
}

int * FarmersField::_allocIntArray(unsigned m, unsigned n)
{
    int * a = new int[m * n];
    for(unsigned i = 0; i < m*n; ++i)
    {
        a[i] = 0;
    }
    return a;
}

int FarmersField::_coordHelper(unsigned m, unsigned n)
{
    return m * this -> _n_size + n;
}

int FarmersField::RemoveLamps(void)
{
    int r = 0;
    for(unsigned m = 0 ; m < this -> _m_size; ++m)
    {
        for(unsigned n = 0 ; n < this -> _n_size; ++n)
        {
            if(this -> _canRemoveLamp(m,n))
            {
                ++r;
                this -> _removeLamp(m,n);
            }
        }
    }
    return r;
}

char * FarmersField::Cstr(void)
{
    unsigned size = this -> _m_size * this -> _n_size + _m_size ;
    unsigned target = 0;
    delete(this -> _buffer);
    this -> _buffer = new char[ size ];
    for(unsigned m = 0 ; m < this -> _m_size; ++m)
    {
        for(unsigned n = 0 ; n < this -> _n_size; ++n)
        {
            this -> _buffer[target++] =  (0 == this -> _lamp[this -> _coordHelper(m,n)])? '0' : '1';
        }
        this -> _buffer[target++] = '-'; 
    }
    this -> _buffer[size - 1 ] = 0;
    return this -> _buffer;
}

FarmersField::FarmersField(char * input[])
{
    sscanf_s(input[0], "%u %u", &this -> _m_size, &this -> _n_size);

    this -> _lamp = this -> _allocIntArray(this -> _m_size, this -> _n_size);
    this -> _lumination = this -> _allocIntArray(this -> _m_size, this -> _n_size);
    this -> _buffer = new char[1];

    for(unsigned m = 0 ; m < this -> _m_size; ++m)
    {
        for(unsigned n = 0 ; n < this -> _n_size; ++n)
        {
            if('0' != input[m+1][n])
            {
                this -> _setLamp(m,n);
            }
        }
    }
}

FarmersField::FarmersField(const FarmersField & field)
{
    this -> _m_size = field._m_size;
    this -> _n_size = field._n_size;

    this -> _lamp = this -> _allocIntArray(this -> _m_size, this -> _n_size);
    this -> _lumination = this -> _allocIntArray(this -> _m_size, this -> _n_size);
    this -> _buffer = new char[1];

    for(unsigned m = 0 ; m < this -> _m_size; ++m)
    {
        for(unsigned n = 0 ; n < this -> _n_size; ++n)
        {
            if(0 != field._lamp[this -> _coordHelper(m,n)])
            {
                this -> _setLamp(m,n);
            }
        }
    }

}

FarmersField::~FarmersField(void)
{
    delete(this -> _lamp);
    delete(this -> _lumination);
    delete(this -> _buffer);
}

}

そして、コードが実行するために構築されたものをコードが実行することを示す一連のテスト:

#include "../../Utility/GTest/gtest.h"

#include "FarmersField.h"

TEST(FarmersField, Example1) 
{
    using namespace FarmersLand;
    char * input[] = {"3 3", "100", "010", "001"};
    FarmersField f(input);
    EXPECT_STREQ("100-010-001", f.Cstr());
    EXPECT_EQ(2, f.RemoveLamps());
    EXPECT_STREQ("000-010-000", f.Cstr());
}

TEST(FarmersField, Example2) 
{
    using namespace FarmersLand;
    char * input[] = {"3 6", "100000", "010000", "001000"};
    FarmersField f(input);
    EXPECT_STREQ("100000-010000-001000", f.Cstr());
    EXPECT_EQ(1, f.RemoveLamps());
    EXPECT_STREQ("000000-010000-001000", f.Cstr());
 }

TEST(FarmersField, Example3) 
{
    using namespace FarmersLand;
    char * input[] = {"6 3", "100", "010", "001", "000", "000", "000",};
    FarmersField f(input);
    EXPECT_STREQ("100-010-001-000-000-000", f.Cstr());
    EXPECT_EQ(1, f.RemoveLamps());
    EXPECT_STREQ("000-010-001-000-000-000", f.Cstr());
 }

TEST(FarmersField, Example4) 
{
    using namespace FarmersLand;
    char * input[] = {"3 3", "000", "000", "000",};
    FarmersField f(input);
    EXPECT_STREQ("000-000-000", f.Cstr());
    EXPECT_EQ(0, f.RemoveLamps());
    EXPECT_STREQ("000-000-000", f.Cstr());
 }

TEST(FarmersField, Example5) 
{
    using namespace FarmersLand;
    char * input[] = {"3 3", "111", "111", "111",};
    FarmersField f(input);
    EXPECT_STREQ("111-111-111", f.Cstr());
    EXPECT_EQ(8, f.RemoveLamps());
    EXPECT_STREQ("000-010-000", f.Cstr());
 }

TEST(FarmersField, Example6) 
{
    using namespace FarmersLand;
    char * input[] = {"6 6", "100001", "001010", "001001", "001010", "110000", "100001",};
    FarmersField f(input);
    EXPECT_STREQ("100001-001010-001001-001010-110000-100001", f.Cstr());
    EXPECT_EQ(6, f.RemoveLamps());
    EXPECT_STREQ("100011-001010-000000-000010-010000-000001", f.Cstr());
 }

外部ライブラリを使用するテストユーティリティを提供してください。
— user2369284 2014年


0

Perl 3420バイト

ゴルフの解決策ではありませんが、この問題は興味深いものでした。

#!/usr/bin/perl
use strict;
use warnings; 

{
   package Farm; 
   use Data::Dumper; 

   # models 8 nearest neighbors to position i,j forall i,j
   my $neighbors = [ [-1, -1],
                     [-1,  0],
                     [-1, +1], 
                     [ 0, -1], 
                     # current pos 
                     [ 0,  1], 
                     [+1, -1], 
                     [+1,  0], 
                     [+1, +1] ];

   sub new { 
      my ($class, %attrs) = @_; 
      bless \%attrs, $class;
   }  

   sub field { 
      my $self = shift;
      return $self->{field};
   }

   sub rows {
      my $self = shift;
      return $self->{rows};
   }

   sub cols {
      my $self = shift;
      return $self->{cols};
   }
   sub adjacents {
      my ($self, $i, $j) = @_;

      my @adjs; 
   NEIGHBORS:
      for my $neighbor ( @$neighbors ) {
         my ($imod, $jmod) = ($neighbor->[0] + $i, $neighbor->[1] + $j); 
         next NEIGHBORS 
            if $imod >= $self->rows || $jmod >= $self->cols;

         # push neighbors
         push @adjs, 
            $self->field->[$imod]->[$jmod];

      }

      return @adjs;
   }

   sub islit { 
      my ($lamp) = @_;

      return defined $lamp && $lamp == 1;
   }

   sub can_remove_lamp { 
      my ($self, $i, $j) = @_; 

      return scalar grep { islit($_) } $self->adjacents($i, $j);
   }

   sub remove_lamp { 
      my ($self, $i, $j) = @_;

      $self->field->[$i]->[$j] = 0;
   }

   sub remove_lamps {
      my ($self) = @_; 

      my $removed = 0;
      for my $i ( 0 .. @{ $self->field } - 1) {
         for my $j ( 0 .. @{ $self->field->[$i] } - 1 ) { 
            next unless islit( $self->field->[$i]->[$j] ); 

            if( $self->can_remove_lamp($i, $j) ) {
               $removed++; 
               $self->remove_lamp($i, $j);
            }
         }
      }

      return $removed;
   }

   1;
}

{ # Tests
   use Data::Dumper;
   use Test::Deep;
   use Test::More; 

   { # 3x3 field
      my $farm = Farm->new( rows  => 3,
                            cols  => 3,
                            field => [ [1,0,0],
                                       [0,1,0],
                                       [0,0,1]
                                     ]
      );

      is( 2, 
          $farm->remove_lamps,
          'Removed 2 overlapping correctly'
      );

      is_deeply( $farm->field, 
                 [ [0,0,0],
                   [0,0,0],
                   [0,0,1],
                 ],
                 'Field after removing lamps matches expected'
      );

   }

   { # 5x5 field
      my $farm = Farm->new( rows  => 5,
                            cols  => 5,
                            field => [ [0,0,0,0,0],
                                       [0,1,0,0,0],
                                       [0,0,1,0,0],
                                       [0,0,0,0,0],
                                       [0,0,0,0,0]
                                     ]
      );

      is( 1, 
          $farm->remove_lamps,
          'Removed 1 overlapping lamp correctly'
      );

      is_deeply( $farm->field,
                 [ [0,0,0,0,0],
                   [0,0,0,0,0],
                   [0,0,1,0,0],
                   [0,0,0,0,0],
                   [0,0,0,0,0],
                 ],
                 'Field after removing lamps matches expected'
      );
   }
}

(I / Oが取り出されたため、具体的なテストを表示できました)


0

Python-305バイト

import sys,itertools
w,h=map(int,input().split());w+=1
l=[i for i,c in enumerate(sys.stdin.read())if c=="1"]
f=lambda l:{i+j for i in l for j in(0,1,-1,w-1,w,w+1,1-w,-w,-w-1)if(i+j+1)%w}&set(range(w*h))
for n in range(1,len(l)):
 for c in itertools.combinations(l,n):
  if f(c)^f(l):print(len(l)-n);exit()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.