シンコペーションを見つける


33

q四分音符をe表すsと8 分音符を表すs のみで構成される文字列の入力が与えられると、シンコペーションされる四分音符のインデックスを出力します。

シンコペーションは複雑ですが、この課題のために、「シンコペート」の定義は非常に単純です。つまり、「オフビート」で始まる4分音符、つまりn / 4で「and」としてカウントされるビートです。時間。

あるいは、奇数の8分音符が先行する4分音符として定義することもできます。たとえば、*以下のマークが付いたノートはシンコペートされていると見なされ、そのインデックスも表示されます。

eqqeqqeqqe
 **    **
 12    78
Output: 1 2 7 8

入力は、常に4/4時間の整数の小節から構成されます(4分音符は1小節の4分の1、8分音符は1小節の8分の1)。(入力も空になることはありません。)出力は、数字を含まない区切り文字または配列/リスト/などで区切られた要素を持つ単一の文字列にすることができます。出力は、必要に応じて1から始まる(つまり、最初のインデックスが0ではなく1)場合があり、任意の数値ベース(単項、十進など)になる場合もあります。

これはであるため、バイト単位の最短コードが優先されます。

テストケース:

In                        Out
-----------------------------------------------
eqqqe                     1 2 3
qeqeq                     2
qqqeqqeeeeqeqeqeqqeqqeqq  4 5 10 14 19 20
eeeeeqeeqeeqqqqeqeqeeqe   5 8 11 12 13 14 18 21
qqqq                      <none>
eeeeeeee                  <none>

1
出力は1から始まりますか?
ルイスメンドー

1
インデックスがどのように機能するかを示すために、実際の例を実行できますか
ピーターテイラー

1
@LuisMendo確かに、コードが短くなる場合。
ドアノブ

@PeterTaylorさて、あなたが考えていたのはそのようなものですか?
ドアノブ

入力は引用符を含む文字列にすることができますか?'eqqqe'代わりにeqqqe
ルイスメンドー

回答:


12

ゼリー12 9 バイト

=“e”µ<^\O

プログラムとして、上記のコードでは入力を引用符で囲む必要があります。それは許可されていないため、これは関数の送信です。出力は1ベースです。オンラインでお試しください!

使い方

=“e”µ<^\O    Monadic link. Argument: s (string)

=“e”         Check each character for equality with 'e'. Yields a Boolean array.
    µ        Start a new, monadic chain.
      ^\     Compute the array of partial reductions by XOR, i. e., the parities
             of all prefixes of the Boolean array.
     <       Check if the Booleans are strictly smaller than the parities.
             A truthy outcome indicates an off-beat quarter note.
        O    Yield all indices of 1's.

更新

上記のコードは、我々が必要とするので、ゼリーの最新バージョンでもう動作しない文字 Eを、しかし“e”、文字列を生成します。1バイトを節約する修正(合計8バイト)

=”eµ<^\O

これは完全なプログラムとして機能します。オンラインでお試しください!


7

ルビー、46

i=e=0
gets.bytes{|n|e^=n
e&4|n>114&&p(i)
i+=1}

stdinへの入力。改行で区切られた標準出力への出力。

コメント済み

i=e=0               #i keeps index, e keeps track of 8ths.
gets.bytes{|n|      #iterate through bytes in the input
e^=n                #xor e with input. We're interested in the 4's bit, which is only affected by ascii e, not ascii q
e&4|n>114&&p(i)     #e&4 evaluates to 4 or 0. OR with n and if the value is greater than ascii code for q, print index
i+=1}               #increment index

6

JavaScriptのES7、50の 48バイト

あなたが私に尋ねるなら、JSのかなり短い。[for...of]基本的にマップとフィルターを組み合わせた構文は、この課題に役立ちます。

s=>[for(c of(i=f=0,s))if(++i&&c>'e'?f%2:f++&0)i]

1インデックス配列を出力する匿名関数を定義します。

テストスニペット

これは、ES7化されていないコードのバージョンではありません。

a = function(s) {   // Create a function a that takes in a parameter s and does these things:
  var r = [],       // Set variable r to an empty array,
  i = 0, f = 0;     // i to 0, and f to 0.
  for(c of s) {     // For each character c in s:
    i++;            //  Increment i by 1.
    if(             //  If
      c == 'q' ?    //   if c == 'q',
      f%2 === 1 :   //    f is even; otherwise,
      f++ && false) //    increment f and don't execute this:
      r.push(i);    //   Add i to the end of r.
  } return r;       // Return r.
}
<input type="text" value="eqqqe" id=O />
<button onclick="P.innerHTML='['+a(O.value)+']'">Try it</button>
<p id=P />


3
非常に良い説明!そしてまた、[のために...の]👍ES7の新しい使用方法の良い例
Aᴄʜᴇʀᴏɴғᴀɪʟ

それでは、「ECMAScript 7でのゴルフのヒント」という新しい質問が必要ですか?
ニール

@Neil私はES6ポストをES6 / 7に更新しようとしましたが、OPは編集をロールバックしました。それまでの間、これがあります:codegolf.stackexchange.com/a/61489/42545
ETHproductions

5

J、20 19 17バイト

=&'e'(I.@:<~:/\@)

バイトを保存してくれたrandomraと、2個保存してくれたDennisに感謝します。これは、次のように使用される名前のない単項動詞です。

  f =: =&'e'(I.@:<~:/\@)
  f 'eqqqe'
1 2 3

ここで試してみてください。

説明

=&'e'(I.@:<~:/\@)
=&'e'               Replace every 'e' with 1, other chars with 0
     (         @)   Apply the verb in parentheses to the resulting 0-1 vector
           ~:/\     Cumulative reduce with XOR (parity of 'e'-chars to the left)
          <         Element-wise less-than with original vector
      I.@:          Positions of 1s in that vector

5

GNU grep、 3 + 17 = 20 3 + 15 = 18バイト

プログラムにはオプションが必要boPです。コードは

q(?!(q|eq*e)*$)

として保存し、としてsynco実行しgrep -boPf syncoます。

出力セパレーターの:q後に改行が続きます。たとえば、の出力eqqqe

1:q
2:q
3:q

フラグの意味は次のとおりです。

  • P:PCRE正規表現を使用します。
  • o:これは、正規表現に一致する行の部分のみを印刷することを意味しますが、それが重要な理由ではありません。 o行ごとに複数の一致を許可する効果があるため、
  • b:ファイルの先頭から各一致の先頭のオフセットをバイト単位で出力します。

このパターンでは、4分音符の後に偶数の8分音符がないことを確認します。


ないgrep独自の権利で言語としての資格?とにかく、素晴らしい答えを得るために+1
デジタルトラウマ

@DigitalTraumaなぜそうなのかわかりません... PCRE正規表現を使用できるため、少なくともチューリング完全である必要があり、ここに示すようにファイルからコードを実行できます。
feersum

私がいた印象で PCREはチューリング完全であることが証明されていないこと。とにかく、あなたの表現は要件を満たしているので、私はそれで問題ありませんが、理論的な理由で不満を持つ他の人がいるかもしれません。
デジタル外傷

@DigitalTrauma Huh、私はチューリング完全性の事について妄想していたようです。
feersum

5

MATL、12 14 16バイト

j101=tYs2\<f

2バイトを削除してくれたDennisに感謝します(そして彼の素晴らしいオンラインプラットフォームでMATLをホストしてくれました!)

これは現在のバージョン(9.3.0)を使用しますの言語/コンパイラーを使用します。

入力と出力は、stdinとstdoutを介して行われます。結果は1ベースです。

>> matl j101=tYs2\<f
> eeeeeqeeqeeqqqqeqeqeeqe
6  9 12 13 14 15 19 22

または、オンラインでお試しください!

説明

j             % input string
101=          % vector that equals 1 at 'e' characters and 0 otherwise
t             % duplicate
Ys2\          % cumulative sum modulo 2
<             % detect where first vector is 0 and second is 1
f             % find (1-based) indices of nonzero values

3

Python 2、94 85 79 75 66バイト

編集:ドアノブとアレックスAに感謝します

編集:ありがとうアレックスA。

編集: input()を使用するため、入力は引用符付きの文字列でなければなりません。

編集:列挙を使用することを推奨してくれたZgarbに感謝します。

単にeの数をカウントし、qの場合、eカウントが奇数かどうかを確認してから、インデックスを出力します。

e=0
for j,k in enumerate(input()):
 if"q">k:e+=1
 elif e%2:print j

ここで試してみてください


8バイトを節約するために、2番目if ...を単にan elseに置き換えることができます。
ドアノブ

print1バイトの後にスペースを削除することもできます
アレックスA.

私はあなたが変えることができると思うelse: if e%2:だけにelif e%2:
アレックスA.

i[j]<"q"なくチェックすることで、もう1バイト節約できますi[j]=="e"
アレックスA.

2
@TanMath引用符付きの入力を取ると2バイト節約できるので、Doorknobに尋ねました。しかし、それはできません
ルイスメンドー

3

Haskell、58 51バイト

f x=[i|(i,'q')<-zip[0..]x,odd$sum[1|'e'<-take i x]]

使用例:f "eeeeeqeeqeeqqqqeqeqeeqe"-> [5,8,11,12,13,14,18,21]

リストの前に奇数のs がある場合はi、すべての文字の現在のインデックスをリストを検索して出力します。'q''e'


2

Minkolang 0.15、28バイト

(o"q"=7&z1+$z8!z2%,2&iN$I$).

ここで試してみてください。

説明

(                        Open while loop
 o                       Read in character from input
  "q"                    Push the character "q"
     =                   1 if the top two items on stack are equal, 0 otherwise
      7&                 Pop and jump 7 spaces if truthy

        z                Push register value on stack
         1+              Add one
           $z            Pop top of stack and store in register
             8!          Jump eight spaces

        z                Push register value on stack
         2%              Modulo by 2
           ,             boolean not
            2&           Pop and jump two spaces if truthy
              i          Push loop counter
               N         Output as number

                $I       Push length of input
                  $).    Close while loop when top of stack is 0 and stop.

2

C(関数)、65

追加のゴルフをしてくれた@Dennisに感謝します!

i,n;f(char*m){for(i=n=0;*m;i++)*m++&4?++n:n%2?printf("%d ",i):0;}

1
i,n;f(char*m){for(i=n=0;*m;m++,i++)*m&4?++n:n%2?printf("%d ",i):0;}うまくいくと思う。
デニス

2

Python 3、109 95 80 90 88 76 68 67 66 64バイト

qsとesの数をカウントし、q先行するesの数が奇数の場合、現在のインデックスを追加します。

編集:現在、sのインデックスのリストを出力し、それらの前にq奇数のesがあります。8バイトのおかげで保存されたドアノブとの2つのおかげでfeersumを

lambda s:[x for x,m in enumerate(s)if("e"<m)*s[:x].count("e")%2]

ゴルフをしていない:

def f(s):
    c = []
    for index, item in enumerate(s):
        if item == "q":
            if s[:index].count("e")%2 == 1:
                c.append(index)
    return c

1
inputand printステートメントを不要にするために、これをラムダにできませんでしたか?
ドアノブ

使用するenumerateよりも短くする必要がありrange(len(...ます。
feersum

2

JavaScriptのES6、63の 60 58バイト

x=>[...x].map((e,i)=>e>'e'?n%2&&a.push(i):n++,a=[],n=0)&&a

配列を出力する無名関数。2バイトを保存してくれたuser81655に感謝します。これは、より適切にサポートされている構文を使用したバージョンではありません。

f=function(x) {
  a=[] // Indeces of syncopated notes
  n=0 // Number of e's encountered so far
  x.split('').map(function(e,i) { // For each letter...
    e>'e'? // If the letter is q...
      n%2&& // ...and the number of e's is odd...
        a.push(i): // ...add the current index to the array
      n++ // Otherwise, it is e so increment the counter
  })
  return a
}

run=function(){document.getElementById('output').textContent=f(document.getElementById('input').value)};document.getElementById('run').onclick=run;run()
<input type="text" id="input" value="qqqeqqeeeeqeqeqeqqeqqeqq" /><button id="run">Run</button><br />
<samp id="output"></samp>


0

Mathematica、76バイト

Flatten[Range[#+1,#2-1]&@@@StringPosition[#,"e"~~"q"..~~"e",Overlaps->1<0]]&

私が気づいた興味深い何か。シンコペートされた部分はすべて形式のものですeqqq..qqeですので、それらを検出してqsのインデックスを指定します。


0

ジャプト、29 23 21バイト

もう競い合っていません!

0+U ¬®¥'e} å^ ä© m© f

オンラインでお試しください!

使い方

         // Implicit: U = input string, e.g.    "eqqeqeq"
0+U      // Add a 0 to the beginning.           "0eqqeqeq"
¬        // Split into chars.                   ['0,'e,'q,'q,'e,'q,'e,'q]
®¥'e}    // Map each item X to (X == 'e).       [F, T, F, F, T, F, T, F]
å^       // Cumulative reduce by XOR'ing.       [0, 1, 1, 1, 0, 0, 1, 1]
ä©       // Map each consecutive pair with &&.  [0, 1, 1, 0, 0, 0, 1]
m©       // Map each item with &&. This performs (item && index):
         //                                     [0, 1, 2, 0, 0, 0, 6]
f        // Filter out the falsy items.         [   1, 2,          6]
         // Implicit output                     [1,2,6]

非競合バージョン、18バイト

U¬m¥'e å^ ä©0 m© f

オンラインでお試しください!


0

Befunge、43バイト

:~:0\`#@_5%2/:99p1++\>2%#<9#\9#.g#:*#\_\1+\

オンラインでお試しください!

説明

スタック上の2つの暗黙的なゼロから開始します:ノート番号とビートカウントです。

:               Make a duplicate of the beat count.
~               Read a character from stdin.
:0\`#@_         Exit if it's less than zero (i.e. end-of-file).
5%2/            Take the ASCII value mod 5, div 2, translating q to 1 and e to 0.
:99p            Save a copy in memory for later use.
1+              Add 1, so q maps to 2 and e to 1.
+               Then add that number to our beat count.
\               Get the original beat count that we duplicated at the start.
2%              Mod 2 to check if it's an off-beat.
99g*            Multiply with the previously saved note number (1 for q, 0 for e).
_               Essentially testing if it's a quarter note on an off-beat.
       \.:\     If true, we go turn back left, get the beat count, and output it.
         >2     Then push 2 onto the stack, and turn right again.
2%              That 2 modulo 2 is just zero.
99g*            Then multiplied by the saved note number is still zero.
_               And thus we branch right on the second pass.
\1+\            Finally we increment the note number and wrap around to the start again.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.