Kaç tane yarı ton


21

Kuralları

Görev

Dizeler veya listeler / diziler olarak girilen iki not verildiğinde, birbirinden kaç tane yarı ton hesapladığını (notların kendileri de dahil) hesaplayarak sayı olarak çıktı alın.

Bir yarı ton açıklaması:

Bir yarı ton, klavyede bir adım yukarı veya aşağıdır. Bir örnek C ila C # 'dır. Notun altında görebileceğiniz gibi C beyaz bir notta ve C # ise sadece siyah nottur. Yarı tonlar, aşağıdakiler dışında, siyah nottan sonraki beyaz notaya yukarı veya aşağı doğru atılımdır:

  • B'den C'ye
  • C'den B'ye
  • E'den F'ye
  • E ila E

tuş takımı

Örnekler

'A, C' -> 4

'G, G#' -> 2

'F#, B' -> 6

'Bb, Bb' -> 13


kurallar

  • İki nota arasındaki en büyük mesafe 13 yarı tondur.
  • Girilen ikinci not her zaman ilk girilen notun üstünde olacaktır.
  • Girdiyi bir dize veya bir dizi / liste olarak alabilirsiniz. Bir dize olarak alırsanız, notlar virgülle ayrılır (örneğin String -> 'A, F', Array -> ['A', 'F']).
  • Her zaman iki geçerli not alacağınızı varsayabilirsiniz.
  • Keskinler olarak #ve daireler de gösterilecektir.b
  • Kodunuz enharmonik eşdeğerleri desteklemelidir (örneğin, hem F # hem de Gb'yi desteklemesi gerekir)
  • Kodunuzun, adlandırılmış, ancak keskin veya düz olmayan bir adla desteklenmesi gerekmez (yani, E # veya Cb'yi desteklemeniz gerekmez). Bonus puanınız olsa kodunuz destekliyorsa bonus puan.
  • Kodunuzun çift keskinlik veya çift daire desteklemesi gerekmez.
  • Hem aynı notaları hem de aynı perdeyi (örn. 'Gb, Gb' veya 'A #, Bb') alırsanız, ikincinin birincinin üzerinde bir oktav olmayacağını varsayabilirsiniz.
  • Bu kod golf, bu yüzden en az sayıda bayt olan cevap kazanır.

2 tane alıyorum G -> G#çünkü ikisi de dahil.
HyperNeutrino

@HyperNeutrino Yep üzgünüm. Benim adıma yanlışlık.
Amorris

1
CbVeya gibi notlara hitap etmek zorunda mıyız E#? Peki ya çift keskinlikler / daireler?
Sok

1
@Tamam Hayır, kodunuzun E # veya Cb gibi notları desteklemesi gerekmez ve çift keskin uçları ya da daireleri desteklemesi gerekmez. Sorunu daha net hale getirmek için güncelledim. Herhangi bir karışıklık için özür dilerim.
Amorris

2
Tonlara bir müzik teorisi anlamda mesafeden konuşurken Sadece açık olmak değil , üzerinde başlatmak not ekleyin. Matematikte, (X, Y]C ila C # 1 yarı ton ve C ila C 12 yarı ton olduğu şekilde temsil edilir .
Dom,

Yanıtlar:



7

JavaScript (ES6), 78 bayt

@Neil sayesinde 1 bayt kaydedildi

Körleme sözdizimindeki notları alır (a)(b).

a=>b=>((g=n=>'0x'+'_46280ab_91735'[parseInt(n+3,36)*2%37%14])(b)-g(a)+23)%12+2

Test durumları

Özet fonksiyonu

Karma işlevinin amacı, bir notu onaltılık değerde saklanan yarı ton ofsetlerini (C = 0, C # = 1, ..., B = 11) içeren arama tablosundaki bir işaretçiye dönüştürmektir.

İlk önce nota bir '3' ekleriz ve elde edilen dizgiyi baz-36'da ayrıştırırız, bu bir N tamsayısına yol açar . Çünkü '#' geçersiz bir karakter, sadece onu izleyen herhangi bir karakter ile birlikte dikkate alınmaz.

O zaman hesaplıyoruz:

H(N) = ((N * 2) MOD 37) MOD 14

Aşağıda sonuçların bir özeti bulunmaktadır.

 note | +'3' | parsed as | base 36->10 |   *2  | %37 | %14 | offset
------+------+-----------+-------------+-------+-----+-----+--------
  C   |  C3  |    c3     |         435 |   870 |  19 |   5 |  0x0
  C#  |  C#3 |    c      |          12 |    24 |  24 |  10 |  0x1
  Db  |  Db3 |    db3    |       17247 | 34494 |  10 |  10 |  0x1
  D   |  D3  |    d3     |         471 |   942 |  17 |   3 |  0x2
  D#  |  D#3 |    d      |          13 |    26 |  26 |  12 |  0x3
  Eb  |  Eb3 |    eb3    |       18543 | 37086 |  12 |  12 |  0x3
  E   |  E3  |    e3     |         507 |  1014 |  15 |   1 |  0x4
  F   |  F3  |    f3     |         543 |  1086 |  13 |  13 |  0x5
  F#  |  F#3 |    f      |          15 |    30 |  30 |   2 |  0x6
  Gb  |  Gb3 |    gb3    |       21135 | 42270 |  16 |   2 |  0x6
  G   |  G3  |    g3     |         579 |  1158 |  11 |  11 |  0x7
  G#  |  G#3 |    g      |          16 |    32 |  32 |   4 |  0x8
  Ab  |  Ab3 |    ab3    |       13359 | 26718 |   4 |   4 |  0x8
  A   |  A3  |    a3     |         363 |   726 |  23 |   9 |  0x9
  A#  |  A#3 |    a      |          10 |    20 |  20 |   6 |  0xa
  Bb  |  Bb3 |    bb3    |       14655 | 29310 |   6 |   6 |  0xa
  B   |  B3  |    b3     |         399 |   798 |  21 |   7 |  0xb

Yassı ve keskin nişancılar hakkında

Aşağıda bu hash fonksiyonunun '#' ile takip edilen bir notun, 'b' ile takip eden bir sonraki notla aynı sonucu verdiğine dair kanıt vardır . Bu paragrafta, baz-36 büyüklükleri için @ ön ekini kullanıyoruz .

Örneğin, Db dönüştürülecek @ db3 ve C # dönüştürülür @c (önceki paragrafa bakınız). Bunu kanıtlamak istiyoruz:

H(@db3) = H(@c)

Veya genel durumda, Y = X + 1 ile :

H(@Yb3) = H(@X)

@ b3 olduğu 399 ondalık. Bu nedenle:

H(@Yb3) =
@Yb3 * 2 % 37 % 14 =
(@Y * 36 * 36 + 399) * 2 % 37 % 14 =
((@X + 1) * 36 * 36 + 399) * 2 % 37 % 14 =
(@X * 1296 + 1695) * 2 % 37 % 14

1296 , 1 modulo 37'ye uygundur , bu nedenle şu şekilde basitleştirilebilir:

(@X + 1695) * 2 % 37 % 14 =
((@X * 2 % 37 % 14) + (1695 * 2 % 37 % 14)) % 37 % 14 =
((@X * 2 % 37) + 23) % 37 % 14 =
((@X * 2 % 37) + 37 - 14) % 37 % 14 =
@X * 2 % 37 % 14 =
H(@X)

Özel bir durum geçiştir G # için Ab bizim istediğimiz gibi, Hb yukarıdaki formüllere uyması için. Ancak, bu aynı zamanda çalışır çünkü:

@ab3 * 2 % 37 % 14 = @hb3 * 2 % 37 % 14 = 4

@Neil Teşekkürler! Optimizasyonunuz benimkinden daha fazla bayt tasarrufu sağlıyor.
Arnauld

Huh, aslında Batch
Neil

@Neil Batch'taki modulo işareti, bölenin işareti olduğundan, sanırım?
Arnauld

Hayır, bu JS'de olduğu gibi temettü işaretidir, ancak daha önceki bir golf nedeniyle ters çevrilmiş olan sonucun işareti için düzeltmek için biraz golfçü olduğu ortaya çıktı.
Neil

4

Perl, 39 32 bayt

içerir +1içinp

STDIN'de başlangıç ​​ve bitiş notlarını iki satır halinde verin

(echo "A"; echo "C") | perl -pe '$\=(/#/-/b/-$\+5/3*ord)%12+$.}{'; echo

Sadece kod:

$\=(/#/-/b/-$\+5/3*ord)%12+$.}{


@wastl Yani bana söylendi. Hangi meta
gönderiyi

Benim yorumum bir link. Tıklamaktan çekinmeyin.
18'de

Bu benimkine çok benziyor gibi görünüyor - ama Perl için çok kısa, +1
Level River St

@LevelRiverSt de bu olduğunu Ton Hospel.
msh210

4

Japt , 27 bayt

®¬x!b"C#D EF G A"ÃrnJ uC +2

Çevrimiçi test edin! Girdiyi iki karakter dizisi olarak alır.

Ayrıca, herhangi bir temel notadaki herhangi bir keskinlik veya düzlük için de geçerlidir!

açıklama

®¬x!b"C#D EF G A"ÃrnJ uC +2   Let's call the two semitones X and Y.
®                Ã            Map X and Y by
 ¬                              splitting each into characters,
  x                             then taking the sum of
   !b"C#D EF G A"               the 0-based index in this string of each char.
                                C -> 0, D -> 2, E -> 4, F -> 5, G -> 7, A -> 9.
                                # -> 1, adding 1 for each sharp in the note.
                                b -> -1, subtracting 1 for each flat in the note.
                                B also -> -1, which happens to be equivalent to 11 mod 12.
                                The sum will be -2 for Bb, 2 for D, 6 for F#, etc.
                              Now we have a list of the positions of the X and Y.
                  rnJ         Reduce this list with reversed subtraction, starting at -1.
                              This gets the difference Y - (X - (-1)), or (Y - X) - 1.
                      uC      Find the result modulo 12. This is 0 if the notes are 1
                              semitone apart, 11 if they're a full octave apart.
                         +2   Add 2 to the result.

2

Perl 5 + -p, 66 bayt

s/,/)+0x/;y/B-G/013568/;s/#/+1/g;s/b/-1/g;$_=eval"(-(0x$_-1)%12+2"

Çevrimiçi deneyin!

Virgülle ayrılmış değerler alır. Ayrıca Cb, B #, E #, Fb ve çoklu # / b için de çalışır.

Açıklama:

# input example: 'G,G#'
s/,/)+0x/; # replace separator with )+0x (0x for hex) => 'G)+0xG#'
y/B-G/013568/; # replace keys with numbers (A stays hex 10) => '8)+0x8#'
s/#/+1/g; s/b/-1/g; # replace accidentals with +1/-1 => '8)+0x8+1'
$_ = eval # evaluate => 2
    "(-(0x$_-1)%12+2" # add some math => '(-(0x8)+0x8+1-1)%12+2'

Eval için açıklama:

(
    - (0x8) # subtract the first key => -8
    + 0x8 + 1 # add the second key => 1
    - 1 # subtract 1 => 0
) % 12 # mod 12 => 0
+ 2 # add 2 => 2
# I can't use % 12 + 1 because 12 (octave) % 12 + 1 = 1, which is not allowed

2

Ruby , 56 bayt

->a{a.map!{|s|s.ord*5/3-s[-1].ord/32}
13-(a[0]-a[1])%12}

Çevrimiçi deneyin!

Harfler ASCII kod sürelerine göre şu şekilde ayrıştırılır 5/3(bu, gereken sayıda yarı ton sayısını ve 108 ofsetini verir)

A    B    C    D    E    F    G
108  110  111  113  115  116  118

Geçen karakteri ( #, bşöyle ya da yeniden yazmak) 32 bölü onun ASCII kodu olarak ayrıştırılır

# letter (natural) b 
1  { --- 2 --- }   3

Bu, harf kodundan çıkarılır.

Sonra nihai sonuç olarak döndürülür 13-(difference in semitones)%12


2

Stax , 25 24 bayt

╝─°U┤ƒXz☺=≡eA╕δ┴╬\¿☺zt┼§

Çevrimiçi çalıştırın ve hata ayıklayın

Aynı programın karşılık gelen ascii gösterimi budur.

{h9%H_H32/-c4>-c9>-mrE-v12%^^

Etkili bir şekilde, her bir notun klavye dizinini bir formül kullanarak hesaplar, ardından ortaya çıkan aralığı hesaplar.

  1. Temel nottan başlayın, A = 2, B = 4, ... G = 14
  2. Son karakterin ascii kodunun 2 - code / 32nerede codeolduğunu , kazara ofsetini hesaplayın .
  3. Onları birlikte ekleyin.
  4. Sonuç> 4 ise, B # 'yu çıkarmak için 1 çıkarın.
  5. Sonuç> 7 ise, E # 'yi çıkarmak için 1'i çıkarın.
  6. Ortaya çıkan iki not dizinini modüler olarak çıkarın ve 1 ekleyin.

1
["F#","B"]6 olmalıdır.
Weijun Zhou

1
Teşekkürler. Hesaplamanın yarısını diğerini ayarlamadan değiştirdim. Sabitlendi.
özyinelemeli

1

Toplu, 136 135 bayt

@set/ac=0,d=2,e=4,f=5,g=7,a=9,r=24
@call:c %2
:c
@set s=%1
@set s=%s:b=-1%
@set/ar=%s:#=+1%-r
@if not "%2"=="" cmd/cset/a13-r%%12

Açıklama: Alt cprogramdaki ikameler #not isminde +1ve bile değiştirilir -1. Bu durum duyarsız olduğu için Bbolur -1-1. C... değişkenleri A(ayrıca büyük / küçük harfe duyarsız) bundan dolayı uygun sayıda yarı ton olarak seçilmiştir B=-1. Sonuçta ortaya çıkan dize değerlendirilir ve @ xnor'ın sonucu değerden çıkarma hilesi, not değerlerinin birbirinden çıkarılmasını istenen efekti verir. Düzenleme: Sonunda @ Arnauld'un 1 byte tasarruf ederek istenen cevabı elde etmek için 13'ten modülayı çıkarma hilesini kullanıyorum.



1

Jöle , 28 bayt

O64_ṠH$2¦ḅ-AḤ’d5ḅ4µ€IḞṃ12FṪ‘

İki karakter listesinin listesini kabul eden ve bir tamsayı döndüren tek renkli bir bağlantı.

Çevrimiçi deneyin! veya tüm olası durumları görün .

Nasıl?

Notları sıfırdan on ikiye tamsayılar üzerinde eşlemek için giriş karakterlerinin sıralarında bazı tuhaf aritmetik işlemlerini gerçekleştirir ve daha sonra onikiyle modüle için bir proxy olarak bir baz dekompresyon gerçekleştirir, sonra sıfırın ardından 12 ile sonra bir tane ekler.

O64_ṠH$2¦ḅ-AḤ’d5ḅ4µ€IḞṃ12FṪ‘ - Main link, list of lists    e.g. [['F','#'],['B']]  ...or [['A','b'],['G','#']]
                  µ€         - for €ach note list          e.g.  ['F','#'] ['B']          ['A','b'] ['G','#']
O                            - { cast to ordinal (vectorises)    [70,35]   [66]           [65,98]   [71,35]
 64                          -   literal 64
   _                         -   subtract (vectorises)           [-6,29]   [-2]           [-1,-34]  [-7,29]
        ¦                    -   sparse application...
       2                     -   ...to indices: [2] (just index 2)
      $                      -   ...do: last two links as a monad:
    Ṡ                        -          sign                     [-6,1]    [-2]           [-1,-1]   [-7,1]
     H                       -          halve                    [-6,-0.5] [-2]           [-1,-0.5] [-7,0.5]
         ḅ-                  -   convert from base -1            5.5       -2             0.5       7.5
           A                 -   absolute value                  5.5       2              0.5       7.5
            Ḥ                -   double                          11.0      4              1.0       15.0
             ’               -   decrement                       10.0      3              0.0       14.0
              d5             -   divmod by 5                     [2.0,2.0] [0,3]          [0.0,0.0] [2.0,4.0]
                ḅ4           -   convert from base 4             10.0      3              0.0       12.0
                             - } -->                             [10.0,3]                 [0.0,12.0]
                    I        - incremental differences           [-7.0]                   [12.0]
                     Ḟ       - floor (vectorises)                [-7]                     [12]
                      ṃ12    - base decompress using [1-12]      [[5]]                    [[1,12]]
                         F   - flatten                           [5]                      [1,12]
                          Ṫ  - tail                              5                        12
                           ‘ - increment                         6                        13

Ayrıca 28 baytta ...

Xnor'ın Python 2 cevabının (doğrudan olmayan) bir limanı ...

O×5:3z60_Ṡ¥2¦60U1¦Fḅ-‘N%12+2

Tüm olası davaları dene


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.