started at ; stage 2 at ; ended at
I've had it with these prompts, man... your challenge is to, uh, squints at paper make a spirograph. submissions may be written in any language.
a spirograph is a sort of toy that lets you draw geometric shapes known as hypotrochoids and epitrochoids by rolling a disc around a ring.
today we will emulate this behaviour. given a radius r
, a larger radius R
, and a distance value d
, the goal is to trace out the line drawn by a point
of distance d
from a circle of radius abs(r)
rolling around a circle of radius R
.
if r
is negative, the result is an epitrochoid and the r
circle rolls around the outside of the R
circle, such as in this example with R = 3
, r = -1
, and d = 0.5
:
otherwise, it is a hypotrochoid and it rolls on the inside, such as in this example with R = 5
, r = 3
, and d = 5
:
your challenge is to create a program that renders and displays one of these shapes, given the three parameters. you are only required to output the final shape; in the examples above, the only thing to be returned would be the path of the red line at the end of the animation. as any language is allowed, and the output is visual, there is no fixed API.
you can download all the entries
written by indigo (away until 9/26)
submitted at
0 likes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | e ← ⍸⍣¯1 cycloid ← { R ← 1⌷⍺ r ← 2⌷⍺ d ← 3⌷⍺ x ← ((R - r) × (2 ○ ⍵)) + d × 2 ○ ⍵ × (R - r) ÷ r y ← ((R - r) × (1 ○ ⍵)) - d × 1 ○ ⍵ × (R - r) ÷ r x y } plot ← { bin ← (⍳ ⍺ ⍺) ∊ ⌈ (⍺ ÷ 2) + ⍵ (⊂⍺ ⍺ ⍴ 1 + bin) ⌷ ' o' } draw ← { size ← 1⌷⍺ resolution ← 2⌷⍺ R ← 1⌷⍵ r ← 2⌷⍵ d ← 3⌷⍵ cycle ← | 2 × resolution × (R ∧ r) ÷ R size plot ↓⍉↑ ((size ÷ 2) ÷ R + d + |r) × ⍵ cycloid ○(⍳ cycle) ÷ resolution } ⎕ ← (50 50) draw (8 ¯2 0.3) |
written by Flamore
submitted at
0 likes
you have a skill issue
tiny error with args, just needs the Z adding
@@ -36 +36 @@
- function EpiX(R,r,d,t){
+ function EpiX(R,r,d,t,Z){
@@ -39 +39 @@
- function EpiY(R,r,d,t){
+ function EpiY(R,r,d,t,Z){
@@ -42 +42 @@
- function HypX(R,r,d,t){
+ function HypX(R,r,d,t,Z){
@@ -45 +45 @@
- function HypY(R,r,d,t){
+ function HypY(R,r,d,t,Z){
@@ -57,2 +57,2 @@
- let x = EpiX(R,r,d,t);
- let y = EpiY(R,r,d,t);
+ let x = EpiX(R,r,d,t,Z);
+ let y = EpiY(R,r,d,t,Z);
@@ -76,2 +76,2 @@
- let x = HypY(R,r,d,t)
- let y = HypY(R,r,d,t)
+ let x = HypY(R,r,d,t,Z);
+ let y = HypY(R,r,d,t,Z);
written by Zaya
submitted at
1 like
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | -- sample usage: love . 5 3 5 local R = arg[2] and tonumber(arg[2]) or 3 local r = arg[3] and tonumber(arg[3]) or -1 local d = arg[4] and tonumber(arg[4]) or 0.5 local max_radius = R + math.abs(r) + d local Rpx = R * 25 local rpx = r * 25 local dpx = d * 25 local x, y = max_radius * 25, max_radius * 25 local data = love.image.newImageData(1024, 1024) for angle = 0, 360, 0.1 do local x1 = Rpx * math.cos(angle * math.pi / 180) local y1 = Rpx * math.sin(angle * math.pi / 180) data:setPixel(x + x1, y + y1, 0, 0, 1, 1) end local img = love.graphics.newImage(data) local angle = 0 function love.draw() angle = angle - 1 local radius = (Rpx - rpx) local x1 = radius * math.cos(angle * math.pi / 180) local y1 = radius * math.sin(angle * math.pi / 180) local xo, yo = x + x1, y + y1 data:setPixel(xo, yo, 1, 1, 1, 1) local ratio = (1 - (R/r)) local x1 = dpx * math.cos(angle * ratio * math.pi / 180) local y1 = dpx * math.sin(angle * ratio * math.pi / 180) data:setPixel(xo + x1, yo + y1, 1, 0, 0, 1) img:replacePixels(data) love.graphics.draw(img, 0, 0, 0, 1, 1) end |
written by taswelll
submitted at
2 likes
1 2 3 4 5 6 7 8 9 10 | #!/bin/sh # USAGE: ./cg43.sh 6 5 1N (d R r) sed -i 's/return math.floor(x)/return Fraction(math.floor(x))/' x7/core.py echo P1 > img echo 640 480 >> img cp cg43.x7 cg43.x7.tmp echo "$* ;2" >> cg43.x7.tmp python -m x7 cg43.x7.tmp >> img pnmtopng img > img.png rm img cg43.x7.tmp |
1 2 | d.;p2D0.{Z+d;p+;p2*DJ2*;p*f- 6iM2*1+` d{_M1fT^*} Mi1fE1+*`` ZfD` 0fEf-`fp}M^*24*J24D`fp 355 113D:p d_&&`;p2**ed0>`N`24*Ji{M24D_d0+`f_f`d_+`lpf;1fp`D*;1` Z+}v_ppp480i640i0$$`E 320 240.Z24*+J`eE3iM^+1-`fp`f_s`s1$`p``EE |
written by seshoumara
submitted at
2 likes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | #!/usr/bin/dc -f [Problem]c # spirograph: hypotrochoids and epitrochoids (echo 'R r d' as input*) # https://cg.esolangs.gay/43/ [Restrictions]c # *negative numbers are given using _ prefix, not - which is a dc command # the SVG shape can't be saved to a file, only printed :( [main]c [ #save each input parameter to its own register ?sdsrsR #based on r's sign execute the approppriate shape drawing function 0lr>hlex ]sm #TODO: fix it!! [hypotrochoids]c [ #gen angle range using LCM(r,R)/R as scaling factor lrlRlLxlR/dsf 360*lSx10k #calculate plot coordinates, stored in x and y arrays [ ddddd #calculate x lRlr-rlAxlCx*r lRlr-lr/*lAxlCxld* +r:x #calculate y lRlr-rlAxlCx d*1r-lVxv *r lRlr-lr/*lAxlCx d*1r-lVxv ld* -r:y #loop back if there's still an angle to process z0r>_ ]ds_x #print then quit 0klpxqq ]sh #TODO: fix it!! [epitrochoids]c [ #make r positive lrlVxsr #gen angle range using no (1) scaling factor 1dsf 360*lSx10k #calculate plot coordinates, stored in x and y arrays [ ddddd #calculate x lRlr+rlAxlCx*r lRlr+lr/*lAxlCxld* -r:x #calculate y lRlr+rlAxlCx d*1r-lVxv *r lRlr+lr/*lAxlCx d*1r-lVxv ld* -r:y #loop back if there's still an angle to process z0r>_ ]ds_x #print then quit 0klpxqq ]se [print]c [ #gen angle range lf360*lSx #print SVG header [<?xml version="1.0" encoding="UTF-8" standalone="no"?>]nAP [<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ]n ["http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">]nAP [<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" ]n [xmlns:xlink="http://www.w3.org/1999/xlink">]nAP [ <path d="]n #add start point d[M ]n;xn[ ]nr;yn [ #add line segment d[ L ]n;xn[ ]nr;yn #loop back if there's still an angle to process z0r>_ ]ds_x #print SVG footer [ Z"/>]nAP[</svg>]nAP ]sp #TODO: fix it!! ######################### MATH ######################### #3: [stop] -> [0 1 2 3 ... stop] [seq]c [ 0r [ #push increment and float stop to top rd1+3R #push [increment stop] d3Rd_4Rr #loop back if stop != increment !=_ ]ds_x #pop stop d-+ ]sS #2: [a b] -> [GCD] [GCD]c [ #change to [max min] d3Rd_4Rr [r]s_>_ #Euclidean algorithm [ #change to [min max%min] d_3R% #loop back on non-zero remainder d0r>_ ]ds_x #pop remainder (0), GCD=min + ]sG #2: [a b] -> [LCM] [LCM]c [ #push [a b] d3Rd_4Rr #change to [|ab| GCD] *lVx _3RlGx #divide to get LCM / ]sL #1: [a] -> [cos] [COS]c [ 10k #Taylor serie dddddddd*******40320/r dddddd*****720/0r-r dddd***24/r d*2/0r- 1++++0k ]sC #1: [degrees] -> [radians] [d2g]c [ 10k #push 1 rad 180 3.1415926535 / #convert /0k ]sA #1: [a] -> [abs] [abs]c [ 10kd*v0k ]sV ######################################################## lmx |
written by LyricLy
submitted at
0 likes
1 2 3 | #!/usr/bin/env -S wolframscript -function -signature Integer Integer Real String -f (* wrong orientation for the r < 0 case but I don't think it matters *) ({R, r, d, file} |-> Export[file, ParametricPlot[{(R - r) Cos[t] + d Cos[t ((R - r) / r)], (R - r) Sin[t] - d Sin[t ((R - r) / r)]}, {t, 0, 2 Pi (LCM[R, r] / R)}]]) |
written by dadsdy
submitted at
0 likes
1 2 3 4 5 | Desmos Latex (paste in) c\left(t\right)=\left(\cos t,\sin t\right) f\left(r,R,d,t\right)=\left(R-r\right)c\left(t\left|r\right|\right)+d\operatorname{sgn}\left(r\right)c\left(t\operatorname{sgn}\left(r\right)\left(r-R\right)\right) f\left(3,5,5,t\right) f\left(-1,3,0.5,t\right) |
written by soup girl
submitted at
0 likes
Written out with signs. Formatted: https://discord.com/channels/346530916832903169/726738757092376627/1153756045315948685
/* I mean it's not
like anybody was
going to compile
it anyway lmao */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
void draw(int Rn,
int Rd,int rn,int rd,
int dn,int dd,char*
fn){int an=Rn*rd,
ad=Rd*rn,ae=ad;
double bn=an-ad;
while(ae)ae^=an
^=ae^=an%=ae;
ad/=an;double bd
=rd*Rd,w=bn/bd,
v=w*rd/rn,d=dn/
dd,m=512.0/(Rn*dd
*rd+Rd*dn*rd-Rd*
dd*rn)*Rd*dd*rd;
unsigned char*img
=calloc(1,1049600
);for(double t=0;t
<6.284*ad;t+=
0.0001){int x=(w*
cos(t)+d*cos(v*t))
*m-1; int y=(w*sin(
t)-d*sin(v*t))*m-1;
img[x-1024*y+
523776]=1;}FILE*
fp=fopen(fn,"w");
fputs("P3 1024 1"
"024 255 ",fp);for
(int i=0;i<1048576;
i++)fputs(img[i]?
"0 0 0 ":"255 255"
" 255 ",fp);fclose(
fp);free(img);}int
main(){draw(5,1,3,1
,5,1,"test1.ppm");
draw(5,1,31,10,5,1,
"test2.ppm");}
// code guessing
int main(){draw(5,1
,3,1,5,1,"test1.ppm"
);draw(5,1,31,10,
5,1,"test2.ppm");}
1 | cg: couldn't decode file contents |
written by Olivia
submitted at
2 likes
1 2 3 4 5 | function spironolactone(R,r,d) [~,D]=rat(R/abs(r));%D←R÷⍨R∧|r t=2i*pi*(0:1e-3:D);%t←({○0j2×⍳D×⍵}÷⊢)1000 plot((R-r)*exp(t)+d*exp(t-R/r*t))%]Plot (9∘○{⍺⍵}11∘○) ((R-r)×*t)+d×*t×1-R÷r end |
written by Palaiologos
submitted at
0 likes
1 2 3 4 5 6 7 8 | spiro←{ R r d←⍵⋄v←600 600⍴255 x←{((R+r)×2○⍵)+d×2○(⍵×R+r)÷r} y←{((R+r)×1○⍵)-d×1○(⍵×R+r)÷r} ⍺ {(⍺ 1)⎕NPUT⍨⊂(⍕255,⍨'P2',⍴⍵),' ',⍕,⍵} v⊣{ ⊢v[300+⌊20×x⍵;300+⌊20×y⍵]←0 }¨(⍳62831×(R∧|r)÷R)×1e¯4 } |
written by olus2000
submitted at
4 likes
1 2 | Try It Online: https://pico-8-edu.com/?c=AHB4YQYaAwDrwX4wefP9V58dnf0SySNkz-AEYXN79QZN9gwPEN5-w1F33XVRf0ybDhxW3XRXEdzVJkkb31UVQV0U1Um7a8HOzsAzDM0kD1C9wGEjg91Uv9AHa1Nj4drCQhQ-QNQU1dxMO74ydt-clg2OawobLCYrZogTR4wlo2NR_BLXpVbwyytUQ0sDD9FqBgQ7AyNS4sryZnGgG12wxtZEPxPF1dRasjUcLzTPsxY4xtATzTs5QmtgdmeqFRTHnr1fyR5zI2USjsTnjfo_z_LLG31tq_ep6pHttZmpCcWhfiHYUhcYWGjGHI-GESuOX5DnwZ6jNM2TiproCr_Rrvg5oSt_OH66Qo7SFT8W0pmkEVQJZ0ZHX6Pb6tdHF2eybCMWU38mmu49dFnilYlkvG03bkgH6jsVAxQTipXtdWMckY-V04POv1Ykg2cq9yXpxogv0lQw0PcpJAZmlhY3mpl2e37MA5ojaxvZkA_akZG4mgyLYmIiSRaSGcuuVE0SmUGjZF8NLvZGF28kckG6BvmOYbXDdA7LQ6f0hoUFzNAtzO-pz6wHbVUNjly5f0YYDi2kS004oCIyX1xh-lzQLsyktTPGAu_K0OwFt95hggP6sEsmFjTppbKyObCtb1PtHNEtHRBuh_N3bK2aTsC_vr5gf2NoZKGuZ4aadFEewhTrAweEO4U8pJZgo4CnpS1hONRMF9PFhqaJX-enHZE7XnuOP6qsqhzvyPFHlA2rjlc8e6Nv6mZhb6_feJE3OaIbjSebrXBlQWe_gZyPqpmwXKMSE6jEGk5pvnO6cUrh2jCkUrgXpoJtBYKsX0pFEIKlBUVd_UVviKZXQz7mEJ31gYBRHUs2rATW0mKzV3FDVzZN18wK9rpK_uApth7DGkb0l0Q71WaHcCdg3SNhMDUUJUMbReiqAzbKqHF9AtesbFRV0rgegSlWoyuGVtpbdARGjNgWSZ8uKtnDOvvVgH69REKS5ATLr3JEpHLPQ6SvVu_YT22-Q1bStjukW7E_tC8A&g=w-w-w-w1HQHw-w2Xw-w3Xw-w2HQH |
written by JJRubes
submitted at
3 likes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | let Rslider; let rslider; let dslider; function setup() { createCanvas(400, 400); background(0); Rslider = createSlider(0, 30, 5); Rslider.position(20, 20); rslider = createSlider(-15, 15, 3); rslider.position(220, 20); dslider = createSlider(0, 30, 5); dslider.position(20, 360); } const gcd = (a, b) => b == 0 ? a : gcd (b, a % b) const lcm = (a, b) => a / gcd (a, b) * b function hypoX(R, r, d, theta) { if (R == r) { return d * cos(theta); } return (R - r) * cos(theta) + d * cos((R - r) / r * theta); } function hypoY(R, r, d, theta) { if (R == r) { return d * sin(theta); } return (R - r) * sin(theta) - d * sin((R - r) / r * theta); } function scale_and_draw(R, r, d, rot) { let extent = TWO_PI * lcm(r, R) / R; let k = (width / 2 - 10) / (R - r + d); if (r > R) { k = (width / 2 - 10) / (r - R + d); } R *= k; r *= k; d *= k; noFill(); beginShape(); for(let i = 0; i < 1000; i++) { let x = hypoX(R, r, d, extent / 1000 * i); let y = hypoY(R, r, d, extent / 1000 * i); let acc_factor = mag(x, y); let wobble_dir = TWO_PI - TWO_PI * noise(5 * rot, x / 200, y / 200); let x_temp = x * cos(rot) - y * sin(rot) + 5 * cos(wobble_dir); y = x * sin(rot) + y * cos(rot) + 5 * sin(wobble_dir); x = x_temp; vertex(x + width / 2, y + height / 2); } endShape(CLOSE); } let rotation = 0; let smooth_vel = 0.001; function draw() { let R = Rslider.value(); let r = rslider.value(); if (r == 0) { r = 1/2; } let d = dslider.value(); background(0, 100); strokeWeight(2); stroke(255); let vel = mag(movedX / width, movedY / height); vel *= vel * 3; vel += 0.001; smooth_vel = 0.9 * smooth_vel + 0.1 * vel; scale_and_draw(R, r, d, rotation, smooth_vel); rotation += smooth_vel; } |
1 2 3 4 5 6 7 | html, body { margin: 0; padding: 0; } canvas { display: block; } |
written by luatic
submitted at
0 likes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | -- (c) 2021 🥺🥺🥺 -- this code was manualy cursed to meet the lowest standards ✅✅✅ -- "Inter-token spacing is the root of all evil." - Mahatma Gandhi local splurped={} do local ts={_G} local s={} repeat local ns={} local fr={} for _,t in pairs(ts) do s[t]=1 for k,v in pairs(t) do if fr[k]==nil then fr[k]=v else fr[k]=fr end if type(v)=="table" and not s[v] then ns[#ns+1]=v end end end for k,v in pairs(fr) do if splurped[k]==nil and v~=fr then splurped[k]=v end end ts=ns until#ts==0 end setfenv(1,setmetatable({},{__index=splurped})) local function mapva(f,...) if select("#",...)==0 then return end return f((...)),mapva(f,select(2,...)) end p,x,pts,stp=400,0,{},{} -- 400² is the HOLY RESOLUTION - DO NOT TOUCH! function love.load(args) R,r,d=mapva(tonumber,unpack(args)) m=p/(R-r+abs(d))*0.5*0.75 R,r,d=R*m,r*m,d*m mdt = min(abs(1/(R-r)),abs(r/(R-r)/d))/10 setTitle(((r<0)and"epi"or"hypo").."trochoid") setMode(p,p) end function love.update(fdt) n=ceil(fdt/mdt) dt=fdt/n for i=1,n do x=x-dt y=-x*(R-r)/r cx,cy=p/2,p/2 rx,ry=cx+(R-r)*cos(x),cy+(R-r)*sin(x) px,py=floor(rx-d*cos(y)),floor(ry-d*sin(y)) h=py*p+px if not stp[h] then stp[h]=1 insert(pts,{px,py}) end end end function love.draw() setColor(0,1,0,1) ellipse("line",cx,cy,R,R) ellipse("line",rx,ry,abs(r),abs(r)) line(rx,ry,px,py) setColor(1,0,0,1) points(pts) end |
1 2 3 | so uh i maded some sussy hax but they shoud work on LOVE 11.3 (Mysterious Mysteries) oh uh also run is "love . R r d" in foldr |
written by ultlang
submitted at
1 like
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # Code by LyricLy from PIL import Image from math import sin,cos,radians as rad,\ copysign as s i = Image.new(mode='L',size=(512,512)) s = 0 #code by code by code def tf(s,point): return (int(s*point[0]+256),int(\ s*point[1]+256)) def spiro(R,r,d): assert R>r s = 250/max(R,R-r,R-r+d) for a in range(3600): α=a*r/10 # Code by RocketRace p=(cos(rad(α))*R,sin(rad(α))*R) i.putpixel(tf(s, p),120) c=(p[0]-cos(rad(α))*r,p[1]-\ sin(rad(α))*r) i.putpixel(tf(s,c),80) δ=rad(α)+-1*rad(α)*R/r path=(cos(δ)*d+c[0],sin(δ)*d+c[1]) i.putpixel(tf(s,path),255) i.save("spiro.png") spiro(5,3,5) # coded by palaiologos |
written by razetime
submitted at
1 like
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from manim import * class e(Scene): def construct(self): r=float(input("r = ")) R=float(input("R = ")) d=float(input("d = ")) d/=r p=ValueTracker(0) C=Circle(radius=R) c=always_redraw(lambda:VGroup(Circle(radius=abs(r),color=GREEN),Dot().shift(abs(d*r)*RIGHT),Dot(),Line().set_length(d*r).shift(0.5*d*r*RIGHT)).rotate(p.get_value(),about_point=ORIGIN).move_to(C.get_center()).shift((R+r)*RIGHT).rotate(abs(r/R)*p.get_value(),about_point=C.get_center())) t=TracedPath(c[1].get_center) self.play(Create(C)) self.play(Create(c)) self.add(t) self.play(p.animate.set_value(20*PI), run_time=10, rate_func=rate_functions.linear) self.wait() with tempconfig({"quality": "medium_quality", "preview": True}): scene=e() scene.render() |
(R r d)←⍺
. You can thank me laterok i will thank you later
post a comment