Programmiergarten

12

Programmiergarten

Als professioneller Softwareentwickler können Sie es nicht riskieren, sich dem harten, nicht künstlichen Sonnenlicht auszusetzen, aber Sie haben auch ein Faible für Blumen und möchten Ihren Garten das ganze Jahr über in gutem Zustand halten.

Zu diesem Zweck wird jeden Monat ein Gärtner eingestellt, der das Blumenbeet am Fuße Ihres Hauses aufräumt. Sie müssen jedoch sicherstellen, dass der Gärtner seine Arbeit ordnungsgemäß erledigt, und eine angemessene Bezahlung für den hart arbeitenden Gefährten ausarbeiten. Natürlich ist eine Softwarelösung am besten.

Eingang

Ihr Programm erhält eine Eingabe, die das Blumenbeet beschreibt, wie es aktuell erscheint, sowie Details zu Elementen, die entfernt werden müssen. Das Programm muss den Garten ohne Unordnung ausgeben und eine Aufschlüsselung der Gärtnerlöhne ausdrucken. Die Eingabe kann entweder über STDIN oder als einzelnes Befehlszeilenargument erfolgen.

Die erste Eingabezeile hat das Format

width height unwanted_item_type_count

Wo widthist die Breite des Blumenbeets, heightist die Höhe des Blumenbeets (beide in ASCII-Zeichen) und unwanted_item_type_countgibt an, wie viele Zeilen mit einer Beschreibung eines Objekttyps folgen, der aus dem Garten entfernt werden soll.

Jede Zeile für jeden unerwünschten Elementtyp hat das Format

width height string_representation name fee_per_item

Dabei widthist die Breite des Elements, heightdie Höhe des Elements (beide in ASCII-Zeichen), string_representationdie Zeichenfolgendarstellung des Elements ohne Zeilenumbrüche, nameein Bezeichner für den Elementtyp (Leerzeichen werden durch Unterstriche ersetzt) ​​und fee_per_itemist, wie viel der Gärtner für die Entfernung jeder Art von Gegenständen bezahlt werden muss.

Beispielsweise

3 2 .R.\|/ rouge_flower 3

Stellt einen Elementtypnamen dar rouge_flower, dessen Entfernung 3 kostet, und sieht folgendermaßen aus:

.R.
\|/

Die Elemente enthalten keine Leerzeichen und kein Element darf einen Rahmen haben, der ausschließlich aus Punkten besteht, und die Zeichenfolgendarstellung hat auch die genaue beschriebene Größe. Daher sind alle folgenden Eingaben ungültig:

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

Beachten Sie, dass 0 eine gültige Gebühr ist (Gebühren sind immer ganze Zahlen größer als -1).

Beachten Sie auch, dass das Blumenbeet überwiegend aus Punkten ( .) und nicht aus Leerzeichen besteht und Sie Leerzeichen sicher als Begrenzung für alle Eingaben verwenden können. Das Blumenbeet wird immer von Punkten begrenzt.

Nachdem die unerwünschten Elementtypen aufgelistet wurden, wird die ASCII-Darstellung des Blumenbeets mit der angegebenen Breite und Höhe angezeigt.

Ausgabe

Die Ausgabe sollte nach STDOUT erfolgen oder eine geeignete Alternative, wenn Ihre Sprache dies nicht unterstützt.

Die Ausgabe beginnt mit einem Ausdruck des Blumenbeets, wobei jedoch alle unerwünschten Elemente entfernt (durch Punkte ersetzt) ​​werden, sodass Sie sehen können, wie sie angezeigt werden sollen, und überprüfen, ob der Gärtner seine Arbeit erledigt hat. Jeder Gegenstand im Blumenbeet wird von einem Punktrechteck umgeben und ist ein zusammenhängender Gegenstand (dh es gibt keine Trennpunkte innerhalb des Gegenstandes). Beispielsweise

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

zeigt 2 separate Artikel

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

zeigt 1 Artikel

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

ist ungültig, da der Stein (#) zwar angepasst werden kann, die Schlange (Sie konnten nicht sagen, dass es eine Schlange war?) dies nicht kann, da der Stein die erforderliche Umgebung von Punkten beeinträchtigt.

...
\@.
...

Dies ist auch ungültig, da sich die Schnecke am Rand des Blumenbeets befindet und der Rand in einer gültigen Eingabe immer durch Punkte begrenzt sein muss.

Danach sollte eine Auflistung aller Arten von unerwünschten Artikeln mit Angabe der Anzahl, der Kosten pro Artikel und der Kosten für alle Artikel (Anzahl * Kosten pro Artikel) in folgendem Format vorliegen:

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

Danach sollte es eine einzelne Zeile geben, die die Gesamtkosten (die Summe der Kosten für unerwünschte Artikel) ergibt:

total cost <total_cost>

Beispiel

Für diesen gegebenen Eingang

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

Das Programm sollte diese Ausgabe erzeugen

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

Die Ausgabe muss durch einen Zeilenumbruch abgeschlossen werden.

Dies ist Code-Golf, möge der kürzeste Code gewinnen.

Zusätzlicher Testfall

Bearbeiten: Früher enthielt dies Unicode, was im Blumenbeet nicht erlaubt ist, viel zu modern. Dies wurde behoben, tut mir leid.

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
.........................
........@................
....$..\|/...........@...
............|.......\|/..
...#.......\@/...........
.........................
.........................
......@.......@......@...
.....\|/....\\|//...\|/..
.............\|/.........
.#....................#..
.........$.......|.......
...\/.......\/..\@/..\/..
..\\//.....\\//.....\\//.
.........................

Erwartete Ausgabe:

.........................
........@................
.......\|/...........@...
....................\|/..
.........................
.........................
.........................
......@..............@...
.....\|/............\|/..
.........................
.........................
.........................
...\/.......\/.......\/..
..\\//.....\\//.....\\//.
.........................
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
VisualMelon
quelle
Dürfen wir davon ausgehen, dass der Begrenzungsrahmen jedes unerwünschten Elements genau ist? Das heißt, kein Rand in der Artikelbeschreibung ist vollständig gepunktet?
John Dvorak
@JanDvorak ja, das scheint eine vernünftige Einschränkung zu sein. Ich werde das zu der Frage hinzufügen, und ich werde Ihre Formulierung unter der Annahme ausleihen, dass es Ihnen nichts ausmacht, wenn ich das tue.
VisualMelon
Kriecht die Schnecke auch in eine andere Richtung? \@und @/zum Beispiel ... Oder müssen sie ewig nach Westen zeigen?
Han Soalone
@SickDimension Die unerwünschten Elemente sollten nur genau wie beschrieben abgeglichen werden. Unterschiedliche Drehungen und Spiegelungen sollten nicht abgeglichen werden. Dies schließt nicht aus, dass eine Schnecke in die andere Richtung kriecht, aber im Beispiel wird niemand dafür bezahlt, sie zu entfernen.
VisualMelon

Antworten:

3

Perl - 636

Es gibt definitiv noch mehr Möglichkeiten zum Golfen. Und wahrscheinlich auch bessere Möglichkeiten.

<>;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 Zeichen + 1, damit die -CFlagge die Euro handhabt.

Wenn Sie die Eingabe in gespeichert haben input.txt, können Sie sie ausführen mit:

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"}'

Hier ist die deparsed Version. Ich ging durch und fügte einige Kommentare hinzu, um die Dinge zu erklären. Vielleicht werde ich die Variablennamen irgendwann lesbarer machen. Es kann einige Randfälle geben, mit denen dies nicht funktioniert, aber es funktioniert zumindest mit den Beispielen.

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
}

Fühlen Sie sich frei, Verbesserungen vorzuschlagen!

hmatt1
quelle
Gute Arbeit, und ich fürchte, ich habe gesündigt, ich habe angegeben, dass das Blumenbeet ASCII sein soll, und dann bin ich ganz aufgeregt und habe Unicode in das Beispiel eingefügt. Ich werde das Beispiel so ändern, dass es nur ASCII ist Sie.
VisualMelon
1
@VisualMelon Es war interessant zu lernen, wie man einen Einzeiler dazu bringt, mit Unicode zu arbeiten. Ich wusste vorher nichts über die -CFlagge. Ich werde es sowieso dort belassen, um kompatibel zu sein, da es nur einen Unterschied von 1 Zeichen gibt.
hmatt1
0

Python 3, 459 Bytes

    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)

Angenommen, die Eingabe wird als Liste von Zeichenfolgen angegeben.

Triggernometrie
quelle
Ich mag den ~HTrick; Ich kann das jetzt nicht testen, aber ich werde es später heute versuchen.
VisualMelon
Ich kann nicht scheinen, dieses zu erhalten, um richtig zu laufen ( ValueError: not enough values to unpack (expected 3, got 1), Python 3.6.6); Können Sie einen TIO-Link oder eine Beschreibung zur Ausführung bereitstellen? Ich denke, es könnte die Regeln biegen, wenn man annimmt, dass sich die Eingabe in einer Zeile befindet, aber ich war mir darüber in der Frage nicht ganz im Klaren, also werde ich mich nicht beschweren.
VisualMelon
@VisualMelon - bah, ich habe wahrscheinlich etwas falsch kopiert / pastaed. Ich komme bei der Arbeit nicht zu TIO, daher überprüfe ich meine Arbeit und poste heute noch einen Link.
Triggernometrie