27
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Should the radius r be in pixels or just some scaling factor? \$\endgroup\$ – Karl Napf Jun 13 '17 at 3:42
  • \$\begingroup\$ @Karl Napf Pixels. \$\endgroup\$ – darrylyeo Jun 13 '17 at 4:04
  • \$\begingroup\$ Can we output anything to STDOUT, as long as we draw the Reuleaux triangle properly? \$\endgroup\$ – Erik the Outgolfer Jun 14 '17 at 16:14
  • \$\begingroup\$ @EriktheOutgolfer That is fine. \$\endgroup\$ – darrylyeo Jun 14 '17 at 23:24

19 Answers 19

21
\$\begingroup\$

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...

\$\endgroup\$
13
\$\begingroup\$

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

\$\endgroup\$
  • 5
    \$\begingroup\$ It's quite lovely \$\endgroup\$ – ATaco Jun 13 '17 at 7:23
10
\$\begingroup\$

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

\$\endgroup\$
9
\$\begingroup\$

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.

\$\endgroup\$
6
\$\begingroup\$

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'/>

\$\endgroup\$
6
\$\begingroup\$

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.

\$\endgroup\$
5
\$\begingroup\$

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.

\$\endgroup\$
  • 3
    \$\begingroup\$ Welcome 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 &. \$\endgroup\$ – Martin Ender Jun 13 '17 at 6:01
  • \$\begingroup\$ I think the input has to be pixels, not a scaling factor. \$\endgroup\$ – internet_user Jun 13 '17 at 16:50
  • 1
    \$\begingroup\$ @pycoder: Yes, that constraint was edited in after I posted my solution. \$\endgroup\$ – Michael Seifert Jun 13 '17 at 17:06
4
\$\begingroup\$

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.
\$\endgroup\$
  • \$\begingroup\$ Wow, that's practially a built-in! \$\endgroup\$ – Neil Jun 14 '17 at 8:51
4
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ 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). \$\endgroup\$ – Gilles 'SO- stop being evil' Jun 14 '17 at 17:03
  • \$\begingroup\$ @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 \$\endgroup\$ – Chris H Jun 16 '17 at 15:16
  • \$\begingroup\$ 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. \$\endgroup\$ – Gilles 'SO- stop being evil' Jun 16 '17 at 18:07
  • \$\begingroup\$ @Gilles I must admit I only went up to 20000 sp. \$\endgroup\$ – Chris H Jun 16 '17 at 18:23
  • 1
    \$\begingroup\$ 1pt = 65536sp so 20000sp is still tiny. \$\endgroup\$ – Gilles 'SO- stop being evil' Jun 16 '17 at 18:46
3
\$\begingroup\$

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).
\$\endgroup\$
  • \$\begingroup\$ Does GLSL have a standard input method you could use? \$\endgroup\$ – darrylyeo Jun 13 '17 at 16:21
  • \$\begingroup\$ 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). \$\endgroup\$ – tigrou Jun 14 '17 at 13:03
2
\$\begingroup\$

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>

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

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.)

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

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
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Clever! n=>s.style.width=n would work also. \$\endgroup\$ – darrylyeo Jun 14 '17 at 1:02
  • \$\begingroup\$ I can't seem to figure out how you came to 112 bytes. \$\endgroup\$ – darrylyeo Jun 14 '17 at 1:09
  • \$\begingroup\$ @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. \$\endgroup\$ – Neil Jun 14 '17 at 1:18
  • \$\begingroup\$ Hmm, probably only works in Chrome. \$\endgroup\$ – darrylyeo Jun 14 '17 at 1:20
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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 ^_^ \$\endgroup\$ – Carel Jun 14 '17 at 1:24
  • 1
    \$\begingroup\$ I still count 223, not 226. Also, can you remove the spaces in len * dir and the dot at the end? \$\endgroup\$ – Rɪᴋᴇʀ Jun 14 '17 at 2:24
1
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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)

\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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