Chính phủ có nguồn cung cấp tường hạn chế


28

Giới thiệu

Những người chơi golf có kiến ​​thức đã chuẩn bị cho chúng ta về trận lụt ngày tận thế . Các khu vực có nguy cơ đã được sơ tán, và dân số di chuyển lên vùng cao.

Chúng tôi đã đánh giá thấp trận lụt (hoặc có lẽ có lỗi trong mã của @ user12345). Một số khu vực trên mặt đất cao đang nhanh chóng tiếp cận mực nước biển. Các bức tường phải được dựng lên để đảm bảo sự tồn tại của các vùng đất đông dân cư hiện nay. Đáng buồn thay, chính phủ có một nguồn cung cấp tường hạn chế.

Vấn đề

Kịch bản ngày tận thế của chúng tôi được mô tả bởi hai số trên một dòng nm. Theo sau dòng đó là ncác dòng có mgiá trị trên mỗi dòng, chỉ được phân tách bằng một khoảng trắng. Mỗi giá trị sẽ là một trong bốn ký tự.

  • xBất khả xâm phạm. Nước không thể chảy ở đây. Tường không thể được dựng lên ở đây.
  • -Không ổn định. Nước có thể chảy qua đây. Tường không thể được dựng lên ở đây.
  • .Ổn định. Nước có thể chảy qua đây. Tường có thể được dựng lên ở đây.
  • oEncampment. Nước có thể chảy qua đây. Nếu nó làm, tất cả mọi người chết. Tường không thể được xây dựng ở đây.

Nước sẽ chảy từ tất cả các cạnh của bản đồ, trừ khi cạnh đó không thể xuyên thủng hoặc một bức tường được xây dựng trên gạch. Viết chương trình có thể xuất ra số lượng tường tối thiểu cần thiết để bảo vệ phần đóng gói.

Ví dụ đầu vào

 6 7
 x . . x x x x
 x . . x - - x
 x . x x - - x
 x . o o o - .
 x . o o o - .
 x x x x x x x

Ví dụ đầu ra

3

Giả định

  • Nước chỉ chảy trực giao
  • Encampments chỉ tồn tại dưới dạng một khối liền kề trực giao cho mỗi kịch bản
  • Một giải pháp sẽ luôn tồn tại (mặc dù nó có thể đòi hỏi số lượng lớn tường)
  • Không thể đặt mã hóa trên một cạnh, vì kịch bản sau đó sẽ không có giải pháp
  • 2 n<< 16
  • 2 m<< 16
  • Đầu vào có thể được cung cấp từ stdin, đọc từ "city.txt" hoặc được chấp nhận dưới dạng một đối số

Mã ngắn nhất sẽ thắng!


2
Liệu chương trình có thể được chấp nhận hay không, nhưng mất nhiều thời gian hơn vũ trụ đã biết đã tồn tại để cung cấp giải pháp cho một số trường hợp nhất định của vấn đề?
Claudiu

@Claudiu Tôi hơi mới với Code Golf. Yêu cầu của tôi không thể xác định giới hạn thời gian, vì vậy không tồn tại. Gánh nặng rơi vào câu trả lời để chứng minh rằng một giải pháp là chính xác cho tất cả các trường hợp của vấn đề. Nếu bạn có một giải pháp giải quyết một số trường hợp (nhưng không phải tất cả) một cách thông minh / tuyệt vời, tôi vẫn khuyến khích bạn đăng nó chỉ để giải trí.
Rainbolt

2
Code golf thường không yêu cầu hạn chế thời gian.
Hosch250

Mát mẻ! Một câu hỏi khác: là đầu vào bắt buộc phải như bạn đã chỉ định hoặc chúng ta có thể đặt nó ở dạng khác không?
Claudiu

@Claudiu Tôi không thể chấp nhận bất cứ điều gì ngoài yêu cầu. Tuy nhiên, bạn có thể đề xuất chỉnh sửa các yêu cầu bằng nút chỉnh sửa . Thấy chưa có câu trả lời, có lẽ tôi sẽ chấp nhận chỉnh sửa ngay lập tức.
Rainbolt

Câu trả lời:


10

Mathicala, 256 253 ký tự

d="city.txt"~Import~"Table";g=EdgeAdd[#,∞<->Tr@#&/@Position[VertexDegree@#,2|3]]&@GridGraph@d[[1,{2,1}]];{o,x,s}=Tr/@Position[Join@@d[[2;;]],#]&/@{"o","x","."};Catch@Do[If[Min[GraphDistance[VertexDelete[g,x⋃w],∞,#]&/@o]==∞,Throw@Length@w],{w,Subsets@s}]

Đầu vào được đọc từ "city.txt".

Giải trình:

Mathematica có nhiều chức năng để đối phó với đồ thị.

Đầu tiên, tôi đọc dữ liệu từ "city.txt".

d="city.txt"~Import~"Table";

Sau đó, tôi xây dựng một biểu đồ lưới với các đỉnh 'm' * 'n' ( GridGraph@d[[1,{2,1}]]) và thêm vào đó một "đỉnh ở vô cực" được kết nối với mọi đỉnh trên "các cạnh" của đồ thị. Đỉnh này là nơi nước chảy từ.

g=EdgeAdd[#,∞<->Tr@#&/@Position[VertexDegree@#,2|3]]&@GridGraph@d[[1,{2,1}]];

o, xsbiểu thị các vị trí của "o", "x" và "." tương ứng.

{o,x,s}=Tr/@Position[Join@@d[[2;;]],#]&/@{"o","x","."};

Sau đó, đối với bất kỳ tập hợp con wcủa s(các tập con đều được sắp xếp theo chiều dài), tôi xóa các đỉnh trong xwtừ g( VertexDelete[g,x⋃w]), và tìm ra chiều dài của con đường đi ngắn nhất từ các "đỉnh ở vô cực" vào trại o. Nếu chiều dài là vô cùng, thì việc đóng gói sẽ an toàn. Vì vậy, chiều dài của cái đầu tiên wlà số lượng tường tối thiểu cần thiết để bảo vệ một vùng đất.

Catch@Do[If[Min[GraphDistance[VertexDelete[g,x⋃w],∞,#]&/@o]==∞,Throw@Length@w],{w,Subsets@s}]

Tốt đẹp! Tôi hình dung tôi sẽ bị cuốn theo một cách tiếp cận khác trong một ngôn ngữ khác.
Claudiu

1
Nâng cao nhưng tôi sẽ tự hào hơn nếu bạn giải thích mã của bạn cho phần còn lại của chúng tôi.
Michael Stern

Ai đó có thể xác nhận rằng câu trả lời này là chính xác hoặc cung cấp một intepreter trực tuyến cho "Mathicala"? Gặp khó khăn trong việc tìm kiếm một.
Rainbolt

1
@Rizer Tôi đã xác minh nó, và nó là vững chắc. Không có trình thông dịch trực tuyến cho MM, nhưng có một định dạng tài liệu CDF có thể tải xuống mà tôi và một vài người khác đã bắt đầu thử nghiệm để chia sẻ giải pháp. Bạn cũng có thể nhận Mathicala miễn phí với máy tính Raspberry Pi ARM, với sự cảnh báo mà bạn bị giới hạn bởi sức mạnh tính toán của hộp. FWIW, người dùng MM của chúng tôi làm hết sức để giữ cho nhau trung thực và chúng tôi đang nỗ lực để làm cho bài nộp của chúng tôi dễ tiếp cận hơn (một vấn đề cũng gặp phải với các ngôn ngữ Matlab, Maple, MS không hoạt động trên Mono, v.v.)
Jonathan Van Matre

4

C, 827 799 522

Chơi gôn

#define N for(
#define F(W,X,Y,Z) N i= W;i X Y;i Z)
#define C(A,B,C) if(c[A][B]==C)
#define S(W,X,Y,Z,A,B) p=1;F(W,X,Y,Z)C(A,B,120)p=0;if(p){F(W,X,Y,Z){C(A,B,46){c[A][B]='x';z++;Q();break;}}}else{F(W,X,Y,Z){C(A,B,120)break;else c[A][B]='o';}}
p,m,z,w,h,o,i,u,l,x,y;char c[16][16];Q(){N u=0;u<h;u++)N l=0;l<w;l++)if(c[u][l]=='o'){x=u;y=l;S(x,>,m,--,i,y)S(y,>,m,--,x,i)S(y,<,w,++,x,i)S(x,<,h,++,i,y)}}main(int a, char **v){h=atoi(v[1]);w=atoi(v[2]);N m=-1;o<h;o++)N i=0;i<w;i++)scanf("%c",&c[o][i]);Q();printf("%d",z);}

Đầu vào được đưa ra với chiều cao và với các đối số dòng lệnh, và sau đó lưới được đọc dưới dạng một chuỗi trên stdin như vậy: ./a.out 6 7 < inputtrong đó đầu vào ở dạng này (trái sang phải, từ trên xuống dưới):

x..xxxxx..x - xx.xx - xx.ooo-.x.ooo-.xxxxxxx

"Có thể đọc được":

#define F(W,X,Y,Z) for(i= W;i X Y;i Z)
#define C(A,B,C) if(c[A][B]==C)
#define S(W,X,Y,Z,A,B) p=1;F(W,X,Y,Z)C(A,B,120)p=0;if(p){F(W,X,Y,Z){C(A,B,46){c[A][B]='x';z++;Q();break;}}}else{F(W,X,Y,Z){C(A,B,120)break;else c[A][B]='o';}}

/*Example of an expanded "S" macro:
p=1;
for(i=x;i>m;i--) if(c[i][y]==120) p=0;
if(p)
{
    for(i=x;i>m;i--)
    {
        if(c[i][y]==46)
        {
            c[i][y]='x';
            z++;
            Q();
            break;
        }
    }
}
else
{
    for(i= x;i > m;i --)
    {
        if(c[i][y]==120) break;
        else c[i][y]='o';
    }
}
*/

p,m,z,w,h,o,i,u,l,x,y;
char c[16][16];
Q(){
    for(u=0;u<h;u++)
        for(l=0;l<w;l++)
            if(c[u][l]=='o')
            {
        x=u;y=l;
        S(x,>,m,--,i,y)
        S(y,>,m,--,x,i)
        S(y,<,w,++,x,i)
        S(x,<,h,++,i,y)
            }
}

main(int a, char **v)
{
    h=atoi(v[1]);
    w=atoi(v[2]);
    for(m=-1;o<h;o++)
        for(i=0;i<w;i++)
            scanf("%c",&c[o][i]);
    P();
    Q();
    printf("%d\n",z);
    P();
}

//Omitted in golfed version, prints the map.
P()
{
    for(o=0;o<h;o++)
    {
        for (i=0;i<w;i++) printf("%c",c[o][i]);
        printf("\n");
    }   
}

Không nơi nào ngắn bằng giải pháp của @Claudiu, nhưng nó chạy rất nhanh. Thay vì lấp đầy từ các cạnh, nó tìm thấy phần đóng gói và hoạt động ra bên ngoài từ các mã thông báo 'o'.

  • Nếu nó gặp phải bất kỳ mặt đất không ổn định nào bên cạnh phần đóng gói, nó sẽ mở rộng phần đóng gói lên nó.
  • Nếu bất kỳ sự bao bọc nào trên lưới không có ít nhất một bức tường ở mỗi hướng, thì nó sẽ di chuyển theo hướng đó cho đến khi nó có thể xây dựng một bức tường.
  • Sau khi mỗi phần tường mới được đặt, nó sẽ đệ quy để tìm phần tường tiếp theo để đặt.

Vị trí tường mẫu:

x..xxxx                           x..xxxx
x..x--x                           x..xoox
x.xx--x                           x3xxoox
x.ooo-.  <-- results in this -->  xooooo1
x.ooo-.                           xooooo2
xxxxxxx                           xxxxxxx

Ôi cách tiếp cận thú vị! Nó luôn luôn đưa ra câu trả lời ngắn nhất? ví dụ câu trả lời nào cho bản đồ này ? Nó phải là 3 (đánh dấu nơi các bức tường mới đi cùng @). Tôi đã thử tự chạy mã của bạn nhưng có vẻ như
Claudiu

Rất tiếc, có vẻ như chơi golf và rượu không hòa hợp với nhau ... Tôi đã chơi golf trong một số hành vi không xác định. Nên sửa ngay bây giờ cùng với 277 ký tự không cần thiết.
Comitern

2
@Claudiu - Xem bình luận của tôi ở trên, kết quả cho bản đồ bạn đã đăng ở pastebin.com/r9fv7tC5 . Điều này sẽ luôn đưa ra câu trả lời ngắn nhất, nhưng tôi chỉ thử nó với 10 hoặc 15 bản đồ mà tôi nghĩ có thể đưa ra các trường hợp góc. Tôi tò mò muốn xem liệu có ai có thể xác định bản đồ mà nó thất bại không.
Comitern

4

Python, 553 525 512 449 414 404 387 368 ký tự (+4? Để gọi)

Tôi đã có quá nhiều niềm vui khi chơi golf này. Nó lớn hơn 82 byte nếu bạn cố nén nó! Bây giờ đó là thước đo của sự nhỏ gọn và thiếu sự lặp lại.

R=range;import itertools as I
f=map(str.split,open('city.txt'))[1:]
S=[]
def D(q):
 q=set(q)
 def C(*a):
    r,c=a
    try:p=(f[r][c],'x')[a in q]
    except:p='x'
    q.add(a)
    if'.'==p:S[:0]=[a]
    return p<'/'and C(r+1,c)|C(r-1,c)|C(r,c+1)|C(r,c-1)or'o'==p
 if sum(C(j,0)|C(j,-1)|C(0,j)|C(-1,j)for j in R(16))<1:print n;B
D(S);Z=S[:]
for n in R(len(Z)):map(D,I.combinations(Z,n))

Cấp độ thụt là không gian, tab.

Cách sử dụng :

Đọc từ city.txt:

6 7
x . . x x x x
x . . x - - x
x . x x - - x
x . o o o - .
x . o o o - .
x x x x x x x

Gọi như sau:

$ python floodfill_golf.py 2>X
3

Đây 2>Xlà để ẩn stderr kể từ khi chương trình thoát ra bằng cách đưa ra một ngoại lệ. Nếu điều này được coi là không công bằng, vui lòng thêm 4 ký tự cho lệnh gọi.

Giải thích :

Lực lượng vũ phu đơn giản. Clàm đầy lũ và trả về đúng nếu nó bị đóng gói. Không có phần đệm thêm vì phải mất quá nhiều không gian để đặt phần đệm đúng cách. D, được cung cấp một tập hợp các bức tường để điền vào, các cuộc gọi Ctừ mọi điểm trên cạnh sao Ccho các bức tường đó, và in chiều dài và thoát ra nếu không ai trong số chúng đạt được sự bao bọc. Danh sách các bức tường cũng được sử dụng để theo dõi lũ lụt, do đó không cần sao chép bảng! Trickily, Ccũng nối thêm bất kỳ điểm trống nào nó tìm thấy vào một danh sách S, do đó, hàm Dnày cũng được sử dụng để xây dựng danh sách các điểm trống trước tiên. Vì lý do này, tôi sử dụng sumthay vì any, để đảm bảo tất cả các .s được thu thập trong lần chạy đầu tiên.

Tôi gọi Dmột lần, sau đó sao chép danh sách các điểm trống vào ZSsẽ tiếp tục được thêm vào (không hiệu quả, nhưng rẻ hơn về số lượng ký tự). Sau đó, tôi sử dụng itertools.combinationsđể chọn từng combo điểm trống, từ 0 điểm trở lên. Tôi chạy từng combo thông qua Dvà nó in ra độ dài của cái đầu tiên hoạt động, đưa ra một ngoại lệ để thoát khỏi chương trình. Nếu không có câu trả lời được tìm thấy thì không có gì được in.

Lưu ý rằng hiện tại, chương trình không hoạt động nếu không cần tường. Đó là +3 ký tự để xử lý trường hợp này; không chắc chắn nếu nó cần thiết.

Cũng lưu ý rằng đây là một O(2^n)thuật toán, trong đó nsố lượng điểm trống. Vì vậy, đối với một bảng 15x15 hoàn toàn trống rỗng với một bảng mã ở giữa, điều này sẽ mất 2^(15*15-1)= 2.6959947e+67lặp để hoàn thành, đó sẽ là một thời gian rất dài thực sự!


1

Groovy: 841 805 754

i=new File("city.txt").getText()
x=i[2] as int
y=i[0] as int
m=i[4..i.length()-1].replaceAll('\n','').toList()
print r(m,0)
def r(m,n){if(f(m))return n;c=2e9;g(m).each{p=r(it,n+1);if(p<c)c=p;};return c;}
def f(m){u=[];u.addAll(m);for(i in 0..(x*y)){for(l in 0..m.size()-1){n(l,u);s(l,u);e(l,u);w(l,u);}};m.count('o')==u.count('o')}
def n(i,m){q=i-x;if((((q>=0)&(m[q]=='!'))|(q<0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def s(i,m){q=i+x;if((((q>=0)&(m[q]=='!'))|(q<0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def e(i,m){q=i+1;if((((q%x!=0)&(m[q]=='!'))|(q%x==0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def w(i,m){q=i-1;if((((i%x!=0)&(m[q]=='!'))|(i%x==0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def g(m){v=[];m.eachWithIndex{t,i->if(t=='.'){n=[];n.addAll(m);n[i]='W';v<<n}};return v}

Ung dung:

def i = new File("city.txt").getText()
x=i[2].toInteger()
y=i[0].toInteger()
def m=i[4..i.length()-1].replaceAll('\n','').toList()
println r(m, 0)

def r(m, n){
    if(f(m)) return n
    def c = Integer.MAX_VALUE

    getAllMoves(m).each{ it -> 
        def r = r(it, n+1)
        if(r < c) c = r
    }
    return c;
}

def f(m){
    def t = []
    t.addAll(m)
    for(i in 0..(x*y)){
        for(l in 0..m.size()-1){
            n(l,t);s(l,t);e(l,t);w(l,t);
        }
    }
    m.count('o')==t.count('o')
}

def n(i,m){
    def t = i-x;
    if( ( ( (t >= 0) && (m[t]=='!') ) || (t < 0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    }
}

def s(i,m){
    def t = i+x;
    if( ( ( (t >= 0) && (m[t]=='!') ) || (t < 0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    }
}

def e(i,m){
    def t = i+1;
    if( ( ( (t%x!=0) && (m[t]=='!') ) || (t%x==0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    } 
}

def w(i,m){
    def t = i-1;
    if( ( ( (i%x!=0) && (m[t]=='!') ) || (i%x==0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    }
}

def getAllMoves(m){
    def moves = []
    m.eachWithIndex { t, i ->
        if(t=='.'){
            def newList = []
            newList.addAll(m)
            newList[i]='W'
            moves << newList
        }
    }
    return moves
}

Nhiều môn đánh gôn sắp tới ...

Trả về 2E9 nếu không có giải pháp.


0

APL Dyalog , 91 byte

⊃∊{1∊a[⍸×{(×d)∧s 3∨/3∨⌿⍵}⍣≡4=d←0@⍵⊢a]:⍬⋄≢⍵}¨c[⍋≢¨c←(,⍳2⊣¨b)/¨⊂b←⍸2=a←(s←(4,4,⍨⍉)⍣2)'xo.'⍳⎕]

giả sử ⎕IO=0, sử dụng các tính năng từ v16.0 ( @), thời gian chạy là theo cấp số nhân của số .-s

được đánh giá đầu vào, phải là một ma trận các ký tự

'xo.'⍳ thay thế xbằng 0, obằng 1, .bằng 2 và tất cả những người khác bằng 3

s←(4,4,⍨⍉)⍣2 một hàm bao quanh một ma trận với 4s

a← gán ma trận số được bao quanh bởi 4s cho một biến a

b←⍸2= blà danh sách các cặp tọa độ trong đó 2s (tức là .-s)

(,⍳2⊣¨b)/¨⊂b tạo ra tất cả sự kết hợp của các yếu tố b

c[⍋≢¨c←...] sắp xếp chúng theo kích thước

{... :⍬⋄≢⍵}¨ cho mỗi kết hợp, kiểm tra một cái gì đó và trả về độ dài của nó hoặc một danh sách trống

⊃∊ kết quả không trống đầu tiên

d←0@⍵⊢a davới một số yếu tố được thay thế bằng 0

4= tạo ma trận boolean - 4s ở đâu? tức là đường viền chúng ta đã thêm

{...}⍣≡ tiếp tục áp dụng chức năng {}cho đến khi kết quả ổn định

3∨/3∨⌿⍵ "boolean hoặc" mỗi phần tử với hàng xóm của nó

s kết quả sẽ nhỏ hơn, vì vậy hãy tạo lại đường viền

(×d)∧ áp dụng các phần tử khác không của d(không phải tường) làm mặt nạ boolean

a[⍸× ...] những gì trong atương ứng với 1s trong ma trận boolean của chúng tôi?

1∊ Có bất kỳ 1s, tức là o, đóng gói?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.