ハーモニカの演奏を手伝って


8

昨日、私はハーモニカを買いました:

私のハーモニカ 図1:ハーモニカ。

しかし、人々を感動させ、大人になった男性を泣かせてしまうソウルフルブルースハーモニカを演奏できるという私の夢は、次の2つの問題にすぐに打ちのめされました。

  1. ハーモニカは特定のノートのみを再生できます。
  2. 私はハーモニカを弾くのがうんざりです。

ハーモニカのスキルが不足しているにもかかわらず、私が演奏できる曲はまだいくつかあります。しかし、ハーモニカでいくつかの曲を演奏できるかどうかはすぐにはわかりません。音楽の音符を考慮して、ハーモニカで演奏できるかどうかを判断するプログラムを作成します。

上の写真が示すように、私のハーモニカには10個の穴があります。それぞれの穴で、息を吸い込んだり吸い込んだりすることができます-私が選択した穴と、それに吸い込むか吐き出すかによって、結果の音のピッチが変わります。吐き出すときと吸い込むときのピッチは穴ごとに異なりますが、同じ音符になる組み合わせもあります。全体として、私のハーモニカは19の異なるピッチを演奏できます。ピッチは音楽の科学表記法で表示されます。文字は音符を表し、数字はそのオクターブを表します。

 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    

たとえば、3番ホールで息を吐いた場合、G4メモが表示されます。2番ホールを吸い込んだ場合、メモ取得しG4ます。7ホール目で息を吐くと、C6

ハーモニカに息を吹き込むときは、息を吐いたり吸い込んだりする以外に、息を細くする広くするかを選択することもできます。薄く呼吸すると、1つの穴だけが鳴りますが、広く呼吸すると、その穴の両側にある1つの穴と両方の穴が鳴ります。私は2つの穴を吹き飛ばすためのアンブシュアスキルがありません-1つまたは3つです。

たとえば、4番の穴に細く息を吐くと、4番の穴だけが鳴るので、C5の音がします。4ホールに大きく息を吐くと、3、4、および5ホールが鳴り、G4、C5、E5のコードが得られます。4番ホールを広く吸入すると、3、4、5番ホールが鳴りますが、代わりにピッチを吸入し、B4、D5、F5の和音を生成します。どちらかの端の穴については、私がそれらに大きく息を吹き込んだ場合、2つの穴だけが聞こえることに注意してください(穴0または穴11がないため)。

しかし、私は同時に吸ったり吐いたりすることはできません。たとえば、4、5、6番のホールに息を吹きかけて、C5、E5、G5のノートを同時に鳴らし、コードを形成することができます。ただし、同時に吸い込むことも吐くこともできないので、C5、F5、A5のコードを演奏するのは不可能です。これはまだ明確ではありませんが、このコメントスレッドは役に立つかもしれません。

入力は音楽の音符です。メモは、表の上部と同じように表記され、カンマで区切られています。中括弧で囲まれた音符は和音を表します。例えば:

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

これは、「C4、D4、G4、D5、F5、A5が同時に、B5が同時に」という意味です。True私のハーモニカで音楽を演奏できる場合は、プログラムはこの形式の文字列を入出力として受け取りFalseます。入力と出力のサンプルについては、上記の例ではを出力する必要がありますTrue{C5,F5,A5}一方、入力は出力されますFalse

これはコードゴルフなので、最短のエントリーが勝ちます。

ここにいくつかのテストケースがあります:

入力(ACメジャースケール):

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

出力:

False

(ハーモニカはF4またはA4を演奏できないため)

入力(Let It Goの最初の 2小節):

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

出力:

True

入力:

{E6,G6,F6}

出力:

False

入力:

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

出力:

True

あなたはコードが低いピッチから高いピッチの順番で来ると仮定するかもしれません。


2
ノートからノートへ移動しながら、吐き出しと吸い込みを交互に行う必要がありますか?
COTO 2014

1
@COTOいいえ。私には無制限の呼吸能力があると仮定します。
2014

参照されているコメントスレッドリンクが機能しません。これは私にとってはうまくいき
ardnew

使用できるテストケースのセットはありますか?
14

4
ブルーシャープ(リヒターチューンドハーモニカ)は演奏できますが、ブルースのみを演奏します。C6がB5に下がっているホール7は奇妙に見えますが、正しいです。解決策は2つあります:チューニングの異なるより高度なハーモニカを購入するか、ノートを曲げることを学びます(曲げることができる場合でも、すべてのノートを再生することはできませんが、ハウリングブルースを再生して欲求不満を表現できます) 。)1つか3つのノートしか演奏できないというルールはかなり正確です。以下は、リヒターチューニングの優れた表現です:en.wikipedia.org/wiki/Richter-tuned_harmonica。さまざまなキーのセクションも音楽的に興味深い
Level River St

回答:


2

Python- 218 209 189文字

最小:

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

読みやすくするために:

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

問題の説明のようにフォーマットされた文字列が与えられた場合、シーケンスが説明されたハーモニカで再生可能であるかどうかをt返します。TrueFalse

コード内の音符の順序はチェックされません。特に断りのない限り、問題の説明には含まれていないため、これで十分だと思います。指定されたすべてのテストに合格します。

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}")

たくさんのスペースを削除できます:] if "".join(x) not-> ]if"".join(x)notキーワードは文字列に隣接することができるので"and"正しいです。
Bakuriu 2014

ここで最初のコードゴルフなので、何かが足りないと思った。ありがとう!
Poik

1

JavaScript- 245 243文字

縮小:

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

そして拡張:

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

この関数pは文字列を入力として受け入れTrue、音符/和音シーケンスが再生可能であるFalse場合は戻り、そうでない場合は戻ります。入力が構文的に有効でない場合は、未定義の結果を返します。

また、コード例はホールの昇順で入力されていると大胆に想定しています(例のように)。

関数は論理返すことが許されている場合、文字カウントが14によって減少させることができるtruefalseその文字列同等ではなく。


1

JavaScript(ES6)、230

@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'}

私がES6を学び始めているので、これをさらにゴルフするためのヒントに感謝します!:-)


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 ","}=="")

未ゴルフ:

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?
)

不正な入力は正しく処理されないことに注意してください。任意の文字列が受け入れられ、多くの不正な文字列はtrueを返します。次に例を示します。

{C,7.D}.C

trueを出力します。


1

リボル-188

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

未ゴルフ:

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 "}"
        ]
    ]
]

使用例(Rebolコンソールで):

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

このコードは次のような意味不明なものをキャッチしますが、

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

ただし、次のようなことが可能になります。

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

「C4、D4」として解析するためです。

次に、より厳密なバージョンのコードを示します。

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

これは228文字になり、今では戻りますfalse...

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

1

JavaScriptのES6、211 209 190の文字

私はこれがさらにゴルフできることを知っています。私は数時間でそうしようとします。

このコードを最新のFirefoxのWebコンソールで実行すると、という名前のメソッドを取得できます。このメソッドCは、次のように呼び出すことができC("{G4,C5,E5},{F5,A5,B5}")、それによって、TrueまたはFalseそれに応じて戻ります。

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

構文的に有効な入力を想定しています。

編集:正規表現と長さのチェックを簡略化しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.