Biorąc pod uwagę dwie nazwy nut, masz napisać program, który określa, czy interwał utworzony przez te dwie nuty jest spółgłoskowy czy dysonansowy.
Wprowadzenie
W muzyce zachodniej jest tylko 12 „różnych” dźwięków. Ich nazwiska, sortowane od najniższego do najwyższego, są następujące: C, C#, D, D#, E, F, F#, G, G#, A, A#, B
. Sekwencja jest cykliczna, tzn. Kontynuowana jest następna C
po B
nieskończoności.
Odległość między dwoma tonami nazywana jest interwałem . Odstęp między dowolnymi dwiema nutami sąsiadującymi z powyższą serią (np. C — C#
Lub E — F
) nazywa się półtonem . Przerwa między bardziej odległymi nutami jest zdefiniowana jako liczba kroków półtonowych potrzebnych do przejścia od pierwszego do drugiego (przy możliwym owinięciu wokół sekwencji). Kilka przykładów: D to E
= 2 półtonów, C to G
= 7 półtonów, B to D#
= 4 półtonów (dotyczy to sekwencji). 1
Teraz te interwały są podzielone na dwie kategorie: spółgłoska (brzmi przyjemnie, jeśli grasz dwie nuty jednocześnie) i dysonans (nie tak bardzo).
Zdefiniujmy przedziały spółgłosek: 0, 3, 4, 5, 7, 8 i 9 półtonów.
Reszta jest dysonansowa, a mianowicie: 1, 2, 6, 10 i 11 półtonów.
Wyzwanie
Napisz „program” (w szerokim znaczeniu tego słowa: funkcja jest całkowicie OK), aby wykonać następujące czynności:
Weź jako nazwę dwie nazwy nut (ciągi z powyższej sekwencji). Możesz wziąć je w dowolny sposób (od standardowego, jako argumenty, oddzielone czymkolwiek chcesz, możesz nawet wziąć je jako listę znaków (np
["C","#"]
.). Jednak nie możesz przypisywać żadnych innych nazw notatkom (szczególnie ty nie może ich numerować od 0 do 11 i używać liczb).Dla waszych maniaków muzycznych nuty zostaną określone bez oktawy. W tym przypadku nie ma również znaczenia, w jakiej kolejności przychodzą nuty, a która jest niższa, a która wyższa. Wreszcie, nie musisz obsługiwać żadnych nazw, których nie ma na powyższej liście. Żadnych innych ulepszeń, takich jak
E#
mieszkania, podwójnych przeróbek i tak dalej.Wybierz dowolne dwie różne wartości. Twój program musi wypisać jeden z nich, ilekroć interwał utworzony przez dwie nuty na wejściu jest spójny, a drugi, jeśli tak nie jest. (Może być
True
iFalse
, ale nawet gatunku i e jeśli chcesz :))To jest golf golfowy. Wygrywa najkrótszy program w bajtach w każdym języku. Baw się dobrze!
Przykłady i przypadki testowe
Note 1 Note 2 Output Interval [semitones]
C D Dissonant 2
A# A# Consonant 0
G D Consonant 7 (wraparound)
D# A Dissonant 6
F E Dissonant 11
A C Consonant 3
Nie dodam ich więcej, ponieważ nie ma w tym szczególnie zdradliwych przypadków.
To moje pierwsze wyzwanie, więc wszelka konstruktywna krytyka jest mile widziana :—). Jeśli uważasz, że wyjaśnienie teorii jest niechlujne, możesz zadawać pytania. Na koniec, proszę nie mów mi, że jest to dupe od tego czy tego . Upewniłem się, że tak nie jest. (Ta ostatnia jest dość podobna, ale bardziej złożona. Myślałem, że postawienie nieco prostszego wyzwania ułatwi ludziom przyłączenie się.)
1 : Starałem się maksymalnie uprościć to wyjaśnienie. Istnieje wiele teorii dotyczących interwałów. Proszę nie bić mnie za to, że to pominęłem.
APL (Dyalog) ,
6239 bajtówZastosowania
⎕IO←0
; 0 oznacza spółgłoskę, 1 jest dysonansem. Pobiera listę znaków nuty podstawowej jako lewy argument, a listę ostrych znaków jako prawy argument.Wypróbuj online!
{
…}
Anonimowa funkcja gdzie⍺
lewy argument i⍵
prawy argument⎕A[
...]∊'BCGKL'
jest lphabet, indeksowane przez następujących, członek ciąg?⍕#
sformatuj główną przestrzeń nazw (daje ostry znak)⍵=
czy odpowiednie znaki argumentów (śruty) są równe?(
…)+
Dodaj:'C D EF G A '⍳⍺
indeksy znaków lewego argumentu w ciągu-/
różnica między nimi|
całkowita wartośćźródło
MATL ,
302726 bajtówWprowadza dwie nuty w różnych wierszach. Wyjścia
0
dla spółgłoski,1
dla dysonansu.Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .
Wyjaśnienie
Ciąg 11 znaków
koduje zarówno nuty, jak i dysonansowe interwały w następujący sposób.
Program najpierw znajduje indeksy 1 znaków wejściowych w powyższym ciągu. Nieostre dane wejściowe
D
dadzą1
,E
dadzą3
, ...C
dadzą11
. Liczby te można również uznać za tablice numeryczne 1 × 1. Takie ostre wejścieC#
da tablicę 1 × 2[11 0]
, co oznacza, żeC
znaleziono ją w pozycji11
i#
nie znaleziono.Zauważ, że litery
JPIL
nigdy nie będą obecne na wejściu. Na razie są one używane tylko jako symbole zastępcze, tak że na przykład uwagaE
to dwa półtony powyżejD
. Przydadzą się jednak również do zdefiniowania dysonansowych interwałów.Liczby w pierwszym wpisie tablicy 1 × 1 lub 1 × 2 odpowiadają skokowi nut w półtonach, nie licząc ostrych symboli (jeszcze). Zauważ, że skala zdefiniowana przez te liczby nie zaczyna się od
C
; ale to nie ma znaczenia, ponieważ chcemy tylko interwałów, czyli różnic między nutami. Odjęcie uzyskanych liczb dałoby albo interwał, albo 12 minus interwał. Ale najpierw musimy wziąć pod uwagę ostry symbol.Aby rozważyć ostre nuty, golfowym sposobem (w MATL) jest dodanie
1
do każdego wpisu uzyskanej wcześniej tablicy 1 × 1 lub 1 × 2, a następnie zsumowanie tablicy (2 bajty). Tak więc nuty nieostre są zwiększane o,1
a nuty ostre o2
. To sprawia, że ostre nuty 1 półton są wyższe niż nuty nieostre, zgodnie z wymaganiami. Dodajemy również dodatkowy półton do wszystkich nut, ale to nie zmienia odstępów między nimi. Więc teraz nutaD
poda numer tonu2
,D#
da3
, ...C
da12
,C#
da13
.Dissonant interwały
1
,2
,6
,10
, lub11
. Mają one symetrię modulo-12 : przerwa między dwiema nutami jest dysonansowa wtedy i tylko wtedy, gdy interwał z nutami w odwrotnej kolejności, modulo 12, jest dysonansowy.Jeśli obliczymy kolejne różnice łańcucha
'DJEFPGIALBC'
, otrzymamy wektor numerycznyktóry zawiera dokładnie przedziały dysonansowe, oprócz niektórych wartości ujemnych, które nie będą ani użyteczne, ani szkodliwe. Zauważ, że wybór dodatkowych liter
JPIL
w ciągu'DJEFPGIALBC'
określa (poprzez kolejne różnice) interwały dysonansowe.Aby sprawdzić, czy dwie nuty wejściowe są dysonansowe, bierzemy bezwzględną różnicę ich liczb wysokości. Na przykład
C
iD#
poda odpowiednio liczby12
i3
, a absolutna różnica wynosi9
. Rzeczywista różnica byłaby-9
, a rzeczywisty przedział byłby3
(uzyskany jako-9
modulo 12). Ale dzięki symetrii, o której mowa powyżej, możemy rozważyć9
zamiast3
. Ponieważ9
nuty nie występują w wektorze kolejnych różnic, nuty są spójne.źródło
JavaScript (ES6),
6864 bajtówZapisuje nuty jako dwa ciągi w składni curry
(a)(b)
. Zwraca0
za dysonans lub1
spółgłoskę.Przypadki testowe
Pokaż fragment kodu
Sformatowane i skomentowane
źródło
Galaretka , 26 bajtów
Monadyczny link pobierający listę dwóch notatek (jako listy znaków) i powracający
0
spółgłoskę i1
dysonans.Wypróbuj online! lub zobacz wszystkie dane wejściowe w pakiecie testowym .
W jaki sposób?
źródło
Galaretka , 31 bajtów
Wypróbuj online!
wheeeeee 32 bajty za długie
Wyjaśnienie
źródło
"G#", "A"
(dysonans) daje różnicę,11
której nie ma[1,2,6]
.Mathematica, 55 bajtów
Odwzoruj wewnętrzne wbudowane
Sound`PitchToNumber
wejście (lista dwóch ciągów), weź absolutną różnicę, a następnie dopasuj wzór dla dysonansowych liczb interwałów.Dla zabawy (niekonkurencyjny)
Oto kilka krótszych funkcji, które naruszają ograniczenie „nie możesz przypisywać żadnych innych nazw nutom”. Podstawowy
Music`
pakiet ma predefiniowane stałe nut (jakA4 = 440.
) i funkcjęHertzToCents
(którą można grać w golfa). Zamiast łańcuchów użyjemy stałych notatek jako argumentów, ale podanych w innym formacie dla każdej funkcji.Import pakietu
<<Music`;
zajmuje 9 bajtów.Ta funkcja przekształca ciąg znaków (jak
"F#"
) w stałą nutową (jakFsharp3
):Aby zaakceptować odstępach większych niż oktawę, wymienić
Abs[…]
zMod[…,12]
.Dlaczego niektóre interwały są uważane za dysonansowe? Interwał to stosunek dwóch częstotliwości. Jeśli stosunek ma „prosty” licznik i mianownik, jest on bardziej spójny. W 5-limitowym strojeniu stosunki można rozdzielić na liczby całkowite tylko liczb pierwszych mniejszych lub równych 5. Żaden przedział w równym temperamencie, oprócz oktawy, nie jest tylko przedziałem ; są one jedynie bliskimi przybliżeniami przy użyciu mocy 12. pierwiastka z 2.
Zamiast twardego kodowania, które liczby przedziałów są dysonansowe, możemy znaleźć racjonalne przybliżenie przedziału, a następnie ustalić, czy jego licznik i mianownik są „proste” (co oznacza, że mianownik jest mniejszy niż 5, a stosunek nie dzieli 7).
Ta tabela pokazuje każdy z etapów tego procesu.
Racjonalne przybliżenie leży w
1/17
przedziale, ponieważ jest to największy próg, który rozróżnia wszystkie 12 równych temperowanych interwałów. Najpierw dopasowujemy liczby wymierne do wzorcaRational[a_,b_]
(lub tylkoa_~_~b_
), a następnie dopasowujemy tylko liczby całkowite_
.Kulminuje to następująca raczej krótka funkcja, która określa, czy arbitralny stosunek częstotliwości (większy niż 1) jest spółgłoskowy czy dysonansowy.
źródło
Mathematica, 118 bajtów
Formularz wejściowy
Wyjścia
dzięki @JonathanFrech -16 bajtów
źródło
Consonant
iDissonant
. Zamiast nich możesz wypisać dowolne dwie wartości (0/1, ... cokolwiek). To może zaoszczędzić trochę bajtów.If[...,0,1]
i zdefiniowaćTrue->Consonant; False->Dissonant
?StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]
- 42 bajtów{1,2,6,10,11}
je1|2|6|10|11
Węgiel drzewny , 30 bajtów
Wypróbuj online! Link jest do pełnej wersji kodu. Wyjścia 1 dla spółgłoski, 0 dla dysonansu. Wyjaśnienie:
źródło
⌕ζ
jest używany do „znajdowania indeksu”?ζ
jest zmienną przypisaną wcześniej.J, 68 bajtów
wyjaśnienie
Prosta, niezbyt golfowa implementacja w J:
Dane wejściowe są podawane w postaci notatek w pudełkach (wytworzonych przy użyciu cięcia), w kolejności.
Znajdź ich indeksy w zakresie notatek:
(<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]
Odejmij pierwszy od drugiego:
-~/
Resztę podziel po podzieleniu przez 12:
12|
Sprawdź, czy jest to jedna z dysonansowych notatek:
e.&1 2 6 10 11
Wypróbuj online!
źródło
/// ,
9088 bajtówWypróbuj online! (wszystkie przypadki testowe jednocześnie)
,B#
w każdym przypadku testowym.,
dla spółgłoski,,#
dla dysonansu.##
) lubE#
w niektórych szczególnych przypadkach. W przeciwnym razie dane wyjściowe są,
dla spółgłoski,#,
dla dysonansu (dzięki symetrii modulo 12)źródło
C (gcc) , 91 bajtów
połączenie:
f("A#", "D")
Zwracana wartość:
Bonus: funkcja nie rozróżnia wielkości liter.
Wypróbuj online!
źródło
return (
s nie ma dwóch niepotrzebnych miejsc ?g(char*s){s=(s[1]&1|2**s&15)*4/5;}f(char*x,char*y){x=1952220<<g(x)>>g(y)&2048;}
i fajne rozwiązanie!Python 2,
125 117 83 7877 bajtówGdzie
""
na końcu faktycznie znajdują się postacie"\x02\x04\x0c\x14\x16"
Wypróbuj online!
(+3, ponieważ na początku zapomniałem 11 lub 22)
-8 bajtów od Jonathana Frecha i przejście na Python 2 .
-34 bajty z sugestiami Jonathana Frecha i użyciem
str
indeksu zamiastlist
.-4 bajty z inliningu
i
i Neil odwraca sugestię ciągu znaków (tylko -2 tak naprawdę, jak zapomniałem()
o generatorze)-5 bajtów od cofania
i
i zmiany formatu wejściowego-1 bajty od Jonathana Frecha zi bez
map()
nadruku.Pobiera dane wejściowe w jednym wierszu standardowego formatu:
True
jest dysonansowy,False
jest spółgłoskowy.Stare objaśnienie:
Python
str.index
zwraca najniższy (dodatni) indeks początkowy pasującego podciągu,"ABACABA".index("A") == 0
a więc i"ABACABA".index("BA") == 1
. Z tego powodu możemy umieścić nazwy nut równomiernie rozmieszczone w łańcuchu i dopóki (na przykład)A
pojawi się wcześniejA#
, udostępnianieA
nie będzie stanowiło problemu.i
jest teraz funkcją, która zwraca indeks w'C C#D D#E F F#G G#A A#B'
argumencie (nazwa nuty), który wynosi 2 * (liczba półtonów, od której nuta jest wyższaC
)Python 2
input()
jest (przeważnie) równoważny zeval(input())
Python3, więc z poprawnym wejściem formatu'C#','F'
(na przykład)a='C#'
ib='F'
Jeśli odległość między pierwszą nutą a drugą nutą w ciągu nie jest równa 2, 4, 12 lub 20 (ponieważ nazwy nut są reprezentowane przez 2 znaki), wówczas interwał jest dysonansowy, drukuj True, w przeciwnym razie jest zgodny, wydrukuj False.
źródło
eval(input())
(13 bajtów) zamiastinput().split()
(15 bajtów).
) zamiast ciągu pustego.C (gcc) , 115
117120bajtyWypróbuj online!
Zwraca 1/0 dla spółgłosek i dyssonatów. Zawsze interesujące jest wykonywanie operacji na łańcuchach za pomocą czystego C. Weź dane jako
f("A#", "C")
źródło
PowerShell , 107 bajtów
Wypróbuj online!
Wyjścia
True
dla dyssonantu iFalse
dla spółgłoski.Pobiera dane wejściowe
$a
i$b
dwie notatki jako ciągi znaków. Wykonuje-split
operację na skali, która dzieli się na białe znaki, aby utworzyć tablicę notatek, przechowuje ją w$x
. Znajduje.indexof
$b
w tej tablicy, odejmuje indeks$a
, a następnie przyjmujeabs
jego wartość olute. Sprawdza, czy ta liczba jest-in
dysonansowymi zakresami.źródło
Python 2 , 68 bajtów
Wypróbuj online!
Wyjścia:
1
dysonans,0
spółgłoska.źródło
SQL, 582 bajty
SQL Fiddle
Nadal mam trochę do zrobienia w golfa, ale chciałem go tu zabrać, zanim całkowicie go zniszczę.
Jeśli dane wejściowe są w formacie literowym, to umieszczenie tych liter w tabeli z wartościami jest w porządku, prawda?
źródło
Perl 5 , 106 bajtów
Wypróbuj online!
Zwraca false dla dysonansu, true dla spółgłoski.
źródło