Tek bir ok atma


22

Giriş

Bir dartın dart tahtasına düştüğü yerin koordinatları verildiğinde, dartın puanını döndüren bir program veya işlev yazın. Dart koordinatları x,ydart tahtası ortasından ölçülen, milimetre hassasiyetinde iki tamsayı olarak verilmiştir .

Bir dart nasıl yapılır

Dart, dairesel bir tahtaya dart atarak oynanan bir oyundur. Dart tahtası 20 eşit büyüklükte "takozlar" ayrılmıştır. Tepeden başlayıp saat yönünde ilerleyen bölümler 20,1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12 5. Dartınız, takozların herhangi birinin siyah veya beyaz kısımlarına girerse, o kamanın dışında belirtilen değeri puanlarsınız.
İşte bir dart tahtası bir resim.


Ancak, dartınız, dart tahtasının dış yeşil / kırmızı halkasına girerse, çarptığınız kamanın dışında belirtilen noktaları iki katına çıkarırsınız. Benzer şekilde, iç yeşil / kırmızı halkayı (iki beyaz / siyah bölüm arasındaki biri) vurarak kama dışının üzerinde gösterilen sayıyı üçe katlarsınız. Dartınız en içteki daireye (kırmızı boğa gözü) çarpıyorsa, bunun yerine 50 puan alırsınız ve son olarak dartınız ikinci en içteki daireye vurursa (boğa gözünün etrafındaki yeşil halka), 25 puan alırsınız.

Dart tahtasının ortasından ölçülen halkaların boyutları aşağıdaki gibidir:

görüntü ölçeklenmiyor


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

Not 1: Sunulan resimler yalnızca gösterim amaçlıdır ve ölçeklenmez.

Not 2: Verilen ölçümler yaklaşık değerlerdir ve gerçek bir dart tahtası için doğru olmayabilir.

Not 3: Verilen tüm ölçümler [inclusive-exclusive). Bu zorluğun amaçları doğrultusunda, telleri vurarak ve zıplayan dart konusunda endişelenmeyeceğiz. Dart, radyal çizgilerden biriyle "telin üzerine" inerse, kravatın saat yönünde mi yoksa saatin tersi yönünde mi kırılacağına karar vermek cevaplayıcıya aittir. Bağlantı kopma yönü tutarlı ve belirtilmiş olmalıdır.

Not 4: Dart tahtası standart bir şekilde asılır ve 20 bölümün ortası doğrudan bullseye, 3 bölümü de doğrudan bullseye bağlıdır.

Giriş

x,yDart tahtası ortasına göre milin metre cinsinden ölçülen dartın koordinatlarını temsil eden iki tam sayı .

Çıktı

Verilen koordinatlarda inen bir darta verilecek puan sayısı için tek bir tamsayı.

Numune

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

puanlama

. Kaynak kodunuzdaki en az bayt kazanır.

Standart boşluklar yasaktır .


1
@Shaggy Bunu yapmak için uygun bir neden görmüyorum.
Jonathan Allan,

5
@Shaggy Neden böyle olması gerektiğini açıklayabilir misiniz? Şahsen dartlarımın dart tahtasına vurma garantisi olsa, çok sevinirdim, ama meydan okuma uğruna, fantezi üzerine gerçeğe bağlı kalmanın en iyisi olduğunu düşündüm.
mypetlion

1
Test durumları Önerilen: -150,-1ve -150,0bunların her ikisi de vermeli 11ve bazı uygulamalarda bir kenar söz konusu olabilir, bu kutupsal koordinatlarda teta yakınsak için -pi ve teta = + pi arasındaki geçiş olduğu gibi. (İlk cevabım ikinci cevapta başarısız oldu.)
Arnauld

1
Dangit, x = y = 0 beni tamamen mahvediyor! İyi bir meydan okuma.
BradC

1
Umarım sakıncası yok, ikinci fotoğrafın daha iyi bir versiyonunda yazıyorum.
BradC

Yanıtlar:


19

JavaScript (ES7), 137 bayt

Körleme sözdizimindeki koordinatları alır (x)(y). Saat yönünün tersine kravat molası kullanır.

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)

Çevrimiçi deneyin!

Nasıl?

(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θπθ+π

Grafik çıktı

Aşağıdaki ES6 kod snippet'i, golf kodundakiyle aynı mantığı kullanarak dart tahtası çizer.


8

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

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

Giriş, fare tıklaması ile, çıkış yolu ile yapılır alert. Düzenleme: @Arnauld tarafından önerilen şekilde biraz daha yaklaşık renkler kullanarak 12 bayt kaydedildi.


Kimsenin en kullanırsanız sizi suçlayacak tahmin b33ve 474kırmızı ve yeşil için. :-)
Arnauld

Her ne kadar @Arnauld Yeterince adil, b33olduğu bb3333böylece b22(aka bb3322) daha yakın orijinal olduğunu be3628.
Neil

7

Intel 8086/8087 derlemesi, 180 144 142 138 bayt

Bu, 8087 matematik eş işlemcisini tüm trig ve kayan nokta aritmetiği için kullanır. Tüm hesaplamalar, donanımda 80 bit kayar nokta hassasiyetiyle yapılır.

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

Bir MASM MAKRO (temel olarak bir işlev) olarak yazılmış, X ve Y'yi koordinat olarak alır ve hesaplanan puanı AX'ta döndürür. Kravat saat yönünde kırılmış.

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

PC DOS için örnek bir test programı. Buradan indirin 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  ?

Çıktı

Yukarıdaki test programının örnek kullanımı . Gerçek IBM PC, 8087, DOSBox veya en sevdiğiniz emülatör gerekli.

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

* Düzenlemeler:

  • -38 bayt trunkate rounding deyimi ve 10.5 sabiti kaldırarak. Şimdi saat yönünde kırın.
  • Artık gerekli olmayan FRNDINT'i kaldırarak -2 bayt
  • -4 bayt, FMUL aynı kaynağı / hedefi kullan

6

Jöle , 56 bayt

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

Çifti [x,y]skoru veren bir liste olarak kabul eden monadik bir bağlantı .
Saat yönünde kravat kırma kullanır.

Çevrimiçi deneyin! Veya test odasına bakın

NB bir ikili versiyonu da 56 bayttır

Nasıl?

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

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

Ayrı satırlarda X ve Y istemi.

Saat yönünün tersine bağlar.

TI-Basic belirtilmiş bir dildir ; Burada kullanılan tüm belirteçler bir bayttır.

Açıklama:

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 boole karşılaştırmalarının bunları ekleyerek ve puan değerleriyle çarparak 0 veya 1 döndürmesi gerçeğini kullanır.


3

T-SQL, 392 374 366 bayt

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

Satır sonları okunabilirlik içindir. İlki , aksi halde hata yapabilecek ancak skoru değiştirmeyen bir problemi UPDATEönemser .x=y=0ATN2()

Girdi önceden var olan tablo aracılığıyla alınır t , bizim IO kurallarımıza göre . Kullanım nedeniyle TOP 1, bu tablo yalnızca bir satır içermelidir.

Temelde 3 masaya katılıyorum:

  • Tablo p : Giriş tablosundan t gelen x ve y , kutupsal r'e dönüştürülür ve puanlama kamalarının dart içine düştüğü -11 ila pozitif 11 arasındaki bir sayıyı temsil eden bir "kama" değeri w olur. "Tie breaker" saatin tersi yönünde. ( Biraz kısa olan denedim , ama tutarsız bir bağ kırıcı verdi.)ROUND()
  • Tablo lar : Bu "kama" değeri dönüştürmek için bir arama tablosudur a bir skor içine b .
  • Tablo d : Bu bir arama çizelgesidir ve merkezden mesafeye göre puan hesaplamasını döndürür. e , mesafedir ve r'ye katılır ve yalnızca tek bir satırı döndürür TOP 1. F değeri sabit bir puandır (boğa gözü için) veya kama puanının çarpanıdır.

EDIT : Düştü ORDER BY, en azından SQL 2017'de, onsuz düzgün çalışıyor gibi görünüyor. AND y=0Güncelleme durumuna da düştüm ; Tüm tamsayı ydeğerleri için test ettim , skoru asla değiştirmeyecek x=0şekilde değiştirdim x=1.

DÜZENLEME 2 : g sütunu d tablosundan kaldırıldı , yerine doğrudan IIF()döndürülen f(boğa gözü için) veya f*b8 baytlık bir ifadeyle değiştirildi . Ayrıca sonra boşluk kaldırıldı TOP 1.


2

Haskell , 198 bayt

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]

Bağla saat yönünün tersine kırılıyor. (#)bir arama işlevidir. Kutupsal açı, atan211 numaralı kesme noktasından başlayarak sayı listesinden indekslemek için kullanılır . Mesafe, fonksiyon listesinden indekslemek için kullanılır [const 50, const 25, id, (*3), id, (*2), const 0]ve en sonunda bu fonksiyon daha önce sahip olduğumuz sayıya uygulanır.

Çevrimiçi deneyin!


1

5 Perl -MMath::Trig':pi' -MMath::Trig':radial' -apl , 166 bayt

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

Çevrimiçi deneyin!

STDIN'de ayrılmış iki koordinat alanını alır. Bağ kopma saat yönünün tersine doğrudur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.