Draw the € sign

Mathematica, 193 183 177 173 169 166 bytes

Yay, maths! I'm plotting the region that satisfies a certain (rather complicated) set of inequalities:


Usage is e[height], e.g. e[100]:

enter image description here

Or e[200]:

enter image description here

You may notice, that the sharper edges are slightly rounded off. That's because the region can only be plotted by sampling the points in space, and Mathematica doesn't sample each pixel by default. The sampling resolution can be increased by adding another option PlotPoints-># (which uses one sample per pixel), which adds 14 characters. I don't recommend running it with that option, because it significantly increases runtime and barely increases visual appeal beyond #/4 or so. Hence, (after approval of the OP) it is not included in the score.

Here is a slightly ungolfed version:

e[height_] := (
  angle = 40°;
  d = {-5 Sin[angle] - 6, 5 Cos[angle]};
      (Abs[y] > .5 && Abs[y] < 1.5
       r > 25 && r < 36)
      {x, y + 6}.d > 0
      {x + 7.5, y + .5 - Sign[y]}.d < 0
      r > 25 && r < 36 && x < 5 Cos[angle] 
    /. r -> x^2 + y^2
    {x, -7.5, 4.5},
    {y, -6, 6},
    Frame -> False,
    ImageSize -> height

Note that in the golfed version, I've scaled the coordinate system by a factor of 2 to avoid the .5s, but it turns out that the character count is actually identical.

Here is an explanation for how I worked out the formula. I divided the shape into two regions. One contains the ring and the stripes and is cut off to the right with the BCDE slope and to the left with the IJ and GH slopes (more on that later). The other contains the same ring, but is simply cut off at the x coordinate of point D. The conditions for the two regions are combined with ||, which acts as a set union here.

The ring is just defined as 5 < r < 6, where r is the distance from the origin. is easier to work out though (x²+y²), so I'm using 25 < x² + y² < 36 to get all the points in the ring.

The stripes are between ±.5 and ±1.5. We can handle both stripes at the same time, by taking the modulus of y, so the stripes (of infinite length) just fulfil .5 < |y| < 1.5. Again, to take the union of the stripes and the ring, I'm just using ||.

The interesting thing is probably how to get the "masks" though. Point D has an x coordinate of 5 cos 40°, so the mask taking care of lower edge (combined with the ring only) is just x < 5 cos 40°. This can be applied via set intersection which translates to && in logic.

The other masks are the really tricky part. First, let's get the slope of BCDE. We can easily construct points C and D, as (0, -6) and 5 (cos 40°, sin 40°), respectively. The vector pointing along the line is then just D - C = (5 cos 40°, 5 sin 40° + 6). To apply the mask on the right, I only need to figure out if a point lies to the left or the right of that line (let's call line vector p). I can figure this out by taking the vector from C to my point of interest and projecting it onto a vector perpendicular to p. The sign of the projection will tell me the side the point is on. Obtaining the perpendicular vector is pretty simple in 2D: flip the coordinates and reverse the sign of one of them. That's the variable d in my code: (-5 sin 40° - 6, 5 cos 40°). The vector from C to a point of interest q = (x, y) is q - C = (x, y + 6). The projection is just the scalar product (or dot product) between q and d. The way I chose d it happens to point to the left, so I want d.(q-C) > 0. This condition applies the right-hand mask.

For the left-hand mask I can use basically the same idea. The slope is the same and therefore so is d. I just need offset my point from the lower-left corners of stripes instead of from C. Those have coordinates (-7.5, 0.5) (upper stripe) and (-7.5, -1.5) (lower stripe). So that would call for two independent rules for the two stripes. However, note that all points affected by the lower mask are in the lower stripe and hence have negative y. And all points affected by the upper mask have positive y. So I can simply switch my offset using Sign[y] which is 1 for positive and -1 for negative y. So my offset point becomes (-7.5, -0.5 + Sign[y]). Otherwise the mask works just like the right-hand mask. Of course, this time the projection needs to be negative. So, naively that would be something like RH-projection > 0 && LH-projection < 0 (which is also what I originally had in the code). But we can shorten this, because multiplying a positive and a negative number has to give a negative number, so it's just RH * LH < 0 (where RH and LH are the respective projections).

That's it. Putting it all together leads to the following logical structure:

  (is_in_circle || is_in_stripe)
  is_in_circle && left_of_edge

Just to be clear, the coordinates in my explanation refer to the construction diagram given in the challenge. As mentioned above my code actually multiplies all of them by 2 - I changed it to save bytes, but the byte count is actually identical, and I couldn't be bothered to revert the change again. Also integers look nicer.



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

In BBC basic, all graphics are handled at the low level using machine-specific ASCII control characters (but some high level commands are also available for the common ones for convenience.) The ones used here are 22 (change display mode) 29(change origin) and 25, equivalent to the PLOT statement, which takes an additional action parameter (draw line, circle, triangle, etc. in background/foreground with relative/absolute move) before the X and Y parameters.

So all I have to do is send a load of characters to the VDU controller. values terminated in semicolon are 16 bit. others are 8 bit. The total number of bytes sent to the VDU controller is 91, though that in itself would not qualify as an answer because by that stage the size is hardcoded.

The obvious place for the origin is the centre of the circle, but there are actually more commands involved in producing the bars. So I shifted the origin down 1.5 to the bottom of the lower bar, which reduces the number of fractions and negative numbers required. It remains on the vertical line with the centre of the circle, which is important because the line E starts from this vertical line.

Actually, I only had to calculate 3 numbers off the drawing: the top inner corner of the C shape (5 cos 40, 5 sin 40 + 1.5) = (3.8302,3.1394+1.5) = approx (12/3.1, 4.6) and the gradient of the line E:x/y=3.8302/(6+3.1394)=0.4157 = approx 1/2.4

As I only have the free evaluation version (interpreted), I take the symbol height as user input. If you buy the full version (29.99GBP) you can compile and then read the command line with w=VAL(@cmd$)/12.

Ungolfed code

In the golfed code, there is only one VDU statement, but in the ungolfed code I break it down into several for clarity. Also, because BBC basic is little endian, the combination p,0, can be golfed to p; but I left it ungolfed for clarity.

  w=h/12                   :REM w is the width of the line, which is 1/12 the height of the symbol, hardcoded at 900.
  s=w/2.4                  :REM s/w is the gradient x/y of line E. s is the horizontal offset of the top and bottom of the ends of horizontal bars
  p=25                     :REM VDU p,action,x;y; is the equivalent of PLOT action,x,y

  VDU 22,6                 :REM change mode
  VDU 29,640;400;          :REM set origin

  VDU p,4,0;1.5*w;         :REM move to centre of circle
  VDU p,153,6*w;0;         :REM draw circle in foreground colour
  VDU p,4,0;1.5*w;         :REM move to centre of circle
  VDU p,159,h/3.1;4.6*w;   :REM draw circle in background colour, ending at the upper inner point of the C shape.
  VDU p,0,9*s;9*w;         :REM move relative along slant gradient, 9 spaces in y direction, to define the upper cut on the circle
  VDU p,87,h/3.1;-19*w;    :REM draw triangle in background colour, based on the last two points and the absolute point specified here (vertical line for lower cut)

  VDU p,4,-7.5*w;0;        :REM move absolute to bottom left of lower bar
  VDU p,0,s;w;             :REM move relative to top left of lower bar
  VDU p,85,4.5*s;0;        :REM draw triangle to bottom right corner of lower bar (absolute)
  VDU p,81,s;w;            :REM draw triangle to top right of lower bar (relative)

  VDU p,0,s;w;             :REM move relative to bottom right of upper bar
  VDU p,0,s;w;             :REM move relative to top right of upper bar
  VDU p,85,-7.5*w;2*w;     :REM draw triangle to bottom left of upper bar (absolute)
  VDU p,81,s;w;            :REM draw triangle to top left of upper bar (relative)

enter image description here

HTML, 250 249 248 242 244 234 229

<svg viewBox=-7.5,-6,12,12
clip-path=url(#c) fill=none stroke=#000><circle
r=5.5 /><path

While this is only using SVG stuff, it heavily relies on lax HTML parsing and has to be served as HTML. Strict SVG would require a lot more bytes.

Try it!