程序员花园


12

程序员花园

作为专业的软件开发人员,您不会冒险将自己暴露在强烈的非人工阳光下,但是您对鲜花也情有独钟,并希望全年保持花园良好的状态。

为此,每个月都会雇用一名园丁来整理房子脚下的花坛。但是,您需要确保园丁工作正常,并为辛勤工作的同事制定适当的薪酬。自然,软件解决方案是最好的。

输入值

将为您的程序提供输入,以描述花坛当前的状态以及需要删除的项目的详细信息。该程序必须输出没有混乱的花园,并打印出园丁的工资明细。输入可以来自STDIN,也可以作为单个命令行参数。

输入的第一行格式为

width height unwanted_item_type_count

width花圃的宽度在哪里,花坛height的高度(都是ASCII字符),并unwanted_item_type_count告诉您接下来将出现几行,其中包含要从花园中移除的物品类型的描述。

每种不需要的商品类型的每一行的格式为

width height string_representation name fee_per_item

其中width是项目的宽度,是项目height的高度(均以ASCII字符表示),string_representation是不带换行符的项目的字符串表示形式,是项目name类型的标识符(空格将由下划线替换),以及fee_per_item是指园丁为清除每种物品而需要支付的费用。

例如

3 2 .R.\|/ rouge_flower 3

表示name的项目类型,该项目类型rouge_flower需要花费3来删除,如下所示:

.R.
\|/

这些项目将不包含空格,并且任何项目都不能具有完全由点组成的边框,并且字符串表示形式也将是所述的确切大小。因此,以下所有都是无效输入:

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

请注意,0是有效费用(费用始终是大于-1的整数)。

还要注意,花坛主要由点(.)而不是空格组成,您可以放心地将空格用作所有输入的定界。花坛总是以点本身为界。

列出不需要的项目类型之后,然后是给定宽度和高度的花坛的ASCII表示形式。

输出量

输出应该输出到STDOUT,或者如果您的语言不支持,则输出到STDOUT。

输出从花坛的打印输出开始,但是所有不需要的物品都被删除(用圆点代替),因此您可以看到它的外观并检查园丁的工作。花坛中的每个项目都将由一个矩形的点包围,并且将是一个连续的项目(即,项目内部没有分隔的点)。例如

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

显示2个单独的项目

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

显示1项

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

是无效的,因为可以匹配石头(#),但蛇(您不能说它是蛇吗?)不能匹配,因为石头会干扰所需的点周围。

...
\@.
...

这也是无效的,因为蜗牛位于花坛的边缘,并且该边缘必须始终由有效输入中的点包围。

此后,应列出每种类型的不需要的物品,并以以下格式给出计数,每件物品的成本以及所有物品的成本(计数*每件物品的成本):

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

在此之后,应该有一行显示总成本(不需要的项目的成本之和):

total cost <total_cost>

对于此给定的输入

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

程序应产生此输出

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

输出必须以换行符终止。

这是代码高尔夫球,请以最短的代码为准。

附加测试用例

编辑:这曾经包含Unicode,这在花坛中是不允许的,太现代了。这已得到纠正,对此感到抱歉。

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

预期产量:

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

我们是否可以假设每个不需要的项目的边界框都是准确的?也就是说,商品说明中的边框没有全点吗?
John Dvorak 2014年

@JanDvorak是的,这似乎是一个足够合理的约束。我将其添加到问题中,并且我将借用您的措辞,以为您不介意我这样做。
VisualMelon 2014年

蜗牛也会向不同方向爬行吗?\@@/例如..或者,他们必然要永远点向西?
Han Soalone 2014年

@SickDimension不需要的项目仅应按照它们所描述的精确匹配,不同的旋转和翻转不应匹配。这并不排除蜗牛会向另一个方向爬行的可能性,但是在该示例中没有人支付将其删除的费用。
VisualMelon 2014年

Answers:


3

Perl-636

肯定还有更多的高尔夫运动可以做。可能还有更好的方法。

<>;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个字符+ 1个-C标志来处理欧元。

如果您存储了输入,则input.txt可以使用以下命令运行它:

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

这是已删除的版本。我仔细阅读并添加了一些评论以帮助解释问题。也许我会在某个时候使变量名更具可读性。在某些情况下可能无法使用,但至少可以在示例中使用。

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
}

随时提出改进建议!


做得很好,我怕自己犯了错,我确实指定花圃是ASCII,然后激动不已,将Unicode放入示例中-我将更改示例,使其仅是ASCII,抱歉为您。
VisualMelon 2014年

1
@VisualMelon很有趣,学习如何使单行代码与unicode一起工作。-C在此之前,我不知道该标志。我将其保留在那里以兼容,因为它只有1个字符的差异。
hmatt1 2014年

0

Python 3,459字节

    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)

假设输入将以字符串列表形式给出。


我喜欢这个~H把戏。我现在无法测试,但今天晚些时候将尝试进行测试。
VisualMelon

我似乎无法使其正常运行(ValueError: not enough values to unpack (expected 3, got 1),python 3.6.6);您能否提供TIO链接或有关如何运行它的一些说明。我认为通过假设所有输入都在一行上可能会弯折规则,但是我对这个问题并不完全清楚,所以我不会抱怨。
VisualMelon

@VisualMelon-h,我可能复制/粘贴了不正确的内容。我上班无法到TIO,所以我将检查工作并在今天晚些时候发布链接。
Triggernometry '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.