Taman Programmer

12

Taman Programmer

Menjadi pengembang perangkat lunak profesional, Anda tidak bisa mengambil risiko mengekspos diri terhadap sinar matahari non-artifisial yang keras, tetapi Anda juga memiliki titik lemah untuk bunga, dan ingin menjaga taman Anda dalam kondisi yang baik sepanjang tahun.

Untuk tujuan ini, seorang tukang kebun disewa setiap bulan untuk merapikan petak bunga di kaki rumah Anda. Namun Anda perlu memastikan tukang kebun melakukan pekerjaannya dengan benar, dan mencari pembayaran yang sesuai untuk rekan kerja yang bekerja keras. Secara alami solusi perangkat lunak adalah yang terbaik.

Memasukkan

Program Anda akan diumpankan input yang menggambarkan petak bunga seperti yang terlihat saat ini, dan detail item yang perlu dihapus. Program ini harus menampilkan taman tanpa kekacauan, dan mencetak rincian upah tukang kebun. Input dapat berupa dari STDIN, atau sebagai argumen baris perintah tunggal.

Baris input pertama adalah format

width height unwanted_item_type_count

di mana widthlebar petak bunga, heightadalah tinggi petak bunga (keduanya dalam karakter ASCII), dan unwanted_item_type_countmemberi tahu Anda berapa banyak garis akan mengikuti yang berisi deskripsi jenis item yang akan dihapus dari kebun.

Setiap baris untuk setiap jenis item yang tidak diinginkan adalah format

width height string_representation name fee_per_item

di mana widthlebar item, heightadalah ketinggian item (baik dalam karakter ASCII), string_representationadalah representasi string dari item tanpa jeda baris, nameadalah pengidentifikasi untuk jenis item (spasi akan diganti dengan garis bawah), dan fee_per_itemadalah berapa banyak tukang kebun harus dibayar untuk menghilangkan setiap jenis barang.

Sebagai contoh

3 2 .R.\|/ rouge_flower 3

Merupakan jenis item nama rouge_flower, yang biaya 3 untuk dihapus, dan terlihat seperti ini:

.R.
\|/

Item tidak akan berisi spasi, dan tidak ada item yang memiliki batas yang seluruhnya terdiri dari titik-titik, dan representasi string juga akan menjadi ukuran yang tepat seperti yang dijelaskan. Karenanya, semua yang berikut ini adalah input yang tidak valid:

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

Perhatikan bahwa 0 adalah biaya yang valid (biaya akan selalu bilangan bulat lebih besar dari -1).

Perhatikan juga bahwa petak bunga sebagian besar terdiri dari titik ( .) daripada spasi, dan Anda dapat menggunakan spasi dengan aman sebagai batasan untuk semua input. Petak bunga selalu dibatasi oleh titik-titik itu sendiri.

Setelah jenis item yang tidak diinginkan dicantumkan, maka muncul representasi ASCII dari petak bunga dengan lebar dan tinggi tertentu.

Keluaran

Outputnya harus STDOUT, atau alternatif yang sesuai jika bahasa Anda tidak mendukungnya.

Output dimulai dengan print-out dari petak bunga, tetapi dengan semua item yang tidak diinginkan dihapus (diganti dengan titik-titik), sehingga Anda dapat melihat bagaimana seharusnya muncul dan memeriksa tukang kebun telah melakukan tugasnya. Setiap item di petak bunga akan dikelilingi oleh titik persegi panjang, dan akan menjadi item yang bersebelahan (yaitu tidak akan ada titik pemisah di dalam item). Sebagai contoh

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

menunjukkan 2 item terpisah

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

menunjukkan 1 item

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

tidak valid, karena sementara batu (#) dapat dicocokkan, ular (Anda tidak bisa mengatakan itu adalah ular?) tidak bisa karena batu itu mengganggu persyaratan titik yang mengelilingi.

...
\@.
...

Ini juga tidak valid, karena siput berada di tepi petak bunga, dan ujung harus selalu dibatasi oleh titik-titik dalam input yang valid.

Setelah ini, harus ada daftar setiap jenis barang yang tidak diinginkan, memberikan perhitungan, biaya per item, dan biaya untuk semua item (jumlah * biaya per item), dalam format:

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

Setelah ini, harus ada satu baris menghasilkan total biaya (jumlah biaya untuk item yang tidak diinginkan):

total cost <total_cost>

Contoh

Untuk input yang diberikan ini

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

Program harus menghasilkan output ini

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

Output harus diakhiri oleh line-break.

Ini kode-golf, semoga kode terpendek menang.

Kasing uji tambahan

Sunting: ini digunakan untuk memuat Unicode, yang tidak diizinkan di petak bunga, terlalu modern. Ini sudah diperbaiki, maaf soal itu.

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

Output yang Diharapkan:

.........................
........@................
.......\|/...........@...
....................\|/..
.........................
.........................
.........................
......@..............@...
.....\|/............\|/..
.........................
.........................
.........................
...\/.......\/.......\/..
..\\//.....\\//.....\\//.
.........................
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
sumber
Bolehkah kita menganggap kotak pembatas setiap item yang tidak diinginkan adalah tepat? Artinya, tidak ada batas dalam uraian item yang sepenuhnya titik?
John Dvorak
@ JanDvorak ya, itu sepertinya kendala yang cukup masuk akal. Saya akan menambahkan itu ke pertanyaan, dan saya akan meminjam kata-kata Anda dengan anggapan bahwa Anda tidak keberatan saya melakukannya.
VisualMelon
Apakah siput akan merangkak ke arah yang berbeda juga? \@dan @/misalnya .. Atau apakah mereka terikat untuk menunjuk ke barat selamanya?
Han Soalone
@SickDimension item yang tidak diinginkan hanya harus dicocokkan persis seperti yang dijelaskan, rotasi dan flips yang berbeda tidak boleh dicocokkan. Ini tidak menghalangi kemungkinan bahwa siput akan merangkak ke arah lain, tetapi tidak ada yang dibayar untuk menghapusnya dalam contoh.
VisualMelon

Jawaban:

3

Perl - 636

Pasti ada beberapa golf lagi yang bisa dilakukan. Dan mungkin cara yang lebih baik untuk melakukannya juga.

<>;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 karakter +1 untuk -Cbendera untuk menangani euro.

Jika Anda memiliki input yang tersimpan di input.txtdalamnya, Anda dapat menjalankannya dengan:

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

Ini adalah versi yang sudah dihapus. Saya membaca dan menambahkan beberapa komentar untuk membantu menjelaskan berbagai hal. Mungkin saya akan membuat nama variabel lebih mudah dibaca kapan-kapan. Mungkin ada beberapa kasus tepi yang tidak bekerja dengan ini, tetapi setidaknya berfungsi dengan contoh.

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
}

Jangan ragu untuk menyarankan peningkatan!

hmatt1
sumber
Kerja bagus, dan saya khawatir saya telah berdosa, saya memang menentukan bahwa petak bunga akan menjadi ASCII, dan kemudian menjadi bersemangat dan memasukkan Unicode dalam contoh - Saya akan mengubah contoh sehingga hanya ASCII, maaf karena membuat pekerjaan untuk kamu.
VisualMelon
1
@VisualMelon itu menarik untuk belajar cara mendapatkan satu-liner untuk bekerja dengan unicode. Saya tidak tahu tentang -Cbendera sebelum ini. Saya akan membiarkannya di sana agar tetap kompatibel karena perbedaannya hanya 1 karakter.
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)

Mengasumsikan input akan diberikan sebagai daftar string.

Triggernometri
sumber
Saya suka ~Htriknya; Saya tidak dapat menguji ini sekarang, tetapi saya akan mencoba melakukannya hari ini.
VisualMelon
Sepertinya saya tidak bisa menjalankan ini dengan benar ( ValueError: not enough values to unpack (expected 3, got 1), python 3.6.6); dapatkah Anda memberikan tautan TIO atau deskripsi tentang cara menjalankannya. Saya pikir itu mungkin membengkokkan aturan dengan mengasumsikan input semua pada satu baris, tetapi saya tidak sepenuhnya jelas tentang hal itu dalam pertanyaan jadi saya tidak akan mengeluh.
VisualMelon
@VisualMelon - bah, saya mungkin salah menyalin / menempelkan sesuatu. Saya tidak dapat membuka TIO di tempat kerja, jadi saya akan memeriksa pekerjaan saya dan mengirim tautan hari ini.
Triggernometri