Draw A Reuleaux Triangle!

27

2

The Reuleaux triangle is the shape formed by the intersection of three circles, with each circle passing through the others' centers. Regardless of rotation, a Reuleaux triangle's width will always equal the radius of the circles:

From Wolfram MathWorld

Image: Wolfram MathWorld

Write a program that takes a width r as input and displays a Reuleaux triangle of that width (in pixels).

You must display the shape in isolation, i.e. solid-filled, un-stroked, and over a solid-filled background.

- Shortest program in bytes wins.

darrylyeo

Posted 2017-06-13T00:34:49.033

Reputation: 6 214

1Should the radius r be in pixels or just some scaling factor? – Karl Napf – 2017-06-13T03:42:18.813

@Karl Napf Pixels. – darrylyeo – 2017-06-13T04:04:16.500

Can we output anything to STDOUT, as long as we draw the Reuleaux triangle properly? – Erik the Outgolfer – 2017-06-14T16:14:45.217

@EriktheOutgolfer That is fine. – darrylyeo – 2017-06-14T23:24:26.840

Answers

21

JavaScript + HTML, 164 158 + 13 = 171 bytes

w=+prompt(f=(x,y)=>x*x+y*y<w*w);C.width=C.height=w*2;for(y=-w;++y<w;)for(x=-w;++x<w;)f(x,y)&f(w-x,y)&f(w/2-x,y-w*.866)&&C.getContext`2d`.fillRect(x+w,y+w,1,1)
<canvas id=C>

I don't know why I enjoy answering these mathy drawing challenges with <canvas> so much...

ETHproductions

Posted 2017-06-13T00:34:49.033

Reputation: 47 880

13

Love2D, 320 bytes.

j=math.rad(60)i="increment"m=math s=m.sin C=m.cos g=love.graphics f="fill"S=g.stencil function love.draw()r=arg[2]c=function(x,y)return function()g.circle(f,x,y,r,r*4)end end X=r/2 Y=0 S(c(X,Y),i,1)S(c(X+C(j)*r,Y+s(j)*r),i,1,true)S(c(X-C(j)*r,Y+s(j)*r),i,1,true)g.setStencilTest("greater",2)g.rectangle(f,0,0,2*r,2*r)end

Probably not the optimal solution, it uses Love2D's stencils, setting up the 3 circles, and filling in over where they intersect.

Call via the command line, like love tri.love 256

Example Output

ATaco

Posted 2017-06-13T00:34:49.033

Reputation: 7 898

5It's quite lovely – ATaco – 2017-06-13T07:23:38.660

10

Python 2, 111 bytes

from turtle import*
r=input()
ht()
begin_fill()
c=circle
c(r,60)
seth(120)
c(r,60)
seth(240)
c(r,60)
end_fill()

example run

Jonathan Allan

Posted 2017-06-13T00:34:49.033

Reputation: 67 804

9

Mathematica 101 100 98 Bytes

Taking a different approach than @MichaelSeifert, and probably interpreting this a little more literally with regard to the pixel clause:

Image@Boole@Table[And@@(({x,y}∈#~Disk~2)&/@{{0,c=√3},d={1,0},-d}),{x,-1,1,2/#},{y,c-2,c,2/#}]&

Usage Example:

%@10

10 pixels 10 pixel image

50 pixels 50 pixel image

100 pixels 100 pixel image

Saved a byte thanks to @MartinEnder (infix notation) and another 2 bytes by defining d.

Kelly Lowder

Posted 2017-06-13T00:34:49.033

Reputation: 3 225

6

PHP+SVG, 165 bytes

<?$h=3/8*$w=2*$d=2*$r=$_GET[0];$q=$r+sqrt($r**2-($r/2)**2);echo"<svg width=$w height=$w><path d='M$r,$r A$r,$r 0 0 1 $d,$r A$r,$r 0 0 1 $h,$q A$r,$r 0 0 1 $r,$r'/>";

Example Output for Input 128

<svg width=512 height=512><path d='M128,128 A128,128 0 0 1 256,128 A128,128 0 0 1 192,238.85125168441 A128,128 0 0 1 128,128'/>

Jörg Hülsermann

Posted 2017-06-13T00:34:49.033

Reputation: 13 026

6

PostScript, 96 86 85 75 73 72 bytes

dup(^@^^Z<^@Z<){sin mul exch dup}forall
0 1 2{newpath 369 arc clip}for fill

Takes the input as a value on the stack. ^^ and ^@ represent literal control characters. (^@^^Z<^@Z<) is the string of characters with code points 0, 30, 90, 60, 0, 90, and 60, respectively. Those are then interpreted as angles in degrees, because obviously that’s what code points are for.

Saved 10 bytes because closepath isn’t needed (both clip and fill implicitly close the path).

Saved 1 byte by using repeat instead of defining a function.

Saved 10 bytes by switching to a completely different approach.

Saved 2 bytes by doing tricks with the stack.

Saved 1 byte by using 0 1 2{}for instead of 3{}repeat.

Grimmy

Posted 2017-06-13T00:34:49.033

Reputation: 12 521

5

Mathematica, 134 131 bytes

N.B. This solution is no longer valid, as the question was later edited to require r to be measured in pixels. Thanks to Martin Ender for helping me shave off a few bytes in the comments.

r=Input[];RegionPlot[And@@((Abs[y+I x-#]^2<3r^2)&/@Table[Exp[2n I/3Pi]r,{n,3}]),{x,-1,1},{y,-1,1},Frame->False,BoundaryStyle->None]

enter image description here

The input value must be scaled between 0 and 1 for this code to work. Note that almost a quarter of this code is required to display the shape "in isolation", as this is not Mathematica's default.

Michael Seifert

Posted 2017-06-13T00:34:49.033

Reputation: 161

3Welcome to PPCG! r Exp[2 I Pi n/3] can be Exp[2I n/3Pi]r to save some spaces. And it's generally shorter to write an unnamed function, i.e. drop the r=Input[];, replace r with # and append a &. – Martin Ender – 2017-06-13T06:01:26.270

I think the input has to be pixels, not a scaling factor. – internet_user – 2017-06-13T16:50:31.047

1@pycoder: Yes, that constraint was edited in after I posted my solution. – Michael Seifert – 2017-06-13T17:06:24.017

4

TeX/TikZ, 128 121 112 bytes

\input tikz\footline{}\tikz\draw[draw=none,fill=red](0,1)\foreach~ in{1,2,3}{[rotate=~*120]arc(0:60:\r pt)};\bye

The code is based on this answer at TeX.se.

TeX is vector-based, so doesn't do pixels. The radius is a float with a maximum of about 15 before it hits the edge of the page. It's also not really built for commandline input, so need to be run as

pdftex  "\def\r{2} \input rt.tex"

where the code above is saved in rt.tex

Chris H

Posted 2017-06-13T00:34:49.033

Reputation: 581

A few tips to make this shorter: you don't need any of the newlines; you don't need .tex; \footline{} is just as good as \nopagenumbers; use ~ as a variable name instead of \i. To satisfy the “pixel” requirement, you could use \r sp; 1sp is the sort-of equivalent to a pixel for TeX since it's the finest location TeX can manage (I don't know if it applies to tikz though). – Gilles 'SO- stop being evil' – 2017-06-14T17:03:34.433

@Gilles I can't get anything with sp but I think pt is a good idea. All your other ideas worked (some hadn't seemed to in my tests). Thank you – Chris H – 2017-06-16T15:16:00.980

You can remove the space after ~ to save one more byte. \input tikz\footline{}\tikz\draw[draw=none,fill=red](0,1)\foreach~in{1,2,3}{[rotate=~*120]arc(0:60:\r sp)};\bye works for me. Try pdftex "\def\r{2000000} \input rt.tex" — at 2sp finding the shape visually would be difficult given how small it is. – Gilles 'SO- stop being evil' – 2017-06-16T18:07:28.380

@Gilles I must admit I only went up to 20000 sp. – Chris H – 2017-06-16T18:23:08.530

11pt = 65536sp so 20000sp is still tiny. – Gilles 'SO- stop being evil' – 2017-06-16T18:46:02.497

4

BBC BASIC, 58 bytes

I.r:L.r,r,r,r:F.i=0TO9S.PI/1.5PLOT177,r*COS(i),r*SIN(i)N.

Download interpreter at http://www.bbcbasic.co.uk/bbcwin/download.html

Ungolfed

INPUTr                       :REM input a radius
LINEr,r,r,r                  :REM draw a line of length 0 from r,r to r,r to establish a cursor history away from the corner of the screen
FORi=0 TO 9 STEP PI/1.5      :REM in steps of 120 degrees (going round and round the three sides of an equilateral triangle)
  PLOT177,r*COS(i),r*SIN(i)  :REM move relative by r*COS(i),r*SIN(i) and draw a sector with arc between new and last graphics cursor positions,
NEXT                         :REM with the centre of the arc at the penultimate graphics cursor position.

Level River St

Posted 2017-06-13T00:34:49.033

Reputation: 22 049

Wow, that's practially a built-in! – Neil – 2017-06-14T08:51:20.460

3

GLSL, 298 229 characters

precision lowp float;
uniform vec2 resolution;float r=100.;void main(){vec2 p=gl_FragCoord.xy-resolution.xy/2.;float h=sqrt(3.)/4.*r;gl_FragColor=vec4(length(p+vec2(r/2.,h))<r&&length(p+vec2(-r/2.,h))<r&&length(p-vec2(0.,h))<r);}

Try it here

Bonus

  • Radius can be set by changing r variable
  • Triangle width is in pixels as requested (you have to make zoom is set to 1x in GLSL sandbox).

tigrou

Posted 2017-06-13T00:34:49.033

Reputation: 2 349

Does GLSL have a standard input method you could use? – darrylyeo – 2017-06-13T16:21:21.283

In glslsandbox, it is possible to get mouse cursor position. This could be used to control triangle radius (eg : radius would be mouse distance from center). – tigrou – 2017-06-14T13:03:26.607

2

JavaScript (ES6) + HTML, 196 + 13 = 209 bytes

Uses a path-based approach instead of a pixel-filling approach.

r=>{c.width=c.height=r*2
with(Math)with(c.getContext`2d`)scale(e=r*.578,e),beginPath(a=s=>s*PI/3),moveTo(2,1),[2,4,6].map(s=>arcTo(cos(i=a(s-1))+1,sin(i)+1,cos(j=a(s))+1,sin(j)+1,sqrt(3))),fill()}

<canvas id=c>

f=
r=>{c.width=c.height=r*2
with(Math)with(c.getContext`2d`)scale(e=r*.578,e),beginPath(a=s=>s*PI/3),moveTo(2,1),[2,4,6].map(s=>arcTo(cos(i=a(s-1))+1,sin(i)+1,cos(j=a(s))+1,sin(j)+1,sqrt(3))),fill()}

f(200)

//r=>{c.width=c.height=r*2
//with(Math)with(c.getContext`2d`)translate(r,r),scale(r,r),beginPath(a=s=>s*PI/3),S=sqrt(3),moveTo(1/S,0),[2,4,6].map(s=>arcTo(cos(i=a(s-1))/S,sin(i)/S,cos(j=a(s))/S,sin(j)/S,1)),fill()}

//r=>{c.width=c.height=r*2
//with(Math)with(c.getContext`2d`)translate(r,r),scale(r,r),beginPath(),P=PI/2,A=(s,_)=>(_?sin:cos)(s*PI/3)/sqrt(3),moveTo(A(0),0),[2,4,6].map(s=>arcTo(A(s-1),A(s-1,1),A(s),A(s,1),1)),fill()}
<canvas id=c>

darrylyeo

Posted 2017-06-13T00:34:49.033

Reputation: 6 214

2

Logo, 53 bytes

to t :r filled 0[repeat 3[arc 60 :r fd :r rt 120]]end

uses the filled command to fill the shape in colour 0 (black.) The code in the outer square brackets is executed without any line being drawn, but Logo keeps track of the turtle movements and fills in the shape once the bracket is exited.

Logo, 64 61 bytes

to t :r repeat 3[pd arc 60 :r pu fd :r rt 120]fd 9 fill end

Pen Down, draw 60 degree arc with turtle at the centre, Pen Up, move pen to start of arc, turn 120 deg.

Repeat 3 times, then move inside the shape and fill it.

Try at http://turtleacademy.com/playground/en

Call like cs ht t 100 (clear screen, hide turtle, t with r=100.)

Level River St

Posted 2017-06-13T00:34:49.033

Reputation: 22 049

2

MATL, 35 bytes

9Bo&ZQ*3X^/G_G&:t!J*+8L&!-|G<A&e0YG

This produces a file called image.png. For input r, the size of the image is 2*r+1, and the width of the triangle is r as required.

Try it at MATL Online! The online interpreter automatically opens the created file and displays the image with arbitrary scaling; click on it to obtain the actual-size version.

Alternatively, here are two example outputs from the offline compiler running on Matlab, with inputs 50 and 100. The last part of the code 0YG has been replaced by IYG so that the figure is directly displayed (with the right size) instead of written to a file.

enter image description here

Explanation

9B      % Push 9 in binary: [1 0 0 1] with logical values
o       % Convert to double
&ZQ     % Roots of polynomial with coefficients [1 0 0 1], as a 3×1 column vector
*       % Multiply by implicit input r
3X^/    % Divide by sqrt(3). This gives a 3×1 vector with the circle centers
G_G&:   % Push row vector [-r -r+1 ... r-1 r], with size 1×(2*r+1)
t!J*    % Duplicate, transpose, multiply by 1j
+       % Add with broadcast. This gives a (2*r+1)×(2*r+1) 2D-array of complex
        % numbers, which defines the pixel grid
8L      % Push [3 1 2]
&!      % Permute dimensions as indicated. This gives a 1×(2*r+1)×(2*r+1) 3D-array
-|      % Subtract with broadcast. Absolute value. This gives a 3×(2*r+1)×(2*r+1)
        % 3D-array with the distance from each circle center to each grid point
G<      % Less than r? Gives a 3×(2*r+1)×(2*r+1) 3D-array containing true or false
A       % All: this gives a 1×(2*r+1)×(2*r+1) array containing true for
        % columns of the original 3D-array that contained all true values
&e      % Squeeze the first singleton dimension to give a (2*r+1)×(2*r+1) 2D-array
0YG     % Save as image file with default file name

Luis Mendo

Posted 2017-06-13T00:34:49.033

Reputation: 87 464

2

JavaScript (ES6) + SVG (HTML5), 28 + 102 = 130 bytes

f=
n=>s.setAttribute('width',n)
<input type=number value=82 oninput=f(this.value)><br>
<svg id=s width=82 viewbox=0,0,82,82><path d=M0,71a82,82,0,0,0,82,0A82,82,0,0,0,41,0A82,82,0,0,0,0,71>

Byte count excludes code needed for convenient user input of desired size.

Neil

Posted 2017-06-13T00:34:49.033

Reputation: 95 035

Clever! n=>s.style.width=n would work also. – darrylyeo – 2017-06-14T01:02:37.870

I can't seem to figure out how you came to 112 bytes. – darrylyeo – 2017-06-14T01:09:09.063

@darrylyeo That suggestion didn't work for me, sorry, but I agree about the byte count, I can't figure out how I came to it either. – Neil – 2017-06-14T01:18:08.637

Hmm, probably only works in Chrome. – darrylyeo – 2017-06-14T01:20:53.773

1

MetaPost (242 226 Bytes)

outputtemplate:="%j-%c.ps";
prologues:=1
beginfig(1);
 len:=1cm;
 path p[];
 p[1]:=len * dir -30 {dir 90} .. len * dir  90;
 p[2]:=p[1] rotated 120;
 p[3]:=p[1] rotated 240;
 fill p[1] -- p[2] -- p[3] -- cycle;
endfig;
end.

It may be possible to reduce this somewhat, I'm new to metapost.

Carel

Posted 2017-06-13T00:34:49.033

Reputation: 121

I was a bit lazy and used the text editors byte count. I didn't know you could remove the colons, Thanks. I literally have an hour of MetaPost under the belt now ^_^ – Carel – 2017-06-14T01:24:12.063

1I still count 223, not 226. Also, can you remove the spaces in len * dir and the dot at the end? – Rɪᴋᴇʀ – 2017-06-14T02:24:27.223

1

k, 141 100 98 bytes

s:*/2#;l:2*r:.:0:`
`0:(,"P1")," "/'$(,l,l),&/{(s'n+x)</:(s r)-s'y+n:r-!l}./:r*%(0 0;4 0;1 3)%4
\\

Input is taken from stdin, output is stderr (or stdin depending on the interpreter) in pgm format. For example:

Example of the program working.

Explanation:

s:*/2#               /set s to a squaring function
r:.:0:`              /get user input, set to r
l:2*                 /width/height is 2 times r
r*%(0 0;4 0;1 3)%4   /the coordinates of circle centers
{ }./:               /for each coordinate pair (x, y) get a circle
                     /function to get a circle:
n:r-!l               /  set n to {r, r-1, ..., -(r-1)}
(s'n+x)</:(s r)-s'y+ /  use b^2<r^2-a^2 on all points to get a circle
                     /  where x and y shift the circle right and down
&/                   /get intersections of circles (fold binary and)
(,l,l),              /prepend height and width for PGM format
" "/'$               /convert to string, add spaces
(,"P1"),             /prepend PGM header
`0:                  /output to stderr
\\                   /exit

zgrep

Posted 2017-06-13T00:34:49.033

Reputation: 1 291

0

05AB1E, 66 bytes

’)
¨€(ÿ,60)
lt(60’Ð’€š éà £Ø*
ht()
ï…_œã(ÿÿÿ)
„–_œã()
„ˆ 1:ht()’.e

Can't use TIO, since it opens a window and draws the Reuleaux triangle there.

Asks for input, and then opens up a Python turtle window drawing the triangle.

Jonathan Allan's answer gave me the inspiration to do this, although I altered his code a bit.

Essentially, this is a combination of 05AB1E's compressing capabilities and Python's ease of turtle graphics.

Erik the Outgolfer

Posted 2017-06-13T00:34:49.033

Reputation: 38 134

0

OpenSCAD, 91 bytes

module t(r){intersection_for(t=[0,120,240]){rotate(t)translate([r/sqrt(3),0,0])circle(r);}}

I'm not sure how kosher this is, as pixels aren't really a well-defined unit in any mesh grid formats that I know of. In stead, the module t draws a reuleaux triangle of given radius r in whatever native units are in use.

Sample preview output for t(100): t(100)

Julian Wolf

Posted 2017-06-13T00:34:49.033

Reputation: 1 139

0

SmileBASIC, 87 86 85 83 82 81 79 78 77 76 75 bytes

INPUT R
C.5Y=R*.87C 1C.GPAINT.,0DEF C X
A=X*240GCIRCLE R*X,Y+2,R,A-60,A
END

Ungolfed:

INPUT RADIUS
CIRCLE 0.5
Y=RADIUS*(SQR(3)/2)
CIRCLE 1
CIRCLE 0
GPAINT 0,0
DEF CIRCLE X
 ANGLE=X*240
 GCIRCLE RADIUS*X,Y+2,RADIUS,ANGLE-60,ANGLE
END

12Me21

Posted 2017-06-13T00:34:49.033

Reputation: 6 110