fundo
Os arquivos MIDI são bem diferentes dos arquivos de áudio WAV ou MP3. Os arquivos MP3 e WAV contêm bytes que representam uma "gravação" do áudio, enquanto os arquivos MIDI possuem uma série de mensagens MIDI armazenadas em eventos MIDI, informando ao sintetizador MIDI qual instrumento virtual tocar ou um seqüenciador MIDI o andamento da reprodução. Essas mensagens são armazenadas em trilhas, e uma coleção de trilhas compõe uma sequência MIDI, cujos eventos podem ser analisados por um seqüenciador e têm suas mensagens transmitidas do seqüenciador para o receptor de um sintetizador.
Na maioria das vezes, as mensagens MIDI armazenadas nos eventos MIDI são mensagens Note On que instruem o sintetizador a tocar uma nota específica, ou mensagens Note Off que instruem o sintetizador a parar de tocar a nota. Essas mensagens contêm dois bytes de dados, o primeiro informa o sintetizador da velocidade da nota (velocidade mais alta resulta em uma nota mais alta) e o segundo informa o sintetizador da nota a ser tocada (por exemplo, C médio). Os eventos também contêm marcações que servem para informar ao seqüenciador quando enviar as mensagens.
O desafio
O desafio é escrever um programa completo ou uma função que analise uma série de mensagens MIDI Note On e Note Off em uma sequência MIDI de faixa única e envia para STDOUT um gráfico mostrando quando determinadas notas estão ativadas, quando estão desativadas e as velocidade dessas notas. O eixo vertical do gráfico representa o valor da nota e deve ser rotulado como descrito abaixo, e o eixo horizontal representa o tempo nos ticks MIDI (embora deva permanecer sem rótulo para reduzir problemas de complexidade e espaçamento).
Sua entrada pode ser quatro matrizes ou listas separadas, cada uma contendo uma série de valores inteiros; uma matriz ou lista bidimensional contendo quatro sub-matrizes / sub-listas com uma série de valores inteiros; ou qualquer outro meio conveniente; isso representa os eventos MIDI da coleção com as mensagens Note On e Note Off na faixa. Os valores na primeira dessas matrizes especificam a nota, o segundo a velocidade, a terceira a nota no evento e o quarto na nota desativada. Por exemplo, considerando quatro matrizes como estas:
{60, 62, 64, 65, 67}
{20, 40, 60, 80, 100}
{ 0, 4, 8, 12, 16}
{ 2, 6, 10, 14, 18}
A análise do primeiro elemento de cada matriz fornece dois eventos: um evento no tick 0 com uma mensagem que possui um comando Note On, nota 60 (C média) e velocidade da nota de 20; e um evento no tick 2 com uma mensagem que possui um comando Note Off com a mesma nota e velocidade.
Regras
O gráfico deve apresentar os números de 0 a 127 exibidos em ordem decrescente no lado esquerdo (representando o valor da nota), quando a nota é iniciada, a duração de cada nota (nota desativada menos a nota ativada) e a velocidade da nota. Os símbolos que representam as notas dependem de sua velocidade:
- 0-15:
O
- 16-31:
=
- 32-47:
#
- 48-63:
-
- 64-79:
@
- 80-95:
+
- 96-111:
0
- 112-127:
*
Você pode assumir o seguinte:
- Os valores para nota e velocidade estarão dentro do intervalo [0, 127].
- Os comprimentos de cada uma das quatro matrizes sempre serão iguais.
Aqui estão alguns exemplos:
{60, 62, 64, 65, 67}
{20, 40, 60, 80, 100}
{ 0, 4, 8, 12, 16}
{ 2, 6, 10, 14, 18}
127|
126|
125|
...
67 | 00
66 |
65 | ++
64 | --
63 |
62 | ##
61 |
60 |==
59 |
...
2 |
1 |
0 |
{60, 48, 62, 47, 64, 45, 65, 43, 67, 41, 65, 43, 64, 45, 62, 47, 60, 48}
{63, 31, 75, 90, 12, 23, 122, 104, 33, 19, 57, 42, 5, 82, 109, 86, 95, 71}
{0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16}
{2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18}
127|
126|
...
68 |
67 | ##
66 |
65 | ** --
64 | OO OO
63 |
62 | @@ 00
61 |
60 |-- ++
59 |
...
49 |
48 |== @@
47 | ++ ++
46 |
45 | == ++
44 |
43 | 00 ##
42 |
41 | ==
40 |
...
1 |
0 |
Aqui está um exemplo que exibe as primeiras notas de Ode to Joy:
{48, 55, 64, 64, 65, 67, 55, 67, 65, 64, 62, 52, 55, 60, 60, 62, 64, 55, 64, 62, 62}
{45, 45, 63, 63, 63, 63, 89, 66, 66, 66, 66, 30, 30, 103, 103, 103, 103, 127, 55, 55, 55}
{ 0, 0, 0, 4, 8, 12, 16, 16, 20, 24, 28, 32, 32, 32, 36, 40, 44, 48, 48, 54, 56}
{16, 16, 2, 6, 10, 14, 32, 18, 22, 26, 30, 48, 48, 34, 38, 42, 46, 64, 50, 55, 64}
127|
...
67 | -- @@
66 |
65 | -- @@
64 |-- -- @@ 00 --
63 |
62 | @@ 00 - --------
61 |
60 | 00 00
59 |
58 |
57 |
56 |
55 |################++++++++++++++++================****************
54 |
53 |
52 | ================
51 |
50 |
49 |
48 |################
...
0 |
Você pode reduzir sua pontuação em 25% se o envio enviar uma sequência MIDI real como entrada, analisar as mensagens Note On e Note Off de qualquer faixa de sua escolha, desde que contenha pelo menos quatro eventos com mensagens Note On e Note Off e saídas um gráfico como descrito acima.
Isso é código de golfe, então o código mais curto vence. Boa sorte!
Ruby, 106 bytes
Isso foi divertido. Não sei por que ninguém tentou.
Essa função recebe a entrada como quatro argumentos de matriz e retorna uma matriz de seqüências de caracteres, uma para cada linha do gráfico.
Nota: Isso pressupõe arbitrariamente que não haverá mais de 10.000 ticks. Se você executá-lo em seu terminal, sugiro canalizá-lo para
less
que você possa rolar horizontalmente. Você pode mudar1e4
se quiser mais ticks, até o fim9e9
, mas isso levará um terabyte ou dois de RAM.Veja em repl.it: https://repl.it/Cx4I/1
fonte
Python 2,
163160156145 bytesEsta não é a maneira mais divertida de fazer isso, mas foi uma das mais simples. Se eu pudesse descobrir como substituir partes de strings sem transformá-las em listas, substituí-las e transformá-las novamente em strings, isso seria muito útil aqui. Sugestões de golfe são bem-vindas.
Edit: 18 bytes graças a Leaky Nun. Experimente no Ideone !
fonte
str.sub(/(?<=.{20}).{3}/,"foo")
é equivalente astr[20,3] = "foo"
. Obviamente, isso significa construir o regexp por interpolação / concatenação de strings com as variáveis index / length - o que é barato em bytes Ruby, mas talvez não em Python.Japt , 65 bytes
Experimente online!
Recebe a entrada como uma lista de notas no formato
[pitch, start_tick, end_tick, velocity]
. Se a entrada de entrada como listas separadas for obrigatória (ou seja, uma lista contendo todos os arremessos, uma contendo todas as velocidades etc.), isso pode ser realizado ao custo de 1 byte .Explicação:
fonte