Draw the ☣ (Biohazard Symbol)

70

12

Draw the Biohazard symbol in an arbitrary colour on a distinctly coloured background. The specific proportions were published in the June 27th 1974 issue of the Federal Register of the US Government.

Details

  • As output, writing to a file (raster and vector formats are permitted) or displaying on the screen are both allowed.

  • You can draw just the border or the filled shape.

  • If you use raster images, you should take a parameter (or two) as input that lets you adjust the resolution of the output (e.g. width/height).

  • The background must at least have the size of the bounding box of the symbol but may be larger.

  • Outputting the unicode symbol ☣ is not sufficient.

  • The exact ratios of the used distances are given in following diagram (which was originally from here):

I also tried to make an additional diagram with the same measurements that is hopefully a little bit easier to read:

(Inspired by a post on 99%invisible)

flawr

Posted 2019-09-04T11:33:57.253

Reputation: 40 560

2Loophole: can we just put a 1x1 pixel image inside a variable sized background? – John Dvorak – 2019-09-04T13:49:42.123

I don't think it is, if you set the resolution large enough the symbol should still appear. And in any case I hope people here have enough common sense to understand what we mean:) – flawr – 2019-09-04T14:11:31.707

1If I had time to spare I would give it a try with PostScript or turtle graphics. – Guy Coder – 2019-09-04T14:46:21.600

Hmmm, I wonder what a Racket solution would look like. Or a Processing or Compressed Turtle solution. – noɥʇʎԀʎzɐɹƆ – 2019-09-04T21:15:50.923

Since you want the points to be blunted can you put that in your question? Currently it doesn't provide the information such as how long the bluntings should be only how wide apart. – Post Rock Garf Hunter – 2019-09-05T13:07:10.703

1@SriotchilismO'Zaic The length is determined by the two circles: They each have a given center and radius, so the length is determined by the size of the gap. – flawr – 2019-09-05T13:09:55.893

@flawr What is the center of the larger circle then? I don't see it indicated on the diagram. – Post Rock Garf Hunter – 2019-09-05T13:10:37.350

1That is "E" in the original diagram (the crosses represent the circle centers), and $11$ in the one I added below (where the radius meets the axis of symmetry). – flawr – 2019-09-05T13:13:22.983

Ah I see thanks the diagram makes it look like E has only to do with the central annulus. I will fix my answer to center it correctly and then it should blunt properly. – Post Rock Garf Hunter – 2019-09-05T13:22:37.390

Answers

101

T-SQL, 442 441 426 355 349 344 bytes

DECLARE @ VARCHAR(MAX)=REPLACE(REPLACE(REPLACE('DECLARE @a5MULTIPOINT((0 31),(19 -2),(-19 -2))'',@b5MULTIPOINT((0 39),(26 -6),(-26 -6))'',@5POINT(0 9)'',@d5LINESTRING(0 9,0 99,90 -43,0 9,-90 -43)''SELECT @a830%b821)%86)%d81)%d84%819))).STUnion(@827%820)).STIntersection(@b819)))'
,8,'.STBuffer('),5,' GEOMETRY='''),'%',').STDifference(@')EXEC(@)

Saved 70+ bytes by using REPLACE() for long keywords and executing as dynamic SQL. See the post-replacement code in the screenshot below.

I doubled the coordinate values from the sample illustration and moved up 9 units, to reduce the number of decimals displayed.

This was done in SQL 2017, using geo-spatial features introduced in SQL 2008. Lots of useful built-in geometry functions, including STBuffer, which gives me a simple way to define circles of different sizes around a point.

Visual of output, with annotated code:

Biohazard symbol in T-SQL using geo-spatial functions

For more T-SQL drawing, see my Easter Bunny.

For more practical applications of this tech in SQL, read this article or watch this video. SE even has a related site, gis.stackexchange.com.

Edits:

  1. Saved 1 byte by changing a coordinate from 104 to 99.
  2. Saved 15 bytes by taking the STDifference of a STUnion of objects, instead of each individually.
  3. Saved 71 bytes by using REPLACE() on repeated keywords, then executing as dynamic SQL. Reverted Edit 2, to leave more replacements of STDifference.
  4. Saved 4 bytes by moving the center up 9 units, which changed a few coordinates to single (negative) digits. This also freed up the numeral 5 to use as a replacement character instead of '#', saving 2 more bytes on the quotes.
  5. Saved 5 bytes by moving ) into the STDifference replacement string; thanks, @Nicholas!

BradC

Posted 2019-09-04T11:33:57.253

Reputation: 6 099

59Why... does this exist? – Alexander - Reinstate Monica – 2019-09-05T01:55:03.863

28@Alexander For databases that contain or use geographic data, like population census, or scientific studies, or even just customer sales by geographic region. Or just for drawing bunnies and biohazard symbols. – BradC – 2019-09-05T02:54:23.377

26SQL is bad enough for the one thing it's meant for, who in their right mind would want to go beyond that. Imagine GUIs written in SQL. I need annotations, aspects, and a unit testing framework. We need to go deeeeeper. – Alexander - Reinstate Monica – 2019-09-05T03:26:31.470

24

@Alexander As you wish: TSQLT

– FreeMan – 2019-09-05T14:35:26.337

16@FreeMan Oh for f...'s sake. – Alexander - Reinstate Monica – 2019-09-05T14:49:52.290

4Legitimately the funniest thread I've read in a while. Thanks guys. – AleksandrH – 2019-09-06T00:06:34.073

2You can save 4 more by including ) in your STDiff replace. ').STDifference(@' – Nicholas – 2019-09-10T00:30:16.583

@Nicholas 5 bytes, actually, thanks! – BradC – 2019-09-10T13:35:59.877

33

Tex + Tikz, 232 bytes

43 bytes saved by switching to tex. Thanks to Phelype Oleinik

Some bytes saved thanks to Skillmon

\input tikz \tikz[x=1,y=1,white]{\def\f{\foreach\1in{90:,210:,330:}}\def\u{\draw[line width=}\def~{circle(}\f\fill[red](\122)~30);\f{\u2](0,)--(\111);\u8](\130)--(\160);\fill(\130)~21);}\fill~6);\u7,red]~23.5);\f\u2](\130)~20);}\bye

With line breaks and without \def:

\input tikz
\tikz[x=1,y=1,white]{
\foreach\1in{90,210,330}\fill[red](\1:22)circle(30);
\foreach\1in{90,210,330}{
\draw[line width=2](0,0)--(\1:11);
\fill(\1:30)circle(21);
\draw[line width=8](\1:30)--(\1:60);
}
\fill(0,0)circle(6);
\draw[line width=7,red](0,0)circle(23.5);
\foreach\1in{90,210,330}\draw[line width=2](\1:30)circle(20);
}
\bye

Explanation

This is a little outdated I will fix it when I can figure out how to make the images not enourmous

Here I am going to explain how the uncompressed answer solves the problem. I may at some point explain how the compression works. First we draw the big black circles:

\foreach\x in{90,210,330}\fill(\x:21)circle(30);

enter image description here

Then we draw some white lines:

\foreach\x in{90,210,330}\draw[white,line width=2cm](0,0)--(\x:11);

enter image description here

Then we draw white circles:

\foreach\x in{90,210,330}\fill[white](\x:30)circle(21);

enter image description here

Then we add a central white circle:

\fill[white](0,0)circle(6);

enter image description here

Then we add a black annulus:

\draw[line width=7cm](0,0)circle(25.5);

enter image description here

Then we remove parts of the black annulus

\foreach\x in{90,210,330}\draw[white,line width=2cm](\x:30)circle(20);

enter image description here

Post Rock Garf Hunter

Posted 2019-09-04T11:33:57.253

Reputation: 55 382

9You haven't blunted the six outer points. There should be 4 units of white space between each pair. – Level River St – 2019-09-04T23:20:34.097

1@LevelRiverSt The six outer points are now 4 units away from their partner. – Post Rock Garf Hunter – 2019-09-05T04:35:07.543

2Those "claw tips" are too pointy, they should consist of straight line segments parallel to the segments coming from the center circle. Also the 20.88 looks quite suspicious. – flawr – 2019-09-05T06:42:53.680

You can save another byte by using \1 instead of \x, as you can then use \def\f{\foreach\1in{90,210,330}}. – Skillmon – 2019-09-05T09:26:14.777

1@flawr well... they're now literally quite a bit smaller than 5000x5000... only 90x90 now... barely can make out the details :D – Nelson – 2019-09-07T17:03:49.680

@flawr The explanation has not changed. I need to figure out how to make the images the right size before I update them. – Post Rock Garf Hunter – 2019-09-07T21:08:05.677

@SriotchilismO'Zaic rasterize them at 300dpi, this should give good results (see my answer). – Skillmon – 2019-09-09T10:39:33.837

17

C, 8010 bytes

Way back, before SVG or EMF, you had to deal with raster, and if you wanted something to load right away, say before the O/S was ready, like a Windows startup screen, you had to use RLE, or run-length-encoding. This monster outputs a PBM file using RLE as the data. Build like usual and run like this ./biohazard > biohazard.pbm.

If you were to include all the frameworks required to generate, e.g. the SVG engine in HTML, the Java libraries, etc. this would likely be the smallest self-contained solution, because puts is the only external function, and it's typically one of the smallest stdio.h functions.

Regarding this detail:

If you use raster images, you should take a parameter (or two) as input that lets you adjust the resolution of the output (e.g. width/height).

I interpreted "should" as different from "must", e.g. as in RFC 2119, so I didn't include scaling, because for this code it would only be feasible to do multiples of the original, e.g. ./biohazard 2 and that would introduce atoi, printf and other complications which would detract from the main focus of the submission.

int o,i,x[]=
{4946,3,33,2,389,8,33,8,378,13,33,13,369,17,33,16,363,20,33,20,356,19,41,19,350,18,49,18,344,18,55,18,339,17,61,17,334,
17,66,17,330,17,71,17,325,17,75,17,321,17,79,17,317,17,83,17,313,17,87,16,311,16,90,17,307,17,93,17,303,17,97,17,300,
17,99,17,297,17,102,18,293,18,105,17,291,18,107,18,288,17,110,18,285,18,113,17,283,18,115,18,280,18,117,18,277,19,119,
18,275,19,121,19,272,19,123,19,270,19,125,19,268,19,127,19,266,19,129,19,263,20,131,19,261,20,133,19,259,20,134,20,257,
20,136,20,255,21,137,20,253,21,139,20,251,21,141,20,249,21,142,21,248,21,143,21,246,21,145,21,244,21,146,22,242,22,147,
22,240,22,149,22,238,22,150,22,238,22,151,22,236,22,152,23,234,23,153,23,232,23,155,22,232,23,155,23,230,23,157,23,228,
24,157,24,226,24,159,23,226,24,159,24,224,24,160,25,222,25,161,24,222,24,162,25,220,25,163,25,219,25,163,25,218,25,164,
26,216,26,165,25,216,26,165,26,214,26,166,26,214,26,167,26,212,27,167,26,212,26,168,27,210,27,169,27,209,27,169,27,208,
27,170,28,207,27,170,28,206,28,171,27,206,28,171,28,204,29,171,28,204,28,172,29,202,29,172,29,202,29,173,29,201,29,173,
29,200,30,173,29,200,30,173,30,198,31,173,30,198,30,174,31,197,30,174,31,196,31,174,31,196,31,175,31,195,31,175,31,194,
32,175,31,194,32,175,32,193,32,175,32,193,32,175,32,192,33,175,32,192,33,175,33,191,33,175,33,190,34,175,33,190,34,175,
33,190,34,175,34,189,34,174,35,189,34,174,35,188,35,174,35,188,35,174,36,187,36,173,36,187,36,173,36,187,36,173,36,186,
37,74,25,74,36,186,37,67,39,67,36,186,37,62,49,61,38,185,37,58,57,57,38,185,38,53,64,54,38,185,38,50,71,50,38,185,38,
47,76,48,38,185,38,45,81,44,39,184,40,41,87,41,39,184,40,39,91,39,39,184,40,37,95,37,39,184,40,35,99,34,41,183,41,32,
103,32,41,183,41,30,107,30,41,183,41,28,111,27,42,183,42,25,115,25,42,183,42,24,117,24,42,183,42,22,121,21,43,183,43,
19,124,20,43,183,43,18,127,18,43,183,43,17,129,16,44,183,44,14,133,14,44,183,44,13,135,12,45,183,45,11,137,11,45,183,
45,10,139,9,46,183,46,9,138,10,46,183,46,10,137,9,47,183,47,9,136,10,47,183,47,10,135,9,48,183,48,10,56,20,57,10,48,
183,49,9,50,33,49,10,48,184,49,10,45,41,45,10,48,184,50,10,40,49,40,10,49,184,50,10,37,55,36,10,50,185,50,10,33,60,34,
10,50,185,51,10,30,65,30,10,51,185,51,11,27,69,27,10,52,185,52,10,25,73,24,11,52,185,53,10,22,77,21,11,53,185,53,11,19,
81,19,10,53,186,54,11,16,85,16,10,54,185,56,11,13,88,14,11,56,181,59,11,11,91,11,11,59,176,63,11,8,94,9,11,63,171,66,
11,6,97,6,11,66,167,68,12,4,99,4,11,69,163,71,12,1,102,2,11,72,159,74,126,75,155,77,124,78,151,80,123,79,149,82,120,83,
145,85,118,86,141,88,116,88,139,90,114,91,135,93,112,93,133,96,109,96,130,98,107,98,127,101,104,102,124,104,101,104,
122,106,99,106,119,110,95,109,117,112,93,112,114,115,89,115,112,118,85,118,110,120,82,121,107,124,78,124,105,127,74,
127,103,131,69,130,101,134,65,133,99,137,60,137,97,141,54,141,95,146,47,145,93,151,39,150,91,157,29,156,89,166,13,165,
88,168,9,168,86,169,9,169,84,170,9,170,82,171,9,171,80,172,9,171,79,173,9,172,78,173,9,173,76,174,9,174,74,175,9,175,
72,176,9,175,72,176,9,176,70,177,9,177,68,64,20,93,10,94,20,63,68,57,34,83,17,83,33,58,66,54,42,77,21,76,43,54,64,51,
50,71,25,71,49,51,64,48,57,65,29,65,56,49,62,46,63,61,31,61,62,47,60,45,67,58,33,58,67,44,60,43,71,55,35,54,72,43,58,
41,36,8,32,52,37,51,33,8,35,41,58,40,36,17,26,49,39,48,27,16,37,40,56,39,38,22,23,46,41,45,24,21,39,39,55,37,40,26,21,
43,42,44,21,26,40,37,54,36,42,29,20,41,43,41,20,29,42,36,53,35,43,29,21,39,44,39,22,29,43,35,52,34,45,29,23,37,45,37,
23,29,45,34,51,33,46,29,24,35,46,35,25,29,46,33,50,32,48,29,26,33,47,33,26,29,47,33,49,31,49,29,27,32,47,32,27,29,49,
31,48,31,49,30,28,30,48,30,29,29,50,31,47,29,51,30,30,28,49,28,30,29,51,30,46,29,52,29,32,27,49,27,31,29,53,28,46,28,
53,29,33,26,49,26,32,29,54,28,44,28,54,29,34,25,49,25,33,29,55,27,44,27,55,29,35,24,49,23,35,29,56,27,43,26,56,29,36,
22,50,22,36,29,57,26,42,26,57,29,37,21,50,21,37,29,58,26,41,25,58,29,38,21,49,20,38,29,59,25,40,25,59,29,39,20,49,19,
39,29,60,24,40,24,60,29,40,19,49,19,39,29,61,24,39,23,61,29,41,18,49,18,40,29,62,23,38,23,62,30,41,17,49,17,41,29,63,
22,38,22,63,30,42,16,48,17,42,29,63,23,37,21,65,29,43,16,47,16,43,29,64,22,36,22,65,29,43,16,47,15,44,29,65,21,36,21,
66,29,44,13,50,14,44,29,66,21,35,20,67,29,45,11,53,11,45,29,67,20,34,20,68,29,46,8,57,8,46,29,67,20,34,20,68,29,46,6,
61,5,46,30,68,19,34,19,69,29,47,4,63,4,46,30,69,19,33,18,70,30,47,1,67,1,47,29,70,19,32,19,70,30,163,29,71,18,32,18,71,
30,61,2,37,2,61,29,72,18,31,17,73,29,59,5,35,5,58,30,72,18,31,17,73,29,58,7,33,7,57,30,73,17,30,17,74,30,55,10,31,10,
55,30,73,17,30,17,74,30,53,13,28,14,53,30,74,16,30,16,75,30,51,17,25,16,52,29,75,17,29,16,76,29,50,20,21,19,50,30,76,
16,29,15,77,30,50,21,16,22,50,30,77,15,29,15,77,30,50,26,7,25,51,30,77,15,28,15,78,30,51,57,50,30,78,15,28,15,78,31,50,
56,51,30,79,15,27,14,80,30,51,55,51,30,79,15,27,14,80,30,51,55,50,31,80,14,27,13,81,31,51,53,51,30,81,14,27,13,82,30,
51,53,51,30,82,13,27,13,82,31,50,52,51,31,82,13,26,13,83,31,51,51,51,31,82,13,26,13,83,31,51,51,50,31,84,12,26,13,84,
31,50,50,51,31,84,12,26,12,85,31,51,49,50,32,84,13,25,12,85,32,50,49,50,31,86,12,25,12,86,31,50,48,50,32,86,12,25,11,
87,32,50,47,50,32,86,12,25,11,87,32,50,47,49,32,88,11,25,11,88,32,49,47,49,32,88,11,25,11,88,32,49,46,49,32,89,11,25,
10,90,32,49,45,49,32,89,11,25,10,90,33,48,45,48,33,90,10,25,10,91,32,48,45,47,33,91,10,25,10,91,33,47,44,48,33,91,10,
25,10,91,34,46,44,47,33,92,10,25,9,93,33,47,43,46,34,92,10,25,9,93,34,46,43,46,33,93,10,25,9,94,34,45,43,45,34,94,9,25,
9,94,35,44,43,44,34,95,9,25,9,95,34,44,42,44,35,95,9,25,9,95,35,43,42,44,34,96,9,25,9,96,35,42,42,43,35,96,9,25,8,97,
36,42,41,42,35,97,9,25,8,98,36,41,41,41,36,97,9,25,8,99,36,40,41,40,36,98,8,26,8,99,37,39,41,39,36,99,8,26,8,100,37,38,
41,38,37,99,8,27,7,100,38,37,41,37,37,101,7,27,7,101,38,36,41,36,38,101,7,27,7,102,38,35,41,35,38,102,7,27,7,102,39,34,
41,34,38,103,7,27,7,103,39,33,41,33,39,103,7,27,7,104,39,32,41,32,39,104,7,27,7,104,41,30,41,30,40,104,7,29,6,105,41,
29,41,29,40,105,7,29,6,106,41,28,41,28,41,105,7,29,6,107,42,26,41,26,42,106,7,29,6,108,42,25,41,25,42,107,7,29,7,107,
44,22,42,23,43,108,6,30,7,108,44,21,42,21,45,108,6,31,6,109,45,19,42,20,45,109,6,31,6,110,46,17,43,17,46,110,6,31,6,
111,47,15,43,15,47,111,6,31,6,112,48,13,43,13,48,112,5,33,5,113,49,11,43,10,50,112,6,33,5,114,50,9,43,9,50,113,6,33,6,
113,50,8,44,9,49,114,6,33,6,114,48,9,45,8,48,115,5,35,5,115,47,9,45,8,47,116,5,35,5,117,45,8,46,9,45,116,6,35,6,117,44,
8,46,9,44,117,5,37,5,118,42,9,47,8,43,118,5,37,5,119,41,9,47,9,41,119,5,37,5,120,40,8,48,9,40,119,5,39,5,120,39,8,48,9,
38,121,5,39,5,121,37,9,49,8,37,122,5,39,5,123,35,9,49,9,35,123,4,41,5,123,34,8,50,9,34,123,5,41,5,124,32,9,51,9,31,125,
5,42,3,127,30,9,51,9,30,127,3,43,1,130,28,9,52,9,29,130,1,176,26,9,53,9,26,310,24,9,54,9,24,314,22,9,55,9,22,317,20,9,
55,9,20,320,18,9,56,10,17,324,15,10,57,9,16,327,13,9,58,10,13,331,10,10,59,9,11,335,8,9,60,10,8,339,5,10,61,9,6,344,2,
9,62,10,2,358,63,368,65,367,65,366,67,365,67,364,69,362,70,362,71,360,73,358,75,356,76,356,77,354,79,352,81,350,82,349,
84,215,2,130,86,130,3,79,5,129,87,128,6,77,6,127,89,126,6,79,6,125,91,124,7,80,6,123,93,122,7,82,6,121,95,120,7,84,6,
119,97,118,7,86,7,115,100,116,7,87,8,113,102,114,7,89,8,111,105,111,7,91,8,109,107,109,7,93,8,107,109,106,9,94,9,103,
112,104,9,96,9,101,115,101,9,98,10,97,118,98,10,100,10,95,121,95,10,102,11,91,124,92,11,104,11,89,127,88,11,107,12,85,
131,85,11,110,12,81,135,81,12,112,13,77,138,78,13,114,14,73,143,73,14,116,15,69,72,2,73,69,15,118,17,63,74,5,73,64,16,
122,17,59,75,7,75,58,18,124,19,53,77,9,77,53,19,126,22,45,79,13,78,46,21,130,24,37,82,15,81,38,24,132,28,27,85,18,86,
27,28,135,37,5,95,21,95,5,37,138,134,24,135,141,131,27,131,144,128,31,127,148,124,34,125,151,121,37,121,155,117,41,117,
159,113,45,113,163,109,49,109,167,105,53,105,171,101,57,101,175,96,62,96,181,91,67,91,185,86,72,86,191,80,78,81,196,74,
84,74,204,67,91,67,211,59,99,59,219,51,107,51,228,40,119,39,242,25,133,25,5311,0};
main(){for(puts("P1\n432 408");x[i];++i,o=!o)while(x[i]--)puts(o?"0":"1");}

user15259

Posted 2019-09-04T11:33:57.253

Reputation:

1Would be nice to explain how you generated the code. – Cœur – 2019-09-06T16:06:59.807

The code outputs a newline after every character; I think you need putchar() or similar. – marcelm – 2019-09-06T20:36:44.993

@marcelm - PBM P1 format is okay with that! – None – 2019-09-06T20:46:38.010

@YiminRong Oh right, the output was PBM; I didn't quite pay attention to that! – marcelm – 2019-09-06T21:32:08.303

2I'm pretty sure that should does mean must for this question, but that would probably be worth taking up with the OP. – Post Rock Garf Hunter – 2019-09-06T22:53:45.210

@SriotchilismO'Zaic - Note that "must" is used in the detail following (regarding backgrounds) so there is a distinction with the OP. – None – 2019-09-07T22:29:38.937

2I don't think that using must necessarily means that there is a distinction. This is really a question you should (or perhaps must) ask the OP. – Post Rock Garf Hunter – 2019-09-07T23:44:25.543

16

TeX + TikZ, 234 230 226 bytes

Originally 5 bytes longer than Sriotchilism O'Zaic's answer, but this one should be correct. It is similar to his answer but saves a few bytes more here and there, it needs one \draw[line width=8] more (in the code below this is done by \28](~30)to(~55);, that's 17 bytes added only for this) to get the tips of the symbol right, hence the 5 bytes more overall code length.

And thanks to Sriotchilism O'Zaic I reread some of the question and realized I can change the colour to red, so that saves a few bytes again:

\input tikz\let~\def~\1{circle(}~\2{\draw[line width=}~~{\foreach~in{90:,210:,330:}}\tikz[x=1,y=1,white]{~\fill[red](~22)\130);~{\fill(~30)\121);\28](~30)to(~55);\22](~0)to(~10);}\fill\16);\27,red]\123.5);~\22](~30)\120);}\bye

TeX-g + TikZ, 195 Bytes

Just if someone cares, the following uses a TeX-based code golf dialect that I'm working on (don't consider the code stable). The byte count includes EOL characters and the EOF character, as those are semantically used (EOL delimits arguments of loops). The dialect is pretty small up until now and only features shorthands for definitions and a for-loop syntax, however it is not specifically written for this answer, so it shouldn't break the rules of code golfing. Repository for the -g.tex-package/file: https://github.com/Skillmon/TeX-g

\input-g <tikz>~"{\:~{90:,210:,330:}}~'{circle(}~_{\draw[line width=}!f\fill\tikz[x=1,y=1,white]{"f[red](~22)'30);
"f(~30)'21);_8](~30)to(~55);_2](~0)to(~10);
f'6);_7,red]'23.5);"_2](~30)'20);
}

Output of both code snippets looks identical:

enter image description here

(too lazy to update the image, just imagine it being red)

Skillmon

Posted 2019-09-04T11:33:57.253

Reputation: 431

My answer is now correct and 2 bytes shorter than yours. I'm sure someone could probably combine some of my answer with some of yours to make a shorter one, but I don't quite understand your answer. – Post Rock Garf Hunter – 2019-09-05T13:48:31.183

@SriotchilismO'Zaic if I change the colour to red (overread the rule that the colour can be arbitrary), I get it to 230 bytes. – Skillmon – 2019-09-05T14:03:16.157

@SriotchilismO'Zaic and obviously you saved more than just one byte by in your answer by looking at mine (just saying). – Skillmon – 2019-09-05T14:06:02.270

Ok, I looked at your answer and did not understand what it was doing so I don't think I could have really taken very much from your answer. But I changed the message to remove a exact number anyway, since maybe I picked up some stuff from your answer without realizing it. – Post Rock Garf Hunter – 2019-09-05T14:13:25.057

2@SriotchilismO'Zaic it's ok. My code is influenced by yours after all, I currently try to write a code golfing package to turn TeX into a code golfing language of some sort. When I finally published it my answer will be shorter :) (This is no language specifically crafted for this question, so it doesn't break the rules) – Skillmon – 2019-09-05T14:19:24.747

With the current version of my TeX code golfing language I get it down to 199 bytes (+EOF byte). – Skillmon – 2019-09-05T17:55:12.577

15

SVG(HTML5), 434 410 321 306 bytes

<svg viewbox=-60,-60,120,120><circle r=23.5 stroke-width=7 fill=#fff stroke=#000 /><use href=#g transform=scale(-1,1) /><g id=g><use href=#p transform=rotate(120) /><use href=#p transform=rotate(240) /><path id=p stroke=#fff stroke-width=2 d=M5,0A5,5,0,0,0,0,-5V-10A20,20,0,0,0,2,-50V-53A31,31,0,0,1,31,-17

Now based on @LevelRiverSt's SVG. Edit: Saved 12 bytes thanks to @G0BLiN.

Neil

Posted 2019-09-04T11:33:57.253

Reputation: 95 035

1I believe that omitting <defs> is safe. This works for me on Firefox, Chrome and Edge. – Arnauld – 2019-09-04T14:23:43.553

@Arnauld Thanks, that means I can get rid of the first <use> as well! – Neil – 2019-09-04T20:33:05.197

You can shorten this by drawing the symbol centered on x=0,y=0. Try this <svg viewbox=-60,-60,120,120><circle r=23.5 stroke-width=7 fill=#fff stroke=#000 /><use href=#g transform=scale(-1,1) /><g id=g><use href=#p transform=rotate(120) /><use href=#p transform=rotate(240) /><path id=p stroke=#fff stroke-width=2 d=M-5,0A5,5,0,0,1,0,-5V-10A20,20,0,0,1,-2,-50V-53A31,31,0,0,0,-31,-17 - should shorten this to 309 bytes. :) – G0BLiN – 2019-11-27T17:41:41.070

1@G0BLiN Thanks, and I was able to save a further 3 bytes by drawing the mirrored version of the path (since it's reflected anyway). – Neil – 2019-11-27T19:56:53.283

12

Processing, 371 368 bytes

translate(width/2,width/2);scale(width/99);int i=0,b=204;float t=TAU/3;noStroke();for(;i<3;i++){fill(0);ellipse(0,-22,60,60);rotate(t);}for(;i<6;i++){fill(b);rect(-4,-60,8,16);ellipse(0,-30,42,42);rotate(t);}ellipse(0,0,12,12);stroke(0);strokeWeight(7);noFill();ellipse(0,0,47,47);for(;i<9;i++){strokeWeight(2);stroke(b);ellipse(0,-30,40,40);line(0,0,0,-9);rotate(t);}

I wasn't sure if Processing should count as rasterized or not for the purpose of this challenge. If it counts as rasterized, the translate and scale is necessary to make the symbol legible and on-screen for a given window size. But, because all of the drawing commands are vectorized, it works at any given scale; so if we assume drawing at the relative origin to be about 200 units wide is fine, the first 43 bytes can be dropped.

This assumes the background color is 204, 204, 204, which is the default background color in processing. It also assumes a rectMode of CORNER and an ellipseMode of CENTER (the defaults)

With an initial size(640, 640), the resulting sketch looks like this:

enter image description here

By doubling the scale, I saved 3 bytes, because .5s are eliminated (though several numbers do flow from 1 digit to 2 digit).

The construction is similar to the TeX solution, drawing black and then gray on top to "erase" the gaps between the shape.

Explanation:

translate(width/2,width/2); // Move to the middle of the canvas
scale(width/99);            // Scale up to fill the canvas

int i=0,b=204;              // Initialize i, and `b` to the background color
float t=TAU/3;              // Save a rotation of one third, in radians

noStroke();
for(;i<3;i++){ // Draw the three big black circles
  fill(0);
  ellipse(0,-22,60,60);
  rotate(t);
}
for(;i<6;i++){
  fill(b);
  rect(-4,-60,8,16);     // "Blunt" the corners on the sharp outer rings
  ellipse(0,-30,42,42); // Cut out the middle of the big circles
  rotate(t);
}
ellipse(0,0,12,12); // Cut out the small circle in the middle
stroke(0);
strokeWeight(7);
noFill();
ellipse(0,0,47,47); // Draw the thick band that goes through all three big circles
for(;i<9;i++){
  strokeWeight(2);
  stroke(b);
  ellipse(0,-30,40,40); // Cut the "gap" between the three big rings
                        //and the band passing through them
  line(0,0,0,-16);      // Cut the lines coming out of the small middle circle
  rotate(t);
}

Curtis Fenner

Posted 2019-09-04T11:33:57.253

Reputation: 220

Looks nice:) I think if you double all the measurements you can avoid the .5! – flawr – 2019-09-05T06:54:27.153

Yes, but that'd also change some of the single digit number to double digit, so I'm not sure how it balances out. If I counted right, it looks like that would save 2 bytes. I was also thinking about using a scale to change it for only part of the code, but wasn't sure where to best put it – Curtis Fenner – 2019-09-05T07:17:09.343

oh you're right, I did not consider that. – flawr – 2019-09-05T07:19:44.090

Doubling the measurements to remove decimals saved almost 10 bytes in my answer, even though a few coords went from single to double digits. Worth a try, anyway. – BradC – 2019-09-05T16:53:08.923

@CurtisFenner -.- I made a mistake and downvoted your answer (when I was trying to upvote it). Since I've downvoted a few days ago, the vote is locked and I can't upvote until an edit is made. Could you please edit something so I can give you the well-deserved upvote? – Ismael Miguel – 2019-09-11T14:40:56.043

1I saved 3 bytes by doubling the scale it's drawn at. @IsmaelMiguel – Curtis Fenner – 2019-09-12T01:11:21.620

@CurtisFenner Awesome! And upvoted! Thank you. By the way, does Processing allow to, say, do (a=fill)(0); and then do a(b); instead of fill(b);? Or similar? You repeat a lot of functions. – Ismael Miguel – 2019-09-12T08:22:21.380

Not like that (Processing is basically just Java). It's possible that adding methods could help a little, though – Curtis Fenner – 2019-09-12T14:07:27.827

Yeah, Java is a mess regarding these things :/ – Ismael Miguel – 2019-09-12T15:01:03.170

12

GLSL, 700 629 564 545 499 bytes

#define v vec2
#define j(x,r)length(x-g)<r
#define k(x,r,q)j(x,q)!=j(x,r)
#define l(b)length(g-b)<1.&&length(g-dot(g,b)*b)<(length(g)<S?A*S:A/S)
float C=.86,S=.5,F=.3,E=.22,A=.02,G=.21;void mainImage(out vec4 o,in v p){v r=iResolution.xy;v g=(p/S-r)/r.y;o.g=(k(v(0,F),G,G-A)||k(v(F*C,-F*S),G,G-A)||k(v(-F*C,-F*S),G,G-A))?o.g=0.:k(v(0),F,G)?C:l(v(0,1))||l(v(C,-S))||l(v(-C,-S))||j(v(0),.06)||j(v(0,F),G)||j(v(F*C,-F*S),G)||j(v(-F*C,-F*S),G)?0.:j(v(0,E),F)||j(v(E*C,-E*S),F)||j(v(-E*C,-E*S),F)?C:0.;}

I was playing around with Shadertoy, so I tried the GLSL shading language. The code just rasterizes circles and lines by testing each fragment, and assigns them a value of one or zero. The size was cut down from >1000 bytes by heavy use of macros.

Shadertoy program

enter image description here

Roninkoi

Posted 2019-09-04T11:33:57.253

Reputation: 161

1Welcome to the site! Neat first answer! – Post Rock Garf Hunter – 2019-09-06T00:05:46.693

I don't know the language, but can the && and || be golfed to & and | at some or all parts? – Kevin Cruijssen – 2019-09-06T07:33:40.917

@KevinCruijssen It's a subset of C, so those would be bitwise operations. For me the compiler complains about type though – Roninkoi – 2019-09-06T08:01:45.460

1@Roninkoi I indeed saw that it was based on C. In C it is possible to use |/& instead of ||/&& for bools, isn't it? Haven't done anything in C in a long time, so not sure. I know it works in Java/C# .NET in most cases. But I only now notice the Shadertoy link you've added, and it doesn't seem to work there as you've already stated. Ah well. Nice first answer btw! Welcome to CGCC. – Kevin Cruijssen – 2019-09-06T08:54:09.767

I cut -30 bytes on posted code but Header sais 566 bytes, and posted code is 628? – PrincePolka – 2019-09-06T20:56:10.720

@PrincePolka Oh, sorry only the Shadertoy was 566. Now posted code is 564 – Roninkoi – 2019-09-07T09:57:06.610

9

GLSL, 319 310 bytes

#define F float
#define H(y)sqrt(x*x+(y)*(y))
void mainImage(out vec4 D,in vec2 u){vec2 U=u*.003-.5;F x=abs(U.x),y=U.y;if(y<.577*x){F t=.5*x+.866*y;y=.866*x-.5*y;x=abs(t);}F c=F(H(y-.11)<.15);F R=H(y);F S=H(y-.15);if(S<.105)c=0.;if(R<.03)c=0.;if(x<(R<.1?.005:.02))c=0.;if(R>.10&&R<.135&&S<.095)c=1.;D=vec4(c);}

This can be rendered on Shadertoy.

sample

You can use the symmetry in the image to draw it with a smaller amount of separate shapes.

Here is a somewhat inflated version:

#define F float
#define H(y) sqrt(x*x+(y)*(y))

void mainImage(out vec4 D,in vec2 u)
{
    // normalized UV
    vec2 U = u*.003 - .5;

    // fold the 6 identical sections to the same UV coordinates
    F x = abs(U.x), y = U.y;
    if (y < .577*x)
    {
        F t = .5*x + .866*y;
        y = .866*x - .5*y;
        x = abs(t);
    }

    // circles and lines
    F c = F(H(y-.11) < .15);
    F R = H(y);
    F S = H(y-.15);
    if (S < .105) c = 0.;
    if (R < .03) c = 0.;
    if (x < (R < .1 ? .005 : .02)) c = 0.;
    if (R > .10 && R < .135 && S < .095) c = 1.;

    // output
    D = vec4(c);
}

(thanks to @Kevin Cruijssen for removing some unnecessary whitespace)

roeland

Posted 2019-09-04T11:33:57.253

Reputation: 191

1You can remove some of the spaces. The one in your define: H(y) sqrtH(y)sqrt; all the spaces at your if-statements: if (if(; and those in your last if-statement surrounding the ANDs: if (R>.10 && R<.135 && S<.095)c=1.;if(R>.10&&R<.135&&S<.095)c=1.;. – Kevin Cruijssen – 2019-09-06T16:22:41.263

8

HTML / JS,  448 435 433  387 bytes

Saved many bytes by using @Neil's pre-minimized version of the SVG
Saved 2 bytes thanks to @Shaggy

A compressed version of this SVG file from Wikimedia Commons.

<body onload="_=`<svg~12y~24y><path id=p d=m28.8117,27.046a3,3}0qb3117q4.004v-1w539|1wq20.7959v-w583a1jxb7975x7.3228xj,8.6032x9.7443l-.4835q.2792|-18.7598q9.0989zm3.4148q8.871a10x0}0q1b453,c9w,9w{-kx3wx3w}1x6.8042,0x0x0{k>~><use href=#p transform=rotate(},cc|a10wx0w}c{}1qb1756,yc26,26) /x,1w.5q,-kb7417j5x5}1c0,b2.`;for(i of`bcjkqwxy{|}~`)with(_.split(i))_=b.innerHTML=join(pop())"id=b>

Try it online! (just outputs the decompressed string)

Demo snippet

setTimeout(_ => document.getElementsByTagName('svg')[0].setAttribute("viewBox", "0 0 100 100"), 0)
<body onload="_=`<svg~12y~24y><path id=p d=m28.8117,27.046a3,3}0qb3117q4.004v-1w539|1wq20.7959v-w583a1jxb7975x7.3228xj,8.6032x9.7443l-.4835q.2792|-18.7598q9.0989zm3.4148q8.871a10x0}0q1b453,c9w,9w{-kx3wx3w}1x6.8042,0x0x0{k>~><use href=#p transform=rotate(},cc|a10wx0w}c{}1qb1756,yc26,26) /x,1w.5q,-kb7417j5x5}1c0,b2.`;for(i of`bcjkqwxy{|}~`)with(_.split(i))_=b.innerHTML=join(pop())"id=b>

Arnauld

Posted 2019-09-04T11:33:57.253

Reputation: 111 334

This works, on CodePen in Chrome Android, for 392. – Shaggy – 2019-09-04T21:30:38.253

1@Arnauld I have inverted my answer, although it cost 5 bytes (I found another unnecessary byte though so overall my score only went up by 4). – Neil – 2019-09-05T08:53:13.033

@Neil Updated accordingly. ;) – Arnauld – 2019-09-05T11:26:18.127

It turns out that @LevelRiverSt's SVG is much smaller! – Neil – 2019-09-08T11:47:00.557

8

Haskell, 530 491 436 435 430 420 bytes

f=fromIntegral
c(a,b)r(x,y)=(x-a)^2+(y-b)^2<r^2
(m#w)t(x,y)|c<-cos(-t),s<-sin(-t)=x*c-y*s>m&&abs(x*s+y*c)<w/2
u a p=any($p)a
i a p=all($p)a
v=(*(pi/6))<$>[9,5,1]
o=c(0,0)
h?r=[c(h*cos a,h*sin a)r|a<-v]
(h%y)x|u[i[u$11?15,(not.)$u$o 3:map(0#1)v++map(9#4)v++15?10.5],i[o 13.5,not.(o 10),u$15?9.5]](60*f x/h-30,60*f y/h-30)="0 "|0<1="1 "
g h|s<-show h,n<-[0..h-1]=writeFile"a.pbm"$unlines$"P1":(s++' ':s):[n>>=(f h%)y|y<-n]

Outputs a PBM file.

This was a lot of fun!

Biohazard

(I had to convert this to PNG to upload to imgur)

Basically we create our own vector graphics functions which render onto an image pixel by pixel by detecting whether the pixel is part of the shape. The shape is constructed as a bunch of circles and lines (radiating from the origin) held together with basic set operations: union, intersection, and not. The circles are composed of their center and a radius, and the lines have a minimum radius, a width, and an angle in that order. Detecting membership in a circle is easy: I just subtract the center coords and compare the magnitude to the radius. The line is slightly more complicated: I rotate the point by the opposite of the angle to bring it (to nullify the rotation) then I just check whether the x and y coordinates fall within the expected range. The minimum radius is to ensure the larger gap at the far ends of the large circles does not overrule the small gaps near the center. After that it's a simple matter of boolean logic to do set math.

EDIT: Thanks a lot to @flawr for taking off 39 bytes!

EDIT2: Thanks a lot to @Christian Sievers for taking off 55 bytes! Good idea making them into functions

EDIT3: Thanks again to @Christian Sievers for shaving off another byte!

EDIT4: Took off 7 bytes thanks to @H.PWiz and @Angs!

EDIT5: Just noticed a bug! I was rendering the lines twice as thick as they were supposed to be! Cost me 2 bytes to fix it (had to divide width by 2; could've adjusted the constant values but changing 1 to 0.5 would also cost 2).

EDIT6: Thanks @Angs for taking off another 10 bytes!

user1472751

Posted 2019-09-04T11:33:57.253

Reputation: 1 511

Wow, this is so cool. It is rare to see someone defining their own types in [tag:code-golf] here:) Two questions: Is it necessary to have negative angles [-90,-210,-330]? And would it be possible to change the <= to <? – flawr – 2019-09-06T20:48:45.210

@flawr The negatives were to get the orientation right, as the circles were out of sync with the lines (I think). I did a lot of fiddling around and at this point I'm scared to mess with it any more, lol. I erred on the side of caution with <= I wasn't sure if < would really count because it might make the proportions slightly off in places or cause weird artifacts – user1472751 – 2019-09-06T20:53:45.433

1

So I tried it and managed to shave a few bytes off

– flawr – 2019-09-06T21:38:48.637

Mainly some unnecessary perenthesis, then using just on size parameter as well as compressing the three angles. – flawr – 2019-09-06T21:39:34.873

1

Oh, in case you didn't know, we have a haskell chat as well as some tips for golfing in haskell.

– flawr – 2019-09-06T21:40:45.593

1

Another small tweak

– flawr – 2019-09-06T21:53:41.207

1

Nice! It's possible without data type

– Christian Sievers – 2019-09-07T13:39:39.247

Oh, and (not.)$... can be written as not.(...), where ... ends with 10.5 before the next ]. – Christian Sievers – 2019-09-07T16:56:14.800

You should be able to save bytes by renaming l to # – H.PWiz – 2019-09-07T18:30:02.397

Using NetPBM saves a whopping two bytes!.

– Angs – 2019-09-09T14:05:17.133

Some refactoring for 10 bytes

– Angs – 2019-09-11T09:56:10.523

7

PostScript, 367 359 328 271 bytes

Code (compressed version):

5 5 scale 36 24 translate <</c{0 360 arc closepath}/r{120 rotate}/R{repeat}/L{setlinewidth}/g{setgray}/F{fill}>>begin 3{0 11 15 c F r}R 1 g 3{0 15 10.5 c F r}R 0 0 3 c F 3{[-.5 2 1 3 -2 25 4 3]rectfill r}R 0 g 4 L 0 0 11.5 c stroke 1 g 1 L 3{0 15 10 c stroke r}R showpage

Code (uncompressed version):

5 5 scale                  % over-all scale
36 24 translate            % over-all shift

% define some short-named procedures for later use
<<
  /c { 0 360 arc closepath }  % append circle (x, y, radius are taken from stack)
  /r { 120 rotate }           % rotate by 120°
  /R { repeat }
  /L { setlinewidth }
  /g { setgray }
  /F { fill }
>> begin

3 {
    0 11 15 c F       % black circle
    r                 % rotate by 120°
} R
1 g                   % set white color
3 {
    0 15 10.5 c F     % white circle
    r                 % rotate by 120°
} R
0 0 3 c F             % small white circle
3 {
    [ -.5 2 1 3       % white gap near center
      -2 25 4 3       % white gap on edge
    ] rectfill
    r                 % rotate by 120°
} R
0 g                   % set black color
4 L                   % set linewidth 4
0 0 11.5 c stroke     % black ring
1 g                   % set white color
1 L                   % set linewidth 1
3 {
    0 15 10 c stroke  % white ring
    r                 % rotate by 120°
} R
showpage

Result (as animation to see how it is drawn):

result

Thomas Fritsch

Posted 2019-09-04T11:33:57.253

Reputation: 361

Great animation. – dana – 2019-09-07T20:33:44.063

6

Ruby, 278 bytes

puts"<svg viewBox='-60-60 120 120'><circle cx='0'cy='0'r='23.5'stroke-width='7'fill='white'stroke='red'/>",(-3..5).map{|i|"<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(#{i/3},-1)rotate(#{i*120})'/>"}

Try it online!

Generates the SVG code below, with the symbol being at 200% of the scale in the OP.

It consists of a circle at the back, and the prongs in the foreground. The prong is scaled -1,0,1 in the X axis and rotated through multiples of 120 degrees. The cases where the X scaling is zero produce no output, while the -1 and +1. provide the two sides of each pair of prongs.

Use is made of a 2-unit wide white border around the prong to cut the back circle, using the stroke and stroke-width attributes. In order for the internal shape to be per the OP, the coordinates are moved by 1 unit (half the width of the border.) Note that the path is deliberately not closed, to suppress the drawing of the final line of the border. This ensures the two halves of each pair of prongs join together.

90 degrees of the inner circle are drawn rather than the expected 60, for golfing reasons. This means there is some overlap between the bases of each pair of prongs, but this does not affect the appearance of the output shape.

<svg viewBox='-60-60 120 120'><circle cx='0'cy='0'r='23.5'stroke-width='7'fill='white'stroke='red'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(-1,-1)rotate(-360)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(-1,-1)rotate(-240)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(-1,-1)rotate(-120)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(0,-1)rotate(0)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(0,-1)rotate(120)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(0,-1)rotate(240)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(1,-1)rotate(360)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(1,-1)rotate(480)'/>
<path fill='red'stroke='white'stroke-width='2'd='M5 0A5 5 0 0 1 0 5v5A20 20 0 0 1 2 50v3A31 31 0 0 0 31 17'transform='scale(1,-1)rotate(600)'/>

Level River St

Posted 2019-09-04T11:33:57.253

Reputation: 22 049

2

Python 3 with pygame, 327 314 287 278 bytes

(Applied various nasty hacks to save 13 bytes; most notably no longer storing the color but calculating it on the fly with -(r>25))
(Refactored to function, losing sys; hacked out math in favour of coordinate constants; small tweaks; saved 27 bytes)
(Rewrote coordinate constants to complex math tricks to get (co)sine, saving 9 bytes)

Function that takes a single integer argument representing half the width/height of the resulting image. E.g. f(500) will create a 1000x1000 pixel window, and draw a biohazard symbol in there.

from pygame import*;D=display
def f(S):
 u=D.set_mode([S*2]*2);b=S>>6
 for p,r,w in(22,30,0),(30,20,0),(0,27,7),(30,21,2),(0,6,0),(51,4,0):
  for l in 0,4/3,8/3:Z=1j**l*p*b;q=S+int(Z.imag),S-int(Z.real);draw.circle(u,-(r>25),q,r*b,w*b);r-20or draw.line(u,0,(S,S),q,b*2);D.flip()

Unshortened version:

import pygame
import math
import sys

size = int(sys.argv[1])
basic = size // 55

screen = pygame.display.set_mode((size * 2, size * 2))

circles = [
    (22, 30, 0, -1),  # basic shape
    (30, 20, 0, 0),   # large cutouts
    (0, 27, 7, -1),   # "background circle"
    (30, 21, 2, 0),   # "background circle" clearance
    (0, 6, 0, 0),     # center disc
    (51, 4, 0, 0),    # blunt the points
]

for pos, radius, width, color in circles:
    for lobe in [0, math.pi * 2 / 3, math.pi * 4 / 3]:
        x = int(math.sin(lobe) * pos * basic) + size
        y = size - int(pos * basic * math.cos(lobe))
        pygame.draw.circle(screen, color, (x, y), radius * basic, width * basic)
        # Hack to draw the small slots in the center
        if radius == 20:
            pygame.draw.line(screen, 0, (size, size), (x, y), basic * 2)

pygame.display.flip()

The key to this program is mostly exploiting the 3-way point symmetry of the symbol, and expressing the drawing operations as sparsely as possible. The heart of it all is circles, which is a list of circle definitions, consisting just of:

  • position: how far outwards from the origin in half basic units
  • radius: the radius of the circle in half basic units
  • width: the border width of the circle (inwards from the outer circle, 0 = fill)
  • color: exploiting the fact that pygame interprets 0 as black and -1 as white

Every drawing operation is repeated three times, rotated 120°. The blunting of the "claws" is done with another circle. The inside "line cuts" are special-cased because I couldn't think of a more efficient way to get them in there. The "basic unit" defined in the specification is doubled here so I didn't have to use .5 in circles and int() all over the place to satisfy pygame.

Result for python3 -c 'from biohazard import *; f(500)':

Display output of this answer

marcelm

Posted 2019-09-04T11:33:57.253

Reputation: 121

1

Good job and welcome to CGCC! The description should say "Python 3 + pygame" when a non-builtin library is used. The input can be taken from standard input or as a function argument to avoid importing the sys module, which shortens the code (see rules). Also, this trick can be applied to avoid the need of importing math.

– Joel – 2019-09-08T13:48:22.810

@Joel Thanks for the feedback! I included pygame in the header, and converted the code to a function. As for math, I refactored that to a list of coordinates; it was only 3 of them anyway. No (co)sine necessary. – marcelm – 2019-09-08T16:19:51.297

1Applying the above-mentioned trick actually saves more bytes than putting all the numbers into the source code. – Joel – 2019-09-08T17:04:53.917

@Joel Thanks for the reminder; earlier I discarded that option because it seemed longer but it looks like I was wrong. It also allowed some more optimizations. – marcelm – 2019-09-08T18:52:04.373

1

Tcl/Tk - 557 bytes

set F #000
set B #F50
pack [canvas .c -bg $B]
rename expr e
rename foreach f
rename proc p
p R r {list [e $r*cos($::a)] [e $r*sin($::a)]}
p D {d r} {lassign [R $d] x y;list [e $x-$r] [e $y-$r] [e $x+$r] [e $y+$r]}
p C {d r c} {.c cr o {*}[D $d $r] -f $c -outline $c}
p L {p q w} {.c cr l {*}[R $p] {*}[R $q] -w [e $w] -f $::B}
p A {d r w c} {.c cr a {*}[D $d $r] -w [e $w] -star 0 -ex 359.9 -sty arc -outline $c}
f x {{C 11 15 $F} {C 15 10.5 $B} {L 0 5 1} {L 20 40 4} {C 0 3 $B} {A 0 11.75 3.5 $F} {A 15 10 1 $B}} {f a {2.62 4.72 6.81} $x}
.c move all 99 99

That version, however, is boring, since you get the same small-sized image no matter what. It does satisfy the OP conditions for displaying on-screen, however. Here is the uncompressed version with commentary and the ability to specify a size added in:

# Input: command line argument is the pixel width (same as the height) of the window to create
# For example:
#   wish a.tcl 500
set window_size $argv

set foreground_color #000
set background_color #F50
pack [canvas .c -bg $background_color -width $window_size -height $window_size]

# Helper procs to generate x,y coordinates
proc radius->x,y r {
  list [expr {$r*cos($::angle)}] [expr {$r*sin($::angle)}]
}

proc center_offset,radius->rectangle {offset r} {
  lassign [radius->x,y $offset] x y
  list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]
}

# Tk's canvas does not scale line widths, so we have to do that manually
# The $scale is a global variable for compressing the code text above
set scale [expr {$window_size*.016}]

# These three procs draw items in the canvas
proc circle {offset r color} {
  .c create oval {*}[center_offset,radius->rectangle $offset $r] -fill $color -outline $color
}
proc line {p q w} {
  .c create line {*}[radius->x,y $p] {*}[radius->x,y $q] -width [expr {$::scale*$w}] -fill $::background_color
}
proc annulus {offset r w color} {
  .c create arc {*}[center_offset,radius->rectangle $offset $r] -width [expr {$::scale*$w}] -start 0 -extent 359.9 -style arc -outline $color
}

# Our list of shapes to draw
#  circle  center_offset, radius,                   color
#  line    end_offset_1,  end_offset_2, line_width
#  annulus center_offset, radius,       line_width, color
foreach command {
  {circle  11 15        $foreground_color}
  {circle  15 10.5      $background_color}
  {line     0  5    1}
  {line    20 40    4}
  {circle   0  3        $background_color}
  {annulus  0 11.75 3.5 $foreground_color}
  {annulus 15 10    1   $background_color}
} {
  # Each command gets applied thrice, rotated $angle radians each time
  foreach angle {2.62 4.72 6.81} $command
}

.c scale all 0 0 $scale $scale
.c move all [expr {$window_size/2}] [expr {$window_size/2}]

# Some random convenience stuff for playing with it
bind . <Escape> exit
after 500 {focus -force .}

Sorry, no pictures (working off my phone today). Produces a black symbol on a biohazard orange background.

Dúthomhas

Posted 2019-09-04T11:33:57.253

Reputation: 541

1

C (gcc) (MinGW), 557 530 524 522 bytes

-27 -6 bytes thanks to ceilingcat

Added compiler option -lm on TiO strictly to be able to show how it runs. Under MinGW this is not necessary.

Takes width of image as a command line argument. Outputs a 3-shade greyscale PGM file to STDOUT. The circle drawing function is slightly longer than it could be, to avoid dreadful runtime on even moderately sized images, the positioning/scaling of the symbol is not perfect, and I suspect shuffling the draw order somewhat might squeeze some more out of this, so there is room for improvement for sure.

Everything is drawn as circles. The rectangular cutouts are painted using the circle drawing function as a moving brush.

char*I;q,j=5,r,c;N(n){n="F=**(..*(C/)F<<*>FF)"[j*4+n]-40;}float d,b,m,x,y,V=2.0944;C(x,y,R,t,z)float x,y,R,t;{for(r=y<R?0:y-R;r<=y+R;r++)for(c=x-R;c<=x+R;c++)d=hypot(c-x,r-y),d<R&d>=R-t?I[r*q+c]=z:0;}main(i,v)int**v;{q=atoi(v[1]);b=q/104.;m=q/2.;for(I=memset(calloc(q,q+1),2,q*q);i=j--;)for(x=0;x<7;x+=V)C(m+cos(x)-N(0)*b*sin(x),m-N(0)*b*cos(x)+sin(x),N(1)*b,N(2)*b,N(3));for(;i<3;i++)for(j=m;j--;C(m-x,m-y,d,d=d>4*b&d<10*b?b:d>50*b?b*4:0,2))d=hypot(x=j*sin(x)-cos(x),y=j*cos(x=i*V)-sin(x));printf("P5 %d %d 2 %s",q,q,I);}

Try it online!

gastropner

Posted 2019-09-04T11:33:57.253

Reputation: 3 264

@ceilingcat Quite the improvement! – gastropner – 2019-11-21T18:00:53.627

0

Wolfram Language (Mathematica), 211 209 bytes

RegionPlot[#2>6&&Norm[#-{22,0}]<30&&Norm[#-{30,0}]>21&&!-1<#[[2]]<1&&!(-4<#[[2]]<4&&#[[1]]>20)||20<#2<27&&Norm[#-{30,0}]<19&@@{#{Cos@#2,Sin@#2},#}&@@{#,Mod[#2,2Pi/3]-Pi/3}&@@AbsArg[I*x-y],{x,s=52,-s},{y,-s,s}]

Here exported with the additional option PlotPoints -> 100 to make it look more accurate:

enter image description here

Roman

Posted 2019-09-04T11:33:57.253

Reputation: 1 190