Code Golf: art tirage ascii étoiles
-
04-10-2019 - |
Question
Depuis cette semaine Noone a posté un défi-golf de code, je vais faire un essai. Je le fais pour que vous puissiez faire autre chose que de jouer avec des épées au cours de ces longs cycles de compilation.
Le défi:
Dessine stars de l'art ASCII, compte tenu de trois chiffres sur l'entrée standard (nombre de pointes, le type d'étoile (étoile est tracée en joignant les sommets qui sont n sommets d'intervalle), et le diamètre de l'étoile). Exemples:
Input: Input: Input:
5 2 20 7 2 20 7 3 20
Output: Output: Output:
x x x
xx xx x
xx x xx xx xx x
x x x xxxx x xx xx
xx x x xxxxx x x x x xxx
xxxx x x xxxx x x x x x x
x xxx x xx x xx xxx x x x
x x xxxx x x xx x xxxxx xx x
x x xxx x x x x xx xxxxxx
x x x xxx x x x x x xx xxxxxx
x x xx x x x x x x xxx
x x x xxx x x x x xx xxxxxx
x x xxx x x x x xx xxxxxx
x x xxxx x x xx x xxxxx xx x
x xxx x xx x xx xxx x x x
xxxx x x xxxx x x x x x x
xx x x xxxxx x x x x xxx
x x x xxxx x xx xx
xx x xx xx xx x
xx x x x
x x x
Depuis pixelliser correctement les lignes peut être un PITA pour un défi-golf de code, je vais laisser une certaine marge de manœuvre, mais pas trop. D'autres exemples:
Assez bon:
x x x x
xx xx x x
x x x x
x xx xx x x x
x x x
x x x
xxx xxx x x
x x xxxxxxxxxxxxxxxxxxxxx
x x xx x x xx
xx x x xx xx x x xx
x x xxx xxx
xxxxxxxxxxxxxxxxxxxxx xxxxx
x x x xx xx x
x xx xx x
xxx xxx
x x xx x x xx
x
x
ne coupe pas:
x xx xx
xx x x
xx x x
x x xx xx
xx x x x x
xxxx x x x xx xx x
x xxxx x x
x xxxx x x x
x x xxx xxx xxx
xx x xxxxxx x x
xx x xxxxxx x x
xx xxx xx x x xx
x x xxx x x x
x xxx x xxxxxxxxxxxxxxxxxxxxx
xxx x x x x
xx x x
x x
x x x x
x x
xx
x
Lack of precission Lack of clipping
Amusez-vous!
La solution
Ruby - 323 276 304 297
a,b,c=gets.split.map &:to_i
o=(0..c).map{' '*c}
m=(1..a).map{|i|r=2*h=Math::PI*i/a
[(1+Math.sin(r))*c/2+0.5,(1+Math.cos(r))*c/2]}
a.times{|n|j,i,x,y=*m[n],*m[n-b]
j,x,i,y=i,y,j,x if k=((i-y)/(j-x))**2>1
s,z=[x,j].sort
s.to_i.upto(z){|m|t=i+(m-j)*(i-y)/(j-x)
k ?(o[t][m]='x'):(o[m][t]='x')}}
puts o
x xx x xx
x x x x x x
xx x x xx xx x x x
x x x xxxx x xx xx xxxxxxxxxxxxxxxx
xxx x x xxxxx xx x x x xx x x x x
x xxx x x xxxxx x x x x x x x x x x x
x xxx x xx x xx xxxx x xxx x x x xx
x x xxxx x x x x xxxxxx x xx x
x x xxx x x xxx x x xxxxx x xx
x x x xxx xx x x x xx x xxxxx xx x x
xx x xx xx x x xx x xxxx x x x
xx x xxx xx x x x xx x xxxx xx x x
x x xxx xx xxx x x xxxxx x xx
x x xxxx x x x x xxxxxxx x xx x
x xxx x xx x xx xxxx x xxx x x x xx
x xxx x x xxxxx x x x x x xx x x x x
xxx x x x xxxx xx x x x xx x x x x
x x x xxxx x x x x xxxxxxxxxxxxxxxx
x x x x xx xx x x x
xx x x xx x x
x xx x x
Autres conseils
C #: 555 428 caractères
using System.Drawing;class P{static void Main(string[]a){int p=int.Parse(a[0]),i=int.Parse(a[1]),l=int.Parse(a[2]),n;var o=System.Console.Out;var b=new Bitmap(l*4/3,l*4/3);var g=Graphics.FromImage(b);g.TranslateTransform(l/8,l/3);for(n=0;n<p;n++){g.DrawLine(Pens.Red,0,0,l,0);g.TranslateTransform(l,0);g.RotateTransform(360*i/p);}for(i=0;i<b.Height;i++,o.WriteLine())for(p=0;p<b.Width;p++)o.Write(b.GetPixel(p,i).A>0?"#":" ");}}
Stars 5 2 20
#
# #
# #
# #
# #
# #
#####################
## # # ##
# # # #
# # # #
## ##
## ##
# # # #
# ### #
# # # #
# ## ## #
# # # #
## ##
# #
OCaml, 659 caractères (wc -c).
Utilise l'algorithme classique Bresenham pour dessiner les lignes, faites récursif pour le plaisir.
Enregistrer sous stars.ml
et courir avec echo 5 2 20 | ocaml stars.ml
.
let pl b x y=b.(x).[y]<-'x'
let ln b x0 y0 x1 y1 =
let rec h p x0 y0 x1 y1 =
if x0>x1 then h p x1 y1 x0 y0
else(
let dx,dy,ys=x1-x0,abs(y1-y0),if y0<y1 then 1 else -1 in
let rec k x y e=
if x<=x1 then(
p y x;
if e<dy then k(x+1)(y+ys)(e-dy+dx)
else k(x+1)y(e-dy)
)in
k x0 y0(dx/2)
)in
if abs(y1-y0)>abs(x1-x0)then
h(fun x y->pl b y x)y0 x0 y1 x1
else h(pl b)x0 y0 x1 y1
let f=float
let g n s d=
let b=Array.init d(fun _->String.make d ' ')in
let r=f(d/2)-.0.1 in
let k h i=int_of_float(r+.r*.h(6.2831853*.(f(i mod n)/.(f n))))in
let x,y=k cos,k sin in
for i=0 to n do ln b(x i)(y i)(x(i+s))(y(i+s))done;Array.iter print_endline b
let()=Scanf.scanf"%d %d %d"g
Sorties
x x x
xx xxx xx
xx x x xxx xx x
x x x xxxxx x x x x
xx x x xxxxxx xx x x x xxx
xxxxx x x xxx x x x xxx x x x x
x xxxx x x x xx xxxxxxx xx x
x x xxx x x xx x xxxxx x
x x x xxxx x x x x x xx xxxxxx
x x xx xx x x xxx x xxx
x x xxx x x x xxx x xxxx
x x xxx xx xx x xx xxxx
x x xxxx x x xx x xxxxxx x
x xxx x x x x x xxxxx x xx x
xxxx x x xxx x x x xx x x x x
xx x x xxxxxx x x x x xxx
x x x xxxxx x x x x
xx x xx xxx xx x
xx x x xx
x x x
Ma première tentative de golf code ...
Python - 550 533 507 484 451 437 caractères
Enregistrer sous k.py
. Exécuter en tant python k.py 5 2 20
import sys,math as m
A=abs;R=range;X=round
p,t,w=map(int,sys.argv[1:])
G=[[' ']*-~w for i in R(w+1)]
def L(a,b,c,d):
s=A(d-b)>A(c-a)
if s:a,b,c,d=b,a,d,c
if a>c:a,b,c,d=c,d,a,b
f=c-a;e=f/2;y=int(X(b));x=int(X(a))
while x<X(c):
e-=A(d-b);p,q=((x,y),(y,x))[s];G[p][q]='x';x+=1
if e<0:y+=(-1,1)[y<d];e+=f
r=w/2;k=m.pi*2/p
s=[(m.sin(k*i)*r+r,m.cos(k*i)*r+r)for i in R(p+t)]
for i in R(p):L(*(s[i]+s[i+t]))
for i in G:print''.join(i)
(peut potentiellement sauver 2 autres caractères en remplaçant tiret 2ème niveau avec des onglets ...)
version élargie disponible ici: http://gist.github.com/591485
sortie Exemple:
x x x
xx xx x
xx x xx x xx x
x x x xxxxx xx xx
xx x x x xxxx x x x x xxx
xxxx x x xxxx x x x x x x
x xxx x xxx x xx xxx x x x
x x xxxx x x xx x xxxxx xx x
x x xxx x x x x xx xxxxxx
x x xxx x x x x x xx xxxxx
x x x x x x x xx xxx
x x x xxx x x x x xx xxxxx
x x xxx x x x x xx xxxx x
x xxxxx x x xx x xxxxx xx x
x xxx x xxx x xx xxx x xx x
x xxx x x xxxx x x x x x x
xx x x x xxxx x x xx xx x
x x x xxxxx xx xx
xx x xx x
x x x x
x
VBScript, 584 511 482 octets
J'ai aussi utilisé l'algorithme Bresenham pour les lignes.
g=Split(WScript.StdIn.ReadAll):t=g(1):d=g(2):ReDim r(d*d)
For i=0 To d*d:r(i)=" ":Next
c=1.57:u=(d-1)/2:b=c*4/g(0):For i=1 To g(0)
Z n:x=g:Z n+c:y=g:Z n-b*t:f=g:Z n-b*t+c:n=n+b
s=Abs(g-y)>Abs(f-x):If s Then W x,y:W f,g
If x>f Then W x,f:W y,g
p=f-x:q=Abs(g-y):h=p\2:v=(y>g)*2+1
For x=x To f:r((s+1)*(y*d+x)-s*(x*d+y))="x"
h=h-q:If h<0 Then y=y+v:h=h+p
Next:Next:For i=0 To d:WScript.Echo Mid(Join(r,""),i*d+1,d):Next
Sub W(a,b):e=a:a=b:b=e:End Sub
Sub Z(e):g=Int(u*Cos(e)+u):End Sub
Sortie:
x x x
xx xx x
xx x xx xxx xx x
x x x xxxx x xx xx
xx x x xxxxx x x x x xx
xxxx x x xxx x x x xx x x xx x
x xxx x x x xx xxxxxx x x
x x xxx x x xx x xxxx x
x x xxx x x x x xx xx xxx
xx x xxx x x x xx xx xxxx
xx x xx x x x xx xx xxx
x x x xxxx x x x x xx xx xxxxxx
x x xxx x x xxx x xxxxxxx
x xxx x x x x x xxxx x x
xxxxx x x xxx x xx xxx x x xx x
xx x x xxxxx xx x x x xx
x x x xxxx x xx xx
xx x x xxx xx x
xx xxx x
x x x
Code élargi:
Dim PI, args, output, i
PI = 4 * Atn(1)
args = Split(WScript.StdIn.ReadAll, " ")
output = Join(Star(args(0), args(1), args(2)), vbNullString)
For i = 1 To Len(output) Step args(2)
WScript.Echo Mid(output, i, args(2))
Next
Function Star(spikes, star_type, diameter)
Dim result(), i, vertexes(), angle, radius, p1, p2
ReDim result(diameter * diameter - 1)
ReDim vertexes(spikes - 1)
For i = 0 To UBound(result)
result(i) = " "
Next
radius = (diameter - 1) / 2
For i = 0 To UBound(vertexes)
vertexes(i) = Array(CLng(radius * Cos(angle) + radius), _
CLng(radius * Sin(angle) + radius))
angle = angle - (2 * PI / spikes)
Next
For i = 0 To UBound(vertexes)
p1 = vertexes(i)
p2 = vertexes((i + star_type) Mod spikes)
DrawLine p1(0), p2(0), p1(1), p2(1), result, diameter
Next
Star = result
End Function
Sub DrawLine(ByVal x0, ByVal x1, ByVal y0, ByVal y1, arr, diameter)
Dim steep, deltax, deltay, error, ystep
steep = Abs(y1 - y0) > Abs(x1 - x0)
If steep Then
Swap x0, y0
Swap x1, y1
End If
If x0 > x1 Then
Swap x0, x1
Swap y0, y1
End If
deltax = x1 - x0
deltay = Abs(y1 - y0)
error = deltax \ 2
If y0 < y1 Then ystep = 1 Else ystep = -1
For x0 = x0 To x1
If steep Then
arr(x0 * diameter + y0) = "x"
Else
arr(y0 * diameter + x0) = "x"
End If
error = error - deltay
If error < 0 Then
y0 = y0 + ystep
error = error + deltax
End If
Next
End Sub
Function Swap(a, b)
Dim temp
temp = a
a = b
b = temp
End Function
Javascript (basé sur la solution de python de Isc), 598 591 586 559 octets (utilisé avec la coquille de rhinocéros: Enregistrer sous « stars.js », dirigé par 'rhino stars.js 7 2 20'):
for(var a=Math,b=parseInt,c=a.floor,d=a.abs,e=arguments,f=b(e[0]),g=b(e[1]),h=b(e[2]),i=[],j=0;j<(h+1)*h;j++)i.push((j+1)%(h+1)?" ":"\n");function k(w,x){i[x*(h+1)+w]="x"}var l=(h-1)/2,m=[];for(j=0;j<f;j++)m.push([c(l*a.cos(a.PI*2/f*j)+h/2),c(l*a.sin(a.PI*2/f*j)+h/2)]);
for(j=0;j<f;j++){var n=m[j][0],o=m[j][1],p=m[(j+g)%f][0],q=m[(j+g)%f][1],r=void 0,s=void 0;if(r=d(q-o)>d(p-n)){s=n;n=o;o=s;s=p;p=q;q=s}if(n>p){s=n;n=p;p=s;s=o;o=q;q=s}for(var t=p-n,u=0,v=d(q-o)/t,y=o<q?1:-1,z=o,A=n;A<=p;A++){r?k(z,A):k(A,z);u+=v;if(u>=0.5){z+=y;u-=1}}}print(i.join(""));
Sortie:
x xx xx x x xx x x xxxx x x x xxx x x x xxx x x xxx xx x xxx xx x xx x x x xxxx x x xxx x xxx x xxxxx x x xx x x x x xx xx x x xx x x xxx x xxxx x xxxxx x x xxx x x x x x xx x x x x x xxx x x x x x x x x x xx x x xx x x x xxx x xxx xxxxx x x x xxxx x x xx xxx xx x x x xx x xx xx x x xx xx x x xx x xxxxxx x x x xxxx x xx xx xxxx xx xx xxxx xx xx xxx xx xx xxxxxx x xxxxxxx x xxxx x x xxx x x xx x x x xx xx xx xx x x x
Code élargi:
var p = parseInt(arguments[0]),
t = parseInt(arguments[1]),
w = parseInt(arguments[2]);
var g = [];
for(var i = 0; i < (w + 1) * w; i++)
g.push((i + 1) % (w + 1) ? ' ' : '\n');
function plot(x, y) { g[y * (w + 1) + x] = 'x';}
function line(x0, y0, x1, y1) {
var steep = Math.abs(y1 - y0) > Math.abs(x1 - x0), temp;
if(steep) {
temp = x0; x0 = y0; y0 = temp;
temp = x1; x1 = y1; y1 = temp;
}
if(x0 > x1) {
temp = x0; x0 = x1; x1 = temp;
temp = y0; y0 = y1; y1 = temp;
}
var deltax = x1 - x0;
var deltay = Math.abs(y1 - y0);
var error = 0;
var deltaerr = deltay / deltax;
var ystep
var y = y0;
if(y0 < y1) ystep = 1; else ystep = -1;
for(var x = x0; x <= x1; x++) {
if(steep) plot(y,x); else plot(x,y);
error = error + deltaerr;
if(error >= 0.5) {
y = y + ystep;
error = error - 1.0;
}
}
}
var r = (w-1)/2, points = [];
for(var i = 0; i < p; i++) {
points.push([
Math.floor(r * Math.cos(Math.PI * 2 / p * i) + w/2),
Math.floor(r * Math.sin(Math.PI * 2 / p * i) + w/2)
]);
}
for(var i = 0; i < p; i++) {
line(points[i][0], points[i][1], points[((i + t) % p)][0], points[((i + t) % p)][1]);
}
print(g.join(''));