text:
Score a single dart
Introduction
Write a program or function that, given the coordinates of where a dart lands on a dartboard, return the score of that dart. Dart coordinates are given as two integers, x,y measured from the center of the dartboard, with millimeter precision.
How to score a dart
Darts is a game played by throwing a dart at a circular board. The dart board is divided into 20 equally sized "wedges". Starting from the top and going clockwise, the sections have values of 20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12,5. If your dart lands in the black or white parts of any of the wedges, you score the value indicated on the outside of that wedge.  .
However, if your dart lands in the outer green/red ring of the dartboard, you score double the points indicated on the outside of the wedge that you hit. Likewise, hitting the inner green/red ring (the one in between the two white/black sections), you score triple the number indicated on the outside of the wedge. If your dart hits the innermost circle (the red bulls-eye) you instead score 50 points and finally, if your dart hits the second-innermost circle (the green ring around the bulls-eye), you score 25 points.
The dimensions of the rings, measured from the center of the dartboard, are as follows:

Bullseye (50): [0mm-6mm)
25:            [6mm-16mm)
Inner Single:  [16mm-99mm)
Triple:        [99mm-107mm)
Outer Single:  [107mm-162mm)
Double:        [162mm-170mm)
Miss (0):       170mm+

Note 1: Pictures provided are for illustration purposes only, and are not to scale.
Note 2: Measurements given are approximate, and may not be accurate to a real dartboard.
Note 3: All measurements given are [inclusive-exclusive). For the purposes of this challenge, we're not going to worry about darts hitting the wire and bouncing off. If the dart lands "on the wire" with one of the radial lines, then it is up to the answerer to decide whether to break the tie clockwise or counter-clockwise. Tie breaking direction must be consistent, and indicated.
Note 4: Dartboard is hung in the standard way with the middle of the 20 section being directly above the bullseye, and the 3 section directly below the bullseye.
Input
Two integers representing the x,y coordinates of where the dart landed, measured in millimeters, relative to the center of the dartboard.
Output
A single integer, for the number of points that would be awarded to a dart that landed at the given coordinates.
Sample
0,0     -> 50
2,101   -> 60
-163,-1 -> 22
6,18    ->  1
-6,18   ->  5
45,-169 ->  0
22, 22  ->  4 (if tie-broken clock-wise)
            18(if tie-broken counter-clockwise)
-150,0  ->  11
-150,-1 ->  11

Scoring
code-golf. Fewest bytes in your source code wins.
Standard loopholes forbidden.

Can you provide a test case where tie breaking is required (a dart hits the wire)?

@ovs Gave an example for the radial wires. Should I provide more? Or do we also need examples of the ring wires? Or is that clear how it works now?

If only we could take input in polar coordinates...

I would suggest guaranteeing that the dart will always hit the board.

@Shaggy I don't see any decent reason to do so.

@mbomb007 That was suggested in the sandbox. But that removes probably half the challenge right there. It sounded to me like expecting the input to have part of the challenge done for you. If enough people think it's a better challenge that way, I can change the challenge and come up with some more sample test cases.

@Shaggy Can you explain why that should be the case? Personally I would love it if my darts were always guaranteed to hit the dart board, but for the sake of the challenge, I thought it best to stick to reality over fantasy.

Suggested test cases: -150,-1 and -150,0 which should both give 11 and may be an edge case on some implementations, as this is the transition between theta converging to -pi and theta = +pi in polar coordinates. (My initial answer failed on the 2nd one.)

Dangit, x=y=0 is totally messing me up!! Good challenge.

Hope you don't mind, I edited in a better version of the second pic.

@BradC Well, I did work really hard on the one I had... No yeah yours does look better. Thanks for the addition.

Thank you for accepting my answer. However, this is a code-golf challenge, so you should either accept the shortest answer or no answer at all (the latter being the most common way).

Can we take input as a complex number?

@lirtosiast Sure. As long as it's the equivalent of Cartesian coordinates. Polar coordinates were suggested, but I decided against that.

JavaScript (ES7), 137 bytes
Takes the coordinates in currying syntax (x)(y). Uses counterclockwise tie-break.
x=>y=>(r=(x*x+y*y)**.5)<6?50:r<16?25:(r<99?1:r<107?3:r<162||r<170&&2)*parseInt('b8g7j3h2fa6d4i1k5c9eb'[Math.atan2(y,x)*3.1831+10.5|0],36)

Try it online!
How?
We translate the input Cartesian coordinates \$(x,y)\$ into polar coordinates \$(r,\theta)\$ with:
$$r=\sqrt{x^2+y^2}$$
$$\theta=\arctan_2(y,x)$$
We use \$r\$ to determine whether the dart is located over the Bullseye, 25, Inner Single, Triple, Outer Single, Double or if the shot is a Miss.
If we're located over a Single, Double or Triple, we use \$\theta\$ to determine in which sector \$s\$ we are with:
$$s=\left\lfloor\frac{\theta+\pi}{2\pi}\times20+\frac{1}{2}\right\rfloor=\left\lfloor\theta\times\frac{10}{\pi}+10+\frac{1}{2}\right\rfloor$$
For a \$340\times340\$ area, we need 4 decimal places of \$10/\pi\$ to get enough precision, which gives:
$$\frac{10}{\pi}\approx3.1831$$
The base scores are stored counterclockwise in a base-36 encoded string of 21 entries, starting and ending at \$11\$:
$$11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11$$
We need to repeat \$11\$ because half of this sector belongs to the first slice (where \$\theta\$ is close to \$-\pi\$), while the other half belongs to the last slice (where \$\theta\$ is close to \$+\pi\$).
Graphical output
The following ES6 code snippet draws the dartboard using the same logic as in the golfed code.

for(ctx = c.getContext('2d'), y = -180; y < 180; y++) {
  for(x = -180; x < 180; x++) {
    r = Math.pow(x * x + y * y, 0.5);
    s = Math.atan2(y, x) * 3.1831 + 10.5 | 0;

    ctx.fillStyle = [ '#000', '#fff', '#be3628', '#487f45', '#bbb', '#ddd' ][
      r < 6 ? 2 : r < 16 ? 3 :
      (r < 99 ? 1 : r < 107 ? 3 : r < 162 ? 1 : r < 170 ? 3 : 4) ^ (s & 1)
    ];
    ctx.fillRect(x + 180, y + 180, 1, 1);
  }
}
<canvas id=c width=360 height=360 style="width:360px;height:360px" />

JavaScript (ES6) + SVG(HTML5), 53 + 523 51 + 519 507 = 576 570 558 bytes

document.write`<svg width=345 height=345>`;i=b=Math.PI/10;s=Math.sin(a=-b/2);c=Math.cos(a);f=(r,f,n)=>document.write(`<path d=M172,172L${[172+r*s,172+r*c]}A${[r,r,0,0,1,172+r*t,172+r*d]}z fill=#${f} n=${n} />`);g=(q,r,m,n,i)=>f(q,i?474:`b32`,n*m)+f(r,i?`fff`:`000`,n);[3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11,8,16,7,19].map(n=>{t=s;d=c;s=Math.sin(a+=b);c=Math.cos(a);g(170,162,2,n,i=!i);g(107,99,3,n,i);});document.write`<circle cx=172 cy=172 r=16 fill=#474 n=25 /><circle cx=172 cy=172 r=6 fill=#b32 n=50`
<body onclick=alert(+event.target.getAttribute`n`)>

Input is via mouse click, output via alert. Edit: Saved 12 bytes by using slightly more approximate colours as suggested by @Arnauld.

I guess nobody's going to blame you if you use b33 and 474 for red and green. :-)

@Arnauld Fair enough, although b33 is bb3333 so b22 (aka bb3322) is closer to your original be3628.

Intel 8086/8087 assembly, 180 144 142 138 bytes
This uses the 8087 math co-processor for all of the trig and floating-point arithmetic. All calculations are done in hardware with 80-bit floating-point precision.
df06 b101 d8c8 df06 af01 d8c8 dec1 d9fa df1e b301 8b16 b301
33c0 81fa aa00 7c03 eb53 9083 fa06 7d05 b032 eb49 9083 fa10
7d05 b019 eb3f 90df 06b7 01df 06b5 01d9 f3df 06b1 01dd d2d9
ebde f9de c9de c1df 1eb3 01a1 b301 bb9c 01d7 83fa 6b7d 0a83
fa63 7c05 b303 eb09 9081 faa2 007c 04b3 02f6 e30b 0810 0713
0311 020f 0a06 0d04 1201 1405 0c09 0e0b 0a00

Written as a MASM MACRO (basically a function), takes X and Y as coordinates and returns the calculated score in AX.  The tie is broken clockwise.
MAX_BULL EQU 6
MAX_25   EQU 16
MIN_3X   EQU 99
MAX_3X   EQU 107
MIN_2X   EQU 162
MAX_2X   EQU 170

; cartesian coordinates to radius
; ST = sqrt( X^2 + Y^2 )
; input: X,Y (mem16,mem16)
; output: Radius (mem16)
FCRAD   MACRO X, Y, R
    FILD  Y         ; ST[] = Y
    FMUL  ST,ST     ; ST = y^2
    FILD  X         ; ST[] = X
    FMUL  ST,ST     ; ST = x^2
    FADD            ; ST = ST + ST1
    FSQRT           ; ST = SQRT(ST)
    FISTP R         ; R = ROUND(ST)
        ENDM

; cartesian coordinates to sector #
; input: X,Y (mem16,mem16)
; output: Sector (mem16)
FCSEC   MACRO X, Y, S
    FILD  Y         ; ST[] = Y
    FILD  X         ; ST[] = X
    FPATAN          ; ST = atan2(Y,X)
    FILD  CTEN      ; ST[] = 10
    FST   ST(2)     ; ST(2) = 10
    FLDPI           ; ST[] = pi
    FDIV            ; ST = 10 / pi
    FMUL            ; ST = A * ST
    FADD            ; ST = ST + 10
    FISTP S         ; S = ROUND(ST)
        ENDM

; score the dart throw
; input: X / Y coordinates (mem16)
; output: Score (AX)
SCORE   MACRO X, Y
        LOCAL IS_BULL, IS_25, IS_3X, IS_2X, MUL_SCORE, DONE
    FCRAD X, Y, FDW         ; FDW = radius(X,Y)
    MOV  DX, FDW            ; DX = FDW = radius
    XOR  AX, AX             ; score is initially 0
    CMP  DX, MAX_2X         ; >= 170 (miss)
    JL   IS_BULL            ; if not, check for bullseye
    JMP  DONE
IS_BULL:
    CMP  DX, MAX_BULL       ; < 6 (inner bullseye)
    JGE  IS_25              ; if not, check for 25
    MOV  AL, 50             ; score is 50
    JMP  DONE
IS_25:
    CMP  DX, MAX_25         ; < 16 (outer bullseye)
    JGE  IS_3X              ; if not, check for triple
    MOV  AL, 25             ; score is 25
    JMP  DONE
IS_3X:
    FCSEC X, Y, FDW         ; FDW = sector(X,Y)
    MOV  AX, FDW            ; load sector # into AX
    MOV  BX, OFFSET SCR     ; load base score table
    XLAT                    ; put base score into AL
    CMP  DX, MAX_3X         ; < 107 (triple upper bounds)
    JGE  IS_2X              ; if not, check for double
    CMP  DX, MIN_3X         ; >= 99 (triple lower bounds)
    JL   IS_2X              ; if not, check for double
    MOV  BL, 3              ; this is triple score
    JMP  MUL_SCORE          ; go forth and multiply
IS_2X:
    CMP  DX, MIN_2X         ; >= 162 (double lower bounds) (> 170 already checked)
    JL   DONE               ; if not, single score
    MOV  BL, 2              ; this is double score
MUL_SCORE:
    MUL  BL                 ; multiply score either 2x or 3x
DONE:
    ENDM

; DATA (place in appropriate segment)
SCR     DB  11,8,16,7,19,3,17,2,15,10,6  ; score table
        DB  13,4,18,1,20,5,12,9,14,11
CTEN    DW  10      ; constant 10 to load into FPU
FDW     DW  ?       ; temp DW variable for CPU/FPU data transfer

An example test program for PC DOS.  Download it here DARTTEST.COM.
INCLUDE DART.ASM            ; the above file
INCLUDE INDEC.ASM           ; generic I/O routines - input int
INCLUDE OUTDEC.ASM          ; generic I/O routines - output int

    FINIT                   ; reset 8087

    MOV  AH, 2              ; display "X" prompt
    MOV  DL, 'X'
    INT  21H
    CALL INDEC              ; read decimal for X into AX
    MOV  X, AX

    MOV  AH, 2              ; display "Y" prompt
    MOV  DL, 'Y'
    INT  21H
    CALL INDEC              ; read decimal for Y into AX
    MOV  Y, AX

    SCORE X, Y              ; AX = SCORE( X, Y )

    CALL OUTDEC             ; display score

X   DW  ?
Y   DW  ?

Output
Example usage of above test program. Actual IBM PC with 8087, DOSBox or your favorite emulator required.
A>DARTTEST.COM
X: 0
Y: 0
50
A>DARTTEST.COM
X: 2
Y: 101
60
A>DARTTEST.COM
X: -163
Y: -1
22
A>DARTTEST.COM
X: 6
Y: 18
1
A>DARTTEST.COM
X: -6
Y: 18
5
A>DARTTEST.COM
X: 45
Y: -169
0
A>DARTTEST.COM
X: 22
Y: 22
4
A>DARTTEST.COM
X: -150
Y: 0
11
A>DARTTEST.COM
X: -150
Y: 0
11
A>DARTTEST.COM
X: -150
Y: -1
11
A>DARTTEST.COM
X: -7
Y: -6
25
A>DARTTEST.COM
X: -90
Y: 138
24

*Edits:

-36 bytes by removing truncate-rounding statement and 10.5 constant. Tie now broken clockwise.
-2 bytes by removing no longer necessary FRNDINT
-4 bytes, FMUL use same source/destination

Jelly, 56 bytes
æA/Æ°_9:18ị“!@umÞẓẓS’Œ?¤
ḅıA<“©Ñckɱȥ‘TṂị“2ı¢¤¢£¡‘¹×>3$?Ç

A monadic link accepting the pair as a list [x,y] which yields the score.
Uses clockwise tie-breaking.
Try it online! Or see the test-suite
N.B. a dyadic version is also 56 bytes
How?
æA/Æ°_9:18ị“!@umÞẓẓS’Œ?¤ - Link 1, segment score: pair [x, y]
  /                      - reduce by:
æA                       -   arc tangent
   Æ°                    - convert from radians to degrees
     _9                  - subtract 9 (align 0 with boundary between 1 & 20)
       :18               - integer divide by 18 (yields a segment index from 0 to 19)
                       ¤ - nilad followed by link(s) as a nilad:
           “!@umÞẓẓS’    -   base 250 number = 2091180117530057584
                     Œ?  -   shortest permutation of natural numbers [1..N] which
                         -   would reside at that index in a list of all permutations of
                         -   those same numbers ordered lexicographically.
                         -   = [18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12,5,20,1]
          ị              - index into (yields the score associated with the segment)

ḅıA<“©Ñckɱȥ‘TṂị“2ı¢¤¢£¡‘¹×>3$?Ç - Main Link: segment score: pair [x, y]
 ı                              - √(-1)
ḅ                               - convert from base = x+iy
  A                             - absolute value = √(x²+y²)
    “©Ñckɱȥ‘                    - code-page index list = [6,16,99,107,162,170]
                                - (i.e. the radial boundaries)
            T                   - list of truthy indexes
             Ṃ                  - minimal value (0 if empty)
               “2ı¢¤¢£¡‘        - code-page index list = [50,25,1,3,1,2,0]
              ị                 - index into
                                - (i.e. get an override score (>3) OR a multiplier (<=3))
                              Ç - call last Link (1) as a monad (get the segment score)
                             ?  - if...
                            $   - ...condition: last two links as a monad:
                          >     -      (override OR multiplier) greater than?
                           3    -      three
                        ¹       - ...then: identity (keep override as is)
                         ×      - ...else: multiply (by multiplier)

TI-Basic (TI-84 Plus CE), 147 146 bytes
Prompt X,Y
abs(X+iY→R
int(E-12+11.5+10π-1R▸Pθ(X,Y→θ
{11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11
25((R<6)+(R<16))+Ans(θ)(R≥16 and R<170)(1+(R≥162)+2(R≥99 and R<107

Prompts for X and Y on separate lines.
Tie-breaks counter-clockwise.
TI-Basic is a tokenized language; all tokens used here are one byte.
Explanation:
Prompt X,Y
# 5 bytes, Prompt for X and Y
abs(X+iY→R
# 8 bytes, store distance from origin in R
int(E-12+11.5+10π-1R▸Pθ(X,Y→θ
# 22 bytes, store index in list of point values by polar angle in θ
{11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11
# 55 bytes, list of point values
25((R<6)+(R<16))+Ans(θ)(R≥16 and R<170)(1+(R≥162)+2(R≥99 and R<107
# 57 56 bytes, calculate the score

Utilizes the fact that TI-Basic boolean comparisons return 0 or 1 by adding them up and multiplying by point values.

T-SQL, 392 374 366 bytes
UPDATE t SET x=1WHERE x=0
SELECT TOP 1IIF(r<16,f,b*f)
FROM(SELECT r=SQRT(x*x+y*y),w=FLOOR(10*ATN2(y,x)/PI()+.5)FROM t)p,
(VALUES(10,11),(9,14),(8,9),(7,12),(6,5),(5,20),(4,1),(3,18),(2,4),(1,13),(0,6),
   (-1,10),(-2,15),(-3,2),(-4,17),(-5,3),(-6,19),(-7,7),(-8,16),(-9,8),(-10,11))s(a,b),
(VALUES(6,50),(16,25),(99,1),(107,3),(162,1),(170,2),(999,0))d(e,f)
WHERE a=w AND r<e

Line breaks are for readability. The initial UPDATE takes care of the x=y=0 problem that would otherwise throw an error with ATN2(), but doesn't change the score.
Input is taken via pre-existing table t, per our IO guidelines. Due to using TOP 1, this table should contain only a single row.
Basically I'm joining 3 tables:

Table p: The x and y from input table t are converted to polar r and a "wedge" value w representing a number from -11 to positive 11, for the scoring wedge the dart fell into. "Tie breaker" is counter-clockwise. (I tried ROUND(), which was slightly shorter, but it gave an inconsistent tie breaker.)
Table s: This is a lookup table to convert a "wedge" value a into a score b.
Table d: This is a lookup table the returns the score calculation based on the distance from the center. e is the distance and joins to r, and returns only a single row based on the TOP 1. The value f is either a fixed score (for a bulls-eye) or a multiplier for the wedge score.

EDIT: Dropped the ORDER BY, it seems to work properly without it, at least on SQL 2017. I also dropped the AND y=0 on the update condition; I tested for all integer y values, changing x=0 to x=1 never changes the score.
EDIT 2: Removed column g from table d, replaced it with an IIF() statement that either returns f directly (for a bulls-eye), or f*b, saved 8 bytes. Also removed the space after TOP 1.

Haskell, 198 bytes
p=pure
a#b=(!!(sum[1|k<-a,k<=b]))
a!b=([6,16,99,107,162,170]#(sqrt$a*a+b*b))[p 50,p 25,id,(*3),id,(*2),p 0]$([pi/20,3*pi/20..6]#(pi+atan2 b a))[11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11]

Tie breaks counter-clockwise. (#) is a lookup function. The polar angle is used to index from the list of numbers, starting at the atan2 cutoff point at 11. The distance is used to index from the list of functions [const 50, const 25, id, (*3), id, (*2), const 0] and at last this function is applied to the number we previously got.
Try it online!

Perl 5 -MMath::Trig':pi' -MMath::Trig':radial' -apl, 166 bytes
($d,$a)=cartesian_to_cylindrical@F;$_=(1+($d>161||$d<6)+($d<107&&$d>98)*2)*($d<170)*($d<16?25:("6 134 181 205 129 14118 167 193 172 1510"=~/../g)[($a/pi*10+41/2)%20])

Try it online!
Takes the two coordinates space separated on STDIN.  Tie-breaking is anticlockwise.


text:
Output an ASCII "splat"
If you throw an ASCII egg in a given direction, you end up with an ASCII splat of size n. It "starts" with one o (the yolk), and continues in a given direction with "lines" consisting of 2 up to n *'s. The *'s are separated by one "space", and the o and all the "lines" of *'s are separated by "lines" of "space".
The direction of the splat can be any one of eight directions from o, for example:
1 2 3
4 o 5
6 7 8

Here are examples of ASCII splats of size 4 in directions 5, 2 and 3 respectively. On the left is the actual ASCII splat, and on the right is the same splat but with the "lines" of "space" replaced with actual "lines" (i.e. - or \ or | depending on the direction) just to clarify what is meant by a "line" of space.
Size 4, direction 5
      *      | | |*
    *        | |*|
  *   *      |*| |*
o   *       o| |*|
  *   *      |*| |*
    *        | |*|
      *      | | |*

Size 4, direction 2
* * * *     * * * *
            -------
 * * *       * * *
            -------
  * *         * *
            -------
   o           o

Size 4, direction 3
*           *
            \
* *         *\*
            \ \
* * *       *\*\*
            \ \ \
o * * *     o\*\*\*

Challenge
Given n ≥ 1 and one of the 8 possible directions, write a function or program that outputs the ASCII splat of size n in the given direction.
Input and output
Any consistent, reasonable input format is allowed. You don't need to map directions to the integers 1 to 8 in the same way I did - if some other way of specifying the direction is easier, go ahead. But say what you did if it isn't clear.
The output will consist of o, *, spaces (U+0020) and newlines (U+000A) that produce the ASCII splat. Leading, trailing, otherwise extra whitespace is permitted on any line.
Rules
This is code-golf. Standard rules apply.
More examples
Size 1, any direction
o

Size 3, direction 6
* * o

  * *

    *

Size 5, direction 7
    o

   * *

  * * *

 * * * *

* * * * *

Charcoal, 20 18 bytes
↘ＥＮ×*⊕ιＭ↗oＵＥ¬﹪η²⟲η

Try it online! Link is to verbose version of code. Explanation:
↘ＥＮ×*⊕ι

Draw a diagonal triangle of splats.
Ｍ↗o

Place the egg.
ＵＥ¬﹪η²

For even rotations, expand the splat horizontally to match the output requirement. This requirement doesn't match Charcoal's usual expectations. Try it online! (verbose) for how it looks without.
⟲η

Rotate the splat as required, using the following code for directions:
321
4o0
567

This 37 31-byte version avoids extraneous whitespace by only rotating in right angles:
¿﹪η²Ｇ↘←θ*«↘Ｅθ×*⊕ι↗»oＵＥ¹﹪η²⟲⊗÷η²

Try it online! Link is to verbose version of code.

Jelly, 37 bytes
”*ẋK¥ⱮmṠ©}”oḷ""LḶ⁶ẋƲ;"ṚƊ®¡z⁶K€ZU$A}¡Y

Try it online!
Directions:
\$\left[\begin{array}c1&2&3\\4&\circ&5\\6&7&8\end{array}\right]\rightarrow\left[\begin{array}c-2&1&-3\\4&\circ&2\\-1&3&-4\end{array}\right]\$

Canvas, 25 bytes
Ｈ*×］oｎ╶２％？！／ ＊］ ＊／｝⤢ ＊⁷⇵⟳

Try it here!
The directions are as follows:
7 6 1
4 ∘ 8
5 2 3

Python 2, 185 bytes
lambda n,d:'\n'.join(g([(d/4*(n+~j)*' '+('*o'[[j>n-2,j<1][d/4]]+' *'*j)*i).ljust(2*n-1)for j in range(n)for i in(0,1)][1:],d%4))
g=lambda a,n:n and g(map(''.join,zip(*a))[::-1],n-1)or a

Try it online!
The numbering is from 0 to 7, as follows:
1 6 0
7 o 5
2 4 3

Notes: Most of the work is to generate the basic patterns for (in my numbering system) 0 and 4. Then the function g rotates the array a 90 degrees d%4 times via recursion to generate the other results.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
A nicely-spaced ASCII spiral
Consider this spiral
###########
#
# #######
# #     #
# # ### #
# # # # #
# # # # #
# #   # #
# ##### #
#       #
#########

Starting in the centre:

The first line (upwards) has 3 characters.
The second line has the same number of characters (3)
Next, we add two chars (5) for the next two sides.
This pattern continues, two sides the same length then increase the length by 2.

I want to generate this spiral for N lines.

Write in any language.
The input/argument, etc. is the number of lines in your spiral.
Each line starts with the ending character of the previous line in the direction 90 degrees clockwise of the previous line.
I don't care how much whitespace is before or after each line, as long as the elements of the spiral line up.
Output text to draw the spiral with any non-whitespace character you choose.
Attempt to do this in the smallest number of bytes.

Test cases (using a hash as output):
N = 1
#
#
#

N = 2
###
#
#

N = 3
###
# #
# #
  #
  #

N = 10
###########
#
# #######
# #     #
# # ### #
# # # # #
# # # # #
# #   # #
# ##### #
#       #
#########

@Shaggy "Output text to draw the spiral with any non-whitespace character you choose." Yep, whatever you like.

Related 1; Related 2.

The initial image has an * instead of #.  Expected?

@Wernisch It was intended to be a helpful starting point, but I suppose it's misleading. You can use any character you like.

05AB1E, 13 11 bytes
Code:
Thanks to Emigna for saving two bytes!
LDÈ-Ì'#3Ý·Λ

Uses the 05AB1E encoding. Try it online!
Explanation
The lengths of each individual edge on the spiral starts with length 3 and gradually increases every two steps by two:
$$
3, 3, 5, 5, 7, 7, 9,\dots
$$
For a spiral with \$n\$ edges, we just need to trim this list to size \$n\$. This is done with the following piece of code:
L                # Create a list from [1 .. input]
 DÈ              # Duplicate and check for each number if even
   -             # Subtract that from the first list
    Ì            # Add 2

This basically gives us the desired list of lengths.
     '#          # Push the '#' character
       0246S     # Push the array [0, 2, 4, 6]
            Λ    # Write to canvas

The canvas works as a function that pops three parameters (where the rightmost parameter is popped first): <length(s)>, <char(s)>, <direction(s)>. The directions parameter is in this case a list of numbers. The numbers that correspond to the directions are:
$$
\left[\begin{array}{r}
7 & 0 & 1 \\
6 & \circ & 2 \\
5 & 4 & 3
\end{array}\right]
$$
In this case, [0, 2, 4, 6] corresponds to the directions list [↑, →, ↓, ←]. The canvas iterates over each length retrieved from the list of lengths, uses the '#' character and cyclically iterates over the directions list.

0246S = 3Ý·

@Emigna Ah I did not think of that, thanks!

Python 2, 176 170 165 161 157 bytes
g=lambda a,r:r and g(map(''.join,zip(*a))[::-1],r-1)or a
R=['#']
n=1
exec"R=g(['  '+l for l in g(R,n)][:-1]+[(n+2)*'#'],3*n);n+=1;"*input()
print'\n'.join(R)

Try it online!
Repeatedly: Uses g to rotate the nth iteration of the spiral into a 'canonical' position (similar to N=3 or N=7), adds a new segment by adding 2 spaces at the left of each existing row, then replacing the last row with all '#'s (resulting in a position comparable to N=4 or N=8), and finally using g again to rotate it back to the correct position. Lather, rinse, repeat.

Charcoal, 16 15 14 bytes
↶ＦＮ«¶×#⁺³⊗÷ι²↷

-2 bytes thanks to @Neil.
Try it online (verbose) or Try it online (pure).
Explanation:
Printing direction is to the right by default, and we want to start upwards, so we start by rotating 45 degrees counterclockwise:
PivotLeft();
↶

Then loop i in the range [0, input):
For(InputNumber()){ ... }
ＦＮ« ...

Print a new-line to mimic the effect of moving back one position:
Print("\n");
¶

Print "#" x amount of times in the current direction:
Print(Times("#", ... ));
×# ...

Where x is: 3 + i // 2 * 2:
Add(3,Doubled(IntegerDivide(i,2))
⁺³⊗÷ι²

And then rotate 45 degrees clockwise for the next iteration of the loop:
PivotRight();
↷

I assume there's no command in Charcoal for moving backwards?

@Emigna Not sure, but I couldn't find it either. Was indeed looking for one myself when I was writing this answer. There is a Move with a given direction, as well as a Jump with given coordinates, but not a MoveBack unfortunately.

⊗÷ι² is a byte shorter than ⁻ι﹪ι². Also, you can get the effect of moving back by printing a \n before the #s, which will allow you to remove the »# for an additional overall byte saving.

@Neil Thanks for the ⊗÷ι², but what would the changes be for printing a \n before the #s? The spiral is incorrect if I add the Print("\n").

Because the arms now overlap you need to make them an extra # longer.

Python 2, 179 178 bytes
thanks to Kevin Cruijssen for -1 byte.
n=input()
S,H=' #'
m=[S*n]*(n%2-~n)
x=n/4*2
y=0--n/4*2
k=2
m[y]=S*x+H+S*n
M=[1,0,-1,0]*n
exec'exec k/2*2*"x+=M[~k];y+=M[k];m[y]=m[y][:x]+H+m[y][x+1:];";k+=1;'*n
print'\n'.join(m)

Try it online!

Python 2, 179 bytes
In this approach formulas are used for x and y deltas instead of a lookup list.
n=input()
S,H=' #'
m=[S*n]*(n%2-~n)
x=n/4*2
y=0--n/4*2
k=2
m[y]=S*x+H+S*n
exec'exec k/2*2*"x+=k%-2+k%4/3*2;y-=(k%2or k%4)-1;m[y]=m[y][:x]+H+m[y][x+1:];";k+=1;'*n
print'\n'.join(m)

Try it online!

n+1+n%2 to n%2-~n for -1 byte. And I need to remember 0--n/4*2 being 1 shorter than -(-n/4*2). Nice answer, +1 from me.

JavaScript (ES6), 185 bytes
Sure this can be golfed more, maybe with currying, but here's my very humble attempt. Line breaks added for readability except penultimate character
r=(a,n=1)=>n?r(a.reduce((_,c)=>c).map((_,i)=>a.map(e=>e[i])).reverse(),n-1):a,
s=n=>n?r(s(n-1)).map((r,i)=>[...r,w,w].map(x=>i?x:'#')):[[w=' ']],
d=n=>r(s(n),1-i).map(r=>r.join``).join`
`

Usage: d(10) returns a string as per the N=10 challenge example.
Defines a function r(a,n) to rotate an array a by n turns; a function s(n) to generate a 2-dimensional array representing a spiral of size n by recursively rotating and adding spacing and lines (not rotated back to starting position); and a function d(n) to draw a spiral of size n, rotated consistently as per the challenge, and rendered as a returned string.
This was a really fun challenge :¬)

Canvas, 20 16 bytes
Ｈ：２％！－├#×；↶ｎ｝╶├⟳

Try it here!
Explanation
ø；｛：２％！－├#×；↶１１╋｝╶├⟳
ø                            push an empty art object
 ；                              swap with the input
   ｛                  ｝    for i in 1 to n:
   ｛：                ｝     duplicate i
   ｛ ２％              ｝    mod 2
   ｛    ！            ｝    negate
   ｛     －           ｝    subtract that from i
   ｛       ├          ｝    add 2
   ｛         #×       ｝    repeat '#' that many times
   ｛           ；     ｝    swap with previous iteration
   ｛             ↶    ｝   turn 90 degrees anticlockwise
   ｛              １１╋｝   overlap at (1,1)
                        ╶├⟳ rotate 90 degrees n+2 times

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/