Забей один дротик


22

Введение

Напишите программу или функцию, которая, учитывая координаты того, где дротик приземляется на мишени, возвращает результат этого дротика. Координаты дротика даны в виде двух целых чисел, x,yизмеренных от центра мишени с точностью до миллиметра.

Как забить дротик

Дартс - игра, в которую играют в метание дротика на круглой доске. Дротик разделен на 20 одинаковых по размеру «клиньев». Начиная сверху и по часовой стрелке, секции имеют значения 20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12 , 5. Если ваш дротик приземляется в черных или белых частях любого из клиньев, вы получаете значение, указанное на внешней стороне этого клина.
вот картина дартс,


Однако, если ваш дротик приземляется во внешнее зеленое / красное кольцо дартс, вы удваиваете очки, указанные на внешней стороне клина, в который вы попали. Аналогично, ударяя по внутреннему зеленому / красному кольцу (то, которое находится между двумя белыми / черными секциями), вы получаете тройное число, указанное на внешней стороне клина. Если ваш дротик попадает в самый внутренний круг (красный бычий глаз), вы вместо этого набираете 50 очков и, наконец, если ваш дротик попадает во второй самый внутренний круг (зеленое кольцо вокруг бычьего глаза), вы получаете 25 очков.

Размеры колец, измеренные от центра мишени, следующие:

изображение не в масштабе


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

Примечание 1: Изображения предоставлены только для иллюстрации и не в масштабе.

Примечание 2: Данные измерения являются приблизительными и могут быть неточными для реального дартс.

Примечание 3: Все измерения даны [inclusive-exclusive). В рамках этой задачи мы не будем беспокоиться о том, что дротики могут ударить по проволоке и отскочить. Если дротик приземляется «на проволоке» с одной из радиальных линий, то ответчик должен решить, сломать ли галстук по часовой стрелке или против часовой стрелки. Направление обрыва связи должно быть последовательным и указанным.

Примечание 4: Дартс подвешен стандартным способом, середина 20-й секции находится прямо над яблочком, а 3-я секция - прямо под яблочком.

вход

Два целых числа, представляющие x,yкоординаты места приземления дротика, измеренные в миллиметрах, относительно центра дротика.

Выход

Одно целое число для количества очков, которое будет присуждено дротику, который приземлился в заданных координатах.

Образец

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

счет

. Побеждает меньшее количество байтов в вашем исходном коде.

Стандартные лазейки запрещены .


1
@ Шэгги Я не вижу достойной причины для этого.
Джонатан Аллан

5
@ Shaggy Можете ли вы объяснить, почему это так? Лично мне бы понравилось, если бы мои дротики всегда гарантированно попадали в доску для дротиков, но ради испытания я решил, что лучше придерживаться реальности, а не фантазии.
mypetlion

1
Предлагаемые тестовые примеры: -150,-1и -150,0которые должны давать 11и могут быть крайним случаем в некоторых реализациях, так как это переход между тета, сходящимся к -pi, и тета = + pi в полярных координатах. (Мой первоначальный ответ не состоялся 2-го.)
Арно

1
Дангит, х = у = 0 меня все портит !! Хороший вызов.
BradC

1
Надеюсь, вы не возражаете, я отредактировал лучшую версию второй картинки.
BradC

Ответы:


19

JavaScript (ES7), 137 байт

Принимает координаты в синтаксисе карри (x)(y). Использует против часовой стрелки тай-брейк.

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)

Попробуйте онлайн!

Как?

Мы переводим входные декартовы координаты в полярные координаты с помощью:(Икс,Y)(р,θ)

рзнак равноИкс2+Y2
θзнак равноагс2(Y,Икс)

Мы используем чтобы определить, находится ли дротик над « яблочком» , 25 , внутренний одиночный , тройной , внешний одиночный , двойной, или же если выстрел был мисс .р

Если мы расположены над одноместным , двухместный или тройкой , мы используем , чтобы определить , в каком секторе мы с:θs

sзнак равноθ+π2π×20+12знак равноθ×10π+10+12

Для области нам нужно 4 десятичных знака чтобы получить достаточную точность, что дает:340×34010/π

10π3,1831

Базовые оценки сохраняются против часовой стрелки в закодированной в base-36 строке из 21 записи, начиная и заканчивая :11

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

Нам нужно повторить потому что половина этого сектора принадлежит первому срезу (где близко к ), а другая половина принадлежит последнему срезу (где близко к ).θ - π θ + π11θ-πθ+π

Графический вывод

Следующий фрагмент кода ES6 рисует дротик, используя ту же логику, что и в коде для игры в гольф.


8

JavaScript (ES6) + SVG (HTML5), 53 + 523 51 + 519 507 = 576 570 558 байт

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

Ввод осуществляется с помощью щелчка мыши, вывод через alert. Редактировать: Сохранено 12 байтов, используя немного более приблизительные цвета, как предложено @Arnauld.


Я думаю, никто не будет обвинять вас, если вы используете b33и 474для красного и зеленого. :-)
Арнаулд

@Arnauld Fair достаточно, хотя b33это bb3333так b22(он же bb3322) находится ближе к оригиналу be3628.
Нил

7

Intel 8086/8087 в сборе, 180 144 142 138 байтов

При этом используется математический сопроцессор 8087 для всех арифметических операций с триггерами и с плавающей запятой. Все вычисления выполняются аппаратно с 80-битной точностью с плавающей точкой.

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

Записывается как MASM MACRO (в основном функция), принимает координаты X и Y и возвращает вычисленный счет в AX. Галстук разорван по часовой стрелке.

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

Пример тестовой программы для ПК DOS. Загрузите его здесь 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  ?

Выход

Пример использования вышеуказанной тестовой программы . Требуется настоящий IBM PC с 8087, DOSBox или вашим любимым эмулятором.

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

* Изменения:

  • -36 байтов путем удаления оператора округления усечения и константы 10,5. Галстук разорван по часовой стрелке.
  • -2 байта, удалив больше не нужно FRNDINT
  • -4 байта, FMUL использовать один и тот же источник / назначение

6

Желе , 56 байт

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

Монадическая ссылка, принимающая пару в виде списка, [x,y]который дает оценку.
Использует разрыв связи по часовой стрелке.

Попробуйте онлайн! Или посмотрите набор тестов

NB диадическая версия также 56 байтов

Как?

æ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 байт

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

Запросы для X и Y в отдельных строках.

Тай-брейки против часовой стрелки.

TI-Basic - это токенизированный язык ; все токены, используемые здесь, являются одним байтом.

Объяснение:

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

Использует тот факт, что булевы сравнения TI-Basic возвращают 0 или 1, складывая их и умножая на значения точек.


3

T-SQL, 392 374 366 байт

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

Разрывы строк предназначены для удобства чтения. Первоначальный UPDATEзаботятся о x=y=0проблеме , которая в противном случае выдаст ошибку с ATN2(), но не меняет рейтинг.

Ввод берется с помощью уже существующей таблицы т , согласно нашим правилам ввода - вывода . Благодаря использованию TOP 1, эта таблица должна содержать только одну строку.

В основном я объединяю 3 таблицы:

  • Таблица p : x и y из входной таблицы t преобразуются в полярное r и значение w клина, представляющее число от -11 до положительного значения 11, для клина выигрыша, в который попал дротик. «Выключатель связи» против часовой стрелки. (Я попытался ROUND(), который был немного короче, но это дало противоречивый прерыватель связи.)
  • Таблица s : Это справочная таблица для преобразования значения «клина» a в показатель b .
  • Таблица d : это справочная таблица, которая возвращает расчет баллов на основе расстояния от центра. e - расстояние, которое соединяется с r и возвращает только одну строку на основе TOP 1. Значение f является либо фиксированной оценкой (для «бычьего глаза»), либо множителем для оценки клина.

РЕДАКТИРОВАТЬ : Удалил ORDER BY, кажется, работает без него, по крайней мере, на SQL 2017. Я также сбросил AND y=0условие обновления; Я проверил для всех целочисленных yзначений, изменяя, x=0чтобы x=1никогда не меняет счет.

РЕДАКТИРОВАТЬ 2 : удалил столбец g из таблицы d , заменил его IIF()оператором, который либо возвращает fнапрямую (для «бычьего глаза»), либо f*bсохранил 8 байтов. Также убрал пробел после TOP 1.


2

Haskell , 198 байт

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]

Галстук разрывается против часовой стрелки. (#)это функция поиска. Полярный угол используется для индексации из списка чисел, начиная с atan2точки отсечения в 11. Расстояние используется для индексации из списка функций, [const 50, const 25, id, (*3), id, (*2), const 0]и, наконец, эта функция применяется к ранее полученному числу.

Попробуйте онлайн!


1

Perl 5 -MMath::Trig':pi' -MMath::Trig':radial' -apl , 166 байт

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

Попробуйте онлайн!

Занимает пространство двух координат, разделенных на STDIN. Разрыв связи против часовой стрелки.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.