Giardino dei programmatori


12

Giardino dei programmatori

Essendo uno sviluppatore di software professionale, non puoi rischiare di esporsi alla dura luce non artificiale del sole, ma hai anche un debole per i fiori e vuoi mantenere il tuo giardino in forma tutto l'anno.

A tal fine, un giardiniere viene assunto ogni mese per riordinare l'aiuola ai piedi della tua casa. Tuttavia, è necessario assicurarsi che il giardiniere stia svolgendo correttamente il proprio lavoro e elaborare un pagamento adeguato per il duro lavoratore. Naturalmente una soluzione software è la migliore.

Ingresso

Il tuo programma riceverà input che descrivono l'aiuola come appare attuale e i dettagli degli elementi che devono essere rimossi. Il programma deve produrre il giardino privo del disordine e stampare una ripartizione della retribuzione dei giardinieri. L'input può provenire da STDIN o come singolo argomento della riga di comando.

La prima riga di input è del formato

width height unwanted_item_type_count

dove widthè la larghezza dell'aiuola, heightè l'altezza dell'aiuola (entrambi in caratteri ASCII) e unwanted_item_type_countti dice quante righe seguiranno contenenti una descrizione di un tipo di oggetto da rimuovere dal giardino.

Ogni riga per ogni tipo di elemento indesiderato è nel formato

width height string_representation name fee_per_item

dove widthè la larghezza dell'elemento, heightè l'altezza dell'elemento (entrambi in caratteri ASCII), string_representationè la rappresentazione in forma di stringa dell'articolo senza interruzioni di riga, nameè un identificatore per il tipo di elemento (gli spazi verranno sostituiti con caratteri di sottolineatura) e fee_per_itemè quanto deve pagare il giardiniere per la rimozione di ogni tipo di oggetto.

Per esempio

3 2 .R.\|/ rouge_flower 3

Rappresenta un tipo di elemento di nome rouge_flower, che costa 3 da rimuovere e si presenta così:

.R.
\|/

Gli elementi non conterranno spazi e nessun articolo può avere un bordo costituito interamente da punti e la rappresentazione della stringa avrà anche la dimensione esatta descritta. Pertanto, tutti i seguenti sono input non validi:

3 1 ( ) space 0
1 1 . dot 0
2 1 .! bang 0
3 2 .@.\|/. plant 0

Si noti che 0 è tuttavia una commissione valida (le commissioni saranno sempre numeri interi superiori a -1).

Nota anche che l'aiuola è prevalentemente costituita da punti ( .) piuttosto che da spazi, e puoi tranquillamente usare gli spazi bianchi come delimitazione per tutti gli input. L'aiuola è sempre delimitata dai punti stessi.

Dopo aver elencato i tipi di oggetti indesiderati, arriva la rappresentazione ASCII dell'aiuola di data larghezza e altezza.

Produzione

L'output dovrebbe essere su STDOUT, o alternativa adatta se la tua lingua non lo supporta.

L'output inizia con una stampa dell'aiuola, ma con tutti gli elementi indesiderati rimossi (sostituiti con punti), quindi puoi vedere come dovrebbe apparire e verificare che il giardiniere abbia fatto il suo lavoro. Ogni oggetto nell'aiuola sarà circondato da un rettangolo di punti e sarà un oggetto contiguo (cioè non ci saranno punti di separazione all'interno dell'elemento). Per esempio

.....
.#.#.
.....

mostra 2 elementi separati

.....
.\@/.
.....

mostra 1 oggetto

......
.#....
....|.
....|.
.o--/.
......

non è valido, poiché mentre la pietra (#) può essere abbinata, il serpente (non si può dire che fosse un serpente?) non può perché la pietra interferisce con il necessario circondamento di punti.

...
\@.
...

Anche questo non è valido, poiché la lumaca si trova sul bordo dell'aiuola e il bordo deve sempre essere delimitato da punti in un input valido.

Successivamente, dovrebbe essere presente un elenco di ciascun tipo di articolo indesiderato, che fornisce il conteggio, il costo per articolo e i costi per tutti gli articoli (conteggio * costo per articolo), nel formato:

<count> <name> at <cost_per_item> costs <cost>

Dopo questo, dovrebbe esserci una sola riga che fornisce il costo totale (la somma dei costi per gli articoli indesiderati):

total cost <total_cost>

Esempio

Per questo dato input

25 18 3
4 2 .\/.\\// weeds 5
2 1 \@ snails 2
1 1 # stones 1
.........................
.\@/.................\@..
............\/...........
......O....\\//..^|^.....
.#...\|/.........^|^.....
..................|......
.................\|/.....
..\@.....\/...........#..
........\\//....#........
....*....................
...\|/......\/......\@/..
...........\\//..........
..................*......
.......\@/.......\|/.....
...O.....................
..\|/.......*............
.......#...\|/....\@.....
.........................

Il programma dovrebbe produrre questo output

.........................
.\@/.....................
.........................
......O..........^|^.....
.....\|/.........^|^.....
..................|......
.................\|/.....
.........................
.........................
....*....................
...\|/..............\@/..
.........................
..................*......
.......\@/.......\|/.....
...O.....................
..\|/.......*............
...........\|/...........
.........................
3 weeds at 5 costs 15
3 snails at 2 costs 6
4 stones at 1 costs 4
total cost 25

L'output deve essere terminato da un'interruzione di riga.

Questo è code-golf, può vincere il codice più corto.

Caso di prova aggiuntivo

Modifica: usato per contenere Unicode, che non è consentito nell'aiuola, troppo moderno. Questo è stato corretto, mi dispiace per quello.

25 15 5
5 3 ..@..\\|//.\|/. overgrown_plants 3
5 3 @-o....|...\|/. semi-articulated_plant 4
3 2 .|.\@/ mutant_plants 5
1 1 $ dollars 0
1 1 # stones 1
.........................
........@................
....$..\|/...........@...
............|.......\|/..
...#.......\@/...........
.........................
.........................
......@.......@......@...
.....\|/....\\|//...\|/..
.............\|/.........
.#....................#..
.........$.......|.......
...\/.......\/..\@/..\/..
..\\//.....\\//.....\\//.
.........................

Uscita prevista:

.........................
........@................
.......\|/...........@...
....................\|/..
.........................
.........................
.........................
......@..............@...
.....\|/............\|/..
.........................
.........................
.........................
...\/.......\/.......\/..
..\\//.....\\//.....\\//.
.........................
1 overgrown_plants at 3 costs 3
0 semi-articulated_plants at 4 costs 0
2 mutant_plants at 5 costs 10
2 dollars at 0 costs 0
3 stones at 1 costs 3
total cost 16

Possiamo supporre che il rettangolo di selezione di ciascun elemento indesiderato sia esatto? Cioè, nessun bordo nella descrizione dell'articolo è interamente punti?
John Dvorak,

@JanDvorak sì, sembra un vincolo abbastanza ragionevole. Lo aggiungerò alla domanda e prenderò in prestito le tue parole sulla presunzione che non ti dispiacerà che io lo faccia.
VisualMelon,

La lumaca striscia anche in una direzione diversa? \@e @/per esempio .. O sono tenuti a puntare eternamente a ovest?
Han Soalone,

@SickDimensiona gli oggetti indesiderati devono essere abbinati esattamente come sono descritti, non devono essere abbinati rotazioni e lanci distinti. Ciò non esclude la possibilità che una lumaca striscia nell'altra direzione, ma nessuno viene pagato per rimuoverlo nell'esempio.
VisualMelon,

Risposte:


3

Perl - 636

C'è sicuramente un po 'più di golf che si può fare. E probabilmente anche modi migliori per farlo.

<>;while(<>){if(/ /){chomp;push@v,$_}else{$t.=$_}}for(@v){r(split/ /)}say$t.$y."total cost $u";sub r{my($e,$w,$c,$h,$z)=@_;($i,$f,$q,$d)=(1,0,0,"."x$e);@m=($c=~/($d)/g);@l=split/\n/,$t;while($i>0){($g,$j)=(1,0);for(0..$#l){if($j==0&&$l[$_]=~/^(.*?)\.\Q$m[$j]\E\./){$j++;$l="."x length$1}elsif($j<@m&&$l[$_]=~/^$l\.\Q$m[$j]\E\./){$j++}elsif($j>0){$l[$_-1]=~s!.\Q$m[$j-1]\E.!" ".$m[$j-1]=~s/\./ /gr." "!e;($j,$g)=(0,0)}if($j==@m){$k=$j;for($f=$_;$f>$_-$j;$f--){$k--;$o="."x length$m[$k];$l[$f]=~s/^($l)\.\Q$m[$k]\E\./$1.$o./}($g,$j)=(0,0);$q++}}if($g){$i--}}$t=join("\n",@l)."\n";$t=~s/ /./g;$p=$z*$q;$u+=$p;$y.="$q $h at $z costs $p\n"}

635 caratteri + 1 per la -Cbandiera per gestire gli euro.

Se si dispone dell'ingresso memorizzato, input.txtè possibile eseguirlo con:

cat input.txt | perl -C -E'<>;while(<>){if(/ /){chomp;push@v,$_}else{$t.=$_}}for(@v){r(split/ /)}say$t.$y."total cost $u";sub r{my($e,$w,$c,$h,$z)=@_;($i,$f,$q,$d)=(1,0,0,"."x$e);@m=($c=~/($d)/g);@l=split/\n/,$t;while($i>0){($g,$j)=(1,0);for(0..$#l){if($j==0&&$l[$_]=~/^(.*?)\.\Q$m[$j]\E\./){$j++;$l="."x length$1}elsif($j<@m&&$l[$_]=~/^$l\.\Q$m[$j]\E\./){$j++}elsif($j>0){$l[$_-1]=~s!\Q$m[$j-1]\E!$m[$j-1]=~s/\./ /gr!e;($j,$g)=(0,0)}if($j==@m){$k=$j;for($f=$_;$f>$_-$j;$f--){$k--;$o="."x length$m[$k];$l[$f]=~s/^($l)\.\Q$m[$k]\E\./$1.$o./}($g,$j)=(0,0);$q++}}if($g){$i--}}$t=join("\n",@l)."\n";$t=~s/ /./g;$p=$z*$q;$u+=$p;$y.="$q $h at $z costs $p\n"}'

Ecco la versione deparsed. Ho esaminato e aggiunto alcuni commenti per aiutare a spiegare le cose. Forse andrò a rendere più leggibili i nomi delle variabili qualche volta. Potrebbero esserci alcuni casi limite con cui questo non funziona ma funziona almeno con gli esempi.

BEGIN { # These are the features we get with -C and -E flags
    $^H{'feature_unicode'} = q(1); # -C gives us unicode
    $^H{'feature_say'} = q(1); # -E gives us say to save 1 character from print
    $^H{'feature_state'} = q(1);
    $^H{'feature_switch'} = q(1);
}
<ARGV>; # throw away the first line
while (defined($_ = <ARGV>)) { # read the rest line by line
    if (/ /) { # if we found a space (the garden doesn't have spaces in it)
        chomp $_; # remove the newline
        push @v, $_; # add to our array
    }
    else { # else, we construct the garden
        $t .= $_;
    }
}
foreach $_ (@v) { # call the subroutine r by splitting our input lines into arguments
    r(split(/ /, $_, 0)); # the arguments would be like r(3,2,".R.\|/","rouge_flower",3)
}
say $t . $y . "total cost $u"; # print the cost at the end

# this subroutine removes weeds from the garden and counts them
sub r {
    BEGIN {
        $^H{'feature_unicode'} = q(1);
        $^H{'feature_say'} = q(1);
        $^H{'feature_state'} = q(1);
        $^H{'feature_switch'} = q(1);
    }
    my($e, $w, $c, $h, $z) = @_; # get our arguments
    ($i, $f, $q, $d) = (1, 0, 0, '.' x $e); # initialize some variables
    @m = $c =~ /($d)/g; # split a string like this .R.\|/ into .R. and \|/
    @l = split(?\n?, $t, 0); # split the garden into lines to process line by line
    while ($i > 0) {
        ($g, $j) = (1, 0);
        foreach $_ (0 .. $#l) { # go through the garden
            if ($j == 0 and $l[$_] =~ /^(.*?)\.\Q$m[$j]\E\./) { # this matches the top part of the weed. \Q and \E make it so the weed isn't intepreted as a regex. Capture the number of dots in front of it so we know where it is
                ++$j;
                $l = '.' x length($1); # this is how many dots we have
            }
            elsif ($j < @m and $l[$_] =~ /^$l\.\Q$m[$j]\E\./) { # capture the next line
                ++$j;
            }
            elsif ($j > 0) { # if we didn't match we have to reset
                $l[$_ - 1] =~ s[.\Q$m[$j - 1]\E.][' ' . $m[$j - 1] =~ s/\./ /rg . ' ';]e; # this line replaces the dots next to the weed and in the weed with spaces
                # to mark it since it didn't work but the top part matches
                # that way when we repeat we go to the next weed
                ($j, $g) = (0, 0);
            }
            if ($j == @m) { # the whole weed has been matched
                $k = $j;
                for ($f = $_; $f > $_ - $j; --$f) { # remove the weed backwards line by line
                    --$k;
                    $o = '.' x length($m[$k]);
                    $l[$f] =~ s/^($l)\.\Q$m[$k]\E\./$1.$o./; 
                }
                ($g, $j) = (0, 0);
                ++$q;
            }
        }
        if ($g) {
            --$i; # all the weeds of this type are gone
        }
    }
    $t = join("\n", @l) . "\n"; # join the garden lines back together
    $t =~ s/ /./g; # changes spaces to dots 
    $p = $z * $q; # calculate cost
    $u += $p; # add to sum
    $y .= "$q $h at $z costs $p\n"; #get message
}

Sentiti libero di suggerire miglioramenti!


Bel lavoro, e temo di aver peccato, ho specificato che l'aiuola sarebbe ASCII, quindi mi sono emozionato e ho inserito l'esempio Unicode - Cambierò l'esempio in modo che sia solo ASCII, mi dispiace per aver lavorato per voi.
VisualMelon,

1
@VisualMelon è stato interessante imparare come far funzionare un one-liner con Unicode. -CPrima non conoscevo la bandiera. Lo lascerò lì per essere compatibile comunque poiché è solo una differenza di 1 carattere.
hmatt1,

0

Python 3, 459 byte

    from re import*
E=input()
W,H,C=map(int,E[0].split())
B,T,O='\n'.join(E[~H:]),0,''
for L in E[1:~H]:
 w,h,s,n,c=L.split();w,h,c=map(int,(w,h,c));r,t='.'*(w+2),0;a=[r]+['.%s.'%s[i:i+w]for i in range(0,w*h,w)]+[r]
 for L in['(%s)'%'\\n'.join('.{%d})%s(.*'%(i,escape(b))for b in a)for i in range(W)]:t+=len(findall(L,B));B=sub(L,r.join('\\%d'%b for b in range(1,h+4)),B,MULTILINE)
 O+='%d %s at %d costs %d\n'%(t,n,c,t*c);T+=t*c
print(B+O+'total cost',T)

Presuppone che l'input verrà fornito come un elenco di stringhe.


Mi piace il ~Htrucco; Non posso provarlo ora, ma proverò a farlo più tardi oggi.
VisualMelon

Non riesco a farlo funzionare correttamente ( ValueError: not enough values to unpack (expected 3, got 1), python 3.6.6); puoi fornire un link TIO o una descrizione su come eseguirlo. Penso che potrebbe piegare le regole supponendo che l'input sia tutto su una riga, ma non ero del tutto chiaro a riguardo nella domanda, quindi non mi lamento.
VisualMelon

@VisualMelon - bah, probabilmente ho copiato / incollato qualcosa in modo errato. Non riesco ad accedere a TIO al lavoro, quindi controllerò il mio lavoro e pubblicherò un link più tardi oggi.
Triggernometria
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.