Помогая фермеру

10

Фермер Джек очень беден. Он хочет зажечь всю свою ферму, но с минимальными затратами. Лампа может освещать как свою ячейку, так и восемь соседей. Он установил лампы в своей области, но ему нужна ваша помощь, чтобы выяснить, сохранил ли он какие-либо дополнительные лампы.

Дополнительные лампы: лампы, которые при снятии с фермы не влияют на количество освещенных ячеек. Кроме того, лампы, которые вы укажете, не будут удалены одна за другой, но они будут удалены одновременно.

Примечание. Единственное действие, которое вы можете выполнить, это удалить некоторые лампы. Вы не можете ни переставлять, ни вставлять лампы. Ваша конечная цель состоит в том, чтобы удалить максимальное количество ламп, чтобы каждая ячейка, которая была освещена ранее, все еще горит.

Помогите Фармеру Джеку определить максимальное количество бесполезных ламп, чтобы он мог использовать их в других местах.

вход

В первой строке вам будут даны размеры поля M и N. Далее M строк, содержащих по N символов, каждый из которых представляет поле.

«1» обозначает ячейку, в которой хранится лампа.

«0» представляет пустую ячейку.

Вывод

Вы должны вывести целое число, содержащее количество бесполезных ламп.

Пример ввода:

3 3
100
010
001

Пример вывода:

2

Победитель:

Поскольку это код гольф, победителем станет тот, кто успешно выполнит задание в наименьшем количестве символов.

user2369284
источник
@PeterTaylor Я отредактировал свой пост. У вас все еще есть путаница?
user2369284
Намного лучше. Спасибо.
Питер Тейлор
мы можем предположить, что ввод заканчивается новой строкой?
Джон Дворак
1
Это похоже на домашнюю работу.
Йоханнес
1
Гарантируем ли мы, что входные лампы будут освещать всю ферму? Я собираюсь угадать нет ...
Кит Рэндалл

Ответы:

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]

Это выключает лишние огни один за другим. Если при выключенном свете освещение не уменьшается, этот свет можно устранить. Жадный подход очень быстр и может легко обрабатывать матрицы 15х15 и намного больше (см. Ниже). Он возвращает единичные решения, но неизвестно, является ли это оптимальным или нет. Оба подхода в версиях для гольфа возвращают количество неиспользованных огней. Подходы без игры в гольф также отображают сетки, как показано ниже.

Перед:

перед

После:

после

Оптимальные решения с использованием всех комбинаций источников света (224 символа)

С благодарностью @ Clément.

Ungolfed версия с использованием всех комбинаций огней

fФорма морфологического преобразования, используемая в, sameCoverageQрассматривает как освещенный (значение = 1 вместо нуля) квадрат 3 x3, в котором находится каждый источник света. Когда источник света находится вблизи края фермы, только квадраты (меньше 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

DavidC
источник
У меня нет Mathematica под рукой, поэтому я не могу проверить этот код, но я думаю, что ваш алгоритм неверен - если я не понял ваши объяснения. Если мое понимание верно, оно опирается на жадную стратегию, которая зависит от порядка обработки света: например, начиная со средней лампы в вашем тестовом примере 3 * 3, вы удалите ее и оставите две боковые лампы. Я не ожидаю, что конкретный порядок, который вы используете в реализации, делает его правильным, но у меня нет контр-примера прямо сейчас.
Климент
Похоже, ваша идея заключается в том, что в исходной настройке может быть возможно иметь 2 лишних источника света, a, b, один из которых более избыточен, чем другой. Таким образом, может случиться так, что будет достигнута лучшая экономика, если ее убрать (сначала). Я чувствую, что это не может произойти с 3 лампами, но это может быть возможно при большем количестве ламп. Первоначально я решил проблему, протестировав все комбинации источников света. Это, безусловно, оптимально и, следовательно, идеально, но я нашел это непрактичным с большим набором источников света.
DavidC
@ Clément Я работаю над решением, которое проверит все возможные комбинации. Это займет некоторое время ...
DavidC
Это, безусловно, будет;) Но этого и следовало ожидать: в нынешнем виде эта проблема является примером минимального набора покрытия - то есть NP. Интересно, дополняют ли дополнительные предположения (почти все покрывающие наборы, кроме боковых) одинаковую мощность) эффективную реализацию.
Климент
Я сильно подозреваю, что жадное решение верное, если вы последовательно проходите по строкам и столбцам, но я еще не доказал это.
Адицу ушел, потому что SE это ЗЛО
3

Питон, 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 битами, установленными для его шаблона освещения. Затем мы исчерпывающе ищем подмножества этого списка, побитовые или совпадающие с побитовыми или всего списка. Самое короткое подмножество - победитель.

m это маска, которая предотвращает закручивание бит при смещении.

Кит Рэндалл
источник
Пожалуйста, попробуйте предоставить программу, которая работает правильно. Java / C++ безопасны для любого вида отступов или пробелов, но Python - нет. Обфускация или сокращение кода - это другое дело, но предоставление программы, которая не запускается, это другое.
user2369284
3
@ user2369284 о чем ты говоришь ?! Он отлично работает (с Python 2)
Aditsu выйти, потому что SE зла
@aditsu У меня есть Python 3.
user2369284
1
@ user2369284 хорошо, синтаксис печати другой, поэтому он терпит неудачу в Python 3
aditsu выход, потому что SE - ЗЛО
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

уйти, потому что SE это зло
источник
Не совсем короткий, но умещается в сектор диска: p Я могу попробовать другой язык позже.
Адицу ушел, потому что SE это ЗЛО
@aditsu Как заставить это работать на Windows?
user2369284
1
@ user2369284: Я не вижу, как вы можете сделать 0011111100 только с 2 лампами. Вы должны покрыть 8 ячеек светом, и каждая лампа может сделать максимум 3.
Кит Рэндалл
@ user2369284 возможно java F <inputfile 2>nul, если это не сработает, тогда java F <inputfileи игнорируйте исключение. Кроме того, он не будет работать с Java 7.
Aditsu выйти, потому что SE зла
@aditsu Мне очень жаль. Это была ошибка опечатки. Ваша программа работает правильно.
user2369284
1

с ++ - 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;}
Hax0r778
источник
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

Преобразование в массивы логических значений, а затем сравнение окрестностей на предмет изменений.

Ограничение (?): Максимальный размер поля фермы составляет 1000 x 1000. Проблема гласит: «Фермер Джек очень беден», поэтому я предполагаю, что его ферма не больше. ;-) Ограничение можно снять, добавив 2 символа.

ПРИМЕЧАНИЕ. Поскольку я начал кодировать это, похоже, требования к вопросу изменились. Было добавлено следующее уточнение: «Лампы, на которые вы укажете, не будут удаляться одна за другой, но будут удалены одновременно» . Неоднозначность исходного вопроса позволила мне сохранить код, протестировав отдельные извлечения ламп. Таким образом, мое решение не будет работать для многих тестовых случаев в соответствии с новыми требованиями. Если у меня будет время, я исправлю это. Я могу не. Пожалуйста, не голосуйте за этот ответ, так как другие ответы здесь могут быть полностью совместимы.

Даррен Стоун
источник
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-байтовые значения. Следовательно, для целей оценки программа из N символов, в которой используются только символы ASCII и символы APL, может рассматриваться как длина 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());
 }
Johannes
источник
Пожалуйста, предоставьте утилиту для тестирования, которая использует внешние библиотеки.
user2369284
Это GTest: code.google.com/p/googletest/downloads/list
Йоханнес
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'
      );
   }
}

(Ввод / вывод был удален, чтобы я мог показать конкретные тесты)

Хантер МакМиллен
источник
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()
Blckknght
источник