Accordi di pianoforte su tasti bianchi


9

Backstory [che non è vero]

Un piano è impostato in questo modo:

! [Http://www.piano-lessons-made-simple.com/images/2-Octave-Labled.gif

Tuttavia, sul mio piano, tutti i tasti neri sono rotti!

Voglio comunque essere in grado di suonare alcuni accordi sul mio pianoforte rotto, comunque.

Nella musica, un accordo è un gruppo di note che vengono suonate insieme. Per consentire l'inserimento di accordi, definirò innanzitutto cos'è un semitono.

Che cos'è un semitono?

Un semitono è la distanza più piccola nella musica occidentale. Se guardi la parte superiore del piano, vedi che di solito puoi passare da un tasto nero a un tasto bianco, o viceversa; tuttavia, tra Be Ce Ee Fnon esiste un tasto nero.

Cos'è un accordo?

Ai fini di questa sfida, definiamo un accordo come un mucchio di note con un certo numero di semitoni tra di loro. Ad esempio, diamo un'occhiata a un 4-3-3accordo a partire C(per la musica, questo è un accordo V 7 in fa maggiore). Iniziamo alle C. Contiamo fino a 4 semitoni: C#, D, D#, E. La nota successiva è E, e contiamo 3 semitoni dopo che: F, F#, G. La nota successiva è G, e contiamo 3 semitoni dopo che: G#, A, Bb. Quindi otteniamo C-E-G-Bb. Sìì! Ma aspetta ... Bbè un tasto nero e quelli sono rotti ... Tuttavia, se iniziamo da G, otteniamo G-B-D-F! Sìì!

Ingresso

L'input viene fornito come un elenco di numeri interi in qualsiasi formato ragionevole. Questo rappresenta l'accordo come descritto sopra.

Produzione

L'output dovrebbe essere un elenco di note su cui posso iniziare a utilizzare solo i tasti bianchi. Questo può anche essere solo una stringa di tutte le fino a 7 note perché tutti i nomi dei tasti saranno un carattere. Devi essere in grado di gestire anche un output vuoto.

Casi test

input -> output // comments
4 3 -> C F G // this is a major triad
3 4 -> D E A // this is a minor triad
4 3 3 -> G // this is the major-minor seventh chord
3 3 3 -> [empty output] // this is the diminished-diminished seventh chord. All of them use black keys
4 4 -> [empty output] // this is an augmented triad
3 3 -> B // this is a diminished triad
1 -> B E // this is just a minor second
11 -> C F // this is just a major seventh

Altre specifiche

  • Scappatoie standard vietate
  • Si può presumere che l'input abbia almeno un numero intero
  • Puoi presumere che tutti i numeri interi siano non negativi e inferiori a 12 (perché il piano si ripete ogni 12 note)
  • L'output può essere in qualsiasi ordine

Criteri vincenti

Sarà accettata la presentazione valida più breve al 15 aprile.


Possiamo assumere "non negativo e inferiore a 12" - non dovrebbe essere "positivo e inferiore o uguale a 12"?
Jonathan Allan,

@JonathanAllan Fondamentalmente non c'è differenza; il mio metodo consente un Unisono perfetto ma non un'ottava perfetta; il tuo viceversa. Teoricamente, la tua restrizione potrebbe avere più senso, ma penso che probabilmente non dovrei cambiarla perché ci sono già risposte e non cambia sostanzialmente la sfida.
HyperNeutrino,

Risposte:


3

Gelatina , 25 byte

236ḃ2ṙЀ7+\€Ṭ
+\ịþ¢Ạ€TịØA

Provalo online! o vedere una suite di test

Come?

236ḃ2ṙЀ7+\€Ṭ - Link 1, white-note-offsets: no arguments
236ḃ2         - 236 in bijective base 2 [2, 2, 1, 2, 2, 1, 2] - semitones G->A, A->B ...
     ṙЀ7     - rotate left by, mapped over [1,2,3,4,5,6,7] - i.e. as above for each
                    starting white key (1st one A->B,B->C,...; 2nd B->C,C->D,...; etc)
         +\€  - reduce €ach with addition - i.e. absolute number of semitones: [[2,3,5,7,8,10,12],[1,3,5,6,8,10,12],[2,4,5,7,9,11,12],[2,3,5,7,9,10,12],[1,3,5,7,8,10,12],[2,4,6,7,9,11,12],[2,4,5,7,9,10,12]]
            Ṭ - untruth (vectorises) - make lists with 1s at those indexes: [[0,1,1,0,1,0,1,1,0,1,0,1],[1,0,1,0,1,1,0,1,0,1,0,1],[0,1,0,1,1,0,1,0,1,0,1,1],[0,1,1,0,1,0,1,0,1,1,0,1],[1,0,1,0,1,0,1,1,0,1,0,1],[0,1,0,1,0,1,1,0,1,0,1,1],[0,1,0,1,1,0,1,0,1,1,0,1]]

+\ịþ¢Ạ€TịØA - Main link: list of semitone gap integers (even negatives will work)
+\          - reduce by addition - gets the absolute semitone offsets needed
    ¢       - last link (1) as a nilad
   þ        - outer product with:
  ị         -     index into - 7 lists, each with 1s for white and 0s for black keys hit
                      note that indexing is modular and all the lists are length 12
                      so any integer is a valid absolute offset, not just 0-11 inclusive
     Ạ€     - all truthy for €ach - for each get a 1 if all keys are white ones, else 0
       T    - truthy indexes - get the valid starting white keys as numbers from 1 to 7
        ị   - index into:
         ØA -     the uppercase alphabet

6

MATL , 31 byte

Grazie a Jonathan Allan per una correzione.

'BAGFEDC'"GYs12X\110BQX@YSYsm?@

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

Il modello 2 2 1 2 2 2 1specifica gli intervalli tra i tasti bianchi consecutivi. Il programma utilizza un loop che applica tutti i turni ciclici a questo modello di base, al fine di testare ogni tasto come una potenziale nota più bassa dell'accordo di input. Per ogni turno, si ottiene la somma cumulativa del modello. Ad esempio, Bcome potenziale nota più bassa, il modello è stato spostato 1 2 2 1 2 2 2e la sua somma cumulativa è 1 3 5 6 8 10 12.

Ora, per vedere se questo può supportare un 4 3 3accordo, calcoliamo la somma cumulativa degli intervalli di accordi, che è 4 7 10; ridurlo tramite modulo 12 basato su 1 (un intervallo di 14darebbe 2); e controlla se quei numeri sono tutti membri dei valori consentiti 1 3 5 6 8 10 12. Questo non è il caso in questo esempio. Se fosse così, avremmo emesso la lettera B.

La corrispondenza tra turni ciclici e lettere di output è definita dalla stringa 'BAGFEDC'. Ciò indica che 'B'(primo carattere) corrisponde a uno spostamento ciclico di 1; 'A'(secondo carattere) corrisponde a uno spostamento ciclico di 2ecc.

'BAGFEDC'  % Push this string
"          % For each character from the string
  G        %   Push input array
  Ys       %   Cumulative sum
  12X\     %   1-based modulo 12, element-wise (1,12,13,14 respectively give 1,12,1,2)
  110BQ    %   Push 110, convert to binary, add 1 element-wise: gives [2 2 1 2 2 2 1]
  X@       %   Push current iteration index, starting at 1
  YS       %   Cyclic shift to the right by that amount
  Ys       %   Cumulative sum
  m        %   Ismember. Gives an array of true of false entries
  ?        %   If all true
    @      %     Push current character
           %   End (implicit)
           % End (implicit)
           % Display (implicit)

5

Mathematica, 110 byte (codifica ISO 8859-1)

±i_:=#&@@@Select["A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#&/@(Accumulate[i~Prepend~#]&/@Range@12),FreeQ@"#"]

Definisce una funzione unaria ±che accetta un elenco di numeri interi come input (in realtà nessuna restrizione sulla dimensione o sui segni dei numeri interi) e restituisce un elenco di stringhe di un carattere. Ad esempio, ±{3,4}restituisce {"A","D","E"}.

"A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#è una funzione che trasforma un elenco di numeri interi nei nomi delle note corrispondenti, ad eccezione #di qualsiasi tasto nero. Questo viene applicato a ciascun elemento di Accumulate[i~Prepend~#]&/@Range@12, che crea un elenco di valori di nota dall'elenco di input elenco di intervalli di note, a partire da ogni possibile nota da 1 a 12. Filtriamo tutti gli elenchi di nomi di note che contengono "#"usando Select[...,FreeQ@"#"], e quindi restituisce la prima nota in ogni elenco rimanente utilizzando #&@@@.


Bella presentazione!
HyperNeutrino

Domanda: Mathematica utilizza il proprio sistema di byte? Sono 110 caratteri ma in UTF-8 sono 111 byte a causa del +/-simbolo.
HyperNeutrino,

Puoi eliminare completamente l'assegnazione e semplicemente "restituire implicitamente" una funzione.
wizzwizz4,

@ wizzwizz4: ho scoperto che dovevo nominare la variabile Accumulate[i~Prepend~#]&perché altrimenti ci sarebbe stato uno scontro al curry. Sentiti libero di trovare una soluzione alternativa però!
Greg Martin,

@HyperNeutrino: hai ragione sul fatto che UTF-8 è la codifica standard, ma Mathematica può (di solito) funzionare anche nella codifica ISO 8859-1. L'ho notato nel post.
Greg Martin,

3

Python 2, 159 155 byte

(Pubblicando questo dopo esserti assicurato che ci sia un contributo valido che è più breve di questo)

import numpy
s='C.D.EF.G.A.B'
def k(y):return lambda x:s[(x+y)%12]
for i in range(12):
    if s[i]!='.'and'.'not in map(k(i),numpy.cumsum(input())):print s[i]

Praticamente solo la soluzione banale. Input come un elenco di numeri interi e output con ogni carattere su una singola riga.

-4 byte rimuovendo una variabile non necessaria


3

JavaScript (ES6), 72 71 68 byte

a=>[..."C1D1EF1G1A1B"].filter((c,i,b)=>!+c>a.some(e=>+b[i+=e,i%12]))

Scorre attraverso ogni tasto omettendo i tasti neri, quindi controllando che la somma cumulativa dei semitoni non atterri mai su un tasto nero.

Modifica: salvato 3 byte grazie a @Arnauld.


4
Leggibilità ?! Sei sicuro di essere nel sito giusto? :-)
wizzwizz4
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.