今天下雨


42

语境

今天是情人节。昨天,你所爱的唯一一个人离开了你,成为了这个她总是觉得“愚蠢而无趣”的家伙。在回家的路上,您一直处于交通阻塞状态,在收音机上听老歌,挡风玻璃上的雨水使您不寒而栗。在车上待了一会儿之后,您发现自己独自呆在小公寓里,除了她以外,别无其他。没有光,你凝视着窗户,让黑暗环绕着你。没有人可以和您聊天,您的朋友很早以前就离开了,因为警告您这个新女孩困扰您。启动计算机,这是您唯一的操作,打开浏览器并发布新的编程难题以进行stackexchange,以改变您的想法。

挑战

用您选择的语言编写一个程序,模拟地面上的雨水。输出可以由ASCII字符或呈现的2D / 3D组成。相机是固定的:您在上面直视地面。您的程序必须包含某种动画,例如每次生成新的“框架”时刷新控制台或页面。它必须是现实的,我知道这有点主观,但是可以说,您不能仅一滴之滴就填满整个领域。

输出不一定要是图像,但是如果您使用的是隐秘语言,则最好提供一个.gif来说明其实际效果(但是,如果您不这样做,它当然不会影响您的分数)。

规则

  • 您的分数是使用的总字节数
  • 如果使用颜色,则为-20分
  • -50如果达到渲染效果
  • 最低分获胜

一个基本的示例,应呈现:

希望您会做得更好,并享受这一挑战。

对不起,我的英语,如果您要更正一些错误,请随时编辑我的帖子

排行榜

如果未列出您的名字,那是因为您的尝试被认为不符合规则。

Tobia - APL - 35  
j6m8 - Processing.js - 38
The Guy with The Hat - Processing - 42  
ace - Processing - 74  
kelunik - JS/CSS - 89  
Riot - Bash - 91  
Michael - JS/jQuery - 105  
Florent - HTML/JS - 123  
David Carraher - Mathematica - 134  
Doorknob - HTML/JS - 150  
undergroundmonorail - Python - 175

恭喜托比亚!


51
我衷心希望第一段不是一个真实的故事。
肯德尔·弗雷

1
@DavidCarraher是的,就像您在天空中看着地板一样。

8
我认为这不应该成为代码问题,因为潜在输出内容过于宽大
Cruncher 2014年

4
第一段以及此渲染的摄影机位置非常惊人。
Tobia

Answers:


26

APL,105个字符/字节* – 20 – 50 = 35分

e←{⍞←∊'␛['⍵}
e¨'36m' '?25l' '2J'
{⍵←3⌊⍵+3×0=?t⍴50
⍵{(⍵c)←⍕¨⍵+1
e⍵';'c'H',' .∘⍟'[⍺]}¨⍳t
∇0⌈⍵-1}0⍴⍨t←24 80

*:大多数APL实现都支持某种形式的(旧式)单字节字符集,该字符集将APL符号映射到高128个字节的值。因此,出于打高尔夫球的目的,仅使用ASCII字符和APL符号的程序可以记为chars = bytes。

我在OS X终端中在Node.js 上Nick的最新apl.js上对其进行了测试。但是我还没有使用他的方言专用的东西,因此它应该可以在任何可以在ANSI终端上运行并支持d-funs {...},链分配(a b)←...和通勤的现代APL上运行,例如Linux或Raspberry PI的Dyalog(与⎕IO←0

1行中的文字是转义字符(1个字节)。您可以Ctrl-V Esc在Linux终端或Vim中使用输入,也可以Alt-027在Windows中输入。另外,我找不到可靠的方法来发现终端大小,因此您可能要编辑最后一行末尾的行数和列数。

我捍卫50分奖金的事实是,每个雨滴都经过以下形状:⍟∘.考虑到从上方观看场景,给人的感觉是略微向下的风。实际上,查看下面的gif图像,您应该得到的印象是,每滴墨滴在地上消失之前都是缓慢地向下和向左移动。

非高尔夫版本:

e←{⍞←∊"␛["⍵}                  # utility to print escape sequence
e¨'36m' '?25l' '2J'            # set cyan, hide the cursor and clear screen
{                              # repeat (⍵=current board of raindrops)
  ⍵←3⌊⍵+3×0=?t⍴50              #   add some new drops (=3) in random places
  ⍵{                           #   print the drops (⍺=drop value, ⍵=coords)
    (r c)←⍕¨⍵+1                #     convert the coordinates to string
    e r';'c'H',' .∘⍟'[⍺]       #     print or clear the drop
  }¨⍳t                         #   ..
  ∇0⌈⍵-1                       #   remove 1 from every drop and repeat
}0⍴⍨t←24 80                    # ..starting with an empty board

输出:

在此处输入图片说明


APL,不同风格

出于竞争。

m←×/t←1+(ζη)←2×(βγ)←24 80
e←{⍞←∊(⎕UCS 27)'['⍵}
s←{⍵[β-1-⍳β;1+⍳γ]}
p←{⍺{e'H'⍺,⍨{⍺,';',⍵}/⍕¨⍵}¨(,s⍵)/,1+⍳βγ}
e¨'2J' '36m' '?25l'
{'/'p⍵←(200<m÷?t⍴m)∨0⍪⍵[⍳ζ;1+⍳η],0
' 'p(~⍵)∧0,⍵[1+⍳ζ;⍳η]⍪0
'.∘°'[?(+/,sδ)/3]pδ←⍵∧~d←.2<m÷⍨?t⍴m
∇⍵∧d}t⍴0

在这里,我的目的是给人以雨滴倾斜而积聚在地面上的印象,同时力求使可见的雨滴数量(平均下降或溅落)保持平均。诀窍是/在每个循环中创建许多新的下落滴,并使下落滴“擦掉”它们经过的所有飞溅滴。

结果奇怪地让人想起了Matrix代码。

输出
(每5s一次加减速就是gif循环)

在此处输入图片说明


很好,但是我认为ESC字符打印不正确。i.stack.imgur.com/vLERQ.png我也尝试使用gedit粘贴代码,但是没有用。
Riking

你的分数错了。这个问题说的是“字节”,而不是“字符”。
jazzpi 2014年

1
@Riking我编辑了那部分。如果再次尝试,它应该可以工作。
Tobia

@Tobia给我看您坐在IBM 5100上的照片,我将购买chars = bytes参数。
primo 2014年


42

重击:111字节-20 = 91分!

在终端机上沉思细雨。分别将数字819和41调整为不同的高度和宽度。

e='printf \e';while :;do for i in {0..819};do((RANDOM<9))&&$e[1\;36m.||$e[1C;((i%41<1))&&$e'
';done;$e[20A;done

屏幕截图

令人愉悦的好处是光标在雨区中itter啪作响。

编辑:由于@manatwork的建议,从140字节缩短到129字节。第2次修改:感谢@manatwork和@Tobia的建议,再加上其他灵感,请从129个字节缩短到111个字节-参见注释。

(注意:屏幕截图显示了以前版本的代码,功能相同)


1
您可以保留:通过加入echo的选项来保留2个字符;使用2个字符\e代替\033;3个字符通过使用:代替true; 使用算术评估(((…)))的5个字符:e='echo -ne \e';while :;do for i in {0..19};do for i in {0..40};do ((RANDOM<9))&&$e"[1;36m".||$e[1C;done;$e' ';done;$e[20A;done
manatwork

1
您不需要算术运算内部的标记。并且在代码末尾必须有尾随换行符。应该只有127个字符。
manatwork

1
我相信@manatwork的意思是您不需要在双括号内使用美元符号:((RANDOM<9))效果也一样。另外,您可以尝试通过将for {0..19}和两者合并{0..40}为一个for {0..819}来缩小代码,方法是使用$((i%41))内部代码。
Tobia 2014年

1
有人阻止我!e='printf \e'比2个字符短2个字符e='echo -ne \e'
Tobia

1
并使用$e[C
-Tobia

39

Python,312字节-50(wind)= 262

from pygame import*
R=__import__('random').randint
t,u=640,480;init();d=display;s=d.set_mode((t,u))
w=[255]*3;r=range(t)
a=[[R(0,t),R(0,u),R(3,6)]for i in r]
while time.wait(9):
 d.flip();event.get();s.fill(R(0,99)<1and w)
 for i in r:x,y,z=a[i];draw.line(s,w,(x,y),(x+z,y+2*z));a[i][0]=(x+z)%t;a[i][1]=(y+z*2)%u

样本输出(50帧循环):

实际的播放包比gif所允许的快得多。


3
我可以@ChristianCareaga,但我认为白色看起来更好。
primo 2014年

8
在我眼中唯一的问题是:您正在从侧面观看雨水,而规则规定固定摄像机朝下看。
Johannes H.

7
@JohannesH。或者,这是一个非常非常大风的日子。
primo 2014年

20
我喜欢偶尔的闪电!:P
帽子的家伙

3
通过使用R=__import__("random").randint代替from random...行来保存一个字符。
SimonT 2014年

35

HTML / JS,170个字符-20 = 150点

<canvas id=c></canvas><script>d=400;with(c)width=height=d,t=getContext('2d');t.fillStyle='blue';setInterval("t.fillRect(Math.random()*d,Math.random()*d,5,5)",50)</script>

(旁注:通过传递一个字符串,以进一步golfed setIntervalwith自动ID变量名......这感觉如此错误!不寒而栗

它只是绘制随机的蓝色矩形。

HTML / JS,309个字符-20-50 = 239点

现在随风!

<canvas id=c></canvas><script>s=400;r=Math.random;with(c)width=height=s,t=getContext('2d');t.fillStyle='blue';o=[];setInterval("t.clearRect(0,0,s,s);for(i=0;++i<o.length;)d=o[i],t.fillRect(d[0],d[1],d[2],d[2]),d[0]+=1,d[1]+=2,d[2]-=1,d[2]<0?o.splice(i,1):0;if(r()<.6)o.push([r()*400,r()*400,20])",50)</script>


163个字节:<canvas id=c /><script>d=400;with(c)width=height=d,t=getContext('2d');t.fillStyle='blue';setInterval("t.fillRect(Math.random()*d,Math.random()*d,5,5)",50)</script>AAAHHH!我用过with!我觉得比传递一个字符串脏setInterval:P
Niet的黑暗ABSOL

@NiettheDarkAbsol谢谢;)似乎(至少在Chrome上)canvas无法自动关闭,但除此之外,它还可以完美地工作!(另外,使用自动ID变量名称也会感到很肮脏:D)
门把手

某些浏览器在该领域似乎更宽容...但它避免使用onload。我必须说我喜欢Math.random()
@Florent

@Doorknob canvas在Chrome中自动关闭!我的答案是在此浏览器中开发/测试的。
Florent 2014年

1
为第二个投票,滴落到地面/水坑中。
GreenAsJade

34

JS + jQuery(172-20-50 = 102)

在浏览器控制台中复制/粘贴该行(通常按F12键):

r=Math.random;w=$(window);setInterval("$('<b>♥</b>').css({color:'red',position:'fixed',top:r()*w.height(),left:r()*w.width()}).appendTo('body').animate({fontSize:0},3e3)",9)

动画红心为情人节而下雨!

在此处输入图片说明


1
好吧,这是不现实的。心脏来自屏幕顶部,并停留在页面的随机位置。这与视点条件并不完全匹配。

10
啊!如何停止呢?
帽子的家伙

1
@ user2509848但是还有其他方法吗?
帽子的家伙

3
@TheGuywithTheHat,重新加载页面
Michael M.

19
辉煌!我认为这抓住了问题的核心。
andrewb 2014年

26

Mathematica

134-20 = 114

2D

n = 99; m = Array[0 &, {n, n}]; r := RandomInteger[{1, n}, {2}]
Table[ArrayPlot[m = ReplacePart[m, r ->  1], ColorRules -> {1 -> Blue}], {k, 250}];
Export["d.gif", d]

2D


3D

雨滴形状是通过围绕z轴的旋转图绘制的。

最初,对于在显示区域上方延伸的区域产生降雨。沿z轴向上移动视点可实现降雨的出现。(比重新计算每个雨滴的位置更有效。)

雨

r = RandomInteger; z = Table[{r@30, r@30, r@160}, {100}];
w = RevolutionPlot3D[{.7 Sin[x] Cos[x], 0,   1.4 Sin[x] }, {x, 0, -Pi/2}, 
PerformanceGoal -> "Speed"][[1]];
c = Map[Translate[w, #] &, z]; 
p = Table[Graphics3D[c, PlotRange -> {k, k + 50}], {k, 1, 100}]
Export["p.gif", p]

有风

使雨随风落下有很大的开销。但是无论如何我都包括在这里。

蓝色地板几乎将{x,y}的查看区域限制在感兴趣的区域内。有一些小故障,但是,哦,

r = RandomInteger;
z = Table[{r@120, r@30, r@180}, {800}];
w = RevolutionPlot3D[{.7 Sin[x] Cos[x], 0,   1.4 Sin[x] }, {x, 
     0, -Pi/2}, PerformanceGoal -> "Speed"][[1]];
c = Map[Translate[w, #] &, z];
g[k_, z1_, w_, c1_] :=
 Module[{z2},
  z2 = Cases[z, {x_, _, _} /; 0 + k < x < 30 + k];
  c = Map[Translate[w, #] &, z2];
  Graphics3D[{Polygon[{{0 + k, 0, 1 + k}, {30 + k, 0, 1 + k}, {30 + k,
        30, 1 + k}, {0 + k, 30, 1 + k}}], c}, 
   PlotRange -> {k, k + 50}]]

p = Table[g[k, z, w, c], {k, 1, 100, 1}];
Export["p.gif", p]

随风


从正上方

最近的雨滴被剪掉了,但我会忽略掉。

从3D之上

m=40;
r=RandomInteger;
positions=Table[{r@m,r@m,r@1000},{800}];
g[lowZ_,pos_]:=
Module[{hiZ=lowZ+103},
Graphics3D[{PointSize[Small],White,Point[{{0,0,lowZ},{0,m,lowZ},{m,0,lowZ},{m,m,lowZ},{0,0,hiZ},{0,m,hiZ},{m,0,hiZ},{m,m,hiZ}}],
ImageSize-> 350,Sphere/@Cases[pos,{_,_,z1_}/;lowZ<z1<hiZ-2]},PlotRange->{lowZ,hiZ}, 
ViewPoint-> {0,0,1},ImagePadding->5]]

将其移到不超过50个字符的一侧,可以降低得分。:)
Ali Caglayan 2014年

1
我喜欢这个

对于最后一个+1,使用正确的摄像机角度,但是您忘了摄像机挡了一些雨。...;)
GreenAsJade

@GreenAsJade,现在已修复3D(从上方)视点的剪辑。
DavidC 2014年

亲爱的,但我比你想的要轻浮。我的意思是,有一台物理相机向下看,所以它应该
遮住了

10

HTML / JavaScript,156123(143-20)

<body bgcolor=0 onload="t=c.getContext('2d');t.fillStyle='#07d';setInterval('n=Math.random()*4e4;t.fillRect(n%270,n/150,1,1)',1)"><canvas id=c>

带注释的版本:

<body bgcolor="#000">
<canvas id="c"></canvas>
<script>
  onload = function() {
    // Retrieve the rendering context
    t=c.getContext('2d');
    // Set rain color
    t.fillStyle='#07d';
    // Render whenever it is possible
    setInterval(function() {
      // Generate a number between 0 and 40,000
      // 40,000 ~= 270 * 150
      n=Math.random()*4e4;
      // Draw a raindrop.
      // Since x and y are not rounded, the raindrop looks blurry!
      t.fillRect(n%270,n/150,1,1)
    }, 1);
  };
</script>
</body>

7

Smalltalk(Smalltalk / X)

随风;-)

|BG CLR N1 H W v WIND drops gen newDrops draw remove move buffer|


BG := Color black.
CLR := Color blue lightened.
H := 100.
W := 100.
N1 := 10.
WIND := 0.
drops := OrderedCollection new.

gen := [:n | ((1 to:n) collect:[:i | Random nextIntegerBetween:1 and:W] as:Set) collect:[:x | x@0]].
newDrops := [drops addAll:(gen value:N1)].
draw := [buffer fill:BG; paint:CLR. drops do:[:d | buffer displayPoint:d]].
remove := [drops := drops reject:[:d | d y > H]].
move := [:wind | drops := drops collect:[:d| (d x + wind)\\W @ (d y + 1)]].
v := View new openAndWait.
buffer := Form extent:(v extent) depth:24 onDevice:v device.

[
    [v shown] whileTrue:[
        draw value.
        v displayForm:buffer.
        move value:WIND.
        remove value.
        newDrops value.
        WIND := (WIND+(Random nextBetween:-1 and:1)) clampBetween:-5 and:5.
        Delay waitForSeconds:0.1.
    ]
] fork.

在视图中输出: 在此处输入图片说明


6
它是合格的,因为它是降雨的侧视图,而不是降雨击中地面。仍然是很好的风效果。

6

处理中,94-20 = 74

void setup(){background(0);fill(0,0,255);}
void draw(){ellipse(random(0,99),random(0,99),3,3);}

(为便于阅读,添加了新行。)

单击此处获取在线演示。


1
处理对于此类问题确实非常有用。
cjfaure 2014年

无法在Firefox中查看它,默认的安全设置阻止Java小程序,并且它不会告诉我如何覆盖。AFAIK有一个JavaScript的Processing.js端口,如果您可以将其转换为JS并发布链接,我将非常感激。
marczellm 2014年

@marczellm我在Ubuntu上使用Firefox 27.0,并且工作正常。您确定没有提示询问您是允许还是阻止该插件?我还将看一下JS版本。
ace_HongKong独立

@ace我告诉所有提示“允许”之后,安全消息仍将其阻止。感谢您的JS版本。
marczellm 2014年

1
@marczellm在答案中添加了javascript版本,请尽情享受:),只是盲目的猜测,也许您当前的Java插件版本已过时,并且存在已知的安全问题
ace_HongKongIndependence 2014年

5

重击

while true;do echo " / / / / /";echo "/ / / / / ";done

我不确定这应该是代码高尔夫,因为对“雨”的外观没有严格的要求。

编辑:如果您希望它看起来像照相机指向下方,请使用以下命令:

while true;do echo " . . . . .";echo ". . . . . ";done

7
“相机是固定的:您正上方直视地面。” 这似乎是从侧面看雨吗?
地下

2
保存9个字符:(while echo \ / / / / /;do echo / / / / /;done或使用递归函数再保存几个字符,但这会很快炸毁堆栈)。@undergroundmonorail强风,相对于相机为对角线。
吉尔斯(Gillles)“所以-别再邪恶了”

@Gilles在这种情况下,我们可以做的while echo -e '\e[0;34m / / / / /';do echo / / / / /;done,并与奖金:)它弄下来到-13
undergroundmonorail

4
那绝对不是下雨的样子:D
Kiwy

5
我真的不认为这应该被视为答案。简而言之:这是不现实的。详细的论点:如果我正确地解释了这个问题,那么降雨应该是随机的(或者至少是伪随机的),并且在很长的一段时间内,每单位面积的分布应该相似。(这是雨的工作原理,对吗?)但是,在这个答案中,可以确保在任何雨滴旁边都不会有雨滴,因此,如果将单位面积作为一个字符的面积,我们会看到分布不均。
ace_HongKong独立

3

Python 2.7:195-20 = 175

我敢肯定,这里还有更多可以做的事情,但这就是我现在要做的:

import os,time
from random import*
l=[i[:]for i in[[' ']*100]*50]
while 1:
 os.system('clear')
 l[randint(0,49)][randint(0,99)]='.'
 print'\033[94m\n'.join(''.join(r)for r in l)
 time.sleep(.05)

当我记得该怎么做时,我将发布输出的gif文件。

这适用于linux。替换'clear''cls'使其可以在Windows上运行,但随后ANSI颜色不起作用,并且我失去了花红。

我有一个二维数组,由一个单字符字符串组成,初始化为。每0.05秒,将其中一个随机选择为.,然后重新绘制屏幕。

from random import*保存两个字符import os,time,random并重复使用random.randint()两次,尽管我不确定这还是选择单元格的最佳方法。我想使用,random.choice()但我想不出一种解决不可变字符串的方法,该方法不会浪费比保存的字符更多的字符。


3
l=[i[:]for i in[[' ']*100]*50],如stackoverflow.com/a/6688361/1114687所示
198-20

哦,哇,我从未见过。如果我正确地阅读了它,那么切片符号除了确保它是唯一列表而不是对同一列表的另一个引用之外,什么都不做,对吗?太棒了!谢谢!
地下

我最初尝试过l=[[' ']*100]*50,但是只创建了对相同的100个元素列表的50个引用,因此我搜索了最短的方法来规避该问题,并找到了上面链接的Stack Overflow答案。
2014年

2

132 + 27-20-50 = 89

Java语言(132)

r=Math.random;setInterval("$('body').append($('<i>∘</i>').css({left:r()*2e3,top:r()*2e3}).animate({left:'+=70',fontSize:0},500))",1)

CSS(27)

i{color:blue;position:fixed

演示:http : //jsfiddle.net/kelunik/5WC87/4/embedded/result/


从侧面看,目前尚不合格。

@BenH您是正确的,错过了这一点,现在我的答案是新版本。
kelunik

在firefox控制台中尝试代码时似乎什么也没发生:/

@BenH这就是为什么有一个jsfiddle-demo的原因。
kelunik 2014年

没有看到。谢谢


1

Processing.js,86-20 = 66

...但是它也会慢慢消失(地面自然吸收雨水)。要点吗?

g=99;r=random;void draw(){fill(0,9);rect(0,0,g,g);fill(0,g,r(g));rect(r(g),r(g),2,2);}

奖励功能包括在绿色和蓝色之间变化(显然是肮脏的“城市”雨)。

另外,我很高兴能在这里使用JavaScript hack;请注意,因为这是处理中。js,您可以添加诸如g = 99的无类型声明或rfor 的别名random(跨语言别名!)之类的东西。

还有其他想法要缩小吗?

可读版本:

g = 99;
r = random;                  // Javascript trickery
void draw() {
    fill(0, 9);
    rect(0, 0, g, g);        // Fade the background
    fill(0, r(g), r);
    rect(r(g), r(g), 2, 2);  // Add a new drop
}

整个事情可以在这里查看。

...加上不褪色的其他版本:58-20 = 38

如果您不喜欢褪色并且不介意灰色污垢:

r=random;void draw(){fill(0,0,255);rect(r(99),r(99),2,2);}

1

Tcl / Tk,139-20 = 119

重用我自己的答案http://codegolf.stackexchange.com/a/143018/29325

必须在交互式外壳中运行

gri [can .c -w 40 -he 40]
set x 0
wh 1 {.c cr o $x [set y [exp int(rand()*40)]] $x [set x $y] -f #[form %06x [exp int(rand()*255**3)]]
upd}

不幸的是,转换expr int(rand()*为a proc会使脚本多一个字节!

在此处输入图片说明

要停止,只需单击无法解释的“ X”按钮。

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.