代码高尔夫:复活节螺旋
还有什么比螺旋更适合复活节代码高尔夫课程呢?
好吧,我几乎猜到了一切。
挑战
按字符数计算最短的代码,以显示由星号 ('*') 组成的漂亮 ASCII 螺旋。
输入是一个数字,R
,它将是螺旋的 x 尺寸。另一个维度 (y) 始终为R-2
。程序可以假设R
始终为奇数且>= 5。
一些示例:
Input
7
Output
*******
* *
* *** *
* * *
***** *
Input
9
Output
*********
* *
* ***** *
* * * *
* *** * *
* * *
******* *
Input
11
Output
***********
* *
* ******* *
* * * *
* * *** * *
* * * * *
* ***** * *
* * *
********* *
代码计数包括输入/输出(即完整程序)。 任何语言都是允许的。
我轻松击败的 303 个字符长的 Python 示例:
import sys;
d=int(sys.argv[1]);
a=[d*[' '] for i in range(d-2)];
r=[0,-1,0,1];
x=d-1;y=x-2;z=0;pz=d-2;v=2;
while d>2:
while v>0:
while pz>0:
a[y][x]='*';
pz-=1;
if pz>0:
x+=r[z];
y+=r[(z+1)%4];
z=(z+1)%4; pz=d; v-=1;
v=2;d-=2;pz=d;
for w in a:
print ''.join(w);
现在,输入 Spiral...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
Python (2.6):156 个字符
感谢您的评论。我删除了无关的空格并使用了 input()。我仍然更喜欢在命令行上获取参数的程序,因此这里的版本仍然使用 176 个字符的 sys.argv:
解释
将螺旋线切成两个几乎相等的部分,顶部和底部,其中顶部的部分行大于底部:
观察顶部部分如何美观且对称。观察底部如何在右侧有一条垂直线,但在其他方面与顶部非常相似。请注意顶部每隔一行的图案:每一侧的星星数量不断增加。请注意,中间的每一行都与之前的锯完全一样,只是它在中间区域填充了星星。
函数 p(r,s) 打印宽度为 r 的螺旋顶部的第 i 行,并将后缀 s 贴在末尾。请注意,i 是一个全局变量,尽管它可能并不明显!当 i 为偶数时,它会用空格填充行的中间,否则用星星填充。 (~i%2 是获得 i%2==0 效果的一种令人讨厌的方法,但实际上根本没有必要,因为我应该简单地交换“*”和“”。)我们首先绘制顶部随着 i 的增加,绘制螺旋线的行,然后我们用 i 减少的方式绘制底部的行。我们将 r 降低 2 并添加后缀“*”以获得右侧的星星列。
Python (2.6): 156 chars
Thanks for the comments. I've removed extraneous whitespace and used input(). I still prefer a program that takes its argument on the command-line, so here's a version still using sys.argv at 176 chars:
Explanation
Take the spiral and chop it in two almost-equal parts, top and bottom, with the top one row bigger than the bottom:
Observe how the top part is nice and symmetrical. Observe how the bottom part has a vertical line down the right side, but is otherwise much like the top. Note the pattern in every second row at the top: an increasing number of stars on each side. Note that each intervening row is exactly the saw as the one before except it fills in the middle area with stars.
The function p(r,s) prints out the ith line of the top part of the spiral of width r and sticks the suffix s on the end. Note that i is a global variable, even though it might not be obvious! When i is even it fills the middle of the row with spaces, otherwise with stars. (The ~i%2 was a nasty way to get the effect of i%2==0, but is actually not necessary at all because I should have simply swapped the "*" and the " ".) We first draw the top rows of the spiral with increasing i, then we draw the bottom rows with decreasing i. We lower r by 2 and suffix " *" to get the column of stars on the right.
Java
328 个字符
比 Python 多 1/6 似乎还不错;)
正确缩进也是如此:
Java
328 characters
As little as 1/6 more than Python seems not too bad ;)
Here's the same with proper indentation:
F#,267 个字符
很多答案都是以空格开头并添加
*
,但我认为以星空开头并添加空格可能更容易。对于那些想深入了解我如何打高尔夫球的人来说,我碰巧在这一过程中节省了很多进步,我在这里附上评论。并非每个程序都完全正确,但它们都在研究更短的解决方案。
首先,我寻找一种如何绘制白色的模式:
好的,我明白了。第一个程序:
我知道
d
,(x,y)-diffs-modulo-4 的元组数组稍后可以通过 x 和 y 减少,两者都索引到同一 int 数组的不同部分,因此是 TODO。剩下的就很简单了,基于对“空白绘画”的视觉洞察。我正在打印一个 2D 数组,这是不对的,需要一个字符串数组,所以:好的,现在让我们将元组数组更改为 int 数组:
A 的
let
可以是一部分上一行的。z
和i
大多是多余的,我可以根据另一个来计算一个。downto
很长,重新计算一下,这样我就可以在循环中转到(up)to
。再收紧一点就会产生最终的解决方案。
F#, 267 chars
A lot of answers are starting with blanks and adding
*
s, but I think it may be easier to start with a starfield and add whitespace.For those looking for insight into how I golf, I happened to save a lot of progress along the way, which I present here with commentary. Not every program is quite right, but they're all honing in on a shorter solution.
First off, I looked for a pattern of how to paint the white:
Ok, I see it. First program:
I know that
d
, the tuple-array of (x,y)-diffs-modulo-4 can later be reduced by x and y both indexing into different portions of the same int-array, hence the TODO. The rest is straightforward based on the visual insight into 'whitespace painting'. I'm printing a 2D array, which is not right, need an array of strings, so:Ok, now let's change the array of tuples into an array of int:
The
let
for A can be part of the previous line. Andz
andi
are mostly redundant, I can compute one in terms of the other.downto
is long, re-do the math so I can go (up)to
in the loop.A little more tightening yields the final solution.
Python:
238-221- 209 个字符欢迎所有评论:
Python :
238-221- 209 charactersAll comments welcome:
Groovy,
373295257243个字符尝试了一种递归方法,从最外部的内部开始构建方块。我使用了绝妙。
等等..
可读的:
编辑:通过仅填充正方形然后覆盖它们来改进(检查新示例):所以我避免只填充矩形的边缘,而是填充整个矩形。
Groovy,
373295257243 charsTried a recursive approach that builds up squares starting from the most extern one going inside.. I used Groovy.
and so on..
readable one:
EDIT: improved by just filling squares and then overriding them (check new example): so I avoided to fill just the edge of the rect but the whole one.
Ruby,237 个字符
我是高尔夫编码新手,所以我离目标很远,但我想我应该尝试一下。
长版
Ruby, 237 chars
I'm new to code golf, so I'm way off the mark, but I figured I'd give it a shot.
Long version
Java,
265250245240 个字符我只是循环遍历 x/y 坐标并输出 ' *' 或 ' ' 表示当前位置。为此,我们需要一种算法来评估任意点是否在螺旋上。我使用的算法基于这样的观察:螺旋相当于同心正方形的集合,除了一组都沿着特定对角线发生的位置;这些位置需要修正(它们必须颠倒)。
有点可读的版本:
对上述内容的简要解释:
向下优化。 265 个字符:
已更新。现在减少到 250 个字符:
又删掉了几个字符。 245 个字符:
仅减少了几个字符。 240 个字符:
Java,
265250245240 charsRather than preallocating a rectangular buffer and filling it in, I just loop over x/y coordinates and output '*' or ' ' for the current position. For this, we need an algorithm which can evaluate arbitrary points for whether they're on the spiral. The algorithm I used is based on the observation that the spiral is equivalent to a collection of concentric squares, with the exception of a set of positions which all happen along a particular diagonal; these positions require a correction (they must be inverted).
The somewhat readable version:
A brief explanation for the above:
Optimized down. 265 chars:
Updated. Now down to 250 chars:
Shaved just a few more characters. 245 chars:
Shaved just a few more characters. 240 chars:
OCaml,299 个字符
这是 OCaml 中的一个解决方案,不是最短的,但我相信相当可读。
它仅使用字符串操作,因为您可以通过镜像前一个螺旋来构建螺旋。
假设您从 n = 5 开始:
现在 n = 7:
您看到所有 5 都去了哪里吗?
这是仅使用 OCaml 提供的有限库的未混淆代码:
这是长度为 299 个字符的混淆版本:
OCaml, 299 chars
Here is a solution in OCaml, not the shortest but I believe quite readable.
It only uses string manipulations using the fact the you can build a spiral by mirroring the previous one.
Let's say you start at with n = 5:
Now with n = 7:
Did you see where all the 5's went ?
Here is the unobfuscated code using only the limited library provided with OCaml:
Here is the obfuscated version which is 299 characters long:
C#,
292262255 chars简单做法:从外向内,逐行绘制螺旋线。
C#,
292262255 charsSimple approach: draw the spiral line by line from the outside in.
Ruby (1.9.2) — 126
Perl,你在哪里? )
Ruby (1.9.2) — 126
Perl, where are you? )