Marque um único dardo


22

Introdução

Escreva um programa ou função que, dadas as coordenadas de onde um dardo pousa em um alvo, retorne a pontuação desse dardo. As coordenadas do dardo são dadas como dois números inteiros, x,ymedidos a partir do centro do alvo, com precisão milimétrica.

Como marcar um dardo

Dardos é um jogo jogado jogando um dardo em um tabuleiro circular. O jogo de dardos é dividido em 20 "cunhas" de tamanho igual. Começando do topo e indo no sentido horário, as seções têm valores de 20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12 5. Se o seu dardo cair nas partes preta ou branca de qualquer uma das cunhas, você marcará o valor indicado na parte externa dessa cunha.
aqui está uma foto de um alvo.


No entanto, se o seu dardo cair no anel externo verde / vermelho do alvo, você pontuará o dobro dos pontos indicados na parte externa da cunha que acertou. Da mesma forma, ao tocar no anel verde / vermelho interno (aquele entre as duas seções branco / preto), você obtém o triplo do número indicado na parte externa da cunha. Se o seu dardo atinge o círculo mais interno (o olho de boi vermelho), você ganha 50 pontos e, finalmente, se o seu dardo atinge o segundo círculo mais interno (o anel verde ao redor do olho de boi), você ganha 25 pontos.

As dimensões dos anéis, medidas a partir do centro do alvo, são as seguintes:

imagem sem 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: As imagens fornecidas são apenas para fins ilustrativos e não estão em escala.

Nota 2: As medidas fornecidas são aproximadas e podem não ser precisas para um alvo de dardos real.

Nota 3: Todas as medidas fornecidas são [inclusive-exclusive). Para os propósitos deste desafio, não vamos nos preocupar com dardos acertando o arame e quicando. Se o dardo cair "no fio" com uma das linhas radiais, cabe ao respondente decidir se quer quebrar o empate no sentido horário ou anti-horário. A direção de desempate deve ser consistente e indicada.

Nota 4: O alvo é pendurado da maneira padrão, com o meio da seção 20 diretamente acima do alvo e a seção 3 diretamente abaixo do alvo.

Entrada

Dois números inteiros representando as x,ycoordenadas de onde o dardo pousou, medido em milímetros, em relação ao centro do alvo.

Saída

Um único inteiro, para o número de pontos que seriam concedidos a um dardo que aterrissasse nas coordenadas fornecidas.

Amostra

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

Pontuação

. O menor número de bytes no seu código-fonte vence.

Falhas padrão proibidas .


1
@ Shaggy Não vejo nenhuma razão decente para fazê-lo.
Jonathan Allan

5
@ Shagy Você pode explicar por que esse deveria ser o caso? Pessoalmente, eu adoraria se meus dardos sempre garantissem atingir o alvo, mas pelo bem do desafio, achei melhor aderir à realidade do que à fantasia.
mypetlion

1
Casos de teste sugeridos: -150,-1e -150,0que devem dar 11e podem ser um caso de vantagem em algumas implementações, pois essa é a transição entre theta convergindo para -pi e theta = + pi nas coordenadas polares. (Minha resposta inicial falhou no 2º um.)
Arnauld

1
Dangit, x = y = 0 está totalmente me atrapalhando !! Bom desafio.
26918 BradC

1
Espero que você não se importe, editei uma versão melhor da segunda foto.
27418 Bradc

Respostas:


19

JavaScript (ES7), 137 bytes

Leva as coordenadas na sintaxe de currying (x)(y). Usa tie-break no sentido anti-horário.

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)

Experimente online!

Quão?

(x,y)(r,θ)

r=x2+y2
θ=arctan2(y,x)

r

θs

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

340×34010/π

10π3,1831

11

11,8,16,7,19,3,17,2,15,10,6,13,4,18,1,20,5,12,9,14,11

11θ-πθ+π

Saída gráfica

O seguinte snippet de código ES6 desenha o alvo usando a mesma lógica do código de golfe.


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

A entrada é através de um clique do mouse, a saída via alert. Editar: salvou 12 bytes usando cores um pouco mais aproximadas, conforme sugerido por @Arnauld.


Eu acho que ninguém vai te culpar se você usar b33e 474para vermelho e verde. :-)
Arnauld 28/06

@ Arnauld Fair o suficiente, embora b33seja bb3333tão b22(aka bb3322) está mais perto do seu original be3628.
28418 Neil

7

Conjunto Intel 8086/8087, 180 144 142 138 bytes

Isso usa o co-processador matemático do 8087 para toda a aritmética trigonométrica e de ponto flutuante. Todos os cálculos são feitos em hardware com precisão de ponto flutuante 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 um MACRO MAC (basicamente uma função), pega X e Y como coordenadas e retorna a pontuação calculada no AX. O empate está quebrado no sentido horário.

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

Um exemplo de programa de teste para PC DOS. Faça o download aqui no 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  ?

Saída

Exemplo de uso do programa de teste acima . É necessário um PC IBM real com 8087, DOSBox ou seu 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

* Edições:

  • -36 bytes, removendo a instrução de truncamento e arredondamento e a constante 10,5. Empate agora quebrado no sentido horário.
  • -2 bytes removendo FRNDINT não mais necessário
  • -4 bytes, FMUL usa a mesma origem / destino

6

Geléia , 56 bytes

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

Um link monádico que aceita o par como uma lista [x,y]que gera a pontuação.
Usa quebra de ligação no sentido horário.

Experimente online! Ou veja a suíte de testes

NB: uma versão diádica também tem 56 bytes

Quão?

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

4

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

Solicita X e Y em linhas separadas.

Desempate no sentido anti-horário.

TI-Basic é uma linguagem tokenizada ; todos os tokens usados ​​aqui são de um byte.

Explicação:

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 o fato de que as comparações booleanas do TI-Basic retornam 0 ou 1 adicionando-as e multiplicando por valores em pontos.


3

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

Quebras de linha são para facilitar a leitura. A inicial UPDATEcuida do x=y=0problema que, de outra forma, geraria um erro ATN2(), mas não altera a pontuação.

A entrada é obtida através da tabela t pré-existente , de acordo com nossas diretrizes de IO . Devido ao uso TOP 1, esta tabela deve conter apenas uma única linha.

Basicamente, eu estou juntando 3 tabelas:

  • Tabela p : Os x e y da tabela de entrada t são convertidos em polar r e um valor "wedge" w que representa um número de -11 a 11 positivo, para a cunha de pontuação em que o dardo caiu. O "desempatador" está no sentido anti-horário. (Tentei ROUND(), que era um pouco mais curto, mas causava um desempate inconsistente.)
  • Tabela s : Esta é uma tabela de pesquisa para converter um valor "em cunha" a em uma pontuação b .
  • Tabela d : Esta é uma tabela de pesquisa que retorna o cálculo da pontuação com base na distância do centro. e é a distância e se une a re retorna apenas uma única linha com base em TOP 1. O valor f é uma pontuação fixa (para um alvo) ou um multiplicador para a pontuação da cunha.

EDIT : Largou o ORDER BY, parece funcionar corretamente sem ele, pelo menos no SQL 2017. Também larguei o AND y=0na condição de atualização; Testei todos os yvalores inteiros , mudando x=0para x=1nunca alterar a pontuação.

EDIT 2 : Removida a coluna g da tabela d , substituída por uma IIF()instrução que retorna fdiretamente (para um alvo) ou f*bsalva 8 bytes. Também removeu o espaço depois TOP 1.


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]

Quebra de gravata no sentido anti-horário. (#)é uma função de pesquisa. O ângulo polar é usado para indexar a partir da lista de números, começando no atan2ponto de corte em 11. A distância é usada para indexar a partir da lista de funções [const 50, const 25, id, (*3), id, (*2), const 0]e, finalmente, essa função é aplicada ao número que obtivemos anteriormente.

Experimente online!


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

Experimente online!

Pega o espaço das duas coordenadas separado em STDIN. O desempate é no sentido anti-horário.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.