스피로 그래프 시간!


14

Spirograph는 hypotrochoids와 epitrochoids를 그리는 장난감입니다. 이 도전을 위해, 우리는 hypotrochoids에 초점을 맞출 것입니다.

에서 위키 백과 :

hypotrochoid는 반경 R 의 고정 원 내부를 중심으로 회전 하는 반경 r 의 원에 연결된 점에 의해 추적되는 룰렛 이며 , 여기서 점은 내부 원의 중심으로부터 거리 d 입니다.

이에 대한 파라 메트릭 방정식은 다음과 같이 정의 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

여기서 θ 는 회전 원의 수평과 중심에 의해 형성된 각도입니다.


당신의 임무는 위에 정의 된 지점에 의해 추적 경로를 그릴 프로그램을 작성하는 것입니다. 입력으로 R , r , d 가 주어집니다 1과 200 사이의 모든 정수인 됩니다.

stdin, arguments 또는 user input에서이 입력을받을 수 있지만 프로그램으로 하드 코딩 할 수는 없습니다. 가장 편리한 형태로 받아 들일 수 있습니다. 문자열, 정수 등으로

취하다:

  • 입력 단위는 픽셀 단위로 제공됩니다.
  • R > = r

출력은 입력에 의해 정의 된 hypotrochoid의 그래픽 표현이어야합니다. ASCII 또는 기타 텍스트 기반 출력은 허용되지 않습니다. 이 이미지는 파일로 저장하거나 화면에 표시 할 수 있습니다. 선택한 입력에 대한 스크린 샷 또는 출력 이미지를 포함하십시오.

대비 제한에 따라 경로 / 배경에 대해 원하는 색상을 선택할 수 있습니다. 두 가지 색상은 스케일의 절반 이상에 HSV 'Value'구성 요소가 있어야합니다. 예를 들어에서 HSV를 측정하는 경우 [0...1]최소한 0.5차이 가 있어야합니다 . 사이 [0...255]에는 최소한의 128차이 가 있어야합니다 .


이것은 코드 골프이며 바이트 단위의 최소 소스 코드 크기입니다.


우리는 가정 할 수 R > r또는 R ≥ r? (동일에 rd.)
마틴 청산

10
2000 번째 질문을 축하합니다. ;-)
Doorknob

@ m.buettner로 제한 R>=r되지만 1-200 범위의 어느 곳에 나있을 수 있습니다. dr
Geobits

우리는 어떤 종류의 해결책에 대해 이야기하고 있습니까?
Kyle Kanos

@KyleKanos 입력이 픽셀 단위이고 각각의 캡이 200이기 때문에 주어진 798x798보다 커서는 안됩니다 R=200, r=1, d=200. 원하는 경우 이미지를 입력 크기로 조정하거나 모두 보이는 한 일정한 크기로 유지할 수 있습니다.
Geobits

답변:


8

Mathematica, 120 바이트

f[R_,r_,d_]:=ParametricPlot[p#@t+#[-p*t/r]d&/@{Cos,Sin},{t,0,2r/GCD[p=R-r,r]Pi},PlotRange->400,ImageSize->800,Axes->0>1]

ungolfed 코드 및 예제 출력 : enter image description here

플롯에 축을 포함시킬 수 있으면 다른 9자를 저장할 수 있습니다.


5

자바 스크립트 (ECMAScript를 6) - (312 개) 314 문자

document.body.appendChild(e=document.createElement("canvas"))
v=e.getContext("2d")
n=(e.width=e.height=800)/2
M=Math
P=2*M.PI
t=0
p=prompt
r=p('r')
R=p('R')-r
d=p('d')
X=x=>n+R*M.cos(t)+d*M.cos(R/r*t)
Y=x=>n+R*M.sin(t)-d*M.sin(R/r*t)
v.beginPath()
v.moveTo(X(),Y())
for(;t<R*P;v.lineTo(X(),Y()))t+=P/2e4
v.stroke()

JS 피들

출력 예

r = 1, R = 200, d = 30

enter image description here


나는 그것을 좋아하지만, ikt는 어떻게 든 망가졌다. R.의 예제를보십시오
edc65

마지막 라인이 될 수있다 (; t <R * P] v.lineTo (X (), Y ())) + t = P / R
edc65

@ edc65 그것은 깨진 것이 아니며 단지 그 예에서 전체 회전을 수행하기에 충분한 반복을 수행하지 않았습니다. 반복을 9 * PI에서 R * 2 * PI로 증가 시켰으며 더 좋을 것입니다 (그러나 PI / 1000에서 증가량을 남겨 두지 않으면 작은 값의 R이 깨질 수 있습니다).
MT0

3

파이썬 : 579

요약

이것은 Mathematica 답변이 주어지면 전혀 경쟁력이 없지만 사진이 예쁘고 누군가에게 영감을 주거나 누군가에게 유용 할 수 있기 때문에 어쨌든 게시하기로 결정했습니다. 그것이 훨씬 더 크기 때문에 나는 기본적으로 골퍼를 두지 않았습니다. 프로그램은 R, r, d의 명령 행 입력을 예상합니다.

스크린 샷

다음은 두 가지 예입니다 (하나는 (5,3,5) 및 하나는 (10,1,7)). example 5-3-5 example 10-1-7

암호

import math
import matplotlib.pyplot as P
from matplotlib.path import Path as H
import matplotlib.patches as S
import sys
a=sys.argv
(R,r,d)=int(a[1]),int(a[2]),int(a[3])
v=[]
c=[]
c.append(H.MOVETO)
t=0
while(len(v)<3 or v.count(v[-1])+v.count(v[-2])<3):
 p=t*math.pi/1000
 t+=1
 z=(R-r)*p/r
 v.append((round((R-r)*math.cos(p)+d*math.cos(z),3),round((R-r)*math.sin(p)-d*math.sin(z),3)))
 c.append(H.LINETO)
c.pop()
v.append((0,0))
c.append(H.CLOSEPOLY)
f=P.figure()
x=f.add_subplot(111)
x.add_patch(S.PathPatch(H(v,c)))
l=R+d-r
x.set_xlim(-l-1,l+1)
x.set_ylim(-l-1,l+1)
P.show()

2
비율을 조정할 수 있습니까? 이미지가 세로로 압축 된 것 같습니다.
AL

3

펄 / Tk의 - 239 227

use Tk;($R,$r,$d)=@ARGV;$R-=$r;$s=$R+$d;$c=tkinit->Canvas(-width=>2*$s,-height=>2*$s)->pack;map{$a=$x;$b=$y;$x=$s+$R*cos($_/=100)+$d*cos$_*$R/$r;$y=$s+$R*sin($_)-$d*sin$_*$R/$r;$c->createLine($a,$b,$x,$y)if$a}0..628*$s;MainLoop

R = 120, r = 20, d = 40 :

R = 120, r = 20, d = 40

R = 128, r = 90, d = 128 :

R = 128, r = 90, d = 128

R = 179, r = 86, d = 98 :

R = 179, r = 86, d = 98


2

가공, 270

import java.util.Scanner;
void setup(){size(500, 500);}
Scanner s=new Scanner(System.in);
int R=s.nextInt(),r=s.nextInt(),d=s.nextInt();
void draw(){
  int t=width/2,q=(R-r);
  for(float i=0;i<R*PI;i+=PI/2e4)
    point(q*sin(i)-d*sin(i*q/r)+t,q*cos(i)+d*cos(i*q/r)+t);
}

입력은 한 줄에 하나씩 콘솔을 통해 입력됩니다.

R = 65, r = 15, d = 24 스크린 샷 : 여기에 이미지 설명을 입력하십시오


2

지오 지브라, 87

즉, GeoGebra를 유효한 언어로 생각하면 말입니다.

R=2
r=1
d=1
D=R-r
Curve[D*cos(t)+d*cos(D*t/r),D*sin(t)-d*sin(D*t/r),t,0,2π*r/GCD[D,r]]

GeoGebra 입력 바의 입력을 승인합니다 <variable>=<value>(예 :) R=1000.

전체 이미지를 보려면 확대 / 축소 크기를 수동으로 변경해야 할 수도 있습니다.

스크린 샷

(창 아래쪽에있는 것은 내가 말한 입력 막대입니다)

여기에서 온라인으로 사용해보십시오 .


1
Kyle Kanos의 제출과 동일한 제한이 있다고 가정합니다. 크기를 픽셀 단위로 지정할 수 없습니다.
Martin Ender

@ m.buettner 네 맞아요 ... 놓쳤습니다
user12205

2

HTML + 자바 스크립트 256286303

편집 moveTo에 대한 첫 번째 호출을 제거하면 어쨌든 작동합니다. 더 많은 커팅 beginPath를 저장할 수는 있지만 처음에만 작동합니다.

Edit2 30 바이트가 thx @ ӍѲꝆΛҐӍΛПҒЦꝆ에 저장되었습니다.

<canvas id=c></canvas>R,r,d:<input oninput="n=400;c.width=c.height=t=n+n;v=c.getContext('2d');s=this.value.split(',');r=s[1],d=s[2],R=s[0]-r;v.beginPath();for(C=Math.cos,S=Math.sin;t>0;v.lineTo(n+R*C(t)+d*C(R/r*t),n+R*S(t)-d*S(R/r*t)),t-=.02);v.stroke()">

테스트

텍스트 상자에 쉼표로 구분하여 입력 한 다음 Tab 키를 누릅니다

R,r,d:<input onchange="n=400;c.width=c.height=t=n+n;v=c.getContext('2d');s=this.value.split(',');r=s[1],d=s[2],R=s[0]-r;v.beginPath();for(C=Math.cos,S=Math.sin;t>0;v.lineTo(n+R*C(t)+d*C(R/r*t),n+R*S(t)-d*S(R/r*t)),t-=.02);v.stroke()"><canvas id=c></canvas>


1
캔버스에 ID를 추가하고 querySelector를 사용하지 않고 전역에서 해당 ID를 사용할 수 없었습니다!
Mama Fun Roll

@ ӍѲꝆΛҐӍΛПҒЦꝆ yeeeeees 내가 할 수 있습니다. 2014
5

와우 그것은 생각했던 것보다 더 많은 바이트가 절약되었습니다.
Mama Fun Roll

2

R, 80 바이트

f=function(R,r,d){a=0:1e5/1e2;D=R-r;z=D*exp(1i*a)+d*exp(-1i*D/r*a);plot(z,,'l')}

그러나 '깨끗한'그림 (축 없음, 레이블 없음)을 원하면 코드가 약간 길어야합니다 (88 자).

f=function(R,r,d)plot((D=R-r)*exp(1i*(a=0:1e5/1e2))+d*exp(-1i*D/r*a),,'l',,,,,,'','',,F)

더 긴 버전의 f를 사용하는 코드 예제 :

f(R<-179,r<-86,d<-98);title(paste("R=",R,", r=",r," d=",d,sep=""))

일부 출력 예 :

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


이것은 입력 크기를 픽셀 단위로 사용하지 않습니까? 첫 번째 예는 두 번째 예의 거의 3 배가되어야합니다.
Martin Ender 2014 년

왜 모든 ,??
plannapus

쉼표는 인수를 구분하는 데 사용되었으며, 대부분 NULL이 아니 었습니다. 여기서 위치 인수 일치는 코드 길이를 줄이기 위해 사용되었습니다. 이것은 물론 나쁜 코딩 연습입니다. 권장되는 방법은 type = "l", xlabel = ""등과 같은 명명 된 인수 목록을 사용하는 것입니다 (그리고 중복 된 쉼표를 제거하십시오!).
Feng

1

C # 813은 999였습니다.

바이트 수를 줄이려면 약간의 작업이 필요합니다. 나는 그것을 조금 줄였습니다. 콘솔에서 공백으로 구분 된 3 개의 정수를 허용합니다.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
class P:Form
{
int R,r,d;
P(int x,int y,int z) {R=x;r=y;d=z;}
protected override void OnPaint(PaintEventArgs e)
{
if(r==0)return;
Graphics g=e.Graphics;
g.Clear(Color.Black);
int w=(int)this.Width/2;
int h=(int)this.Height/2;
List<PointF> z= new List<PointF>();
PointF pt;
double t,x,y;
double pi=Math.PI;
for (t=0;t<2*pi;t+=0.001F)
{
x=w+(R-r)*Math.Cos(t)+d*Math.Cos(((R-r)/r)*t);
y=h+(R-r)*Math.Sin(t)-d*Math.Sin(((R-r)/r)*t);
pt=new PointF((float)x,(float)y);
z.Add(pt);
}
g.DrawPolygon(Pens.Yellow,z.ToArray());
}
static void Main()
{
char[] d={' '};
string[] e = Console.ReadLine().Split(d);
Application.Run(new P(Int32.Parse(e[0]),Int32.Parse(e[1]),Int32.Parse(e[2])));
}
}

출력 샘플 :

스피로 그래프


1

쉘 스크립트 + gnuplot (153)

대부분의 노력은 축과 틱을 제거하고 크기와 범위를 설정하며 정밀도를 높이는 것입니다. 고맙게도, gnuplot은 골프를 즐기기에 자연 스럽기 때문에 대부분의 명령을 축약 할 수 있습니다. 문자를 저장하려면 출력을 이미지 파일로 수동으로 리디렉션해야합니다.

gnuplot<<E
se t pngc si 800,800
se pa
se sa 1e4
uns bor
uns tic
a=$1-$2
b=400
p[0:2*pi][-b:b][-b:b]a*cos($2*t)+$3*cos(a*t),a*sin($2*t)-$3*sin(a*t) not
E

다음과 같이 스크립트를 호출 spiro.sh 175 35 25>i.png하면 여기에 이미지 설명을 입력하십시오


1

R, 169 자

f=function(R,r,d){png(w=2*R,h=2*R);par(mar=rep(0,4));t=seq(0,R*pi,.01);a=R-r;x=a*cos(t)+d*cos(t*a/r);y=a*sin(t)-d*sin(t*a/r);plot(x,y,t="l",xaxs="i",yaxs="i");dev.off()}

들여 쓰기 :

f=function(R,r,d){
    png(w=2*R,h=2*R) #Creates a png device of 2*R pixels by 2*R pixels
    par(mar=rep(0,4)) #Get rid of default blank margin
    t=seq(0,R*pi,.01) #theta
    a=R-r
    x=a*cos(t)+d*cos(t*a/r)
    y=a*sin(t)-d*sin(t*a/r)
    plot(x,y,t="l",xaxs="i",yaxs="i") #Plot spirograph is a plot that fits tightly to it (i. e. 2*R by 2*R)
    dev.off() #Close the png device.
}

예 :

> f(65,15,24)

여기에 이미지 설명을 입력하십시오

> f(120,20,40)

여기에 이미지 설명을 입력하십시오

> f(175,35,25)

여기에 이미지 설명을 입력하십시오


1

SmileBASIC, 96 바이트

INPUT R,Q,D
M=R+MAX(Q,D)
S=R-Q@L
GPSET M+S*COS(I)+D*COS(S/Q*I),M+S*SIN(I)-D*SIN(S/Q*I)I=I+1GOTO@L

입력 : 50,30,50 :

여기에 이미지 설명을 입력하십시오


1

Befunge-98, 113 바이트

&&:00p-10p&20p"PXIF"4(10g'd:*:I10v>H40gF1+:"}`"3**`>jvI@
1(4"TURT"p04/d'*g02I/g00*p03/d'*g<^-\0/g00*g01:Fg03H:<0P

이 코드 는 일부 삼각법 계산을 위해 고정 소수점 수학 (FIXP) 지문을 사용합니다. TURT (Turtle Graphics)를 사용합니다. 의 경로를 그리기 위해 지문을 사용합니다.

Befunge의 거북이 그래픽은 로고 프로그래밍 언어 의 그래픽과 동작이 매우 유사합니다. . 출력 표면 주위를 조종하는 '거북이'(펜 역할)로 그립니다. 이것은 거북이를 특정 방향으로 향하게 한 다음 특정 거리만큼 앞으로 이동하도록 지시합니다.

이 시스템으로 작업하기 위해서는 원래의 스피로 그래프 방정식을 좀 더 거북이 친화적 인 것으로 조정해야했습니다. 이것이 최선의 접근 방법인지 확실하지 않지만, 내가 생각해 낸 알고리즘은 다음과 같이 작동합니다.

ratio = (R-r)/r
distance1 = sin(1°) * (R-r)
distance2 = sin(1° * ratio) * d
foreach angle in 0° .. 36000°:
  heading(angle)
  forward(distance1)
  heading(-ratio*angle)
  forward(distance2)

이것은 실제로 일종의 지그재그 패턴으로 경로를 그립니다. 그러나 이미지를 자세히 확대하지 않으면 실제로 눈에 띄지 않습니다.

다음은 R = 73, r = 51, d = 45 매개 변수를 사용하는 예입니다.

여기에 이미지 설명을 입력하십시오

CCBIcfunge로 코드를 테스트했습니다. 둘 다 SVG 이미지 형식으로 출력을 생성합니다. 이것은 확장 가능한 벡터 형식이므로 결과 이미지의 픽셀 크기는 없습니다. 화면 크기에 맞게 크기가 조정됩니다 (최소한 브라우저에서 볼 때). 위의 예는 수동으로 자르고 크기를 조정 한 화면 캡처입니다.

이론적으로 코드는 Rc / Funge 에서도 작동 할 수 있지만이 경우 출력을 창으로 렌더링하려고하기 때문에 XWindows가있는 시스템에서 실행해야합니다.


0

wxMaxima : 110

f(R,r,d):=plot2d([parametric,(p:R-r)*cos(t)+d*cos(t*(p)/r),(p)*sin(t)-d*sin(t*(p)/r),[t,0,2*%pi*r/gcd(p,r)]]);

이것은를 통해 대화식 세션에서 호출됩니다 f(#,#,#). 샘플로 다음을 고려하십시오 f(3,2,1).

여기에 이미지 설명을 입력하십시오


나는 꽤 출력이 마음에 들지만 이것이 "1에서 200 사이의 정수"또는 "픽셀로 주어진"방식을 따르는 방법을 잘 모르겠습니다.
Geobits

입력은 정수 또는 부동 수 일 수 있습니다. wxMaxima는 어쨌든 작업을 수행하기 위해 부동으로 변환합니다. 정수를 사용하여 이미지를 업데이트합니다. 입력에 대해서도 픽셀로 더 생각해야합니다.
Kyle Kanos

예, 내부적으로 변환 할 것이라고 생각했지만 문제가되지 않습니다. 입력에 대한 정수 제약 조건은 주로 닫힌 루프를 더 쉽게 얻는 것입니다 (그들은 더 잘 보입니다).
Geobits

0

라켓

#lang racket/gui
(require 2htdp/image)

(define frame (new frame%
                   [label "Spirograph"]
                   [width 300]
                   [height 300]))

(define-values (R r d) (values 50 30 10)) ; these values can be adjusted;

(new canvas% [parent frame]
     [paint-callback
      (lambda (canvas dc)
        (send dc set-scale 3 3)
        (for ((t (in-range 0 (* 10(* R pi)) 1)))
          (define tr (degrees->radians t))
          (define a (- R r))
          (define x (+ (* a (cos tr))
                       (* d (cos (* tr (/ a r))))))
          (define y (- (* a (sin tr))
                       (* d (sin (* tr (/ a r))))))
          (send dc draw-ellipse (+ x 50) (+ y 50) 1 1)))])

(send frame show #t)

산출:

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.