Il governo ha una fornitura limitata di muri


28

introduzione

I golfisti esperti di codice ci hanno preparato per l'alluvione del giorno del giudizio . Le aree a rischio sono state evacuate e la popolazione si è spostata su un'altura.

Abbiamo sottovalutato il diluvio (o forse c'era un bug nel codice di @ user12345). Alcune aree d'altura si stanno avvicinando rapidamente al livello del mare. Le pareti devono essere erette per garantire la sopravvivenza degli accampamenti ora densamente popolati. Purtroppo, il governo ha un numero limitato di mura.

Problema

Il nostro scenario del giorno del giudizio è descritto da due numeri su una sola riga ne m. Seguendo quella linea ci sono nlinee con mvalori per linea, separate solo da un singolo spazio. Ogni valore sarà composto da uno di quattro caratteri.

  • xImpraticabili. L'acqua non può scorrere qui. Le pareti non possono essere erette qui.
  • -Instabile. L'acqua può scorrere attraverso questo qui. Le pareti non possono essere erette qui.
  • .Stabile. L'acqua può scorrere qui. Le pareti possono essere erette qui.
  • oAccampamento. L'acqua può scorrere qui. Se lo fa, tutti muoiono. Le mura non possono essere costruite qui.

L'acqua scorrerà da tutti i bordi della mappa, a meno che il bordo non sia impraticabile o non sia costruito un muro sulla piastrella. Scrivi un programma in grado di produrre il numero minimo di pareti richiesto per proteggere un accampamento.

Esempio di input

 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

Esempio di output

3

ipotesi

  • L'acqua scorre solo ortogonalmente
  • Gli accampamenti esistono solo come un blocco contiguo ortogonalmente per scenario
  • Una soluzione esisterà sempre (anche se potrebbe richiedere abbondanti quantità di muri)
  • Gli accampamenti non possono essere posizionati su un bordo, poiché lo scenario non avrebbe quindi soluzione
  • 2 n<<16
  • 2 m<<16
  • L'input può essere fornito da stdin, letto da "city.txt" o accettato come singolo argomento

Vince il codice più corto!


2
Sarebbe accettabile che il programma fosse corretto, ma impiegherebbe più tempo di quanto non esistesse l'universo noto per fornire una soluzione per alcuni casi del problema?
Claudiu,

@Claudiu Sono un po 'nuovo in Code Golf. Il mio requisito non è riuscito a specificare un limite di tempo, quindi uno non esiste. L'onere ricade sulla risposta per dimostrare che una soluzione è corretta per tutti i casi del problema. Se hai una soluzione che risolve alcune (ma non tutte) le istanze in modo intelligente / interessante, ti incoraggio comunque a pubblicarlo solo per divertimento.
Rainbolt

2
Il golf di codice in genere non richiede limiti di tempo.
Hosch250,

Freddo! Un altro D: è necessario che l'input sia come specificato o possiamo inserirlo in un altro modulo?
Claudiu,

@Claudiu Non posso accettare nulla al di fuori dei requisiti. Puoi, tuttavia, suggerire una modifica ai requisiti utilizzando il pulsante Modifica . Visto che non ci sono ancora risposte, probabilmente accetterò subito la modifica.
Rainbolt

Risposte:


10

Matematica, 257 253 caratteri

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

L'input viene letto da "city.txt".

Spiegazione:

Mathematica ha molte funzioni per gestire i grafici.

Innanzitutto, ho letto i dati da "city.txt".

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

Quindi costruisco un grafico a griglia con 'm' * 'n' vertici ( GridGraph@d[[1,{2,1}]]) e aggiungo ad esso un "vertice all'infinito" che è collegato a ogni vertice sui "bordi" del grafico. Questo vertice è da dove proviene l'acqua.

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

E o, xe sdenota le posizioni di "o", "x" e "." rispettivamente.

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

Quindi, per qualsiasi sottoinsieme wdi s(i sottoinsiemi sono ordinati per lunghezza), elimino i vertici tra xe wda g( VertexDelete[g,x⋃w]) e trovo la lunghezza del percorso più breve dal "vertice all'infinito" all'accampamento o. Se la lunghezza è infinita, l'accampamento sarà sicuro. Quindi la lunghezza del primo wè il numero minimo di pareti richiesto per proteggere un accampamento.

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

Bello! Ho pensato che sarei stato preso da un approccio diverso in una lingua diversa.
Claudiu,

1
Effettuare l'upgrade ma lo farei con maggiore orgoglio se spiegassi il tuo codice per il resto di noi.
Michael Stern,

Qualcuno può garantire che questa risposta è corretta o fornire un numero intero online per "Mathematica"? Problemi a trovarne uno.
Rainbolt

1
@Rusher l'ho verificato ed è solido. Non esiste un interprete online per MM, ma esiste un formato di documento CDF scaricabile che io e un paio di altri abbiamo iniziato a sperimentare per condividere soluzioni. Puoi anche ottenere Mathematica gratuitamente con il computer ARM Raspberry Pi, con l'avvertenza che sei limitato dalla potenza di calcolo della scatola. FWIW, noi utenti MM facciamo del nostro meglio per mantenerci onesti e stiamo lavorando per rendere le nostre comunicazioni più accessibili (un problema anche per Matlab, Maple, lingue MS che non funzionano su Mono, ecc.)
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);}

L'input viene dato con l'altezza e con gli argomenti della riga di comando, quindi la griglia viene letta come una singola stringa su stdin in questo modo: ./a.out 6 7 < inputdove l'input è in questa forma (da sinistra a destra, dall'alto verso il basso):

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

"Leggibile":

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

In nessun luogo breve come la soluzione di @Claudiu, ma funziona incredibilmente veloce. Invece di riempirsi di inondazioni dai bordi, trova l'accampamento e lavora verso l'esterno dai token 'o'.

  • Se incontra un terreno instabile vicino all'accampamento, espande l'accampamento su di esso.
  • Se un accampamento sulla griglia non ha almeno un muro in ogni direzione, si sposta in quella direzione fino a quando non può costruire un muro.
  • Dopo aver posizionato ogni nuova sezione di muro, ricorre per trovare la sezione di muro successiva da posizionare.

Posizionamenti di esempio a parete:

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 approccio interessante! Dà sempre la risposta più breve? ad es. quale risposta fornisce per questa mappa ? Dovrebbe essere 3 (segnato dove vanno i nuovi muri @). Ho provato a eseguire il tuo codice da solo, ma non sembra funzionare
Claudiu

Oops, sembra che il golf e l'alcool non si mescolino molto bene ... Ho giocato a golf con un comportamento indefinito. Ora dovrebbe essere riparato insieme ai 277 caratteri non necessari.
Comintern

2
@Claudiu - Vedi il mio commento sopra, i risultati per la mappa che hai pubblicato sono su pastebin.com/r9fv7tC5 . Questo dovrebbe sempre dare la risposta più breve, ma l'ho provato solo con 10 o 15 mappe che pensavo potessero presentare casi angolari. Sarei curioso di vedere se qualcuno è in grado di identificare le mappe per cui non riesce.
Comintern

4

Python, 553 525 512 449 414 404 387 368 caratteri (+4? Per invocazione)

Mi sono divertito troppo a giocare a golf. È 82 byte più grande se si tenta di comprimerlo! Questa è una misura di compattezza e mancanza di ripetizione.

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

I livelli di rientro sono spazio, tab.

Utilizzo :

Legge da 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

Invocare come segue:

$ python floodfill_golf.py 2>X
3

È 2>Xnascondere Stderr poiché il programma esce sollevando un'eccezione. Se questo è considerato ingiusto, sentiti libero di aggiungere 4 caratteri per l'invocazione.

Spiegazione :

Forza bruta semplice. Cesegue un riempimento e restituisce true se colpisce un accampamento. Nessuna imbottitura aggiuntiva poiché è stato impiegato troppo spazio per impostare correttamente l'imbottitura. D, dato un insieme di muri da riempire, chiama Cda ogni punto sul bordo in modo tale da tenere Cconto di quei muri e stampa la lunghezza ed esce se nessuno di loro ha raggiunto l'accampamento. L'elenco dei muri viene utilizzato anche per tenere traccia del riempimento dell'inondazione, quindi non è necessario copiare la scheda! Trickily, Cinoltre , aggiunge tutti i punti vuoti che trova a un elenco S, quindi la funzione Dviene anche utilizzata per costruire prima l'elenco di punti vuoti. Per questo motivo, utilizzo suminvece di any, per garantire che tutti .i messaggi vengano raccolti al primo passaggio.

Invoco Duna volta, quindi copio l'elenco dei punti vuoti in Zpoiché Scontinuerà ad essere aggiunto (inefficiente, ma più economico per il conteggio dei personaggi). Quindi uso itertools.combinationsper selezionare ogni combinazione di punti vuoti, da 0 punti in su. Corro ogni combo De stampa la lunghezza del primo che funziona, sollevando un'eccezione per uscire dal programma. Se non viene trovata alcuna risposta, non viene stampato nulla.

Si noti che attualmente, il programma non funziona se non sono necessari muri. Ci sarebbero +3 personaggi a occuparsi di questo caso; non sono sicuro se è necessario.

Si noti inoltre che questo è un O(2^n)algoritmo, in cui nè il numero di punti vuoti. Quindi, per una scheda 15x15 completamente vuota con un accampamento nel mezzo, ci vorranno 2^(15*15-1)= 2.6959947e+67iterazioni per completare, che sarà davvero molto tempo!


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}

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
}

Molto più golf a venire ...

Restituisce 2E9 se nessuna soluzione.


0

Dyalog APL , 91 byte

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

presuppone ⎕IO=0, utilizza le funzionalità della v16.0 ( @e ), il tempo di esecuzione è esponenziale nel numero di .-s

viene valutato l'input, deve essere una matrice di caratteri

'xo.'⍳ sostituire xcon 0, ocon 1,. con 2 e tutti gli altri con 3

s←(4,4,⍨⍉)⍣2 una funzione che circonda una matrice con 4s

a← assegnare una matrice numerica circondata da 4 secondi a una variabile a

b←⍸2= b è l'elenco delle coppie di coord dove i 2 (cioè il . -s)

(,⍳2⊣¨b)/¨⊂b genera tutte le combinazioni di elementi di b

c[⍋≢¨c←...] ordinali per dimensione

{... :⍬⋄≢⍵}¨ per ogni combinazione, controlla qualcosa e restituisce la sua lunghezza o un elenco vuoto

⊃∊ il primo risultato non vuoto

d←0@⍵⊢a d è a con alcuni elementi sostituiti con 0

4= crea una matrice booleana: dove sono i 4? cioè il confine che abbiamo aggiunto

{...}⍣≡ continuare ad applicare la funzione {}fino a quando il risultato non si stabilizza

3∨/3∨⌿⍵ "booleano o" ogni elemento con i suoi vicini

s il risultato sarà più piccolo, quindi ricreamo il bordo

(×d)∧ applica gli elementi diversi da zero d(i non muri) come maschera booleana

a[⍸× ...] che cosa acorrisponde agli 1 nella nostra matrice booleana?

1∊ ci sono 1, cioè oaccampamenti?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.