Anota un solo dardo

22

Introducción

Escriba un programa o función que, dadas las coordenadas de dónde cae un dardo en un tablero de dardos, devuelva el puntaje de ese dardo. Las coordenadas de dardo se dan como dos enteros, x,ymedidos desde el centro del tablero de dardos, con precisión milimétrica.

Cómo anotar un dardo

Darts es un juego que se juega lanzando un dardo a un tablero circular. El tablero de dardos se divide en 20 "cuñas" de igual tamaño. Comenzando desde arriba y en sentido horario, las secciones tienen valores de 20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12 5. Si su dardo cae en las partes negras o blancas de cualquiera de las cuñas, obtiene el valor indicado en el exterior de esa cuña.
aquí hay una foto de un tablero de dardos.


Sin embargo, si su dardo cae en el anillo exterior verde / rojo del tablero de dardos, obtiene el doble de puntos indicados en el exterior de la cuña que golpeó. Del mismo modo, golpeando el anillo verde / rojo interior (el que está entre las dos secciones blancas / negras), obtienes el triple del número indicado en el exterior de la cuña. Si su dardo golpea el círculo más interno (la diana roja), en su lugar obtiene 50 puntos y, finalmente, si su dardo golpea el segundo círculo más interno (el anillo verde alrededor de la diana), obtiene 25 puntos.

Las dimensiones de los anillos, medidas desde el centro del tablero de dardos, son las siguientes:

imagen no a escala


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

Nota 1: Las imágenes proporcionadas son solo para fines ilustrativos y no están a escala.

Nota 2: Las medidas proporcionadas son aproximadas y pueden no ser precisas para un tablero de dardos real.

Nota 3: Todas las medidas dadas son [inclusive-exclusive). Para los propósitos de este desafío, no nos vamos a preocupar de que los dardos golpeen el cable y reboten. Si el dardo cae "en el cable" con una de las líneas radiales, entonces corresponde al respondedor decidir si romper el lazo en el sentido de las agujas del reloj o en sentido contrario. La dirección de desempate debe ser consistente e indicada.

Nota 4: el tablero de dardos se cuelga de la manera estándar con la mitad de la sección 20 directamente encima de la diana y la sección 3 directamente debajo de la diana.

Entrada

Dos enteros que representan el x,y coordenadas del lugar donde cayó el dardo, medido en milímetros, en relación con el centro del tablero de dardos.

Salida

Un número entero, para el número de puntos que se otorgarían a un dardo que aterrizó en las coordenadas dadas.

Muestra

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

Tanteo

. Pocos bytes en su código fuente gana.

Lagunas estándar prohibidas .

mypetlion
fuente
1
@ Shaggy No veo ninguna razón decente para hacerlo.
Jonathan Allan
55
@ Shaggy ¿Puedes explicar por qué ese debería ser el caso? Personalmente, me encantaría que mis dardos siempre estuvieran garantizados para golpear el tablero de dardos, pero por el bien del desafío, pensé que era mejor apegarme a la realidad sobre la fantasía.
mypetlion
1
Casos de prueba sugeridos: -150,-1y -150,0que deberían dar 11y pueden ser un caso límite en algunas implementaciones, ya que esta es la transición entre theta que converge a -pi y theta = + pi en coordenadas polares. (Mi respuesta inicial falló en la segunda.)
Arnauld
1
¡Dangit, x = y = 0 me está arruinando totalmente! Buen reto
BradC
1
Espero que no te importe, edité una mejor versión de la segunda foto.
BradC

Respuestas:

19

JavaScript (ES7), 137 bytes

Toma las coordenadas en sintaxis curry (x)(y). Utiliza tie-break en sentido antihorario.

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)

Pruébalo en línea!

¿Cómo?

(X,y)(r,θ)

r=X2+y2
θ=arctan2(y,X)

r

θs que estamos con:

s=θ+π2π×20+12=θ×10π+10+12

340×34010/ /π

10π3.1831

11 :

11,8,dieciséis,7 7,19,3,17,2,15,10,6 6,13,4 4,18 años,1,20,5 5,12,9 9,14,11

11θ-πθ+π

Salida gráfica

El siguiente fragmento de código ES6 dibuja el tablero de dardos utilizando la misma lógica que en el código de golf.

Arnauld
fuente
8

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

La entrada es a través del clic del mouse, la salida a través de alert. Editar: ahorró 12 bytes usando colores ligeramente más aproximados como lo sugiere @Arnauld.

Neil
fuente
Supongo que nadie te va a culpar si lo usas b33y 474por el rojo y el verde. :-)
Arnauld
@Arnauld Bastante justo, aunque b33es bb3333así b22(alias bb3322) está más cerca de tu original be3628.
Neil
7

Conjunto Intel 8086/8087, 180 144 142 138 bytes

Utiliza el coprocesador matemático 8087 para todos los aritméticos trigonométricos y de coma flotante. Todos los cálculos se realizan en hardware con precisión de punto flotante de 80 bits.

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

Escrito como MASM MACRO (básicamente una función), toma X e Y como coordenadas y devuelve el puntaje calculado en AX. La corbata se rompe en sentido horario.

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

Un programa de prueba de ejemplo para PC DOS. Descárguelo aquí 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  ?

Salida

Ejemplo de uso del programa de prueba anterior . Se requiere una PC IBM real con 8087, DOSBox o su emulador favorito.

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

* Ediciones:

  • -36 bytes eliminando la instrucción de redondeo truncado y 10.5 constante. Ate ahora roto en sentido horario.
  • -2 bytes eliminando ya no es necesario FRNDINT
  • -4 bytes, FMUL usa la misma fuente / destino
640 KB
fuente
6

Jalea , 56 bytes

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

Un enlace monádico que acepta el par como una lista [x,y]que produce el puntaje.
Utiliza el desempate en sentido horario.

Pruébalo en línea! O ver el conjunto de pruebas

Nota: una versión diádica también tiene 56 bytes

¿Cómo?

æ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)
Jonathan Allan
fuente
4

TI-Basic (TI-84 Plus CE), 147146 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

Solicita X e Y en líneas separadas.

Tie-breaks en sentido antihorario.

TI-Basic es un lenguaje tokenizado ; Todas las fichas utilizadas aquí son un byte.

Explicación:

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

Utiliza el hecho de que las comparaciones booleanas de TI-Basic devuelven 0 o 1 al sumarlas y multiplicarlas por valores de puntos.

pizzapants184
fuente
3

T-SQL, 392 374 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

Los saltos de línea son para facilitar la lectura. La inicial UPDATEse encarga dex=y=0 problema que de otro modo arrojaría un error ATN2(), pero no cambia la puntuación.

La entrada se toma a través de la tabla t preexistente , según nuestras pautas de IO . Debido al uso TOP 1, esta tabla debe contener solo una fila.

Básicamente me estoy uniendo a 3 tablas:

  • Tabla p : Las x e y de la tabla de entrada t se convierten a polar r y un valor de "cuña" w representa un número de -11 a positivo 11, para la cuña de puntuación en la que cayó el dardo. "Tie breaker" es en sentido antihorario. (Lo intenté ROUND(), que fue un poco más corto, pero me dio un desempate incoherente).
  • Tabla s : Esta es una tabla de búsqueda para convertir un valor de "cuña" a en una puntuación b .
  • Tabla d : Esta es una tabla de búsqueda que devuelve el cálculo de puntaje basado en la distancia desde el centro. e es la distancia y se une a r , y devuelve solo una fila en función de TOP 1. El valor f es un puntaje fijo (para una diana) o un multiplicador para el puntaje de cuña.

EDITAR : Se eliminó ORDER BY, parece funcionar correctamente sin él, al menos en SQL 2017. También se eliminó la AND y=0condición de actualización; Probé todos los yvalores enteros , cambiando x=0a x=1nunca cambia la puntuación.

EDITAR 2 : Se eliminó la columna g de la tabla d , se reemplazó con una IIF()declaración que devuelve fdirectamente (para una diana) o f*bguardó 8 bytes. También eliminó el espacio después TOP 1.

BradC
fuente
2

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]

La corbata se rompe en sentido antihorario. (#)Es una función de búsqueda. El ángulo polar se usa para indexar desde la lista de números, comenzando en el atan2punto de corte en 11. La distancia se usa para indexar desde la lista de funciones[const 50, const 25, id, (*3), id, (*2), const 0] y, finalmente, esta función se aplica al número que obtuvimos anteriormente.

Pruébalo en línea!

Angs
fuente
1

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

Pruébalo en línea!

Toma el espacio de dos coordenadas separado en STDIN. El desempate es en sentido antihorario.

Xcali
fuente