Оцінка одного дротика


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
@Shaggy Я не бачу пристойних причин для цього.
Джонатан Аллан

5
@Shaggy Чи можете ви пояснити, чому так має бути? Особисто мені хотілося б, якби мої дротики завжди гарантовано потрапляли на дошку дротика, але заради виклику я вважав, що найкраще дотримуватися реальності над фантазією.
mypetlion

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

1
Dangit, x = y = 0 повністю мене псує !! Гарний виклик.
BradC

1
Сподіваюсь, ви не заперечуєте, я відредагував кращу версію другого малюнка.
BradC

Відповіді:


19

JavaScript (ES7), 137 байт

Бере координати в синтаксисі currying (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)

Спробуйте в Інтернеті!

Як?

Переводимо вхідні декартові координати в полярні координати допомогою:(х,у)(r,θ)

r=х2+у2
θ=арктан2(у,х)

Ми використовуємо щоб визначити, чи розташований дротик над Bullseye , 25 , Внутрішнім одиноким , Потрійним , Зовнішнім одинарним , Подвійним або якщо постріл - міс .r

Якщо ми розташовані над одномісним , двомісний або трійкою , ми використовуємо , щоб визначити , в якому секторі ми з:θс

с=θ+π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 з 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]який дає оцінку.
Використовується для розриву краватки за годинниковою стрілкою.

Спробуйте в Інтернеті! Або дивіться тестовий набір

Примітка, діадична версія також становить 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(), але не змінить бал.

Введення проводиться за допомогою вже існуючої таблиці t , згідно з нашими вказівками щодо IO . Завдяки використанню TOP 1ця таблиця повинна містити лише один рядок.

В основному я приєднуюся до 3 таблиць:

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

EDIT : Випало ORDER BY, схоже, працює без нього, принаймні на SQL 2017. Я також скинув AND y=0умову оновлення; Я перевіряв на всі цілі yзначення, змінюючи, x=0щоб x=1ніколи не змінювати бал.

EDIT 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.