Encuentra la síncopa

33

Dada la entrada de una cadena que consiste enteramente en qs que representan notas negras ys que erepresentan corcheas, genera los índices de las notas negras que se sincopan.

La síncopa es compleja, pero para los propósitos de este desafío, nuestra definición de "síncopa" será muy simple: un cuarto de nota que comienza en "fuera de ritmo", es decir, los latidos cuentan como "y" en n / 4 hora.

Alternativamente, esto puede definirse como cualquier nota negra precedida por un número impar de corcheas. Por ejemplo, las notas marcadas a *continuación se consideran sincopadas y también se muestran sus índices:

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

La entrada siempre consistirá en un número entero de medidas en 4/4 veces (un cuarto de nota es un cuarto de una medida, y una octava nota es un octavo de una medida). (La entrada nunca estará vacía). La salida puede ser una sola cadena con elementos separados por cualquier delimitador que no contenga números o una matriz / lista / etc. La salida puede estar basada en 1 (es decir, el primer índice es 1 en lugar de 0) si lo desea, y también puede estar en cualquier base numérica (unario, decimal, etc.).

Como se trata de , gana el código más corto en bytes.

Casos de prueba:

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>
Pomo de la puerta
fuente
1
¿La salida puede basarse en 1?
Luis Mendo
1
¿Podría hacer un ejemplo trabajado para mostrar cómo funcionan los índices?
Peter Taylor
1
@LuisMendo Claro, si acorta tu código.
Pomo de la puerta
@PeterTaylor Bien, ¿es algo así en lo que estabas pensando?
Pomo de la puerta
¿Puede la entrada ser una cadena que incluye los signos de comillas? 'eqqqe'en lugar deeqqqe
Luis Mendo

Respuestas:

12

Jalea , 12 9 bytes

=“e”µ<^\O

Como programa, el código anterior requiere comillas alrededor de la entrada. Como eso no está permitido, esta es una presentación de función. La salida está basada en 1. Pruébalo en línea!

Cómo funciona

=“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.

Actualizar

El código anterior ya no funciona en la última versión de Jelly, ya que necesitamos un carácter e , pero “e”produce una cadena. Corrección que guarda un byte, para un total de 8 bytes .

=”eµ<^\O

Esto funciona como un programa completo. Pruébalo en línea!

Dennis
fuente
7

Ruby, 46

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

Entrada a stdin. Salida a stdout, nueva línea separada.

Comentado

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
Level River St
fuente
6

JavaScript ES7, 50 48 bytes

Bastante corto para JS, si me preguntas. [for...of]La sintaxis, básicamente mapa y filtro combinados, es útil para este desafío.

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

Define una función anónima que genera una matriz indexada 1.

Fragmento de prueba

Esto utiliza una versión no codificada, no-ES7 del código.

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

ETHproducciones
fuente
3
Muy buena explicación! Y también un gran ejemplo de cómo usar el nuevo [Para ... de] ES
Aᴄʜᴇʀᴏɴғᴀɪʟ
Entonces, ¿necesitamos una nueva pregunta, "Consejos para jugar golf en ECMAScript 7"?
Neil
@Neil Intenté actualizar la publicación de ES6 a ES6 / 7, pero el OP retiró la edición. Mientras tanto, hay esto: codegolf.stackexchange.com/a/61489/42545
ETHproductions
5

J, 20 19 17 bytes

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

Gracias a randomra por guardar un byte, y a Dennis por salvar dos. Este es un verbo monádico sin nombre, que se utiliza de la siguiente manera:

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

Pruébalo aquí.

Explicación

=&'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
fuente
5

GNU grep, 3 + 17 = 20 3 + 15 = 18 bytes

El programa requiere las opciones boP. El código es

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

Guárdelo como synco, luego ejecute como grep -boPf synco.

El separador de salida es :qseguido por una nueva línea. Por ejemplo, la salida para eqqqees

1:q
2:q
3:q

Los significados de las banderas son:

  • P: Use expresiones regulares PCRE.
  • o: Esto significa imprimir solo la parte de la línea que coincide con la expresión regular, pero no es por eso que sea importante. ose usa porque tiene el efecto de permitir múltiples coincidencias por línea.
  • b: Imprime el desplazamiento en bytes del comienzo de cada coincidencia desde el comienzo del archivo.

El patrón verifica que no haya un número par de corcheas después de un cuarto de nota.

Feersum
fuente
¿ grepCalifica como idioma por derecho propio? De todos modos, +1 para una gran respuesta
Digital Trauma
@DigitalTrauma No veo por qué no ... Puede usar expresiones regulares PCRE, por lo que debe ser Turing completo al menos, y puede ejecutar código desde un archivo como se muestra aquí.
fiesta
Tenía la impresión de que no se ha demostrado que PCRE sea Turing completo. De todos modos, su expresión cumple con el requisito, por lo que estoy de acuerdo, pero puede haber otros con quejas por motivos teóricos.
Trauma digital
@DigitalTrauma Huh, parece que me engañé sobre lo de la integridad de Turing.
feersum
5

MATL , 12 14 16 bytes

j101=tYs2\<f

Gracias a Dennis por eliminar 2 bytes (¡y por alojar MATL en su increíble plataforma en línea!)

Esto usa la versión actual (9.3.0) del lenguaje / compilador.

La entrada y salida son a través de stdin y stdout. El resultado está basado en 1.

Ejemplo :

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

O pruébalo en línea!

Explicación

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
Luis Mendo
fuente
3

Python 2, 94 85 79 75 66 bytes

EDITAR: Gracias Doorknob y Alex A.

EDITAR: Gracias Alex A.

EDITAR: ahora usando input (), por lo que la entrada debe ser una cadena con las comillas.

EDITAR: Gracias Zgarb por recomendarme usar enumerate.

Simplemente cuenta el número de e's y si q, verifica si e cuenta es impar, luego imprime el índice.

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

Pruébalo aquí

TanMath
fuente
Puede reemplazar el segundo if ...con solo un elsepara guardar 8 bytes.
Pomo de la puerta
También puede eliminar el espacio después printde 1 byte
Alex A.
Creo que puedes cambiarlo else: if e%2:por justo elif e%2:.
Alex A.
Puede guardar un byte más marcando en i[j]<"q"lugar de i[j]=="e".
Alex A.
2
@TanMath Le pregunté a Doorknob porque me ahorraría 2 bytes para tomar una entrada con comillas. Pero no se puede hacer
Luis Mendo
3

Haskell, 58 51 bytes

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

Ejemplo de uso: f "eeeeeqeeqeeqqqqeqeqeeqe"-> [5,8,11,12,13,14,18,21].

Ir a través de la lista y generar el índice actual ipara cada carácter 'q'si hay un número impar de 'e's antes.

nimi
fuente
2

Minkolang 0.15 , 28 bytes

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

Pruébalo aquí.

Explicación

(                        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.
El'endia Starman
fuente
2

C (función), 65

¡Gracias a @Dennis por el golf extra!

i,n;f(char*m){for(i=n=0;*m;i++)*m++&4?++n:n%2?printf("%d ",i):0;}
Trauma digital
fuente
1
Creo que i,n;f(char*m){for(i=n=0;*m;m++,i++)*m&4?++n:n%2?printf("%d ",i):0;}debería funcionar.
Dennis
2

Python 3, 109 95 80 90 88 76 68 67 66 64 bytes

Cuenta el número de qsys y eagrega el índice de la corriente qsi el número de es anteriores es impar.

Editar: ahora imprime una lista de los índices de s que son qy tienen un número impar de es que los preceden. Ocho bytes guardados gracias a Doorknob y dos más gracias a feersum .

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

Sin golf:

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
fuente
1
¿No podrías hacer de esto una lambda para que las declaraciones inputy sean printinnecesarias?
Pomo de la puerta
Debería ser más corto para usar enumerateen lugar de range(len(....
fiesta
2

JavaScript ES6, 63 60 58 bytes

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

Función anónima que genera una matriz. Gracias a user81655 por guardar dos bytes. Aquí hay una versión no protegida que usa una sintaxis mejor soportada.

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>

NinjaOsoMono
fuente
0

Mathematica, 76 bytes

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

Algo interesante que noté. Todas las partes sincopadas son de formaeqqq..qqe , así que solo las detecto y doy los índices deq s.

LegionMammal978
fuente
0

Japt 29 23 21 bytes

¡Ya no compite!

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

Pruébalo en línea!

Cómo funciona

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

Versión no competitiva, 18 bytes

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

Pruébalo en línea!

ETHproducciones
fuente
0

Befunge, 43 bytes

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

Pruébalo en línea!

Explicación

Comenzamos con dos ceros implícitos en la pila: el número de nota y un conteo de tiempos.

:               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.
James Holderness
fuente