Encontre a sincopação

33

Dada a entrada de uma sequência composta inteiramente por qs representando semínimas ees representando colcheias, produza os índices das semínimas que são sincopadas.

A sincopação é complexa, mas, para os propósitos desse desafio, nossa definição de "sincopado" será muito simples: uma semínima que começa no "off-beat" - ou seja, os tempos contados como "e" em n / 4 Tempo.

Em alternativa, pode ser definido como qualquer semínima precedida por um número ímpar de colcheias. Por exemplo, as notas marcadas *abaixo são consideradas sincopadas e seus índices também são mostrados:

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

A entrada sempre consistirá em um número inteiro de medidas em 4/4 de tempo (uma semínima é um quarto de uma medida e uma colcheia é um oitavo de uma medida). (A entrada também nunca estará vazia.) A saída pode ser uma única sequência com elementos separados por qualquer delimitador que não contenha números ou uma matriz / lista / etc. A saída pode ser baseada em 1 (ou seja, o primeiro índice é 1 em vez de 0), se você desejar, e também pode estar em qualquer base numérica (unária, decimal, etc.).

Como esse é o , o código mais curto em bytes vence.

Casos de teste:

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>
Maçaneta da porta
fonte
1
A saída pode ser baseada em 1?
Luis Mendo
1
Você poderia fazer um exemplo resolvido para mostrar como os índices funcionam?
Peter Taylor
1
@LuisMendo Claro, se o seu código for mais curto.
Maçaneta
@ PeterTaylor Ok, é algo assim que você estava pensando?
Maçaneta
A entrada pode ser uma string incluindo os sinais de cotação? 'eqqqe'em vez deeqqqe
Luis Mendo

Respostas:

12

Geléia , 12 9 bytes

=“e”µ<^\O

Como programa, o código acima requer aspas à volta da entrada. Como isso não é permitido, este é um envio de função. A saída é baseada em 1. Experimente online!

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

Atualizar

O código acima não funciona mais na versão mais recente do Jelly, pois precisamos do caractere e , mas “e”gera uma string. Correção que salva um byte, para um total de 8 bytes .

=”eµ<^\O

Isso funciona como um programa completo. Experimente online!

Dennis
fonte
7

Ruby, 46

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

Entrada para stdin. Saída para stdout, nova linha 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
fonte
6

JavaScript ES7, 50 48 bytes

Muito curto para JS, se você me perguntar. [for...of]sintaxe, basicamente mapa e filtro combinados, é útil para esse desafio.

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

Define uma função anônima que gera uma matriz indexada em 1.

Snippet de teste

Isso usa uma versão ungolfed e não ES7 do 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 />

ETHproductions
fonte
3
Muito boa explicação! E também um grande exemplo de como usar o novo ES7 [For ... de] 👍
Aᴄʜᴇʀᴏɴғᴀɪʟ
Então, precisamos de uma nova pergunta, "Dicas para jogar golfe no ECMAScript 7"?
Neil
@ Neil Tentei atualizar a postagem do ES6 para o ES6 / 7, mas o OP reverteu a edição. Enquanto isso, existe o seguinte: codegolf.stackexchange.com/a/61489/42545
ETHproductions
5

J, 20 19 17 bytes

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

Agradecemos a randomra por salvar um byte e a Dennis por salvar dois. Este é um verbo monádico sem nome, usado da seguinte maneira:

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

Experimente aqui.

Explicação

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

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

O programa requer as opções boP. O código é

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

Salve como e synco, em seguida, execute como grep -boPf synco.

O separador de saída é :qseguido por uma nova linha. Por exemplo, a saída para eqqqeé

1:q
2:q
3:q

Os significados das bandeiras são:

  • P: Use regexes PCRE.
  • o: Isso significa imprimir apenas a parte da linha que corresponde à expressão regular, mas não é por isso que é importante. oé usado porque tem o efeito de permitir várias correspondências por linha.
  • b: Imprima o deslocamento em bytes do início de cada correspondência desde o início do arquivo.

O padrão verifica se não há um número par de colcheias após uma semínima.

feersum
fonte
Será que grepqualifica como uma língua em seu próprio direito? Independentemente disso, +1 para uma grande resposta
Trauma Digital
@DigitalTrauma Não vejo por que não ... Ele pode usar expressões regulares PCRE, portanto deve ser pelo menos Turing-completo e pode executar o código de um arquivo, como mostrado aqui.
precisa saber é
Fiquei com a impressão de que o PCRE não está comprovado como sendo Turing completo. Independentemente disso, sua expressão atende ao requisito, por isso estou bem com isso, mas pode haver outras queixas com base teórica.
Digital Trauma
@DigitalTrauma Huh, parece que fiquei iludido com a coisa de Turing-completude.
precisa saber é
5

MATL , 12 14 16 bytes

j101=tYs2\<f

Agradecemos a Dennis por remover 2 bytes (e por hospedar o MATL em sua incrível plataforma on-line!)

Isso usa a versão atual (9.3.0) do idioma / compilador.

Entrada e saída são através de stdin e stdout. O resultado é baseado em 1.

Exemplo :

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

Ou experimente online!

Explicação

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

Python 2, 94 85 79 75 66 bytes

EDIT: Obrigado Maçaneta e Alex A.

EDIT: Obrigado Alex A.

EDIT: Agora, usando input (), a entrada deve ser uma string com as aspas.

Edição: Obrigado Zgarb por recomendar-me para usar enumerar.

Simplesmente conta o número de e e, se q, verifica se a contagem de e é ímpar e imprime o índice.

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

Experimente aqui

TanMath
fonte
Você pode substituir o segundo if ...por apenas um elsepara salvar 8 bytes.
Maçaneta
Você também pode remover o espaço após print1 byte
Alex A.
Eu acho que você pode mudar else: if e%2:para apenas elif e%2:.
Alex A.
Você pode salvar mais um byte, marcando em i[j]<"q"vez de i[j]=="e".
Alex A.
2
@TanMath, perguntei à maçaneta da porta, porque me economizaria 2 bytes para receber uma entrada com aspas. Mas isso não pode ser feito
Luis Mendo
3

Haskell, 58 51 bytes

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

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

Percorra a lista e produza o índice atual ipara cada caractere 'q'se houver um número ímpar de 'e's antes dele.

nimi
fonte
2

Minkolang 0.15 , 28 bytes

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

Experimente aqui.

Explicação

(                        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
fonte
2

C (função), 65

Obrigado a @Dennis pelo golfe extra!

i,n;f(char*m){for(i=n=0;*m;i++)*m++&4?++n:n%2?printf("%d ",i):0;}
Trauma Digital
fonte
1
Eu acho que i,n;f(char*m){for(i=n=0;*m;m++,i++)*m&4?++n:n%2?printf("%d ",i):0;}deveria funcionar.
Dennis
2

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

Conta o número de se qes e eadiciona o índice da corrente qse o número de es anterior for ímpar.

Editar: Agora, imprime uma lista dos índices de s que qpossuem um número ímpar de es antes deles. Oito bytes salvos graças à maçaneta da porta e mais dois graças ao 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
fonte
1
Você não poderia tornar isso um lambda para tornar desnecessárias as declarações inpute print?
Maçaneta
Deve ser mais curto de usar enumeratedo que range(len(....
precisa saber é
2

JavaScript ES6, 63 60 58 bytes

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

Função anônima que gera uma matriz. Obrigado a user81655 por salvar dois bytes. Aqui está uma versão não destruída que usa uma sintaxe suportada melhor.

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

Mathematica, 76 bytes

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

Algo interessante que eu notei. Todas as partes sincopadas são da forma eqqq..qqe, então eu apenas as detecto e dou os índices dos qs.

LegionMammal978
fonte
0

Japt, 29 23 21 bytes

Não é mais não-concorrente!

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

Experimente online!

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

Versão não concorrente, 18 bytes

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

Experimente online!

ETHproductions
fonte
0

Anterior, 43 bytes

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

Experimente online!

Explicação

Começamos com dois zeros implícitos na pilha: o número da nota e uma contagem de batidas.

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