Знайдіть синкопацію


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}

Вхід до stdin. Вихід у 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

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
Дуже хороше пояснення! А також чудовий приклад того, як використовувати нову [Для ... з] 👍
1616

Отже, чи потрібне нам нове запитання «Поради щодо гольфу в ECMAScript 7»?
Ніл

@Neil Я спробував оновити пост ES6 до ES6 / 7, але ОП відмовив редагування. Тим часом є таке: 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

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: Роздрукуйте зміщення в байтах початку кожного збігу з початку файлу.

Шаблон перевіряє відсутність парної кількості восьмих нот після чверть ноти.


Чи 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 байт

EDIT: Дякую Дорнобу і Алексу А.

EDIT: Дякую Алекс А.

EDIT: Тепер використовується input (), тому вхід повинен бути рядок із лапками.

EDIT: Дякую Згарбу, що рекомендував мені використовувати перерахування.

Просто підраховує кількість e, і якщо q, перевірте, чи число непарних є непарним, а потім надрукувати індекс.

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

Спробуйте тут


Ви можете замінити другий if ...лише на, elseщоб зберегти 8 байт.
Дверна ручка

Ви також можете видалити пробіл printна 1 байт
Алекс А.

Я думаю, ви можете змінити 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

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

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

Підраховує кількість qs і es і додає індекс струму, qякщо число попередніх es непарне.

Редагувати: Тепер він друкує список індексів s, які є, qі непарне число es передує їм. Вісім байт зберігаються завдяки дверній ручці і ще два завдяки 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
Не могли б ви зробити це лямбда, щоб зробити 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

Анонімна функція, яка видає масив. Завдяки користувачеві81655 за збереження двох байтів. Ось версія, яка не підтримується, використовує краще підтримуваний синтаксис.

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

Математика, 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+\

Спробуйте в Інтернеті!

Пояснення

Починаємо з двох неявних нулів на стеку: номер ноти та кількість бит.

:               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.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.