Найти синкопацию

33

Учитывая ввод строки, состоящей целиком из qs, представляющих четвертные ноты, и es, представляющих восьмые ноты, выведите индексы четвертных нот, которые синкопированы.

Синкопация сложна, но для целей этой задачи наше определение «синкопированного» будет очень простым: четвертная нота, начинающаяся с «безударного» - то есть, удары считаются как «и» в n / 4 время.

В качестве альтернативы это может быть определено как любая четвертная нота, которой предшествует нечетное число восьмой ноты. Например, примечания, отмеченные *ниже, считаются синкопированными, а также отображаются их индексы:

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

Ввод всегда будет состоять из целого числа мер в 4/4 времени (четвертная нота - это четверть меры, а восьмая нота - восьмая меры). (Входные данные также никогда не будут пустыми.) Выходные данные могут быть либо одной строкой с элементами, разделенными любым разделителем, который не содержит чисел, либо массивом / списком / и т. Д. Вывод может быть основан на 1 (т. Е. Первый индекс равен 1 вместо 0), если вы хотите, и он также может быть в любой числовой базе (унарной, десятичной и т. Д.).

Поскольку это , выигрывает самый короткий код в байтах.

Тестовые случаи:

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.

Обновить

Приведенный выше код больше не работает в последней версии Jelly, так как нам нужен символ e , но “e”выдает строку. Исправление, которое сохраняет байт, всего 8 байт .

=”eµ<^\O

Это работает как полная программа. Попробуйте онлайн!

Деннис
источник
7

Руби, 46

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

Вход в стандартный ввод. Вывод в stdout, разделение новой строки.

комментарии

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
Уровень реки St
источник
6

JavaScript ES7, 50 48 байт

Довольно коротко для JS, если вы спросите меня. [for...of]Синтаксис, в основном комбинированный map и filter, пригодится для этой задачи.

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

ETHproductions
источник
3
Очень хорошее объяснение! А также отличный пример того, как использовать новую ES7 [For ... of] 👍
Aᴄʜᴇʀᴏɴғᴀɪʟ
Итак, нужен ли нам новый вопрос «Советы по игре в гольф в ECMAScript 7»?
Нил
@Neil Я попытался обновить запись ES6 до ES6 / 7, но OP откатил редактирование. Между тем, есть следующее: codegolf.stackexchange.com/a/61489/42545
ETHproductions
5

J, 20 19 17 байт

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

Спасибо Рэндомре за сохранение байта и Деннису за сохранение двух. Это безымянный монадический глагол, используемый следующим образом:

  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
Zgarb
источник
5

GNU grep, 3 + 17 = 20 3 + 15 = 18 байт

Программа требует опций boP. Код

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

Сохраните как synco, затем запустите как grep -boPf synco.

Выходной разделитель :qсопровождается переводом строки. Например , выход для eqqqeIS

1:q
2:q
3:q

Значения флагов:

  • P: Используйте регулярные выражения PCRE.
  • oЭто означает, что нужно печатать только ту часть строки, которая соответствует регулярному выражению, но это не то, почему это важно. oиспользуется потому, что позволяет несколько совпадений в строке.
  • b: Вывести смещение в байтах начала каждого совпадения от начала файла.

Шаблон проверяет, что после четвертной ноты нет четного числа восьмых нот.

feersum
источник
Квалифицируется ли grepязык как самостоятельный? Независимо от того, +1 за отличный ответ
Digital Trauma
@DigitalTrauma Я не понимаю, почему нет ... Он может использовать регулярные выражения PCRE, поэтому он должен быть по крайней мере завершен по Тьюрингу и может выполнять код из файла, как показано здесь.
feersum
У меня сложилось впечатление, что PCRE не является завершенным по Тьюрингу. Независимо от того, ваше выражение соответствует требованию, так что я согласен с ним, но могут быть и другие с жалобами по теоретическим соображениям.
Цифровая травма
@DigitalTrauma Да, кажется, я заблуждаюсь по поводу полноты Тьюринга.
feersum
5

MATL , 12 14 16 байт

j101=tYs2\<f

Спасибо Деннису за удаление 2 байтов (и за размещение 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 байт

РЕДАКТИРОВАТЬ: Спасибо Doorknob и Алекс А.

РЕДАКТИРОВАТЬ: Спасибо Алекс А.

РЕДАКТИРОВАТЬ: Теперь с помощью input (), поэтому ввод должен быть строка с кавычками.

РЕДАКТИРОВАТЬ: Спасибо Zgarb за то, что рекомендовал мне использовать перечислить.

Просто подсчитывает количество e и, если q, проверит, нечетное ли число e, затем выведите индекс.

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

Попробуй здесь

TanMath
источник
Вы можете заменить второй if ...всего лишь elseна 8 байт.
Ручка двери
Вы также можете удалить пробел после print1 байта
Алекс А.
Я думаю, что вы можете изменить на else: if e%2:просто elif e%2:.
Алекс А.
Вы можете сохранить еще один байт, установив i[j]<"q"вместо i[j]=="e".
Алекс А.
2
@TanMath Я спросил Doorknob, потому что это сэкономило бы мне 2 байта, чтобы получить ввод с кавычками. Но это не может быть сделано
Луис Мендо
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].

Просмотрите список и выведите текущий индекс iдля каждого символа, 'q'если 'e'перед ним нечетное число s.

Ними
источник
2

Минколанг 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

С (функция), 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

Питон 3, 109 95 80 90 88 76 68 67 66 64 байта

Считает количество qс иe s и добавляет индекс текущего, qесли число предшествующих es нечетно.

Изменить: Теперь он печатает список индексов s, которые имеют qи имеют нечетное число es перед ними. Восемь байтов сэкономлено благодаря Doorknob и еще два благодаря feersum .

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

Ungolfed:

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
Sherlock9
источник
1
Не могли бы вы сделать это лямбда, чтобы сделать ненужными заявления inputи 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

Анонимная функция, которая выводит массив. Спасибо 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>

NinjaBearMonkey
источник
0

Mathematica, 76 байт

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

Что-то интересное я заметил. Все синкопированные части имеют форму eqqq..qqe, поэтому я просто обнаруживаю их и даю индексы qs.

LegionMammal978
источник
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

Попробуйте онлайн!

ETHproductions
источник
0

Befunge, 43 байта

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

Попробуйте онлайн!

объяснение

Мы начнем с двух неявных нулей в стеке: номера ноты и количества ударов.

:               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.
Джеймс Холдернесс
источник