¿Sabías que el algoritmo euclidiano es capaz de generar ritmos musicales tradicionales ? Veremos cómo funciona esto describiendo un algoritmo similar, pero ligeramente diferente al del documento.
Elija un número entero positivo n
, el número total de latidos y un número entero positivo k
, el número de latidos que suenan (notas). Podemos pensar en el ritmo como una secuencia de n
bits, k
de los cuales son 1s. La idea del algoritmo es distribuir los 1 lo más uniformemente posible entre los 0.
Por ejemplo, con n = 8
y k = 5
, comenzamos con 5 unos y 3 ceros, cada uno en su propia secuencia:
[1] [1] [1] [1] [1] [0] [0] [0]
En cualquier momento tendremos dos tipos de secuencias: las que están al principio son las secuencias "centrales" y las que están al final son las secuencias "restantes". Aquí los núcleos son [1]
sy los restos son [0]
s. Siempre que tengamos más de una secuencia restante, las distribuiremos entre los núcleos:
[1 0] [1 0] [1 0] [1] [1]
Ahora el núcleo es [1 0]
y el resto es [1]
, y distribuimos nuevamente:
[1 0 1] [1 0 1] [1 0]
Ahora el núcleo es [1 0 1]
y el resto es [1 0]
. Como solo tenemos una secuencia restante, nos detenemos y obtenemos la cadena
10110110
Esto es lo que parece, repetido 4 veces:
Aquí hay otro ejemplo, con n = 16
y k = 6
:
[1] [1] [1] [1] [1] [1] [0] [0] [0] [0] [0] [0] [0] [0] [0] [0]
[1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [0] [0] [0] [0]
[1 0 0] [1 0 0] [1 0 0] [1 0 0] [1 0] [1 0]
[1 0 0 1 0] [1 0 0 1 0] [1 0 0] [1 0 0]
[1 0 0 1 0 1 0 0] [1 0 0 1 0 1 0 0]
1001010010010100
Observe cómo terminamos en el último paso con dos secuencias centrales y sin secuencias restantes. Aquí está, repetido dos veces:
Entrada
Puede escribir una función o un programa completo leyendo desde STDIN, línea de comando o similar. La entrada será dos enteros positivos n
y k <= n
, que puede suponer que está en cualquier orden.
Salida
Su tarea es generar el ritmo generado como una n
cadena larga de caracteres. Puede elegir cualquiera de los dos caracteres ASCII imprimibles distintos (0x20 a 0x7E) para representar notas y descansos.
Casos de prueba
Los siguientes casos de prueba se utilizan x
para representar notas .
ys para representar descansos. La entrada se da en el orden n
, entonces k
.
1 1 -> x
3 2 -> xx.
5 5 -> xxxxx
8 2 -> x...x...
8 5 -> x.xx.xx.
8 7 -> xxxxxxx.
10 1 -> x.........
11 5 -> x.x.x.x.x..
12 7 -> x.xx.x.xx.x.
16 6 -> x..x.x..x..x.x..
34 21 -> x.xx.x.xx.xx.x.xx.x.xx.xx.x.xx.x.x
42 13 -> x...x..x..x..x...x..x..x..x...x..x..x..x..
42 18 -> x..x.x.x..x.x.x..x.x.x..x.x.x..x.x.x..x.x.
Puntuación
Este es el código de golf, por lo que gana el código en la menor cantidad de bytes.
q~\,f>
.Haskell, 125 bytes
Ejemplo de uso:
42 # 13
->x...x..x..x..x...x..x..x..x...x..x..x..x..
.f
toma dos parámetros: núcleo y lista de resto. Comprime ambas listas (víag
) y se llama a sí mismo nuevamente o se detiene si el resto es demasiado corto. La función principal#
crea las listas de inicio y las llamadasf
.fuente
Python, 85
La solución recursiva natural. Los parámetros
(n,k,a,b)
representan un núcleo dek
a
's seguido de un resto den-k
b'
s.Esta solución es ineficiente porque
f
se evalúan ambas llamadas recursivas , lo que provoca un número exponencial de llamadas.Traté de comprimir la invocación condicional de
f
likepero ninguno resultó más corto.
fuente