Hilf mir, meine Mundharmonika zu spielen

8

Gestern habe ich eine Mundharmonika gekauft:

meine Mundharmonika Abbildung 1: Die Mundharmonika.

Meine Träume, seelenvolle Blues-Mundharmonika spielen zu können, die Menschen bewegt und einen erwachsenen Mann zum Weinen bringt, wurden jedoch schnell von zwei Problemen zunichte gemacht:

  1. Die Mundharmonika kann nur bestimmte Noten spielen;
  2. Ich bin deprimierend schlecht darin, Mundharmonika zu spielen.

Trotz meiner mangelnden Fähigkeiten in der Mundharmonika gibt es immer noch einige Songs, die ich darauf spielen kann. Es ist jedoch nicht sofort ersichtlich, ob ich ein Musikstück auf der Mundharmonika spielen kann oder nicht. Schreiben Sie anhand der Noten eines Musikstücks ein Programm, um festzustellen, ob ich es auf meiner Mundharmonika spielen kann oder nicht.

Wie das obige Bild zeigt, hat meine Mundharmonika zehn Löcher. Mit jedem Loch kann ich entweder einatmen oder einatmen - das Loch, das ich wähle, und ob ich einatme oder ausatme, ändert die Tonhöhe des resultierenden Klangs. Jedes Loch hat beim Ausatmen und Einatmen eine andere Tonhöhe, aber es gibt einige Kombinationen, die zur gleichen Note führen. Insgesamt kann meine Mundharmonika 19 verschiedene Tonhöhen spielen. Die Tonhöhen werden in musikalischer Notation dargestellt - der Buchstabe steht für die Note und die Zahl für die Oktave.

 Hole   Breathing   Note  
 1      Exhale      C4    
 1      Inhale      D4    
 2      Exhale      E4    
 2      Inhale      G4    
 3      Exhale      G4
 3      Inhale      B4
 4      Exhale      C5    
 4      Inhale      D5    
 5      Exhale      E5    
 5      Inhale      F5    
 6      Exhale      G5    
 6      Inhale      A5    
 7      Exhale      C6    
 7      Inhale      B5    
 8      Exhale      E6    
 8      Inhale      D6    
 9      Exhale      G6    
 9      Inhale      F6    
 10     Exhale      C7    
 10     Inhale      A6    

Wenn ich zum Beispiel bei Loch 3 ausatme, bekomme ich eine G4Notiz. Wenn ich auf Loch 2 einatme, bekomme ich auch eine G4Notiz. Wenn ich bei Loch 7 ausatme, bekomme ich eine C6.

Wenn ich in die Mundharmonika einatme, kann ich neben dem Ausatmen oder Einatmen auch wählen, ob ich dünn oder weit atmen möchte . Durch dünnes Atmen ertönt nur ein Loch, während durch weites Atmen ein Loch und beide Löcher auf beiden Seiten dieses Lochs ertönen. Ich habe nicht die Fähigkeit, auf zwei Löcher zu blasen - es ist entweder eines oder drei.

Wenn ich zum Beispiel dünn auf Loch 4 ausatme, klingt nur Loch 4, sodass ich einen C5-Sound bekomme. Wenn ich weit auf Loch 4 ausatme, klingen die Löcher 3, 4 und 5 und ich bekomme einen G4-, C5-, E5-Akkord. Wenn ich weit in Loch 4 einatme, klingen die Löcher 3, 4 und 5, aber sie spielen stattdessen die Einatmungstöne, was zu einem B4-, D5-, F5-Akkord führt. Beachten Sie, dass für die Löcher an beiden Enden, wenn ich sie weit einatme, nur zwei Löcher ertönen würden (da es kein Loch 0 oder Loch 11 gibt).

Ich kann jedoch nicht gleichzeitig ein- und ausatmen. Zum Beispiel könnte ich in die Löcher 4, 5 und 6 ausatmen, damit die Noten C5, E5 und G5 gleichzeitig klingen und einen Akkord bilden. Ich kann jedoch nicht gleichzeitig ein- und ausatmen, so dass ich den Akkord C5, F5, A5 nicht spielen kann, da ich in Loch 4 irgendwie ausatmen und in Loch 5 und 6 einatmen müsste Dies ist noch unklar, dieser Kommentarthread könnte nützlich sein.

Die Eingabe sind die Noten der Musik. Die Noten werden auf die gleiche Weise notiert wie oben in der Tabelle und durch Kommas getrennt. Noten in geschweiften Klammern stehen für einen Akkord. Zum Beispiel:

C4,D4,G4,{D5,F5,A5},B5

Dies bedeutet: "C4, dann D4, dann G4, dann D5, F5 und A5 gleichzeitig, dann B5." Ihr Programm verwendet eine Zeichenfolge in diesem Format als Eingabe und Ausgabe, Truewenn ich die Musik auf meiner Mundharmonika oder auf Falseandere Weise abspielen kann. Für Beispiel-Ein- und Ausgänge sollte das obige Beispiel ausgegeben werden True. Der Eingang {C5,F5,A5}hingegen wird ausgegeben False.

Dies ist Code Golf, also gewinnt der kürzeste Eintrag.

Hier einige Testfälle:

Eingang (AC-Dur-Skala):

C4,D4,E4,F4,G4,A4,B4,C5

Ausgabe:

False

(weil die Mundharmonika F4 oder A4 nicht spielen kann)

Eingabe (die ersten 2 Takte von Let It Go ):

E6,F6,A5,E6,F6,F6,E6,A5,F6,E6

Ausgabe:

True

Eingang:

{E6,G6,F6}

Ausgabe:

False

Eingang:

{G4,C5,E5},{F5,A5,B5}

Ausgabe:

True

Sie können davon ausgehen, dass die Akkorde in einer niedrigeren bis höheren Tonhöhe vorliegen.

Absinth
quelle
2
Müssen Sie abwechselnd ausatmen und einatmen, um sich von Note zu Note zu bewegen?
COTO
1
@COTO Nein. Angenommen, ich habe eine unendliche Atemkapazität.
Absinth
Der Link zum referenzierten Kommentarthread funktioniert bei mir nicht. Das funktioniert bei mir: meta.codegolf.stackexchange.com/a/2149/3348
ardnew
Haben Sie eine Reihe von Testfällen, die wir verwenden können?
Neu
4
Ich kann Bluesharp spielen (Richter gestimmte Mundharmonika), aber ich spiele nur Blues darauf. Loch 7 mit C6 nach B5 sieht seltsam aus, ist aber korrekt. Sie haben zwei Lösungen: Kaufen Sie eine fortgeschrittenere Mundharmonika mit unterschiedlicher Stimmung oder lernen Sie, die Noten zu biegen (wenn Sie biegen können, können Sie NOCH nicht alle Noten spielen, aber Sie können einen heulenden Blues spielen, um Ihre Frustration auszudrücken .) Die Regel, nur 1 oder 3 Noten spielen zu dürfen, ist ziemlich genau. Hier ist eine schöne Darstellung der Richter-Stimmung: en.wikipedia.org/wiki/Richter-tuned_harmonica . Abschnitt über verschiedene Tonarten ist auch musikalisch interessant
Level River St

Antworten:

2

Python - 218 209 189 Zeichen

Minimal:

def t(s):from re import sub as r;exec('l=bool([x for x in['+r('"{','("',r('}"','")',r(',','","','"'+s+'"')))+']if"".join(x)not in"C4E4G4C5E5G5C6E6G6C7|D4G4B4D5F5A5B5D6F6A6"])');return not l

Zum leichteren Lesen:

def t(s):
    from re import sub as r
    exec('l=bool([x for x in'
         ' [' + r( '"{' , '("' ,
                  r( '}"' , '")' , 
                    r( ',' , '","' , '"' + s + '"' ))) +
         ']'
         ' if "".join(x) not in "C4E4G4C5E5G5C6E6G6C7|D4G4B4D5F5A5B5D6F6A6"])')
    return not l

Geben Sie bei einer Zeichenfolge, die wie in der Problembeschreibung formatiert ist, tzurück, Truewenn die Sequenz auf der beschriebenen Mundharmonika spielbar Falseist und nicht.

Die Reihenfolge der Noten in den Akkorden wird nicht überprüft. Sofern nicht anders angegeben, halte ich dies für ausreichend, da dies nicht in der Problemstellung enthalten ist und alle angegebenen Tests bestanden werden in:

assert not t("C4,D4,E4,F4,G4,A4,B4,C5")
assert t("E6,F6,A5,E6,F6,F6,E6,A5,F6,E6")
assert not t("{E6,G6,F6}")
assert t("{G4,C5,E5},{F5,A5,B5}")
Poik
quelle
Sie können viele Leerzeichen entfernen: ] if "".join(x) not-> ]if"".join(x)notSchlüsselwörter können neben Zeichenfolgen stehen, "and"ist also korrekt.
Bakuriu
Erster Code Golf hier, also dachte ich, ich hätte etwas vermisst. Vielen Dank!
Poik
1

Javascript - 245 243 Zeichen

Minimiert:

function p(s){function f(s){s=s.replace(/\W/g,'');l=s.length;return((l-6)*(l-2)?l-4?'':'C4E4 G6C7 D4G4 F6A6':'C4E4G4C5E5G5C6E6G6C7 D4G4B4D5F5A5B5D6F6A6').indexOf(s)<0?0:''}return s.replace(/{.*?}/g,f).split(',').map(f).join('')?'False':'True'}

Und erweitert:

function p(s) {
    function f(s) {
        s = s.replace( /\W/g, '' );
        l = s.length;
        return ( (l-6)*(l-2) ? ( (l-4) ? '' : 'C4E4 G6C7 D4G4 F6A6' ) : 'C4E4G4C5E5G5C6E6G6C7 D4G4B4D5F5A5B5D6F6A6' ).
            indexOf( s ) < 0 ? 0 : ''
    }
    return s.replace( /{.*?}/g, f ).split( ',' ).map( f ).join( '' ) ? 'False' : 'True'
}

Die Funktion pakzeptiert eine Zeichenfolge als Eingabe und kehrt zurück, Truewenn die Noten- / Akkordfolge Falseansonsten spielbar ist . Es gibt undefinierte Ergebnisse zurück, wenn die Eingabe syntaktisch nicht gültig ist.

Es wird auch mutig davon ausgegangen, dass Akkordnoten in der Reihenfolge des aufsteigenden Lochs eingegeben werden (wie im Beispiel).

Die Anzahl der Zeichen kann um 14 verringert werden, wenn die Funktion logische trueund falsenicht ihre Zeichenfolgenäquivalente zurückgeben darf .

COTO
quelle
1

JavaScript (ES6), 230

Nur eine umgeschriebene Version der Antwort von @ COTO:

f=s=>{s=s.replace(/\W/g,'');l=s.length;return((l-6)*(l-2)?(l-4?'':'C4E4 G6C7 D4G4 F6A6'):'C4E4G4C5E5G5C6E6G6C7 D4G4B4D5F5A5B5D6F6A6').indexOf(s)<0?0:''};p=s=>{return s.replace(/{.*?}/g,f).split(',').map(f).join('')?'False':'True'}

Würde mich über Tipps zum Golfen freuen, wenn ich anfange, ES6 zu lernen! :-)

rink.attendant.6
quelle
1

Scala 178

print(readLine./:(""){(a,c)=>if("..C4E4G4C5E5G5C6E6G6C7...D4G4B4D5F5A5B5D6F6A6...."sliding(6)flatMap(y=>Seq("{"+y.diff("..")+"}",y take 2))contains a+c)""else a+c diff ","}=="")

Ungolfed:

print(
  readLine.foldLeft(""){(a,c)=>                             # loop through the input
    if("..C4E4G4C5E5G5C6E6G6C7...D4G4B4D5F5A5B5D6F6A6...."  # from the harmonica
      .sliding(6)                                     # take 6 at a time
      .flatMap(y=>Seq("{"+y.diff("..")+"}",y take 2)) # chords + single notes     
      .contains(a+c)) ""                              # clear matches
    else a+c diff ","                                 # drop commas
  }==""                                               # did everything match?
)

Beachten Sie, dass fehlerhafte Eingaben schlecht behandelt werden - jede Zeichenfolge wird akzeptiert und viele fehlerhafte Zeichenfolgen geben true zurück, zum Beispiel:

{C,7.D}.C

druckt wahr.

Paradigmensort
quelle
1

Rebol - 188

t: func[s][trim/with s ","h: next split n:"C4E4G4C5E5G5C6E6G6C7..D4G4B4D5F5A5B5D6F6A6"2 forskip h 2[i

Ungolfed:

t: func [s] [
    trim/with s ","
    h: next split n: "C4E4G4C5E5G5C6E6G6C7..D4G4B4D5F5A5B5D6F6A6" 2
    forskip h 2 [insert h '|]
    h: head h

    parse s [
        any [
            h | "{" x: copy c to "}" (unless find n c [c: n])
            :x c "}"
        ]
    ]
]

Anwendungsbeispiel (in der Rebol-Konsole):

>> t "C4,D4,G4,{D5,F5,A5},B5"
== true

>> t "{C5,F5,A5}"
== false

>> t "C4,D4,E4,F4,G4,A4,B4,C5"
== false

>> t "E6,F6,A5,E6,F6,F6,E6,A5,F6,E6"
== true

>> t "{E6,G6,F6}"
== false

>> t "{G4,C5,E5},{F5,A5,B5}"
== true

Während dieser Code Kauderwelsch wie folgt fängt:

>> t "{C,7.D}.C"
== false

Es wird jedoch solche Dinge ermöglichen durch:

>> t "C,4,D4"
== true

Weil es es als "C4, D4" analysiert.

Hier ist eine strengere Version des Codes:

t: func [s] [
    h: next split n: "C4E4G4C5E5G5C6E6G6C7..D4G4B4D5F5A5B5D6F6A6" 2
    forskip h 2 [insert h '|]
    h: head h
    d: ["," | end]

    parse s [
      any [
            [
                h | "{" x: copy c to "}" (
                    unless all [
                        parse c [any [h d]]
                        find n trim/with copy c ","
                    ] [c: n]
                )
                :x c "}"
            ]
            d
      ]
    ]
]

Dies spielt bis zu 228 Zeichen und kehrt jetzt falseauf ...

>> t "C,4,D4"
== false
draegtun
quelle
1

JavaScript ES6, 211 209 190 Zeichen

Ich weiß, dass dies weiter gespielt werden kann. Ich werde es in ein paar Stunden versuchen;

Führen Sie diesen Code in der Webkonsole von Latest Firefox aus. Sie erhalten eine Methode mit dem Namen, Cdie Sie wie C("{G4,C5,E5},{F5,A5,B5}")folgt aufrufen können, und sie wird zurückgegeben Trueoder Falseentsprechend.

C=n=>(s='D4G4D5F5A5B5D6F6A6,C4E4G4C5E5G5C6E6G6C7',n.split(/[,}{]/g).some(a=>a&&!~s.search(a))||(m=n.match(/{[^}]+/g))&&m.some(a=>a.length!=9|!~s.search(a.replace(/{|,/g,"")))?'False':'True')

Ich gehe von einer syntaktisch gültigen Eingabe aus.

BEARBEITEN : Vereinfachung des regulären Ausdrucks und der Längenprüfung.

Optimierer
quelle