我们沉没还是游泳?


40

问题

甲最坏的情况是由三个数字在一行中描述,nm,和p。在该行之后是每行n具有m值的行。每个值代表每个单元格可以容纳的总水量。

以下几p行描述了接下来p几天的天气。每天有1单位降雨落在一个单元格上。如果一个单元格中的水量超过了它可以容纳的数量,该单元格就会泛洪。如果多个相邻单元格已满,则将它们视为共享公共邻居的一个单元格(单击一组空白时请考虑Minesweeper)。

  • 一个中间单元有4个邻居
  • 两个相邻的满容量中间电池被视为一个具有6个相邻电池的电池
  • 一个角单元有2个邻居
  • 一个壁单元有3个邻居

单元泛洪时,会发生泛洪事件。所有多余的水平均分配给其邻居。如果那导致一个或多个邻居泛洪,则发生另一泛洪事件。这种情况一直持续到水已经沉淀或城市完全被洪水淹没为止。

输入示例

7 5 3
3 2 3 4 5
2 2 0 3 4
1 1 2 3 3
4 1 2 2 2
4 1 1 2 2
4 4 1 2 2
4 4 2 2 2
0 0
1 2
4 3

  • 0 0 表示在第1列第1行下雨了
  • 1 2 表示在第2列第3行下了雨(可以容纳零水,立即洪水!)

经过p几天的降雨,如果城市完全被洪水淹没,请输出Sink。否则,输出Swim

示例输出

游泳

假设条件

  • 输入可以通过stdin提供,从“ city.txt”中读取或接受为参数。允许所有这三个,以免使已经发布的答案无效。
  • 水容量将为非负整数。

40多个本科生大学生团队(来自A&M,UT,LSU,Rice,Baylor等)以各种可用语言参加编程竞赛,在5个小时内无法解决此问题。因此,我不得不提到这个难题有一个陷阱,使解决方案变得微不足道。最短的代码仍然可以胜出,因为我相信最短的代码也可以解决难题。


是价值n线m还是相反?您的示例与书面规范不符。
algorithmhark

@algorithmshark已更正
Rainbolt

13
我不确定,但是在我看来,如果雨量大于所有正方形都可以容纳的总雨量,您就会下沉。否则你会漂浮。是这个吗?
Hosch250 2014年

2
@ hosch250破坏乐趣!
Rainbolt 2014年

1
“多余的水被均匀地分配给邻居。” -这可能是1单位水。它是否以0.25单位为单位分布到每个相邻的小区(假设有一个中间的淹没小区)?
尼尔·斯莱特

Answers:


16

Golfscript,37个 30个字符

新功能和改进功能,感谢PeterTaylor的提示:

~](\(@*\(@@<{+}*>"SwimSink"4/=

说明

Code                     -                                            - Stack
~]                       - parse input into an array of integers      - []
(                        - pop first number and put on stack          - [] 7
\(                       - \ swaps top two, then pop first num again  - 7 [] 5
@                        - bring 3rd down from stack to front         - [] 5 7
*                        - mult. this is grid size                    - [] 35
\(@                      - bring next # out - the days of rain        - [] 3 35
@                        - bring array out                            - 3 35 []
<                        - take first 35 elements out of array.
                           this extracts just the capacities and 
                           consumes the rest                          - 3 []
{+}*                     - fold the array using plus - this sums the
                           entire thing                               - 3 86
<                        - greater-than comparison: 3 > 86?           - 0
"SwimSink"4/             - push a string and split it to groups of 4  - 0 ["Swim" "Sink"]

=                        - index into the array using the result of
                           the comparison. if rain > capacity, then
                           sink, else swim                            - "Swim"

程序然后终止,输出堆栈。


旧版本+说明:

[~](\(@*\(@{\(@\-}*\;0>"Sink""Swim"if

Fors相同的方法,只是Golfscripted =)。可以提高效率。输入来自标准输入。

说明

Code                     -                                            - Stack
[~]                      - parse input into an array of integers      - []
(                        - pop first number and put on stack          - [] 7
\(                       - \ swaps top two, then pop first num again  - 7 [] 5
@                        - bring 3rd down from stack to front         - [] 5 7
*                        - mult. this is grid size                    - [] 35
\(@                      - bring next # out - the days of rain        - [] 3 35
{                        - define a block which...
 \(@                     - brings next number out
 \-                      - swaps and subtracts 2nd down from top
}                                                                     - [] 3 35 {}
*                        - repeat that block 35 times. this ends up
                           pulling the capacities out one by one
                           and decrementing our number-of-days 
                           number by each one                         - [] -84 
\;                       - swap and kill the array to get rid of
                           unused input                               - -84
0>"Sink""Swim"if         - if the num > 0, evaluate to "Sink", 
                           otherwise to "Swim"                        - "Swim"

然后程序输出堆栈,这只是答案。


]如果没有匹配项,[则会将整个堆栈收集到一个数组中,因此[~]可以将初始缩写简化为~]。要获取grid_size数组的第一个元素,请使用<,因此<{+}*几乎可以肯定地节省了添加总容量的时间。0>"Sink""Swim"if可以0>"SinkSwim"4/=
彼得·泰勒

@PeterTaylor:感谢您的提示!你确定~]吗?我尝试了一下,但似乎没有用。尽管必须"SwimSink"使用最后一个技巧,但仍会很好-将使用它。而且阵列事物似乎也很有前途,可以继续努力。
Claudiu 2014年

我可以肯定:这是我和其他人使用多年的标准技巧。
彼得·泰勒

@PeterTaylor:嗯,很奇怪。在链接到的解释器中尝试-它失败。然后-好的,网络解释器可能是非标准的。但是我也尝试过ruby golfscript.rb,但仍然无法使用...您能验证它是否可以正常工作吗?我在这两者上都遇到了相同的错误:undefined method '+' for nil:NilClass (NoMethodError)
克劳迪乌(Claudiu)2014年

1
当您插入字符串文字以替代缺少stdin时,应在其前面加上分号以删除实际上“来自stdin”的空字符串。这样就可以很好地工作
Peter Taylor

20

C:100 96 95个字符

n,m;main(p){scanf("%d%d%d",&n,&m,&p);for(n*=m;n--;scanf("%d",&m))p-=m;puts(p>0?"Sink":"Swim");}

五个小时?花了我五分钟。:)

阿拉加尔,谢谢您的简化!但是,我确实重新排列了main的变量声明和参数,因为如果main的第二个参数不是,则Clang抛出错误char **


3
96 -p;main(n,m){for(scanf("%d%d%d",&n,&m,&p),n*=m;n--;scanf("%d",&m),p-=m);puts(p>0?"Sink":"Swim");}
aragaer

1
95- n,m;main(p){for(scanf("%d%d%d",&n,&m,&p),n*=m;n--;scanf("%d",&m))p-=m;puts(p>0?"Sink":"Swim");}。我也玩过的想法n-=scanf,但不确定之后程序是否正确。首先scanf可以在for不更改字符数的情况下移到其前面。
aragaer 2014年

n-=scanf...因为n-=1基本上是一个预增量,所以将不起作用,因此它将错过东南角。另一个变化是巨大的。
Fors 2014年

7

Python,4行,175个字符

import sys 
F=sys.stdin
n,m,p=[int(a) for a in F.readline().split()]
print("sink") if p > sum([sum(int(x) for x in F.readline().split()) for a in range(n)]) else print("swim")

大声笑,我想知道40支以上的队伍是否在努力解决之后最终找到了收获。


10
我是40多支球队之一。失败之后我们就被抓住了。礼堂里的每个人都同时面容。我想也许我不应该在这里提到它。你们太快了!
Rainbolt 2014年

哎哟! 顺便说一句,我是否应该从stdin获得有关此类问题的输入?-我是Stackexchange的新手。:)
swalladge 2014年

我打算编辑我​​的问题,说指定STDIN,但我担心这会使您的答案无效。我在这里阅读拼图大约一个月了,还没有真正注意到人们是否指定了STDIN。
Rainbolt 2014年

1
@swalladge欢迎来到Codegolf!我建议在标题前面加上来使标题成为标题#
TimWolla 2014年

2
如果使用以下命令input(),则可以将其降低到108 map()n,_,p=map(int,input().split());print(['sink','swim'][p>sum(sum(map(int,input().split()))for a in range(n))])
Blender 2014年

6

J(50个字符)和K(40个)双重功能

原来,这两个解决方案的结构完全一样,因此它们都在这里。但是,K短了很多,这是令人惊喜的。

>Sink`Swim{~(]<[:+/[+/@".@$+1!:1@#1:)/0 2{".1!:1]1

说明:

  • ".1!:1]1 -阅读第一行,并将其转换为整数。
  • (...)/0 2{-接受索引0和2(分别为np)的项目,并将它们分别用作动词的左右参数(...)
  • +1!:1@#1:-逐行阅读n+p
  • [+/@".@$-取($)前n几行([),丢弃其余的行,然后转换为整数(".)并在每一行(+/)求和。
  • ]<[:+/-将各行的总和相加,然后将此值与正确的参数进行比较p。如果p小于总和,我们得出true 。
  • >Sink`Swim{~-选择Swim上述结果是否为true,否则为Sinkfalse。

用法:

   >Sink`Swim{~(]<[:+/[+/@".@$+1!:1@#1:)/0 2{".1!:1]1
7 5 3
3 2 3 4 5
2 0 3 3 4
1 1 2 3 3
4 1 2 2 2
4 1 1 2 2
4 4 1 2 2
4 4 2 2 2
0 0
1 2
4 3
Swim

现在是K:

`Sink`Swim@{z<+//.:'x#0::'(x+z)#`}.. 0:`

解释:

  • . 0:` -读入一行输入,并转换为整数数组。
  • {...}.-使用这三个数字n m p作为x y z此函数的参数。
  • 0::'(x+z)#`-创建x+z输入文件句柄的副本`,然后为它们中的每一行读入(0::')。
  • .:'x#-取第一x项,然后将它们转换为数字向量。
  • z<+//-将整个矩阵求和,然后进行测试,看是否大于z
  • `Sink`Swim@-返回SinkSwim根据测试是否返回true。

用法:

  `Sink`Swim@{z<+//.:'x#0::'(x+z)#`}.. 0:`
7 5 3
3 2 3 4 5
2 2 0 3 4
1 1 2 3 3
4 1 2 2 2
4 1 1 2 2
4 4 1 2 2
4 4 2 2 2
0 0
1 2
4 3
`Swim

6

APL,35

4↑'SwimSink'⌽⍨4×x[3]>+/{+/⎕}¨⍳1⌷x←⎕

不确定是否允许,但会在“城市”之后停止接受输入

x←⎕接受输入并将其存储在变量中x(以空格分隔的数字被解释为数值数组)
1⌷提取索引1(APL数组基于一个)
生成从1到参数的数组(1⌷x←⎕在这种情况下)
¨“映射”操作
{+/⎕}从输入并返回总和
+/对映射操作生成的数组求和。
4×x[3]>测试总和< x[3](返回1或0),然后乘以4
'SwimSink'⌽⍨将字符串旋转该'SwimSink'数量
4↑最后,提取字符串的前4个字符


我认为唯一重要的是,它可以为任何给定的输入输出正确的答案。如果这对于CodeGolf不常见,希望有人会告诉我。
Rainbolt 2014年

更改⎕IO←0,然后替换4↑'SwimSink'⌽⍨4×'Swim' 'Sink'⊃⍨x[3]x[2],并1⌷x具有⊃x节省两个字节。
阿达姆(Adám)'16

6

AWK,70

n{for(;NF;NF--)s+=$NF;n--}NR==1{n=$1;p=$3}END{print p<s?"Swim":"Sink"}

这是laindir对我提交的内容的改进(86):

NR==1{h=$1;w=$2;r=$3;next}NR<=h{for(i=1;i<=w;++i)c+=$i}END{print(c>r?"Swim":"Sink")}

NR<=h应该为NR<=h+1,否则将跳过最后一行容量,从而导致接收器错误。也可以缩短为70,例如n{for(;NF;NF--)s+=$NF;n--}NR==1{n=$1;p=$3}END{print p<s?"Swim":"Sink"}
laindir 2014年

1
@laindir好,非常感谢您的改进!我觉得这很有趣,Awk紧随APL,J和K之后,它们在代码高尔夫方面击败了所有人!:-)
user40989 2014年

@ user40989我不明白。Awk似乎比J / K / APL长40-100%,尽管它们不是高尔夫语言,而是商业编程语言(源自)。
阿达姆(Adám)'16

5

CoffeeScript中- 128 113

将字符串作为唯一参数的函数:

s=(l)->l=l.split /\n/;[n,m,p]=l[x=0].split /\s/;x+=c|0 for c in r.split /\s/ for r in l[1..n];`p>x?"Sink":"Swim"`

您可以删除缩进,然后将所有内容移到第一行并以分号分隔。您也写`p>x?"Sink":"Swim"`而不是if p>x then"Sink"else"Swim"。也不需要第三条语句的括号。
Konrad Borowski

4

SED,128

编写一个sed版本很有趣。它具有以下缺点:

  • 假设该城市有两列以上,以轻松识别雨线。

  • 假设每个城市的容量在0-9之间。

这里是:

1d
s/^. .$/R/
G
:a
s/[\n 0]//
/[2-9]/{s/^/C/
y/23456789/12345678/}
s/1/C/
s/0//
s/RC//
h
ta
${s/R//g
s/^Sink//
s/.*C$/Swim/
p}

-n标志呼叫。


3

SWI-Prolog 79

如果您不介意此答案是通过查询而不是通过stdin进行输入的事实:

s(A,L):-append(A,B),sumlist(B,C),length(L,D),(D>C->E='Sink';E='Swim'),print(E).

答案并没有验证输入格式,但是我认为这不是问题,因为编程竞赛也不需要您这样做。

示例查询(使用问题中的示例):

s([[3,2,3,4,5],
   [2,2,0,3,4],
   [1,1,2,3,3],
   [4,1,2,2,2],
   [4,1,1,2,2],
   [4,4,1,2,2],
   [4,4,2,2,2]],
  [(0,0),
   (1,2),
   (4,3)]).

1

蟒蛇-152

import numpy
n, m, p = map(int,raw_input('').split())
print 'swim' if p<numpy.sum(numpy.matrix(';'.join([raw_input('') for i in range(n)]))) else 'sink'

1
您可以先删除一些空格。之后,,前,后',后)...
Ry-

1

斯卡拉-128

val a=readLine.split(' ')map(_.toInt);println(if((1 to a(0)map(x=>readLine.split(' ')map(_.toInt)sum)sum)>a(2))"swim"else"sink")

也许可以省略一些括号或其他内容,但是Scala对于标点符号和无点样式以及()vs {}和诸如此类的东西真的很善变。


0

Javascript-73个字符

for(i=c=0,a=s.split(/\s/);i++<a[0]*a[1];)c+=a[2+i]*1;c>a[2]?"Swim":"Sink"

假设输入在变量中s,输出为SwimSink

例:

从原始问题开始-将其输入浏览器控制台:

s="7 5 3\n3 2 3 4 5\n2 2 0 3 4\n1 1 2 3 3\n4 1 2 2 2\n4 1 1 2 2\n4 4 1 2 2\n4 4 2 2 2\n0 0\n1 2\n4 3";
for(i=c=0,a=s.split(/\s/);i++<a[0]*a[1];)c+=a[2+i]*1;c>a[2]?"Swim":"Sink"

输出:

Swim
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.