代码高尔夫:复活节螺旋

发布于 2024-08-28 03:45:25 字数 1096 浏览 13 评论 0 原文

还有什么比螺旋更适合复活节代码高尔夫课程呢?
好吧,我几乎猜到了一切。

挑战

按字符数计算最短的代码,以显示由星号 ('*') 组成的漂亮 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...

What's more appropriate than a Spiral for Easter Code Golf sessions?
Well, I guess almost anything.

The Challenge

The shortest code by character count to display a nice ASCII Spiral made of asterisks ('*').

Input is a single number, R, that will be the x-size of the Spiral. The other dimension (y) is always R-2. The program can assume R to be always odd and >= 5.

Some examples:

Input
    7
Output

*******
*     *
* *** *
*   * *
***** *                   

Input
    9
Output

*********
*       *
* ***** *
* *   * *
* *** * *
*     * *
******* *

Input
   11
Output

***********
*         *
* ******* *
* *     * *
* * *** * *
* *   * * *
* ***** * *
*       * *
********* *

Code count includes input/output (i.e., full program).
Any language is permitted.

My easily beatable 303 chars long Python example:

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);

Now, enter the Spiral...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

将军与妓 2024-09-04 03:45:25

Python (2.6):156 个字符

r=input()
def p(r,s):x=(i+1)/2;print "* "*x+("*" if~i%2 else" ")*(r-4*x)+" *"*x+s
for i in range(r/2):p(r,"")
for i in range((r-1)/2-1)[::-1]:p(r-2," *")

感谢您的评论。我删除了无关的空格并使用了 input()。我仍然更喜欢在命令行上获取参数的程序,因此这里的版本仍然使用 176 个字符的 sys.argv:

import sys
r=int(sys.argv[1])
def p(r,s):x=(i+1)/2;print "* "*x+("*" if~i%2 else" ")*(r-4*x)+" *"*x+s
for i in range(r/2):p(r,"")
for i in range((r-1)/2-1)[::-1]:p(r-2," *")

解释

将螺旋线切成两个几乎相等的部分,顶部和底部,其中顶部的部分行大于底部:

***********
*         *
* ******* *
* *     * *
* * *** * *

* *   * * *
* ***** * *
*       * *
********* *

观察顶部部分如何美观且对称。观察底部如何在右侧有一条垂直线,但在其他方面与顶部非常相似。请注意顶部每隔一行的图案:每一侧的星星数量不断增加。请注意,中间的每一行都与之前的锯完全一样,只是它在中间区域填充了星星。

函数 p(r,s) 打印宽度为 r 的螺旋顶部的第 i 行,并将后缀 s 贴在末尾。请注意,i 是一个全局变量,尽管它可能并不明显!当 i 为偶数时,它会用空格填充行的中间,否则用星星填充。 (~i%2 是获得 i%2==0 效果的一种令人讨厌的方法,但实际上根本没有必要,因为我应该简单地交换“*”和“”。)我们首先绘制顶部随着 i 的增加,绘制螺旋线的行,然后我们用 i 减少的方式绘制底部的行。我们将 r 降低 2 并添加后缀“*”以获得右侧的星星列。

Python (2.6): 156 chars

r=input()
def p(r,s):x=(i+1)/2;print "* "*x+("*" if~i%2 else" ")*(r-4*x)+" *"*x+s
for i in range(r/2):p(r,"")
for i in range((r-1)/2-1)[::-1]:p(r-2," *")

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:

import sys
r=int(sys.argv[1])
def p(r,s):x=(i+1)/2;print "* "*x+("*" if~i%2 else" ")*(r-4*x)+" *"*x+s
for i in range(r/2):p(r,"")
for i in range((r-1)/2-1)[::-1]:p(r-2," *")

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.

掩于岁月 2024-09-04 03:45:25

Java

328 个字符

class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),i=n*(n-2)/2-1,j=0,t=2,k;
char[]c=new char[n*n];
java.util.Arrays.fill(c,' ');
int[]d={1,n,-1,-n};
if(n/2%2==0){j=2;i+=1+n;}
c[i]='*';
while(t<n){
for(k=0;k<t;k++)c[i+=d[j]]='*';
j=(j+1)%4;
if(j%2==0)t+=2;
}
for(i=0;i<n-2;i++)System.out.println(new String(c,i*n,n));
}
}

比 Python 多 1/6 似乎还不错;)

正确缩进也是如此:

class S {
    public static void main(String[] a) {
        int n = Integer.parseInt(a[0]), i = n * (n - 2) / 2 - 1, j = 0, t = 2, k;
        char[] c = new char[n * n];
        java.util.Arrays.fill(c, ' ');
        int[] d = { 1, n, -1, -n };
        if (n / 2 % 2 == 0) {
            j = 2;
            i += 1 + n;
        }
        c[i] = '*';
        while (t < n) {
            for (k = 0; k < t; k++)
                c[i += d[j]] = '*';
            j = (j + 1) % 4;
            if (j % 2 == 0)
                t += 2;
        }
        for (i = 0; i < n - 2; i++)
            System.out.println(new String(c, i * n, n));
    }
}

Java

328 characters

class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),i=n*(n-2)/2-1,j=0,t=2,k;
char[]c=new char[n*n];
java.util.Arrays.fill(c,' ');
int[]d={1,n,-1,-n};
if(n/2%2==0){j=2;i+=1+n;}
c[i]='*';
while(t<n){
for(k=0;k<t;k++)c[i+=d[j]]='*';
j=(j+1)%4;
if(j%2==0)t+=2;
}
for(i=0;i<n-2;i++)System.out.println(new String(c,i*n,n));
}
}

As little as 1/6 more than Python seems not too bad ;)

Here's the same with proper indentation:

class S {
    public static void main(String[] a) {
        int n = Integer.parseInt(a[0]), i = n * (n - 2) / 2 - 1, j = 0, t = 2, k;
        char[] c = new char[n * n];
        java.util.Arrays.fill(c, ' ');
        int[] d = { 1, n, -1, -n };
        if (n / 2 % 2 == 0) {
            j = 2;
            i += 1 + n;
        }
        c[i] = '*';
        while (t < n) {
            for (k = 0; k < t; k++)
                c[i += d[j]] = '*';
            j = (j + 1) % 4;
            if (j % 2 == 0)
                t += 2;
        }
        for (i = 0; i < n - 2; i++)
            System.out.println(new String(c, i * n, n));
    }
}
抽个烟儿 2024-09-04 03:45:25

F#,267 个字符

很多答案都是以空格开头并添加 * ,但我认为以星空开头并添加空格可能更容易。

let n=int(System.Console.ReadLine())-2
let mutable x,y,d,A=n,n,[|1;0;-1;0|],
 Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
for i=1 to n do for j=1 to(n-i+1)-i%2 do x<-x+d.[i%4];y<-y+d.[(i+1)%4];A.[y].[x]<-' '
Seq.iter(printfn"%O")A

对于那些想深入了解我如何打高尔夫球的人来说,我碰巧在这一过程中节省了很多进步,我在这里附上评论。并非每个程序都完全正确,但它们都在研究更短的解决方案。

首先,我寻找一种如何绘制白色的模式:

********* 
*       * 
* ***** * 
* *   * * 
* *** * * 
*     * * 
******* * 

********* 
*6543216* 
*1*****5* 
*2*212*4* 
*3***1*3* 
*41234*2* 
*******1* 

*********** 
*         * 
* ******* * 
* *     * * 
* * *** * * 
* *   * * * 
* ***** * * 
*       * * 
********* *

*********** 
*876543218* 
*1*******7* 
*2*43214*6* 
*3*1***3*5* 
*4*212*2*4* 
*5*****1*3* 
*6123456*2* 
*********1*

好的,我明白了。第一个程序:

let Main() =
    let n=int(System.Console.ReadLine())
    let A=Array2D.create(n-2)n '*'
    let mutable x,y,z,i=n-2,n-2,0,n-2
    let d=[|0,-1;-1,0;0,1;1,0|]  // TODO
    while i>0 do
     for j in 1..i-(if i%2=1 then 1 else 0)do
      x<-x+fst d.[z]
      y<-y+snd d.[z]
      A.[y,x]<-'0'+char j
     z<-(z+1)%4
     i<-i-1
    printfn"%A"A
Main()

我知道 d,(x,y)-diffs-modulo-4 的元组数组稍后可以通过 x 和 y 减少,两者都索引到同一 int 数组的不同部分,因此是 TODO。剩下的就很简单了,基于对“空白绘画”的视觉洞察。我正在打印一个 2D 数组,这是不对的,需要一个字符串数组,所以:

let n=int(System.Console.ReadLine())
let s=String.replicate n "*"
let A=Array.init(n-2)(fun _->System.Text.StringBuilder(s))
let mutable x,y,z,i=n-2,n-2,0,n-2
let d=[|0,-1;-1,0;0,1;1,0|]
while i>0 do
 for j in 1..i-(if i%2=1 then 1 else 0)do
  x<-x+fst d.[z]
  y<-y+snd d.[z]
  A.[y].[x]<-' '
 z<-(z+1)%4
 i<-i-1
for i in 0..n-3 do
 printfn"%O"A.[i]

好的,现在让我们将元组数组更改为 int 数组:

let n=int(System.Console.ReadLine())-2
let mutable x,y,z,i,d=n,n,0,n,[|0;-1;0;1;0|]
let A=Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
while i>0 do
 for j in 1..i-i%2 do x<-x+d.[z];y<-y+d.[z+1];A.[y].[x]<-' '
 z<-(z+1)%4;i<-i-1
A|>Seq.iter(printfn"%O")

A 的 let 可以是一部分上一行的。 zi 大多是多余的,我可以根据另一个来计算一个。

let n=int(System.Console.ReadLine())-2
let mutable x,y,d,A=n,n,[|0;-1;0;1|],
 Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
for i=n downto 1 do for j in 1..i-i%2 do x<-x+d.[(n-i)%4];y<-y+d.[(n-i+1)%4];A.[y].[x]<-' '
Seq.iter(printfn"%O")A

downto 很长,重新计算一下,这样我就可以在循环中转到(up)to

let n=int(System.Console.ReadLine())-2
let mutable x,y,d,A=n,n,[|1;0;-1;0|],
 Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
for i=1 to n do for j in 1..(n-i+1)-i%2 do x<-x+d.[i%4];y<-y+d.[(i+1)%4];A.[y].[x]<-' '
Seq.iter(printfn"%O")A

再收紧一点就会产生最终的解决方案。

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.

let n=int(System.Console.ReadLine())-2
let mutable x,y,d,A=n,n,[|1;0;-1;0|],
 Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
for i=1 to n do for j=1 to(n-i+1)-i%2 do x<-x+d.[i%4];y<-y+d.[(i+1)%4];A.[y].[x]<-' '
Seq.iter(printfn"%O")A

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:

********* 
*       * 
* ***** * 
* *   * * 
* *** * * 
*     * * 
******* * 

********* 
*6543216* 
*1*****5* 
*2*212*4* 
*3***1*3* 
*41234*2* 
*******1* 

*********** 
*         * 
* ******* * 
* *     * * 
* * *** * * 
* *   * * * 
* ***** * * 
*       * * 
********* *

*********** 
*876543218* 
*1*******7* 
*2*43214*6* 
*3*1***3*5* 
*4*212*2*4* 
*5*****1*3* 
*6123456*2* 
*********1*

Ok, I see it. First program:

let Main() =
    let n=int(System.Console.ReadLine())
    let A=Array2D.create(n-2)n '*'
    let mutable x,y,z,i=n-2,n-2,0,n-2
    let d=[|0,-1;-1,0;0,1;1,0|]  // TODO
    while i>0 do
     for j in 1..i-(if i%2=1 then 1 else 0)do
      x<-x+fst d.[z]
      y<-y+snd d.[z]
      A.[y,x]<-'0'+char j
     z<-(z+1)%4
     i<-i-1
    printfn"%A"A
Main()

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:

let n=int(System.Console.ReadLine())
let s=String.replicate n "*"
let A=Array.init(n-2)(fun _->System.Text.StringBuilder(s))
let mutable x,y,z,i=n-2,n-2,0,n-2
let d=[|0,-1;-1,0;0,1;1,0|]
while i>0 do
 for j in 1..i-(if i%2=1 then 1 else 0)do
  x<-x+fst d.[z]
  y<-y+snd d.[z]
  A.[y].[x]<-' '
 z<-(z+1)%4
 i<-i-1
for i in 0..n-3 do
 printfn"%O"A.[i]

Ok, now let's change the array of tuples into an array of int:

let n=int(System.Console.ReadLine())-2
let mutable x,y,z,i,d=n,n,0,n,[|0;-1;0;1;0|]
let A=Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
while i>0 do
 for j in 1..i-i%2 do x<-x+d.[z];y<-y+d.[z+1];A.[y].[x]<-' '
 z<-(z+1)%4;i<-i-1
A|>Seq.iter(printfn"%O")

The let for A can be part of the previous line. And z and i are mostly redundant, I can compute one in terms of the other.

let n=int(System.Console.ReadLine())-2
let mutable x,y,d,A=n,n,[|0;-1;0;1|],
 Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
for i=n downto 1 do for j in 1..i-i%2 do x<-x+d.[(n-i)%4];y<-y+d.[(n-i+1)%4];A.[y].[x]<-' '
Seq.iter(printfn"%O")A

downto is long, re-do the math so I can go (up) to in the loop.

let n=int(System.Console.ReadLine())-2
let mutable x,y,d,A=n,n,[|1;0;-1;0|],
 Array.init(n)(fun _->System.Text.StringBuilder(String.replicate(n+2)"*"))
for i=1 to n do for j in 1..(n-i+1)-i%2 do x<-x+d.[i%4];y<-y+d.[(i+1)%4];A.[y].[x]<-' '
Seq.iter(printfn"%O")A

A little more tightening yields the final solution.

把人绕傻吧 2024-09-04 03:45:25

Python:238 - 221 - 209 个字符

欢迎所有评论:

d=input();r=range
a=[[' ']*d for i in r(d-2)]
x=y=d/4*2
s=d%4-2
for e in r(3,d+1,2):
 for j in r(y,y+s*e-s,s):a[x][j]='*';y+=s
 for j in r(x,x+s*e-(e==d)-s,s):a[j][y]='*';x+=s
 s=-s
for l in a:print''.join(l)

Python : 238 - 221 - 209 characters

All comments welcome:

d=input();r=range
a=[[' ']*d for i in r(d-2)]
x=y=d/4*2
s=d%4-2
for e in r(3,d+1,2):
 for j in r(y,y+s*e-s,s):a[x][j]='*';y+=s
 for j in r(x,x+s*e-(e==d)-s,s):a[j][y]='*';x+=s
 s=-s
for l in a:print''.join(l)
神爱温柔 2024-09-04 03:45:25

Groovy,373 295 257 243个字符

尝试了一种递归方法,从最外部的内部开始构建方块。我使用了绝妙

*********
*********
*********
*********
*********
*********
******* *

*********
*       *
*       *
*       *
*       *
*     * *
******* *

*********
*       *
* ***** *
* ***** *
* *** * *
*     * *
******* *

*********
*       *
* ***** *
* *   * *
* *** * *
*     * *
******* *

等等..

r=args[0] as int;o=r+1;c='*'
t=new StringBuffer('\n'*(r*r-r-2))
e(r,0)
def y(){c=c==' '?'*':' '}
def e(s,p){if (s==3)t[o*p+p..o*p+p+2]=c*s else{l=o*(p+s-3)+p+s-2;(p+0..<p+s-2).each{t[o*it+p..<o*it+p+s]=c*s};y();t[l..l]=c;e(s-2,p+1)}}
println t

可读的:

r=args[0] as int;o=r+1;c='*'
t=new StringBuffer('\n'*(r*r-r-2))
e(r,0)
def y(){c=c==' '?'*':' '}
def e(s,p){
 if (s==3)
  t[o*p+p..o*p+p+2]=c*s 
 else{
  l=o*(p+s-3)+p+s-2
  (p+0..<p+s-2).each{
   t[o*it+p..<o*it+p+s]=c*s}
   y()
   t[l..l]=c
   e(s-2,p+1)      
  }   
}
println t

编辑:通过仅填充正方形然后覆盖它们来改进(检查新示例):所以我避免只填充矩形的边缘,而是填充整个矩形。

Groovy, 373 295 257 243 chars

Tried a recursive approach that builds up squares starting from the most extern one going inside.. I used Groovy.

*********
*********
*********
*********
*********
*********
******* *

*********
*       *
*       *
*       *
*       *
*     * *
******* *

*********
*       *
* ***** *
* ***** *
* *** * *
*     * *
******* *

*********
*       *
* ***** *
* *   * *
* *** * *
*     * *
******* *

and so on..

r=args[0] as int;o=r+1;c='*'
t=new StringBuffer('\n'*(r*r-r-2))
e(r,0)
def y(){c=c==' '?'*':' '}
def e(s,p){if (s==3)t[o*p+p..o*p+p+2]=c*s else{l=o*(p+s-3)+p+s-2;(p+0..<p+s-2).each{t[o*it+p..<o*it+p+s]=c*s};y();t[l..l]=c;e(s-2,p+1)}}
println t

readable one:

r=args[0] as int;o=r+1;c='*'
t=new StringBuffer('\n'*(r*r-r-2))
e(r,0)
def y(){c=c==' '?'*':' '}
def e(s,p){
 if (s==3)
  t[o*p+p..o*p+p+2]=c*s 
 else{
  l=o*(p+s-3)+p+s-2
  (p+0..<p+s-2).each{
   t[o*it+p..<o*it+p+s]=c*s}
   y()
   t[l..l]=c
   e(s-2,p+1)      
  }   
}
println t

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.

叫思念不要吵 2024-09-04 03:45:25

Ruby,237 个字符

我是高尔夫编码新手,所以我离目标很远,但我想我应该尝试一下。

x=ARGV[0].to_i
y=x-2
s,h,j,g=' ',x-1,y-1,Array.new(y){Array.new(x,'*')}
(1..x/2+2).step(2){|d|(d..y-d).each{|i|g[i][h-d]=s}
(d..h-d).each{|i|g[d][i]=s}
(d..j-d).each{|i|g[i][d]=s}
(d..h-d-2).each{|i|g[j-d][i]=s}}
g.each{|r|print r;puts}

长版

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.

x=ARGV[0].to_i
y=x-2
s,h,j,g=' ',x-1,y-1,Array.new(y){Array.new(x,'*')}
(1..x/2+2).step(2){|d|(d..y-d).each{|i|g[i][h-d]=s}
(d..h-d).each{|i|g[d][i]=s}
(d..j-d).each{|i|g[i][d]=s}
(d..h-d-2).each{|i|g[j-d][i]=s}}
g.each{|r|print r;puts}

Long version

涫野音 2024-09-04 03:45:25

Java,265 250 245 240 个字符

我只是循环遍历 x/y 坐标并输出 ' *' 或 ' ' 表示当前位置。为此,我们需要一种算法来评估任意点是否在螺旋上。我使用的算法基于这样的观察:螺旋相当于同心正方形的集合,除了一组都沿着特定对角线发生的位置;这些位置需要修正(它们必须颠倒)。

有点可读的版本:

public class Spr2 {

  public static void main(String[] args) {
    int n = Integer.parseInt(args[0]);
    int cy = (n - 5) / 4 * 2 + 1;
    int cx = cy + 2;
    for (int y = n - 3; y >= 0; y--) {
      for (int x = 0; x < n; x++) {
        int dx = cx - x;
        int dy = cy - y;
        int adx = Math.abs(dx);
        int ady = Math.abs(dy);
        boolean c = (dx > 0 && dx == dy + 1);
        boolean b = ((adx % 2 == 1 && ady <= adx) || (ady % 2 == 1 && adx <= ady)) ^ c;
        System.out.print(b ? '*' : ' ');
      }
      System.out.println();
    }
  }

}

对上述内容的简要解释:

cx,cy = center
dx,dy = delta from center
adx,ady = abs(delta from center)
c = correction factor (whether to invert)
b = the evaluation

向下优化。 265 个字符:

public class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),c=(n-5)/4*2+1,d=c+2,e,f,g,h,x,y;
for(y=0;y<n-2;y++){
for(x=0;x<=n;x++){
e=d-x;f=c-y;g=e>0?e:-e;h=f>0?f:-f;
System.out.print(x==n?'\n':(g%2==1&&h<=g||h%2==1&&g<=h)^(e>0&&e==f+1)?'*':' ');
}}}}

已更新。现在减少到 250 个字符:

class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),c=(n-5)/4*2+1,d=c+2,g,h,x,y;
for(y=-c;y<n-2-c;y++){
for(x=-d;x<=n-d;x++){
g=x>0?x:-x;h=y>0?y:-y;
System.out.print(x==n-d?'\n':(g%2==1&&h<=g||h%2==1&&g<=h)^(x<0&&x==y-1)?'*':' ');
}}}}

又删掉了几个字符。 245 个字符:

class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),c=(n-5)/4*2+1,d=c+2,g,h,x,y=-c;
for(;y<n-2-c;y++){
for(x=-d;x<=n-d;x++){
g=x>0?x:-x;h=y>0?y:-y;
System.out.print(x==n-d?'\n':(g%2==1&h<=g|h%2==1&g<=h)^(x<0&x==y-1)?'*':' ');
}}}}

仅减少了几个字符。 240 个字符:

class S{
public static void main(String[]a){
int n=Byte.decode(a[0]),c=(n-5)/4*2+1,d=c+2,g,h,x,y=-c;
for(;y<n-2-c;y++){
for(x=-d;x<=n-d;x++){
g=x>0?x:-x;h=y>0?y:-y;
System.out.print(x==n-d?'\n':(g%2==1&h<=g|h%2==1&g<=h)^(x<0&x==y-1)?'*':' ');
}}}}

Java, 265 250 245 240 chars

Rather 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:

public class Spr2 {

  public static void main(String[] args) {
    int n = Integer.parseInt(args[0]);
    int cy = (n - 5) / 4 * 2 + 1;
    int cx = cy + 2;
    for (int y = n - 3; y >= 0; y--) {
      for (int x = 0; x < n; x++) {
        int dx = cx - x;
        int dy = cy - y;
        int adx = Math.abs(dx);
        int ady = Math.abs(dy);
        boolean c = (dx > 0 && dx == dy + 1);
        boolean b = ((adx % 2 == 1 && ady <= adx) || (ady % 2 == 1 && adx <= ady)) ^ c;
        System.out.print(b ? '*' : ' ');
      }
      System.out.println();
    }
  }

}

A brief explanation for the above:

cx,cy = center
dx,dy = delta from center
adx,ady = abs(delta from center)
c = correction factor (whether to invert)
b = the evaluation

Optimized down. 265 chars:

public class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),c=(n-5)/4*2+1,d=c+2,e,f,g,h,x,y;
for(y=0;y<n-2;y++){
for(x=0;x<=n;x++){
e=d-x;f=c-y;g=e>0?e:-e;h=f>0?f:-f;
System.out.print(x==n?'\n':(g%2==1&&h<=g||h%2==1&&g<=h)^(e>0&&e==f+1)?'*':' ');
}}}}

Updated. Now down to 250 chars:

class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),c=(n-5)/4*2+1,d=c+2,g,h,x,y;
for(y=-c;y<n-2-c;y++){
for(x=-d;x<=n-d;x++){
g=x>0?x:-x;h=y>0?y:-y;
System.out.print(x==n-d?'\n':(g%2==1&&h<=g||h%2==1&&g<=h)^(x<0&&x==y-1)?'*':' ');
}}}}

Shaved just a few more characters. 245 chars:

class S{
public static void main(String[]a){
int n=Integer.parseInt(a[0]),c=(n-5)/4*2+1,d=c+2,g,h,x,y=-c;
for(;y<n-2-c;y++){
for(x=-d;x<=n-d;x++){
g=x>0?x:-x;h=y>0?y:-y;
System.out.print(x==n-d?'\n':(g%2==1&h<=g|h%2==1&g<=h)^(x<0&x==y-1)?'*':' ');
}}}}

Shaved just a few more characters. 240 chars:

class S{
public static void main(String[]a){
int n=Byte.decode(a[0]),c=(n-5)/4*2+1,d=c+2,g,h,x,y=-c;
for(;y<n-2-c;y++){
for(x=-d;x<=n-d;x++){
g=x>0?x:-x;h=y>0?y:-y;
System.out.print(x==n-d?'\n':(g%2==1&h<=g|h%2==1&g<=h)^(x<0&x==y-1)?'*':' ');
}}}}
债姬 2024-09-04 03:45:25

OCaml,299 个字符

这是 OCaml 中的一个解决方案,不是最短的,但我相信相当可读。

它仅使用字符串操作,因为您可以通过镜像前一个螺旋来构建螺旋。

假设您从 n = 5 开始:

55555
5   5
555 5

现在 n = 7:

7777777
7     7
5 555 7
5   5 7
55555 7

您看到所有 5 都去了哪里吗?

这是仅使用 OCaml 提供的有限库的未混淆代码:

(* The standard library lacks a function to reverse a string *)
let rev s =
  let n = String.length s - 1 in
  let r = String.create (n + 1) in
    for i = 0 to n do
      r.[i] <- s.[n - i]
    done;
    r
;;

let rec f n =
  if n = 5 then
    [
      "*****";
      "*   *";
      "*** *"
    ]
  else
    [
      String.make n '*';
      "*" ^ (String.make (n - 2) ' ') ^ "*"
    ] @ ( 
      List.rev_map (fun s -> (rev s) ^ " *") (f (n - 2))
    )
;;

let p n =
  List.iter print_endline (f n)
;;

let () = p (read_int ());;

这是长度为 299 个字符的混淆版本:

open String
let rev s=
  let n=length s-1 in
  let r=create(n+1)in
    for i=0 to n do r.[i]<-s.[n-i]done;r
let rec f n=
  if n=5 then["*****";"*   *";"*** *"]else
    [make n '*';"*"^(make (n-2) ' ')^"*"]
    @(List.rev_map(fun s->(rev s)^" *")(f(n-2)));;
List.iter print_endline (f(read_int ()))

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:

55555
5   5
555 5

Now with n = 7:

7777777
7     7
5 555 7
5   5 7
55555 7

Did you see where all the 5's went ?

Here is the unobfuscated code using only the limited library provided with OCaml:

(* The standard library lacks a function to reverse a string *)
let rev s =
  let n = String.length s - 1 in
  let r = String.create (n + 1) in
    for i = 0 to n do
      r.[i] <- s.[n - i]
    done;
    r
;;

let rec f n =
  if n = 5 then
    [
      "*****";
      "*   *";
      "*** *"
    ]
  else
    [
      String.make n '*';
      "*" ^ (String.make (n - 2) ' ') ^ "*"
    ] @ ( 
      List.rev_map (fun s -> (rev s) ^ " *") (f (n - 2))
    )
;;

let p n =
  List.iter print_endline (f n)
;;

let () = p (read_int ());;

Here is the obfuscated version which is 299 characters long:

open String
let rev s=
  let n=length s-1 in
  let r=create(n+1)in
    for i=0 to n do r.[i]<-s.[n-i]done;r
let rec f n=
  if n=5 then["*****";"*   *";"*** *"]else
    [make n '*';"*"^(make (n-2) ' ')^"*"]
    @(List.rev_map(fun s->(rev s)^" *")(f(n-2)));;
List.iter print_endline (f(read_int ()))
烈酒灼喉 2024-09-04 03:45:25

C#, 292 262 255 chars

简单做法:从外向内,逐行绘制螺旋线。

using C=System.Console;class P{static void Main(string[]a){int A=
1,d=1,X=int.Parse(a[0]),Y=X-2,l=X,t=0,i,z;while(l>2){d*=A=-A;l=l<
4?4:l;for(i=1;i<(A<0?l-2:l);i++){C.SetCursorPosition(X,Y);C.Write
("*");z=A<0?Y+=d:X+=d;}if(t++>1||l<5){l-=2;t=1;}}C.Read();}}

C#, 292 262 255 chars

Simple approach: draw the spiral line by line from the outside in.

using C=System.Console;class P{static void Main(string[]a){int A=
1,d=1,X=int.Parse(a[0]),Y=X-2,l=X,t=0,i,z;while(l>2){d*=A=-A;l=l<
4?4:l;for(i=1;i<(A<0?l-2:l);i++){C.SetCursorPosition(X,Y);C.Write
("*");z=A<0?Y+=d:X+=d;}if(t++>1||l<5){l-=2;t=1;}}C.Read();}}
冬天的雪花 2024-09-04 03:45:25

Ruby (1.9.2) — 126

f=->s{s<0?[]:(z=?**s;[" "*s]+(s<2?[]:[z]+f[s-4]<<?*.rjust(s))).map{|i|"* #{i} *"}<<z+"** *"}
s=gets.to_i;puts [?**s]+f[s-4]

Perl,你在哪里? )

Ruby (1.9.2) — 126

f=->s{s<0?[]:(z=?**s;[" "*s]+(s<2?[]:[z]+f[s-4]<<?*.rjust(s))).map{|i|"* #{i} *"}<<z+"** *"}
s=gets.to_i;puts [?**s]+f[s-4]

Perl, where are you? )

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文