复活节代码高尔夫会议比 Spiral 更合适?嗯,我猜几乎都是。
字符数最短的代码显示由星号('*')组成的漂亮ASCII螺旋。
输入是单个数字 R
,它将是Spiral的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 ......
答案 0 :(得分:15)
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。请注意,我是一个全局变量,即使它可能不是很明显!当我是偶数时它用空格填充行的中间,否则用星星填充。 (〜%2是一种令人讨厌的方式来获得i%2 == 0的效果,但实际上根本不需要,因为我应该简单地交换“*”和“”。)我们首先画出顶部随着i增加螺旋行,然后我们绘制底部行减少i。我们将r降低2并使用后缀“*”来获得右侧的星列。
答案 1 :(得分:6)
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));
}
}
只有1/6比Python似乎不太糟糕;)
以下是正确的缩进:
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));
}
}
答案 2 :(得分:6)
许多答案都是从空白处开始并添加*
s,但我认为从星空开始并添加空格可能更容易。
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-array的不同部分,因此去做。其余的基于对'空白绘画'的视觉洞察力是直截了当的。我正在打印一个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
可以是上一行的一部分。 z
和i
大部分是多余的,我可以用另一个来计算一个。
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
很长,重新做数学运算,所以我可以在循环中(向上)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
稍微紧缩会产生最终解决方案。
答案 3 :(得分:4)
欢迎所有评论:
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)
答案 4 :(得分:4)
尝试了一种递归方法,从内部最外部的方法开始构建方块。我使用 Groovy 。
*********
*********
*********
*********
*********
*********
******* *
*********
* *
* *
* *
* *
* * *
******* *
*********
* *
* ***** *
* ***** *
* *** * *
* * *
******* *
*********
* *
* ***** *
* * * *
* *** * *
* * *
******* *
依旧......
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
编辑:通过填充方块然后覆盖它们来改进(查看新示例):所以我避免填充矩形的边缘而是整个边缘。
答案 5 :(得分:3)
我是打高尔夫球的新手,所以我离开了标记,但我想我会试一试。
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}
答案 6 :(得分:3)
我不是预先分配矩形缓冲区并填充它,而是循环遍历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)?'*':' ');
}}}}
答案 7 :(得分:3)
这是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 ()))
答案 8 :(得分:2)
简单的方法:从外面逐行绘制螺旋线。
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();}}
答案 9 :(得分:2)
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,你在哪里? )