Ogród programisty

12

Ogród programisty

Będąc profesjonalnym programistą, nie możesz ryzykować wystawienia się na surowe, nie sztuczne światło słoneczne, ale masz również słabość do kwiatów i chcesz utrzymać ogród w dobrej formie przez cały rok.

W tym celu co miesiąc wynajmowany jest ogrodnik, aby uporządkować kwietnik u podnóża domu. Musisz jednak upewnić się, że ogrodnik prawidłowo wykonuje swoją pracę, i wypracować odpowiednią zapłatę dla ciężko pracującego faceta. Oczywiście najlepsze jest oprogramowanie.

Wejście

Twój program otrzyma dane wejściowe opisujące kwietnik, gdy wydaje się aktualny, oraz szczegóły dotyczące elementów, które należy usunąć. Program musi wydrukować ogród bez bałaganu i wydrukować zestawienie wynagrodzenia ogrodników. Dane wejściowe mogą pochodzić z STDIN lub jako pojedynczy argument wiersza poleceń.

Pierwszy wiersz wprowadzania ma format

width height unwanted_item_type_count

gdzie widthjest szerokość klombu, heightto wysokość klombu (oba w znakach ASCII) i unwanted_item_type_countinformuje, ile kolejnych wierszy będzie zawierać opis rodzaju przedmiotu, który należy usunąć z ogrodu.

Każdy wiersz dla każdego niepożądanego typu elementu ma format

width height string_representation name fee_per_item

gdzie widthjest szerokość elementu, heightjest wysokością elementu (oba w znakach ASCII), string_representationjest ciągiem znaków elementu bez podziałów linii, namejest identyfikatorem typu elementu (spacje zostaną zastąpione podkreśleniami), oraz fee_per_itemto, ile ogrodnik musi zapłacić za usunięcie każdego rodzaju przedmiotu.

Na przykład

3 2 .R.\|/ rouge_flower 3

Reprezentuje nazwę typu elementu rouge_flower, którego usunięcie kosztuje 3, i wygląda następująco:

.R.
\|/

Elementy nie będą zawierać spacji, a żaden element nie może mieć obramowania składającego się wyłącznie z kropek, a reprezentacja ciągu będzie miała dokładnie opisany rozmiar. W związku z tym wszystkie poniższe dane są nieprawidłowe:

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

Należy pamiętać, że 0 jest jednak ważną opłatą (opłaty będą zawsze liczbami całkowitymi większymi niż -1).

Zauważ również, że kwietnik składa się głównie z kropek ( .), a nie spacji, i możesz bezpiecznie używać białych znaków jako ograniczenia dla wszystkich danych wejściowych. Kwietnik jest zawsze ograniczony samymi kropkami.

Po wyświetleniu niepożądanych typów elementów pojawia się reprezentacja klombu ASCII o danej szerokości i wysokości.

Wynik

Dane wyjściowe powinny być do STDOUT lub odpowiedniej alternatywy, jeśli twój język nie obsługuje tego.

Wyjście zaczyna się od wydruku klombu, ale ze wszystkimi niechcianymi przedmiotami usuniętymi (zastąpionymi kropkami), więc możesz zobaczyć, jak powinien wyglądać i sprawdzić, czy ogrodnik wykonał swoją pracę. Każdy element w kwietniku będzie otoczony prostokątem kropek i będzie elementem jednokierunkowym (tzn. Wewnątrz elementu nie będzie żadnych oddzielających kropek ). Na przykład

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

pokazuje 2 oddzielne pozycje

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

pokazuje 1 pozycję

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

jest nieważny, ponieważ podczas gdy kamień (#) można dopasować, wąż (nie mogłeś powiedzieć, że to był wąż?) nie może, ponieważ kamień zakłóca wymagane otoczenie kropek.

...
\@.
...

Jest to również nieprawidłowe, ponieważ ślimak znajduje się na krawędzi klombu, a krawędź musi zawsze być otoczona kropkami we właściwym wejściu.

Następnie powinna zostać wyświetlona lista każdego rodzaju niechcianego elementu, podając liczbę, koszt jednej pozycji i koszty wszystkich pozycji (liczba * koszt jednej pozycji), w formacie:

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

Następnie powinna pojawić się pojedyncza linia, w której uzyskany zostanie całkowity koszt (suma kosztów niepożądanych przedmiotów):

total cost <total_cost>

Przykład

Dla tego podanego wejścia

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

Program powinien wygenerować ten wynik

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

Wyjście musi być zakończone przez przerwanie linii.

To jest gra w golfa, może wygrać najkrótszy kod.

Dodatkowa walizka testowa

Edycja: zawierało Unicode, co nie jest dozwolone w kwietniku, jest zbyt nowoczesne. Przykro nam z tego powodu.

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

Oczekiwany wynik:

.........................
........@................
.......\|/...........@...
....................\|/..
.........................
.........................
.........................
......@..............@...
.....\|/............\|/..
.........................
.........................
.........................
...\/.......\/.......\/..
..\\//.....\\//.....\\//.
.........................
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
źródło
Czy możemy założyć, że obwiednia każdego niepożądanego elementu jest dokładna? Oznacza to, że żadna ramka w opisie przedmiotu nie jest w pełni kropkowana?
John Dvorak,
@JanDvorak tak, wydaje się to dość rozsądnym ograniczeniem. Dodam to do pytania i pożyczę twoje sformułowanie, zakładając, że nie będziesz miał nic przeciwko, że to zrobię.
VisualMelon,
Czy ślimak będzie również czołgał się w innym kierunku? \@i @/na przykład ... Czy są zobowiązani wiecznie wskazywać na zachód?
Han Soalone
@SickDimension niechciane elementy powinny być dopasowane dokładnie tak, jak są opisane, wyraźne obroty i klapki nie powinny być dopasowane. Nie wyklucza to możliwości pełzania ślimaka w innym kierunku, ale nikt nie otrzymuje zapłaty za usunięcie go w przykładzie.
VisualMelon,

Odpowiedzi:

3

Perl - 636

Jest zdecydowanie więcej golfa, które można zrobić. I prawdopodobnie także lepsze sposoby, aby to zrobić.

<>;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 znaków + 1 dla -Cflagi do obsługi euro.

Jeśli masz zapisane dane wejściowe, input.txtmożesz je uruchomić za pomocą:

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

Oto wyodrębniona wersja. Przeszedłem i dodałem kilka komentarzy, które pomogą wyjaśnić różne rzeczy. Może kiedyś zmienię nazwy zmiennych na bardziej czytelne. Mogą istnieć pewne przypadki krawędzi, z którymi to nie działa, ale działa przynajmniej z przykładami.

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
}

Możesz zaproponować ulepszenia!

hmatt1
źródło
Dobra robota i obawiam się, że zgrzeszyłem, sprecyzowałem, że kwietnikiem będzie ASCII, a potem podekscytowałem się i umieściłem Unicode w przykładzie - zmienię przykład tak, aby był to tylko ASCII, przepraszam za zrobienie pracy dla ty.
VisualMelon,
1
@VisualMelon interesujące było nauczenie się, jak sprawić, by jedna linijka działała z Unicode. Nie wiedziałem wcześniej o -Cflagi. I tak zostawię to, żeby było kompatybilne, ponieważ jest to tylko 1 znak różnicy.
hmatt1
0

Python 3, 459 bajtów

    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)

Zakłada, że ​​dane wejściowe zostaną podane jako lista ciągów znaków.

Triggernometria
źródło
Lubię ~Hpodstęp; Nie mogę tego teraz przetestować, ale spróbuję to zrobić dzisiaj.
VisualMelon,
Nie wydaje mi się, aby działało poprawnie ( ValueError: not enough values to unpack (expected 3, got 1), python 3.6.6); czy możesz podać link do TIO lub opis, jak go uruchomić. Myślę, że może to być naginanie reguł, zakładając, że dane wejściowe są w jednym wierszu, ale nie byłem do końca jasny w tym pytaniu, więc nie będę narzekać.
VisualMelon,
@VisualMelon - bah, prawdopodobnie źle coś skopiowałem / z makaronem. Nie mogę dostać się do TIO w pracy, dlatego sprawdzę swoją pracę i opublikuję link później.
Triggernometry