Quanti semitoni


21

Linee guida

Compito

Dato due note, inserite come stringhe o liste / matrici, calcola quanti semitoni sono separati (comprese le note stesse), generando come un numero.

Spiegazione di un semitono:

Un semitono è un passo avanti o indietro della tastiera. Un esempio è da C a C #. Come puoi vedere sotto la nota C è su una nota bianca e C # è la nota nera solo una sopra di essa. I semitoni sono i salti da una nota nera alla nota bianca successiva, su o giù, ad eccezione di:

  • Da B a C
  • Da C a B.
  • Da E a F.
  • Da F a E

tastiera

Esempi

'A, C' -> 4

'G, G#' -> 2

'F#, B' -> 6

'Bb, Bb' -> 13


Regole

  • La distanza più grande tra due note è di 13 semitoni.
  • La seconda nota immessa sarà sempre al di sopra della prima nota immessa.
  • È possibile accettare input come una stringa o un array / elenco. Se si prende come una stringa, le note saranno separati da virgole (ad esempio String -> 'A, F', Array -> ['A', 'F']).
  • Puoi presumere che ti verranno sempre fornite due note valide.
  • Gli oggetti taglienti saranno indicati come #e gli appartamenti saranno indicati comeb
  • Il tuo codice deve supportare equivalenti enarmonici (ad es. Deve supportare sia F # che Gb)
  • Non è necessario che il codice supporti le note a cui è stato assegnato un nome, ma che possono essere denominate senza un segno di spunta o piatto (ovvero non è necessario supportare E # o Cb). Punti bonus se il tuo codice lo supporta comunque.
  • Non è necessario che il tuo codice supporti doppi taglienti o doppi piatti.
  • Si può presumere che se si ottengono entrambe le stesse note o lo stesso tono (ad esempio "Gb, Gb" o "A #, Bb"), la seconda non sarà esattamente un'ottava sopra la prima.
  • Questo è il codice golf, quindi vince la risposta con il minor numero di byte.

Ne ottengo 2 G -> G#perché sono entrambi inclusi.
HyperNeutrino,

@HyperNeutrino Già dispiaciuto. Errore per mio conto.
Amorris,

1
Dobbiamo soddisfare note come Cbo E#? Che dire di doppi taglienti / piatti?
Ha

1
@Sok No, il tuo codice non deve supportare note come E # o Cb e non deve supportare doppi oggetti taglienti o piatti. Ho aggiornato la domanda per renderlo più chiaro. Mi dispiace per qualsiasi confusione.
Amorris,

2
Per essere chiari, quando parli da una teoria musicale la distanza dei sensi in semitoni non include la nota da cui inizi. In matematica dovrebbe essere rappresentato in (X, Y]modo che C a C # sia 1 semitono e C a C sia 12 semitoni.
Dom

Risposte:


7

Python 2 , 66 byte

r=1
for s in input():r=cmp(s[1:]+s,s)-ord(s[0])*5/3-r
print-r%12+2

Provalo online!


Python 2 , 68 byte

lambda s,t:13-(q(s)-q(t))%12
q=lambda s:ord(s[0])*5/3+cmp(s,s[1:]+s)

Provalo online!


Punti extra per essere in grado di gestire note come B # e Fb, pur rimanendo il più breve finora.
Amorris,

7

JavaScript (ES6), 78 byte

Salvato 1 byte grazie a @Neil

Prende le note nella sintassi del curry (a)(b).

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

Casi test

Funzione hash

Lo scopo della funzione hash è convertire una nota in un puntatore in una tabella di ricerca contenente gli offset dei semitoni (C = 0, C # = 1, ..., B = 11), memorizzati in esadecimali.

Abbiamo prima append un '3' alla nota e analizzare la stringa risultante in base-36, portando ad un numero intero N . Poiché "#" è un carattere non valido, viene semplicemente ignorato, insieme a qualsiasi carattere che lo segue.

Quindi calcoliamo:

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

Di seguito è riportato un riepilogo dei risultati.

 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

A proposito di appartamenti e oggetti taglienti

Di seguito è la prova che questa funzione hash assicura che una nota seguita da un '#' dia lo stesso risultato della nota successiva seguita da una 'b' . In questo paragrafo, usiamo il prefisso @ per le quantità base-36.

Ad esempio, Db verrà convertito in @ db3 e C # verrà convertito in @c (vedere il paragrafo precedente). Vogliamo dimostrare che:

H(@db3) = H(@c)

O nel caso generale, con Y = X + 1 :

H(@Yb3) = H(@X)

@ b3 è 399 in decimale. Perciò:

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 è congruente con 1 modulo 37 , quindi questo può essere semplificato come:

(@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)

Un caso speciale è il passaggio da G # ad Ab , poiché ci aspetteremmo Hb per rispettare le formule di cui sopra. Tuttavia, questo funziona anche perché:

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

@Neil Grazie! La tua ottimizzazione consente di risparmiare più byte del mio.
Arnauld,

Ehm, in realtà ho trovato il contrario con la mia soluzione Batch ...
Neil,

@Neil Perché il segno del modulo in Batch è il segno del divisore, immagino?
Arnauld,

No, è il segno del dividendo, come in JS, ma si è rivelato essere un po 'più golfista nel correggere il segno del risultato che era stato invertito a causa di un golf precedente.
Neil,

4

Perl, 39 32 byte

Include +1perp

Fornisci le note di inizio e fine come due righe su STDIN

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

Solo il codice:

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


@wastl Quindi mi è stato detto. Mi piacerebbe sapere quale meta post, quindi posso andare lì e non sono d'accordo :-)
Ton Hospel

Il mio commento è un link. Sentiti libero di fare clic.
wastl

Sembra che funzioni in modo molto simile al mio - ma incredibilmente abbreviato per Perl, +1
Level River St

@LevelRiverSt bene, questo è Ton Hospel.
msh210,

4

Japt , 27 byte

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

Provalo online! Accetta l'input come una matrice di due stringhe.

Funziona anche con qualsiasi quantità di oggetti taglienti o piatti su qualsiasi nota di base!

Spiegazione

®¬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 byte

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

Provalo online!

Accetta valori separati da virgola. Funziona anche con Cb, B #, E #, Fb e # / b multipli.

Spiegazione:

# 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'

Spiegazione per eval:

(
    - (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

Rubino , 56 byte

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

Provalo online!

Le lettere vengono analizzate in base al loro tempo di codice ASCII 5/3come segue (ciò fornisce il numero richiesto di semitoni più un offset di 108)

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

L'ultimo personaggio (# , bo la lettera di nuovo) è analizzato come il suo codice ASCII diviso per 32 come segue

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

Questo viene sottratto dal codice lettera.

Quindi il risultato finale viene restituito come 13-(difference in semitones)%12


2

Stax , 25 24 byte

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

Esegui ed esegui il debug online

La corrispondente rappresentazione ASCII dello stesso programma è questa.

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

In effetti, calcola l'indice della tastiera di ogni nota usando una formula, quindi calcola l'intervallo risultante.

  1. Inizia dalla nota di base, A = 2, B = 4, ... G = 14
  2. Calcola l'offset accidentale 2 - code / 32dove si codetrova il codice ASCII dell'ultimo carattere.
  3. Aggiungili insieme.
  4. Se il risultato è> 4, sottrai 1 per rimuovere B #.
  5. Se il risultato è> 7, sottrai 1 per rimuovere E #.
  6. Sottrai in modo modulare i due indici di nota risultanti e aggiungi 1.

1
["F#","B"]dovrebbe essere 6.
Weijun Zhou,

1
Grazie. Ho modificato la metà del calcolo senza regolare l'altro. È sistemato.
ricorsivo il

1

Lotto, 136 135 byte

@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

Spiegazione: Le sostituzioni nella csubroutine sostituiscono #il nome della nota con +1e bcon-1 . Poiché questo non fa distinzione tra maiuscole e minuscole, Bbdiventa -1-1. Le variabili per C... A(anche senza distinzione tra maiuscole e minuscole) sono quindi scelte per essere il numero appropriato di semitoni lontano da B=-1. Viene quindi valutata la stringa risultante e il trucco di @ xnor di sottrarre il risultato dal valore dà l'effetto desiderato di sottrarre i valori delle note l'uno dall'altro. Modifica: Finalmente uso il trucco di @ Arnauld per sottrarre il modulo da 13 per ottenere la risposta desiderata, risparmiando 1 byte.



1

Gelatina , 28 byte

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

Un collegamento monadico che accetta un elenco di due elenchi di caratteri e restituisce un numero intero.

Provalo online! o vedi tutti i casi possibili .

Come?

Esegue una bizzarra aritmetica sugli ordinali dei caratteri di input per mappare le note sugli interi da zero a dodici e quindi esegue una decompressione di base come proxy per modulo di dodici, dove zero viene quindi sostituito da 12 e ne aggiunge uno.

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

Anche a 28 byte ...

Una porta (non così diretta) della risposta Python 2 di xnor ...

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

Prova tutti i casi possibili


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.