Hükümetin Sınırlı Duvar Arzı Var


28

Giriş

Bilgili kod golfçüler bizi kıyamet seli için hazırladı . Risk altındaki alanlar boşaltıldı ve nüfus yüksek yerlere taşındı.

Seli hafife aldık (veya belki de @ user12345'in kodunda bir hata vardı). Bazı yüksek zemin alanları deniz seviyesine hızla yaklaşmaktadır. Şimdi yoğun nüfuslu kampların hayatta kalmasını sağlamak için duvarlar inşa edilmelidir. Ne yazık ki, hükümetin sınırlı bir duvar arzı var.

Sorun

Kıyamet günü senaryomuz, tek bir satırda iki sayı ile nve m. Bu satırın ardından satır başına değer niçeren m, yalnızca tek bir boşlukla ayrılmış satırlar bulunur . Her değer dört karakterden biri olacaktır.

  • xGeçilmez. Burada su akamaz. Burada duvarlar yapılamaz.
  • -Kararsız. Buradan su akabilir. Burada duvarlar yapılamaz.
  • .Kararlı. Su buradan akabilir. Burada duvarlar inşa edilebilir.
  • oEncampment. Su buradan akabilir. Olursa, herkes ölür. Burada duvarlar inşa edilemez.

Kenar geçilmez olmadıkça veya karo üzerine bir duvar inşa edilmediyse, haritanın tüm kenarlarından su akacaktır. Bir yerleşimi korumak için gereken minimum duvar sayısını verebilecek bir program yazın.

Örnek Giriş

 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

Örnek çıktı

3

Varsayımlar

  • Su sadece dikey olarak akar
  • Yerleşimler, senaryo başına yalnızca bir tek köşeli bitişik blok olarak bulunur
  • Her zaman bir çözüm bulunacaktır (çok miktarda duvar gerektirse de)
  • Senaryo daha sonra çözülmeyeceğinden, kampanyalar bir kenara yerleştirilemez
  • 2 n<<16
  • 2 m<<16
  • Giriş, stdin'den sağlanabilir, "city.txt" den okunabilir veya tek bir argüman olarak kabul edilebilir.

En kısa kod kazanır!


2
Programın doğru olması kabul edilebilir mi, ancak problemin belirli durumlarına bir çözüm sağlamak için bilinen evrenin varlığından daha uzun sürebilir mi?
Claudiu

@ Claudiu Code Golf için biraz yeni. Gereksinim bir zaman limiti belirtemedi, bu yüzden biri mevcut değil. Yük, sorunun tüm örneklerinde bir çözümün doğru olduğunu kanıtlamak için cevaba düşüyor. Bazı (ancak hepsini değil) örneklerini zekice / serin bir şekilde çözen bir çözümünüz varsa, sizi sadece eğlence için göndermenizi öneririm.
Rainbolt

2
Kod golf genellikle zaman kısıtlaması gerektirmez.
Hosch250

Güzel! Başka bir Q: Girişin sizin belirttiğiniz gibi olması gerekiyor mu yoksa başka bir forma koyabilir miyiz?
Claudiu

@ Claudiu Gereksinimler dışında hiçbir şey kabul edemiyorum. Bununla birlikte, düzenleme düğmesini kullanarak gereksinimler için bir düzenleme önerebilirsiniz . Henüz bir cevap olmadığını görünce, muhtemelen hemen düzenlemeyi kabul edeceğim.
Rainbolt

Yanıtlar:


10

Mathematica, 257 253 karakter

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}]

Giriş okunur "city.txt".

Açıklama:

Mathematica'nın grafiklerle uğraşmak için birçok işlevi vardır.

İlk önce verileri okudum "city.txt".

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

Sonra 'm' * 'n' vertices ( ) ile bir ızgara grafiği oluşturdum GridGraph@d[[1,{2,1}]]ve ona grafiğin "kenarlarında" her köşeye bağlı bir "sonsuzda köşe" ekleyin. Bu köşe suyun aktığı yerdir.

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

Ve o, xve s"x" ve "o" konumlarını belirtmek "" sırasıyla.

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

Sonra herhangi bir alt küme wiçin s(alt kümeler uzunluğa göre sıralanır), ( ) içindeki xve warasındaki köşeleri silerim ve "sonsuzdaki vertex" bölümünden en kısa yolun uzunluğunu bulurum . Uzunluk sonsuzsa, yerleşim güvenli olacaktır. Bu nedenle, ilkinin uzunluğu, bir yerleşmeyi korumak için gereken minimum duvar sayısıdır.gVertexDelete[g,x⋃w]ow

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

Güzel! Farklı bir dilde farklı bir yaklaşımla yakalanacağımı düşündüm.
Claudiu

1
İyileştirme, ancak kodunuzu hepimiz için açıklarsanız daha çok gurur duyardım.
Michael Stern

Birisi bu cevabın doğru olduğunu söyleyebilir veya "Mathematica" için çevrimiçi bir tercüman sağlayabilir mi? Bir tane bulmakta zorlanıyoruz.
Rainbolt

1
@Rusher Doğruladım ve sağlam. MM için çevrimiçi tercüman yoktur, ancak ben ve birkaç başkalarının çözümleri paylaşmak için denemeye başladıkları indirilebilir bir CDF belge formatı vardır. Ayrıca Mathematica'yı ücretsiz olarak Raspberry Pi ARM bilgisayarı ile, kutunun bilgi işlem gücü ile sınırlandırdığın ihtarı alabilirsiniz. FWIW, biz MM kullanıcıları birbirimizi dürüst tutmak için elimizden gelenin en iyisini yapıyoruz ve gönderimlerimizi daha erişilebilir hale getirmek için çalışıyoruz (Matlab, Maple, Mono'da çalışmayan MS dillerinin de karşılaştığı bir sorun)
Jonathan Van Matre

4

C, 827 799 522

golfed:

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

Girdi, yükseklik ve komut satırı argümanları ile verilir ve daha sonra ızgara, stdin üzerinde tek bir dize olarak okunur: ./a.out 6 7 < inputburada girdi bu formdadır (soldan sağa, yukarıdan aşağıya):

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

"Okunabilir":

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

Hiçbir yerde @Claudiu tarafından çözülecek kadar kısa bir çözüm yok, ancak cayır cayır yanan hızlı çalışıyor. Kenarlardan sel doldurmak yerine, yerleşimi bulur ve 'o' belirteçlerinden dışarıya doğru çalışır.

  • Kampanyanın yanında dengesiz bir zeminle karşılaşırsa, kampanyanın üzerine genişler.
  • Izgaradaki herhangi bir yerleşim her yönde en az bir duvara sahip değilse, bir duvar inşa edinceye kadar o yönde hareket eder.
  • Her yeni duvar bölümü yerleştirildikten sonra, yerleştirilecek bir sonraki duvar bölümünü bulmak için tekrarlanır.

Örnek duvar yerleşimleri:

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

Oh ilginç yaklaşım! Her zaman en kısa cevabı verir mi? örneğin bu harita için ne cevabı veriyor ? 3 olmalıdır (yeni duvarların gittiği yere işaretlenir @). Kodunuzu kendim çalıştırmayı denedim ama işe yaramadı
Claudiu

Hata! Golf ve alkolün çok iyi karışmadığı görülüyor ... Belirsiz davranışlarda golf oynamıştım. Şimdi 277 gereksiz karakter ile birlikte düzeltilmelidir .
Comintern

2
@Claudiu - Yukarıdaki yorumuma bakın, gönderdiğiniz harita için sonuçlar pastebin.com/r9fv7tC5 adresinde . Bu her zaman en kısa cevabı vermelidir, ancak sadece köşe senaryoları sunabileceğini düşündüğüm 10 veya 15 harita ile test ettim. Başarısız olduğu haritaları tespit edip edemediğini merak ediyorum.
Comintern

4

Python, 553 525 512 449 414 404 387 368 karakter (başlatma için +4?)

Bunu golf oynarken çok eğlendim. Sıkıştırmayı denersen 82 bayt daha büyük! Şimdi bu bir kompaktlık ve tekrarlama eksikliği ölçüsü.

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

Girinti seviyeleri boşluktur, sekme.

Kullanım :

Şundan okuyor 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

Aşağıdaki gibi çağırınız:

$ python floodfill_golf.py 2>X
3

2>XBir istisna yükselterek Program çıkar beri stderr'yi saklamaktır. Bu haksızlık olarak kabul edilirse arama için 4 karakter eklemekten çekinmeyin.

Açıklama :

Basit kaba kuvvet. Ctaşma dolgusu yapar ve bir kampa girerse doğru yapar. Dolguyu düzgün bir şekilde ayarlamak çok fazla alan harcadığından fazladan ped kullanmayın. Ddoldurulması gereken duvarlar göz önüne alındığında C, kenardaki her noktadan, Cbu duvarları hesaba katan çağrılar ve hiçbiri yerleşime ulaşmadığında, uzunluk ve çıkışları yazdırır. Duvarların listesi sel dolgusunun izini sürmek için de kullanılır, bu nedenle tahtanın kopyalanması gerekmez! Trickily, Caynı zamanda bir liste bulduğu boş noktalar ekler, Sböylece fonksiyon Dolan , aynı zamanda , ilk yapısına boş noktalar listesi kullanılır. Bu sebeple, kullandığım sumyerine anytüm sağlamak için, .ilk çalıştırma-through üzerinde toplanır.

Bir Dkez çağırdım , sonra boş noktaların listesini eklemeye Zdevam Sedeceğim çünkü eklenmeye devam edecek (verimsiz ama karakter sayımında daha ucuz). Sonra itertools.combinationsher bir boş noktayı, 0 noktadan yukarı doğru seçmek için kullanıyorum. Her bir kombinasyonu çalıştırıyorum Dve çalışan ilk programın uzunluğunu yazdırıyor, programdan çıkmak için bir istisna oluşturuyor. Hiçbir cevap bulunamazsa, hiçbir şey yazdırılmaz.

Şu anda, duvar gerekmediğinde programın çalışmadığını unutmayın. Bu davaya bakmak için +3 karakter olmalı; Gerekli olup olmadığından emin değilim.

Ayrıca bunun bir O(2^n)algoritma olduğuna dikkat edin n, boş noktaların sayısı nerede . Yani, ortada bir kampanması olan 15x15 tamamen boş bir tahta için, bu çok uzun bir zaman alacak olan 2^(15*15-1)= 2.6959947e+67tamamlanması gereken süreleri alacaktır !


1

Harika: 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}

Ungolfed:

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
}

Gelmek için çok daha fazla golf ...

Çözüm yoksa 2E9 döndürür.


0

Dyalog APL , 91 bayt

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

varsayar ⎕IO=0, v16.0 ( @ve ) özelliklerinden yararlanır , çalışma süresinin .-s sayısında üstel olduğunu varsayar .

girdi değerlendirilir, karakter matrisi olmalı

'xo.'⍳x0 oile değiştirin , 1 ile, .2 ile ve diğerleri 3 ile

s←(4,4,⍨⍉)⍣2 bir matrisi 4 ile çevreleyen bir fonksiyon

a← 4 ile çevrilmiş sayısal matrisi değişkene atamak a

b←⍸2= b2'lerin (yani .-s) olduğu koordinat çiftlerinin listesidir.

(,⍳2⊣¨b)/¨⊂b elementlerin tüm kombinasyonlarını oluşturmak b

c[⍋≢¨c←...] onları boyuta göre sırala

{... :⍬⋄≢⍵}¨ Her kombinasyon için bir şeyi kontrol edin ve uzunluğunu veya boş bir listeyi döndürün

⊃∊ ilk boş olmayan sonuç

d←0@⍵⊢a dolan a0 ile ikame bazı öğeleri

4= Boole matrisi yarat - 4'ler nerede? yani eklediğimiz sınır

{...}⍣≡{}sonuç kararlı hale gelene kadar işlevi uygulamaya devam et

3∨/3∨⌿⍵ komşularıyla birlikte her bir öğeyi "boole veya"

s sonuç daha küçük olacak, bu yüzden sınırı yeniden oluşturalım

(×d)∧ Sıfır olmayan öğelerini d(duvar olmayan) bir boole maskesi olarak uygulayın

a[⍸× ...] ne abizim boolean matriste 1'ler için karşılık gelir?

1∊ Herhangi biri var omı , yani kampanyalar var mı?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.