ช่วยชาวนา


10

แจ็คชาวนายากจนมาก เขาต้องการทำให้ฟาร์มของเขาสว่าง แต่ด้วยต้นทุนขั้นต่ำ โคมไฟสามารถส่องสว่างเซลล์ของตัวเองเช่นเดียวกับแปดเพื่อนบ้าน เขาจัดเรียงตะเกียงในทุ่งนาของเขา แต่เขาต้องการความช่วยเหลือจากคุณในการค้นหาว่าเขาเก็บตะเกียงพิเศษไว้หรือไม่

โคมไฟพิเศษ: โคมไฟที่นำออกจากฟาร์มจะไม่สร้างความแตกต่างกับจำนวนเซลล์ที่สว่าง นอกจากนี้หลอดไฟที่คุณจะชี้จะไม่ถูกลบทีละหลอด แต่จะถูกลบพร้อมกัน

หมายเหตุ: การดำเนินการเดียวที่คุณสามารถทำได้คือการลบหลอดบางส่วน คุณไม่สามารถจัดเรียงใหม่หรือใส่หลอดได้ เป้าหมายสุดท้ายของคุณคือการลบจำนวนสูงสุดของหลอดไฟเช่นที่ทุกเซลล์ที่สว่างก่อนหน้านี้ยังคงสว่าง

ช่วยชาวนาแจ็คในการหาจำนวนหลอดไฟที่ไร้ประโยชน์มากที่สุดเพื่อให้เขาสามารถใช้งานได้ที่อื่น

อินพุต

คุณจะได้รับในมิติบรรทัดแรกของฟิลด์MและN.ถัดไปMบรรทัดตามที่มีอักขระNตัวแต่ละตัวแทนฟิลด์

'1' หมายถึงเซลล์ที่เก็บหลอดไฟไว้

'0' หมายถึงเซลล์ว่าง

เอาท์พุต

คุณต้องส่งออกจำนวนเต็มที่มีจำนวนหลอดที่ไร้ประโยชน์

ตัวอย่างอินพุต:

3 3
100
010
001

ตัวอย่างผลลัพธ์:

2

ผู้ชนะ:

เนื่องจากเป็นโค้ดกอล์ฟผู้ชนะจะเป็นผู้ที่จะทำงานให้สำเร็จด้วยจำนวนอักขระน้อยที่สุด


@PeterTaylor ฉันได้แก้ไขโพสต์ของฉัน คุณยังมีความสับสนหรือไม่?
user2369284

ดีกว่ามาก ขอบคุณ
Peter Taylor

เราจะสมมติว่าอินพุตนั้นลงท้ายด้วยการขึ้นบรรทัดใหม่ได้หรือไม่
John Dvorak

1
ดูเหมือนว่าจะทำการบ้าน
โยฮันเนส

1
เรารับประกันได้หรือไม่ว่าโคมไฟอินพุตจะส่องสว่างทั่วทั้งฟาร์ม? ฉันจะเดาไม่ ...
Keith Randall

คำตอบ:


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]

สิ่งนี้จะปิดไฟที่ไม่จำเป็นหนึ่งต่อหนึ่ง หากความครอบคลุมของแสงไม่ลดลงเมื่อแสงดับลงแสงนั้นจะถูกกำจัด วิธีโลภนั้นรวดเร็วมากและสามารถจัดการเมทริกซ์ที่ 15x15 และใหญ่กว่าได้อย่างง่ายดาย (ดูด้านล่าง) ส่งคืนโซลูชันเดียว แต่ไม่ทราบว่าเหมาะสมหรือไม่ ทั้งสองวิธีในเวอร์ชันที่ตีกอล์ฟให้ส่งคืนจำนวนไฟที่ไม่ได้ใช้ วิธี Un-golfed ยังแสดงกริดดังต่อไปนี้

ก่อน:

ก่อน

หลังจาก:

หลังจาก

โซลูชันที่เหมาะสมที่สุดที่ใช้ไฟทั้งหมด (224 ตัวอักษร)

ด้วยความขอบคุณ @ Clément

เวอร์ชันที่ไม่ดีนักโดยใช้แสงทั้งหมด

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 หรือไม่ [[mat] ใช้เมทริกซ์ของแสงและส่งกลับเมทริกซ์ของเซลล์ที่พวกมันสว่างขึ้น

c[j]นำแสงจาก j ทั้งหมดมารวมกันและทดสอบเพื่อให้ครอบคลุม ในบรรดาที่มีความครอบคลุมสูงสุดจะเลือกผู้ที่มีหลอดไฟน้อยที่สุด แต่ละสิ่งเหล่านี้เป็นทางออกที่ดีที่สุด

ตัวอย่างที่ 2

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

ตะแกรง

สามารถประหยัดไฟได้สองดวงในขณะที่มีการครอบคลุมแสงเดียวกัน ค [M]

2


ฉันไม่มี Mathematica อยู่ในมือดังนั้นฉันจึงไม่สามารถทดสอบโค้ดนี้ได้ แต่ฉันคิดว่าอัลกอริทึมของคุณไม่ถูกต้อง - ยกเว้นว่าฉันเข้าใจผิดคำอธิบายของคุณ หากความเข้าใจของฉันถูกต้องขึ้นอยู่กับกลยุทธ์โลภที่ขึ้นอยู่กับลำดับของแสงที่ถูกประมวลผล: ตัวอย่างเช่นการเริ่มจากโคมไฟกลางในกรณีทดสอบ 3 * 3 ของคุณจะลบออกและปล่อยโคมไฟสองด้าน ฉันไม่คาดหวังว่าการเรียงลำดับเฉพาะที่คุณใช้ในการนำไปใช้จะทำให้ถูกต้อง แต่ตอนนี้ฉันไม่มีตัวอย่างตอบโต้
Clément

ความคิดของคุณน่าจะเป็นไปได้ว่าอาจเป็นไปได้ที่จะมี 2 ไฟที่ไม่จำเป็น, a, b, ในการตั้งค่าดั้งเดิมซึ่งหนึ่งในนั้นมีความฟุ่มเฟือยมากกว่าที่อื่น ๆ ดังนั้นอาจเป็นไปได้ว่าเศรษฐกิจจะดีขึ้นหากนำออก (ครั้งแรก) ฉันรู้สึกว่าสิ่งนี้ไม่สามารถเกิดขึ้นได้ด้วยแสงทั้งหมด 3 ดวง แต่อาจเป็นไปได้ด้วยจำนวนแสงที่มากกว่า ตอนแรกฉันแก้ปัญหาด้วยการทดสอบชุดไฟทั้งหมด นี่เป็นสิ่งที่ดีที่สุดและเหมาะสมที่สุด แต่ฉันพบว่ามันใช้งานไม่ได้กับชุดไฟขนาดใหญ่
DavidC

@ Clémentฉันกำลังทำงานกับโซลูชันที่จะทดสอบชุดค่าผสมที่เป็นไปได้ทั้งหมด จะใช้เวลาสักครู่ ...
DavidC

แน่นอนว่าจะ;) แต่ต้องคาดหวัง: เนื่องจากปัญหานี้เป็นตัวอย่างของการครอบคลุมชุดขั้นต่ำ - ซึ่งก็คือปัญหา NP ไม่ว่าจะเป็นข้อสันนิษฐานเพิ่มเติม (เกือบทุกชุดยกเว้นยกเว้นด้านข้างมีความเหมือนกันของหัวใจ) อนุญาตให้ดำเนินการอย่างมีประสิทธิภาพหรือไม่เป็นปัญหาที่น่าสนใจ
Clément

ฉันสงสัยอย่างมากว่าทางออกโลภนั้นถูกต้องหากคุณไปตามลำดับโดยแถวและคอลัมน์ แต่ฉันยังไม่ได้พิสูจน์
aditsu ออกจากเพราะ SE นั้นชั่วร้าย

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))

ทำงานโดยใช้ bitmasks Lคือรายการของแสงที่แต่ละแสงถูกแทนด้วยจำนวนเต็ม (สูงสุด) 9 บิตที่ตั้งค่าสำหรับรูปแบบแสง จากนั้นเราจะค้นหาเซ็ตย่อยของรายการนี้อย่างละเอียดซึ่งมีค่าบิต - หรือเท่ากับบิตหรือ - ของรายการทั้งหมด เซตย่อยที่สั้นที่สุดคือผู้ชนะ

m เป็นมาสก์ที่ป้องกันการพันกันของบิตเมื่อขยับ


โปรดลองจัดเตรียมโปรแกรมที่ทำงานอย่างถูกต้อง Java/C++ มีความปลอดภัยในการย่อหน้าหรือการเว้นวรรค แต่ Python ไม่ทำงานการทำให้เป็นรหัสหรือการย่อให้เล็กลงนั้นเป็นอีกสิ่งหนึ่ง
user2369284

3
@ user2369284 คุณกำลังพูดถึงอะไร! มันทำงานได้อย่างสมบูรณ์แบบ (กับ python 2)
aditsu ออกเพราะ SE นั้นชั่วร้าย

@aditsu ฉันมี python 3
user2369284

1
@ user2369284 ดี, ไวยากรณ์การพิมพ์แตกต่างกันดังนั้นจึงล้มเหลวในหลาม 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


ไม่สั้น แต่พอดีกับดิสก์เซกเตอร์: p ฉันอาจลองภาษาอื่นในภายหลัง
aditsu ออกจากเพราะ SE นั้นชั่วร้าย

@aditsu ทำอย่างไรถึงจะทำงานบน windows ได้?
user2369284

1
@ user2369284: ฉันไม่เห็นวิธีที่คุณสามารถทำได้ 0011111100 ด้วยหลอดไฟเพียง 2 หลอด คุณต้องครอบคลุม 8 เซลล์ด้วยแสงและแต่ละหลอดสามารถทำได้มากที่สุด 3
Keith Randall

@ user2369284 บางทีjava F <inputfile 2>nulหากล้มเหลวก็java F <inputfileให้ข้ามข้อยกเว้น นอกจากนี้มันจะไม่ทำงานกับ java 7
aditsu ออกเพราะ SE เป็นความชั่วร้าย

@aditsu ฉันขอโทษจริง ๆ นี่เป็นข้อผิดพลาดที่พิมพ์ผิด โปรแกรมของคุณทำงานอย่างถูกต้อง
user2369284

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 ปัญหาระบุว่า "Farmer Jack แย่มาก" ดังนั้นฉันจึงคิดว่าฟาร์มของเขาไม่ใหญ่ขึ้น ;-) ข้อ จำกัด สามารถลบได้โดยเพิ่ม 2 ตัวอักษร

หมายเหตุ:ตั้งแต่ฉันเริ่มเขียนโค้ดนี้จะปรากฏข้อกำหนดของคำถามเปลี่ยนไป ชี้แจงต่อไปนี้ถูกเพิ่มเข้ามา"โคมไฟที่คุณจะชี้จะไม่เป็นหนึ่งที่ถูกนำออกโดยหนึ่ง แต่พวกเขาจะถูกลบออกไปพร้อม ๆ กัน" ความคลุมเครือของคำถามเดิมทำให้ฉันสามารถบันทึกรหัสได้โดยการทดสอบการถอดหลอดไฟแต่ละอัน ดังนั้นโซลูชันของฉันจะไม่ทำงานสำหรับกรณีทดสอบจำนวนมากภายใต้ข้อกำหนดใหม่ ถ้าฉันมีเวลาฉันจะแก้ไขสิ่งนี้ ฉันอาจจะไม่. โปรดอย่ายกคำตอบนี้เนื่องจากคำตอบอื่น ๆ ที่นี่อาจเป็นไปตามข้อกำหนดทั้งหมด


1

APL, 97 ตัวอักษร / ไบต์ *

ถือว่า a ⎕IO←1และ⎕ML←3สภาพแวดล้อม APL

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

เลย์เอาต์พร้อมหลอดไฟขั้นต่ำ (ไม่รวมอยู่ในเวอร์ชัน golfed):

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 chars ที่ใช้อักขระ ASCII และสัญลักษณ์ APLเท่านั้นจึงถือได้ว่ามีความยาว N ไบต์


0

C ++ 5.806 ไบต์

ยังไม่ได้ปรับขนาดให้เหมาะสม แต่เนื่องจากมีผู้เข้าแข่งขันไม่กี่คนที่ฉันจะทิ้งมันไว้สำหรับตอนนี้

ส่วนหัวของเกษตรกร

#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);
};

}

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


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.