9
\$\begingroup\$

Not to be confused with this question.

You need to draw a times table (also known as Cremona's method for cardioid generation) as shown in this video. The number \$n\$ and \$k\$ will be the inputs.

In the video n and k are 2 and 10 respectively.


How to draw?

  1. Draw a circle, divide its perimeter into equal spaced parts with \$k\$ points and number them with \$0, 1, 2, \dots, k-1\$ .
  2. Draw \$k\$ line segments between \$i\$ and \$i\times n \mod k\$   for all integers \$i\$, \$0 \le i < k\$.

You can use any graphing library that your language allows.

Remember this is a so keep the answer short and sweet.


Examples

Input : n = 2 and k = 27

Input : n = 5 and k = 10

You can also play around with it here. The modulus/points is \$k\$ while multiplication factor is \$n\$.


Challenge

You need to draw at least the circle and the lines.

You can output any file format (svg, png, jpeg) and HTML rendering is also allowed.

You can also write the image to STDOUT


Best of luck because you are going to need it!

\$\endgroup\$
6
  • \$\begingroup\$ From the looks of it, this seems to be Cremona's method for cardioid generation. Related Mathematica SE question. \$\endgroup\$ Commented Jul 13, 2018 at 19:23
  • 4
    \$\begingroup\$ Your description seems to confuse K with N sometimes. I had to read it a couple times to see what you meant. \$\endgroup\$
    – mypetlion
    Commented Jul 13, 2018 at 19:36
  • \$\begingroup\$ What do we need to draw, specifically? Just the lines? Circle and the points too? \$\endgroup\$ Commented Jul 13, 2018 at 19:42
  • 3
    \$\begingroup\$ Frankly, this question should have been posted on the Sandbox and left there for some time (at least a few days). However, since this challenge is already posted, I advise that you keep it here, but make as many clarifications as possible before someone answers the question (to prevent invalidating answers). \$\endgroup\$ Commented Jul 13, 2018 at 19:46
  • 3
    \$\begingroup\$ I like this challenge, and I don't want it to end up being closed. I therefore suggest clarifying what exactly has to be included in the output: the circle, the points and the lines, the lines and the points, the lines only, etc. \$\endgroup\$
    – Mr. Xcoder
    Commented Jul 13, 2018 at 19:55

14 Answers 14

4
\$\begingroup\$

Python 2, 280 241 235 233 bytes

from math import*
n,k=input()
a=2*pi/k
s='<svg viewBox="-49 -49 98 98"><circle r="49"/><path d="'
p=0;exec"s+='M%f,%f L%f,%f '%(49*cos(p),49*sin(p),49*cos(p*n),49*sin(p*n));p+=a;"*k
open('c.svg','w').write(s+'" stroke="red"/></svg>')

Try it online!

Saved 35 bytes due to removing xmlns attribute at the encouragement of qwr; and 4 more since %k was not required. 4 more by using exec instead of for i in range(k).

Writes an SVG file named c.svg. Look, ma! No graphics library! :)

\$\endgroup\$
4
  • \$\begingroup\$ works for me without xmlns tag. Is it optional? \$\endgroup\$
    – qwr
    Commented Jul 13, 2018 at 22:47
  • \$\begingroup\$ @qwr: I think it's required in the relevant RFC if it is served as image/svg+xml (e.g., in a browser as a standalone file and not embedded in an html document). Otherwise - yes, It seems like, e.g., Photoshop will display it properly without. Would save 35 bytes; but seems a bit cheaty :). \$\endgroup\$
    – Chas Brown
    Commented Jul 13, 2018 at 22:58
  • \$\begingroup\$ well this is code golf so I say if it opens in a common program (opens in GNOME image viewer for me) then it's valid. \$\endgroup\$
    – qwr
    Commented Jul 13, 2018 at 22:59
  • \$\begingroup\$ @qwr: Yes, it is code golf, so... \$\endgroup\$
    – Chas Brown
    Commented Jul 14, 2018 at 1:23
3
\$\begingroup\$

Python 2 with pylab, 133 129 bytes

from pylab import*
n,k=input()
gca().add_patch(Circle((0,0),1))
a=2*pi/n
for i in range(n):c=i*a,k*i*a;plot(cos(c),sin(c))
show()

Saved 4 bytes thanks to Mr. Xcoder.

\$\endgroup\$
1
  • \$\begingroup\$ for i in range(n):c=i*a,k*i*a;plot(cos(c),sin(c)) saves 4 bytes \$\endgroup\$
    – Mr. Xcoder
    Commented Jul 13, 2018 at 21:39
3
\$\begingroup\$

JavaScript (ES6), 207 206 bytes

with(Math)f=(k,n,g=i=>[cos(i*=PI*2/k),sin(i)])=>`<svg viewBox=-1,-1,2.01,2.01><circle r=1 fill=none${s=` stroke=#000 stroke-width=.01 `}/><path d=M${[...Array(k)].map((_,i)=>g(i)+`L`+g(i*n)).join`M`}${s}/>`
;o.innerHTML=f(27,2)
<div oninput=o.innerHTML=f(+k.value,+n.value)><input type=number min=2 value=27 id=k><input type=number min=2 value=2 id=n><div id=o>

Output of the function is an HTML5-compatible SVG snippet. The function itself is the first line of the snippet, the rest of the snippet merely serves to demonstrate the function. Edit: Saved 1 byte thanks to @Arnauld.

\$\endgroup\$
1
  • \$\begingroup\$ @ChasBrown Whoops, overlooked that, sorry. There goes 40 bytes... \$\endgroup\$
    – Neil
    Commented Jul 14, 2018 at 10:00
3
\$\begingroup\$

R, 160 bytes

function(n,k,C=cospi,S=sinpi){par(pty="s")
plot(S(z<-0:2e4/1e4),C(z),'l',xaxt='n',yaxt='n',an=F,ax=F,xla="",yla="")
a=2/k*1:k
segments(C(a),S(a),C(a*n),S(a*n))}

Try it online!

... or play with it if you want (change the code and press execute)

  • -2 bytes thanks to @JayCE

Here's the appearance :

enter image description here

\$\endgroup\$
4
  • \$\begingroup\$ Nice! you can check with OP if it's acceptable to print axes, etc. to save about 30 bytes. also a=T works within symbols I believe. Probably more golfing possible... \$\endgroup\$
    – JayCe
    Commented Jul 14, 2018 at 1:37
  • \$\begingroup\$ @JayCe: saved several bytes still without showing the axes. I had to get rid of symbols since it's not really a perfect circle of radius 1 around zero. I resorted to plot \$\endgroup\$
    – digEmAll
    Commented Jul 14, 2018 at 11:58
  • 1
    \$\begingroup\$ I can not test this right now but it should save 2 bytes \$\endgroup\$
    – JayCe
    Commented Jul 14, 2018 at 13:45
  • \$\begingroup\$ Carefully rethinking the formula (...stupid of me) saved a lot of bytes :) \$\endgroup\$
    – digEmAll
    Commented Jul 15, 2018 at 10:20
2
\$\begingroup\$

Javascript 146 bytes + HTML 113 + Js Library cardioidjs = 259 bytes

Note: I dont think this is allowed but acording to OP

You can use any graphing library that your language allows.

Program ask for k and n and uses the lib to create the table

_=document.getElementById('a');l=prompt;c=new Cardioid(_,{iterations:1000,pieces: (t=l("k"))%2?t-1:+t,fun1:l("n"),initialRotation: 180});c.draw()
<script src="https://mircot.github.io/js/cardioid.js"></script>
<canvas id="a" width="500" height="500"></canvas>

\$\endgroup\$
1
  • \$\begingroup\$ Looks valid. But boring. And some redundant spaces? \$\endgroup\$
    – user202729
    Commented Jul 14, 2018 at 7:56
2
\$\begingroup\$

Python 3 + turtle, 126 118 bytes

Just learn about clone. This version creates a turtle for each line drawn, so it clutters the screen a bit. Calling ht() will help.

from turtle import*
n,k=eval(input())
a=clone()
exec('a.circle(99,360*n/k);circle(99,360/k);clone().goto(a.pos());'*k)

A direct port of my LOGO solution. However Python multi-turtle support is a bit different (they're named, not numbered), so turtle 0 in LOGO solution is the default turtle, and turtle 1 is a.

[*map(goto,[a.pos(),pos()])] is exactly 1 byte shorter than p=pos();goto(a.pos());goto(p), and obviously much less readable...


This exits immediately after the drawing is done. To prevent that, adds done() at the end.

Because the drawing may be too slow, add speed(0) at the beginning (after the import statement)

I don't have Python 2 installed, but this (111 bytes) should work.

\$\endgroup\$
2
\$\begingroup\$

Desmos, 58 bytes

r=1
p=[0,...,k-1]2\pi/k
s=-cot(p/2+mod(np,k)/2)
sx+sinp-scosp

View it on Desmos, includes other functions for better visualization

Had more golfability than most Desmos answers, fun to work on. Note: since the link in the submission is broken, you can use this as an interactive tool to play around with them now!

Explanation:

r=1                       Draw circle
p=[0,...,k-1]2\pi/k       Generate list of angles (note: switching to degrees sould save a byte here, but we can't do that as it's not possible through code alone)
s=-cot(p/2+mod(np,k)/2)   Calculate slope of the line for each angle pair
sx+sinp-scosp             Draw the lines
\$\endgroup\$
1
\$\begingroup\$

FMSLogo, 80 77 bytes

[repeat ?[arc2 360/? 99 foreach list ask 1[arc2 360/?*?2 99 pos]pos "setpos]]

Usage

This is an explicit-slot template, which can be used by typing, for example

apply [...] [54 2]

into the Logo prompt, replacing [...] with the program above.

It can be used to draw the circle anywhere on the screen, but the radius is hardcoded (99).

To clear the screen use cs.

Images

(FMSLogo also has a convenient command bitcopy for copying to clipboard. Example run:

pu bk 100 bitcopy 200 200 home pd

)

k = 54, n = 2     k = 90, n = 6

\$\endgroup\$
1
\$\begingroup\$

Excel VBA, 167 bytes

An immediate window function that takes input and output onto the Sheet1 object.

Set s=Sheet1.Shapes:s.AddShape(9,0,0,1E2,1E2).ShapeStyle=7:f=50:c=[2*Pi()/B1]:For i=0To[B1]:j=i*[A1]:s.AddLine f+f*Cos(c*i),f+f*Sin(c*i),f+f*Cos(c*j),f+f*Sin(c*j):Next

Ungolfed and Commented

Set s=Sheet1.Shapes                                             ''  On the Sheet1 Object
s.AddShape(9,0,0,1E2,1E2).ShapeStyle=7                          ''  Add a blue circle
f=50                                                            ''  Hold var as 50
c=[2*Pi()/B1]                                                   ''  Calc Rads Splitting circle into k slices
For i=0To[B1]                                                   ''  Iterate from 0 to k
j=i*[A1]                                                        ''  Calculate Next Point
s.AddLine f+f*Cos(c*i),f+f*Sin(c*i),f+f*Cos(c*j),f+f*Sin(c*j)   ''  Draw a line from i to i*n Mod k
Next                                                            ''  Loop

Output

Output

\$\endgroup\$
1
\$\begingroup\$

Small Basic, 218 bytes

A Script that takes input from the TextWindow and outputs to the GraphicsWindow Object

n=TextWindow.Read()
k=TextWindow.Read()
GraphicsWindow.DrawEllipse(0,0,100,100)
f=50
c=2*Math.Pi/k
For i=0To k
GraphicsWindow.DrawLine(f+f*Math.Cos(c*i),f+f*Math.Sin(c*i),f+f*Math.Cos(c*i*n),f+f*Math.Sin(c*i*n))
EndFor

Try it at SmallBasic.com! Requires IE/Silverlight

Output

Input 3,24

Pic

\$\endgroup\$
1
\$\begingroup\$

Lua (love2d Framework),281 bytes

j,p,z,w,v=love,math,100,200,90 g,r=j.graphics,p.rad c=g.circle function j.load(b)n,k=b[1],b[2]m= 360/k::t::a=function(i)return z*p.sin(r(m*i +v))+w,z*p.cos(r(m*i+v))+w end c("line",w,w,z)for i=1,k do x,y=a(i)c("fill",x,y,3)l=(i*n)%k d,e=a(l)g.line(x,y,d,e)end g.present()goto t end

If this is copied in a main.lua file and run it will show it on screen

output for n=2,k=22

enter image description here

also beware if you run it, that it will probably tell you that it is frozen because it is in an endless draw function in the load function but it will show it on the screen.

Also here is a clean version

--definitions of everything
j,p,z,w,v=love,math,100,200,90 
g,r=j.graphics,p.rad c=g.circle 
function j.load(b)
  --get the parameters
  n,k=b[1],b[2]
  m= 360/k
  --goto label
  ::t::
  --function which takes a point number as input and outputs the x,y adds also 90 to it because why ever love starts 
   a=function(i)return z*p.sin(r(m*i +v))+w,z*p.cos(r(m*i+v))+w end
   --draw the circle
   c("line",w,w,z)
   for i=1,k do 
     --get point position and draw it
     x,y=a(i)
     c("fill",x,y,3)
     --calculate and print the line to the other point
     l=(i*n)%k
     d,e=a(l)
     g.line(x,y,d,e)
   end 
   --show it on screen
   g.present()
   goto t 
end

If someone also wants to play around with it here a version which you can change the n with up and down and the k with left and right arrows :)

--definitions of everything
j,p,z,w,v=love,math,100,200,90 
g,r=j.graphics,p.rad c=g.circle 
function j.load(b)
  --get the parameters
  n,k=b[1],b[2]

end


function u(n,k)
--function which takes a point number as input and outputs the x,y adds also 90 to it because why ever love starts 
   a=function(i)return z*p.sin(r(m*i +v))+w,z*p.cos(r(m*i+v))+w end
   --draw the circle
   m= 360/k

   c("line",w,w,z)
   for i=1,k do 
     --get point position and draw it
     x,y=a(i)
     c("fill",x,y,3)
     --calculate and print the line to the other point
     l=(i*n)%k
     d,e=a(l)
     g.line(x,y,d,e)
   end 
end

function j.draw()
  --n=n+0.001
  --k=k+0.01
  u(n,k)
  love.graphics.print("n: "..n.."\nk: "..k,0,0)
end

function j.keypressed(ke,s)
  k=k*1
  if ke== "up"then
    n=n+1
  elseif ke=="down" then
    if n >1 then n=n-1 end
  elseif ke=="right" then
    k=k+1
  elseif ke=="left" then
    if k>1 then 
      k=k-1 
    end
  end

end
\$\endgroup\$
1
\$\begingroup\$

APL (dzaima/APL), 57 bytes

No MATL answer here yet! yay!

{n←⍺⋄P5.G.circle 3⍴30⋄{P5.G.ln↑30×1+2 1○ᑈ1n×⍵×○2÷k}¨⍳k←⍵}

Made with help from dzaima.

Draws a 30x30 circle with the times table for n and k.

Function submission which takes arguments as n f k, and will display properly on a default sized canvas.

This uses the formula from user58543's answer.

You can test this out using this file and dzaima's APLP5 engine.

Explanation:

{n←⍺⋄P5.G.circle 3⍴30⋄{P5.G.ln↑30×1+2 1○ᑈ1n×⍵×○2÷k}¨⍳k←⍵}
{n←⍺⋄                                                   k←⍵} store left arg in n and right arg in k
      P5.G.circle 3⍴30⋄                                      Draw circle of radius 30

                                                        ⍳k   generate range 1..k
                       {                              }¨     Execute the following for each number i:
                                            1n×⍵×○2÷k        Multiply [1,n] with i×2π/k
                                      2 1○ᑈ                  Take cos and sin of each of those
                                30×1+                        Multiply 30, add 30 to them
                              ↑                              Convert to matrix
                        P5.G.ln                              Plot a line using those coordinates

Output for n=5, k=10:

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ :-) \$\endgroup\$
    – Luis Mendo
    Commented Oct 30, 2020 at 22:42
1
\$\begingroup\$

MATL, 39 37 35 33 31 29 bytes

:qG/ti*vO9Wt:w/h,18L*ZeXG1IZG

Inputs are k, then n.

Try at MATL Online!

How it works

:         % Implicit input: k. Range: [1 2 ... k]
q         % Subtract 1, element-wise: [0 1 ... k-1]
G/        % Push k again; divide element-wise: [0 1/k ...(k-1)/k]
t         % Duplicate
i*        % Input: n. Multiply element-wise: gives [0 n/k ... n*(k-1)/k]
v         % Concatenate vertically: gives 2-row matrix [0 1   ... k-1;
          %                                             0 n/k ... n*(k-1)/k]
O         % Push 0
9W        % Push 9; exponential with base 2: gives 512
t         % Duplicate
:         % Range: gives [1 2 ... 512]
w         % Swap: moves copy of 512 to top
/         % Divide, element-wise: gives [1/512 2/512 ... 1]
h         % Concatenate: gives [0 1/512 2/512 ... 1]
,         % Do the following twice
  18L     %   Push 2*pi*j (predefined literal)
  *       %   Multiply, element-wise
  Ze      %   Exponential with base e, element-wise. Each imaginary number
          %   becomes a point in the unit circle
  XG      %   Plot. Since the input is complex, this plots in the complex
          %   plane. The first time this plots the 2-row matrix defining the
          %   lines, with each column of the matrix plotted separately. The
          %   second time it plots the 512-vector with points in the circle
  1IZG    %   Hold on. This causes the next plot to be added, instead of 
          %   overwriting the previous one
\$\endgroup\$
1
  • 1
    \$\begingroup\$ There we go. :-) \$\endgroup\$
    – Razetime
    Commented Oct 31, 2020 at 2:41
0
\$\begingroup\$

Small Basic + Turtle, 390 bytes

A Script that takes input from the TextWindow and outputs to the GraphicsWindow Object

n=TextWindow.Read()
k=TextWindow.Read()
For i=0To 360
Turtle.Angle=i
Turtle.Move(2.618) 
EndFor
r=150
c=2*Math.Pi/k  
For i=0To k
Turtle.PenUp()
Turtle.MoveTo(470+r*Math.Cos(c*i),240+r*Math.Sin(c*i))
Turtle.PenDown()
Turtle.MoveTo(470+r*Math.Cos(c*i*n),240+r*Math.Sin(c*i*n))
EndFor
GraphicsWindow.DrawLine(f+f*Math.Cos(c*i),f+f*Math.Sin(c*i),f+f*Math.Cos(c*i*n),f+f*Math.Sin(c*i*n))
EndFor

Try it at SmallBasic.com! Requires IE/Silverlight

Ungolfed and Commented

n=TextWindow.Read()                                         ''  Take Input, n
k=TextWindow.Read()                                         ''  Take Input, k
For i=0To 360                                               ''  Draw a Circle of Radius 150
  Turtle.Angle=i                                            ''  By turning 1 degree
  Turtle.Move(2.618)                                        ''  And moving Pi*300/360 Units
EndFor                                                      ''  360 times
r=150                                                       ''  Hold Radius variable
c=2*Math.Pi/k                                               ''  Hold Rad Constant
For i=0To k                                                 ''  Iterate over i
  Turtle.PenUp()                                            ''  Stop Drawing
  Turtle.MoveTo(470+r*Math.Cos(c*i),240+r*Math.Sin(c*i))    ''  Move to Position i
  Turtle.PenDown()                                          ''  Start Drawing again
  Turtle.MoveTo(470+r*Math.Cos(c*i*n),240+r*Math.Sin(c*i*n))''  Move to Position (i*n)Mod k
EndFor                                                      ''  Loop

Output

Input 3,72

Pic

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.