Construyendo un metrónomo


36

Introducción

Hace unos días necesitaba un metrónomo para algo. No tenía ninguno disponible, así que descargué una aplicación de la App Store. ¡La aplicación tenía un tamaño de 71 MB!
71 MB para hacer tic-toc ...?!
Así que el código de golf vino a mi mente y me preguntaba si algunos de ustedes podrían mejorar esto.

Reto

Golf un código que emite algo de sonido. Es bastante irrelevante qué tipo de sonido. Si es necesario, cree un archivo de sonido ... pero un pitido del sistema también hará el trabajo. ( Aquí hay un sonido que creé ... nada especial ) .

Entrada : los latidos por minuto que sale el metrónomo.

Ejemplo

¡Esta es una versión Java sin golf! Es solo para mostrarte la tarea.

public class Metronome {
  public static void main(String[] args) throws InterruptedException {
    int bpm = Integer.valueOf(args[0]);
    int interval = 60000 / bpm;

    while(true) {
        java.awt.Toolkit.getDefaultToolkit().beep();
        // or start playing the sound
        Thread.sleep(interval);
        System.out.println("Beep!");

    }
  }
}

Reglas

No puede usar bibliotecas externas, solo se permiten herramientas del lenguaje en sí.
Solo los bytes del código fuente cuentan ... no el archivo de sonido.

Este es el , por lo que gana el envío con la menor cantidad de bytes.

EDITAR:

Ejemplo de salida: Entonces, algo como esto sería la salida para 120 bps : enlace


1
¿Puede agregar algunos ejemplos de E / S (grabe algo de sonido y cárguelo, publique los enlaces aquí)?
Addison Crump

2
Pregunta: cuando dice "bibliotecas externas", ¿eso incluye las bibliotecas sugeridas con el idioma? (No usaré esto, pero hay un ejemplo en Vitsy en el que puedo acceder a Shell o JS (pero JS está integrado))
Addison Crump


1
Sospecho que la mayoría de las aplicaciones que descargaste son bonitos gráficos y efectos de sonido. Es como esas aplicaciones de linterna que no hacen nada más que poner la pantalla en blanco, pero que de alguna manera logran usar decenas de MB ...
Darrel Hoffman

1
¿Cuál es el requisito de precisión? En su muestra, ambos beep()y la salida de la consola no son exactamente IIRC instantáneos. Ninguno de los dos sleep()es conocido por ser exacto.
Num Lock el

Respuestas:


19

Mathematica, 26 bytes

Pause[Beep[];60/#]~Do~∞&

Donormalmente se usa como un bucle "for" en el sentido más estricto: repita este fragmento de código para cada uno ide xa y... o incluso simplemente repita este fragmento de código nveces. Sin nembargo, en lugar de un número , podemos darle infinito para crear un bucle infinito. El cuerpo del bucle Pause[Beep[];60/#]es, simplemente, una forma de escribir de golf Beep[];Pause[60/#]donde #está el argumento de la función.

Si es admisible que la solución explote la pila de llamadas eventualmente, podemos guardar un byte con una solución recursiva:

#0[Beep[];Pause[60/#];#]&

No sabía que eso ~Do~∞fuera posible. Un Forbucle solo me llevó a 29 bytes. (Además, personalmente creo que la versión de 26 bytes es la única válida).
LegionMammal978

@ LegionMammal978 Desafortunadamente, ~Do~∞no parece funcionar cuando proviene de una variable. (Intenté usar eso cuando jugaba golf con su máquina de la verdad.)
Martin Ender

1
Attributes[Do]incluye HoldAll, así que supongo que _~Do~∞tiene un patrón de evaluación especial.
LegionMammal978

@ LegionMammal978 Parece que las variables lo hacen más, porque el mensaje de error para Do[...,a]donde ase encuentra el infinito en realidad muestra la llamada como Do[...,{a}].
Martin Ender


8

JavaScript, 36 45 42 41 34 bytes

Guardado 1 byte gracias a @RikerW

Guardado 1 byte gracias a @ETHproductions

n=>{for(;;sleep(60/n))print("\7")}

Esta es una función.

Si lo uso `\7`, SpiderMonkey se queja de que los literales octales están en desuso.

Alternativa, 31 bytes

n=>{for(;;sleep(60/n))print``}

El problema es que los no imprimibles se eliminan pero esto debería funcionar.


Maldición, estaba a punto de publicar algo como esto. Todavía lo voy a publicar (porque usa nodo y todo) porque uso un enfoque diferente.
Addison Crump

Si lo miras por la forma en que hice la pregunta, la solución recursiva no sería posible. Los metrónomos están hechos para trabajar y trabajar ... no para estrellarse después de un tiempo.
PERA

@PEAR esto no debería bloquearse porque ninguna variable se está incrementando. La única cosa que podría hacer que se caiga es el buffer del terminal, excepto en las computadoras modernas que podrían tomar> 50-100 años creo
Downgoat

¿Bajo qué entorno funciona esto? Intenté Chrome y Node.js, pero no puedo hacer que funcione.
starbeamrainbowlabs

@starbeamrainbowlabs esto usa el shell de JavaScript (SpiderMonkey)
Downgoat

8

Bash, 53 55 41 bytes

Gracias a @Dennis por reducir 14 bytes 1

De acuerdo, la verdad: soy terrible jugando al golf. Cualquier ayuda sería muy apreciada.

echo " ";sleep `bc -l<<<60/$1`;exec $0 $1
      ^ That's ASCII char 7

1 Santa mierda. No es de extrañar que nadie pueda superar a Dennis.


Es while 1posible?
PERA

@PEAR Nupe: ya lo intenté.
Addison Crump

while printf \\a¿quizás?
Neil

Esto no funciona ya que bash usa la división de enteros. Tendrás que usar bc.
un spaghetto el

1. El carácter BEL no es especial para Bash, por lo que no necesita las comillas. 2. Si lee la entrada como un CLA, no es necesario read. 3. echoexiste con el código 0, por lo que puede usar esa declaración en lugar de true.
Dennis

7

JavaScript ES6 (navegador), 43 bytes

Esto puede estar estirando las reglas:

x=>setInterval('new Audio(1).play()',6e4/x)

Asigne un nombre a esta función (p F=x=>.... Ej. ) E ingrésela en la consola del navegador en esta página . Luego llame a la función con su bps, por ejemplo F(60), y espere a que ocurra la magia. :-)

¿Por qué funciona esto? Bien,b.html está en la misma carpeta que un archivo llamado 1, que es el archivo de sonido de muestra del OP. No estoy seguro de si esto está dentro de las reglas (supongo que es como la versión de shell; necesita ejecutarse en un entorno específico), pero valió la pena intentarlo.

Versión más segura, 57 bytes.

Si el código anterior no está permitido por alguna razón, intente esto en su lugar:

x=>setInterval('new Audio("//ow.ly/Xrnl1").play()',6e4/x)

Funciona en cualquier página!


Esta es una solución interesante. Es aún más corto cuando descargas y cambias el nombre del archivo, ¿no?
PERA el

@PEAR Eso sería más corto, pero luego necesitaría su propia página web con el archivo de sonido en la misma carpeta para ejecutarse.
ETHproductions

Oh, es JavaScript xD ... tienes razón
PEAR

@PEAR Allí, lo hice. ¿Es esta nueva solución dentro de las reglas?
ETHproductions

Huh Puede especificar que es JS con cierta página web. Es un intérprete preexistente, por lo que es un lenguaje válido.
Addison Crump

6

05AB1E , 31 bytes

Código:

I60s/[7ç?D.etime.sleep(#.pop())

Si tuviera un incorporado para esperar N segundos, esto podría haber sido de 11 bytes. Por desgracia, este no es el caso. Aquí está la explicación:

I                               # Push input
 60                             # Push 60
   s                            # Swap the top 2 items
    /                           # Divide the top 2 items
     [                          # Infinite loop
      7ç                        # Push the character \x07
        ?                       # Output it, which give a sound
         .e                     # Evaluate the following as Python code
           time.sleep(       )  # Wait for N seconds
                      #         # Short for stack
                       .pop()   # Pop the last item

Utiliza la codificación ISO 8859-1.


Esta debe ser una de las primeras respuestas 05AB1E O.o Se ve muy raro ver la time.sleepy .pop()en medio de un código de esa manera. ;)
Kevin Cruijssen

6

osascript, 39 bytes

on run a
repeat
beep
delay 60/a
end
end

¿Hay literalmente un comando llamado pitido? Sweeeet!

Ejecutable solo en Mac OS X debido a una licencia restringida, pero para ejecutar, haga:

osascript -e "on run a
repeat
beep
delay 60/a
end
end" bpm

6

Python, 68 67 57 bytes

Guardado 1 byte gracias a @FlagAsSpam

Guardado 9 bytes gracias a @Adnan

import time
a=input()
while 1:print"\7";time.sleep(60./a)

También tomó 2 bytes menos después de convertir las terminaciones de línea al formato UNIX.

Versión anterior, que realmente toma bpm como argumento de línea de comando (66 bytes):

import sys,time
while 1:print"\7";time.sleep(60./int(sys.argv[1]))

44
¿No puedes hacer print"\7";? No estoy seguro, pero estoy bastante seguro de que funciona.
Addison Crump

@Andan No, input () solicita la entrada del usuario. No sé si eso se considera una entrada válida. También la conversión a número es necesaria de todos modos.
webwarrior

1
¿Qué tal a=input()y areemplazar int(sys.argv[1])? Siempre he pensado que Python 2 evalúa automáticamente la entrada y, por lo tanto, no necesita la conversión int, pero puedo estar equivocado.
Adnan

@Andan input()realmente evalúa automáticamente. Olvidé esa característica. Sin embargo, es bastante poco propicio, probablemente un legado de los viejos tiempos.
guerrero web

Se time.sleep(60./a)puede reemplazar con time.sleep(60./input()), mientras se elimina por completo a=input()?
clap


4

Vitsy, 14 bytes

a6*r/V1m
<wVO7

Modo detallado (intérprete próximamente):

0:                              // a6*r/V1m
push a; // 10
push 6;
multiply top two; // 60
reverse stack; // bpm on top
divide top two; // bpm/60
save/push permanent variable; 
push 1;
goto top method; // goes to 1
1:                              // <wVO7
go backward; // infinite loop, from the bottom of 1
wait top seconds;
save/push permanent variable; // pushes the bpm in terms of seconds of delay
output top as character;
push 7;

Básicamente, uso el woperador para esperar una cierta cantidad de segundos según lo especificado por bpm/60, envuelto en un bucle infinito. Luego, hago ruido con la salida del terminal del carácter ASCII 7 ( BEL).


Se ve bien, pero ¿cómo puedo probar esto? :)
PERA

@PEAR Tendrás que descargar el intérprete (olvidé vincularlo en el título). Guárdelo en un archivo y ejecútelo con java -jar Vitsy.jar <filename>.
Addison Crump

4

C #, 118 bytes

class A{static int Main(string[]a){for(;;System.Threading.Thread.Sleep(60000/int.Parse(a[0])))System.Console.Beep();}}

Solución básica


¿Por qué no imprimir ASCII char 7?
Addison Crump

@FlagAsSpam Es más largo: se usa el pitido del sistema y se usa la System.Console.Beep();impresión del personaje System.Console.Write('<\a character>');.
LegionMammal978

Woah Eso es mucho para escribir un personaje.
Addison Crump

4

Java, 103 82 bytes

¡Gracias a @Justin por reducir 21 bytes!

Oh cielos.

void x(int b)throws Exception{for(;;Thread.sleep(60000/b))System.out.print('\7');}

Método y versión de golf del programa de muestra.


Why not System.out.print('\7'); instead of the java.awt.Toolkit.getDefaultToolkit().beep();?
Justin

@Justin \ is solely for escaping regex characters.
Addison Crump

1
no the backslash is an escape sequence. '\7' is the bell character, which makes a sound when it is printed out
Justin

@Justin Huh. Siempre he arrojado errores sobre eso (cuando uso comillas dobles). Mi error. ¡Gracias! : D
Addison Crump

3

GMC-4 Machine Code, 21.5 bytes

El GMC-4 es una computadora de 4 bits de una compañía llamada Gakken para enseñar los principios del lenguaje ensamblador en un conjunto de instrucciones simplificado y una computadora. Esta rutina toma entrada en direcciones de memoria de datos a 0x5Dtravés de0x5F , en decimal big-endian (es decir, un dígito por mordisco).

El algoritmo consiste básicamente en agregar la entrada a la memoria y esperar 0.1s, hasta que sea al menos 600, y luego restar 600 y emitir un pitido, en un bucle infinito. Dado que el GMC-4 tiene un montón de funciones de intercambio de registros pero ninguna copia de registro funciones de , esto se hace de la manera difícil.

En hexadecimal (la segunda línea es la posición en la memoria):

A24A14A04 80EC AF5A2EF AE5A1EF AD5A0EF 8A6 F2AF09 86ADEEE9F09
012345678 9ABC DEF0123 4567890 ABCDEF0 123 456789 ABCDEF01234

En asamblea:

    tiy 2     ;ld y, 0x2
    AM        ;ld a, [0x50 + y]
    tiy 1
    AM
    tiy 0
    AM
start:
    tia 0     ;ld a, 0x0
    cal timr  ;pause for (a+1)*0.1 seconds
    tiy F
    MA        ;ld [0x50 + y], a
    tiy 2
    cal DEM+  ;add a to [0x50 + y]; convert to decimal and carry.
    tiy E     ;do the same for the second digit
    MA
    tiy 1
    cal DEM+
    tiy D     ;and the third.
    MA
    tiy 0
    cal DEM+
    tia A
    M+
    jump beep
    jump start
beep:
    tia 6
    tiy D
    cal DEM-
    cal SHTS  ;'play short sound'
    jump start

Renuncia:

En realidad no tengo un GMC-4. He revisado meticulosamente este programa con documentación en línea, pero es posible que haya cometido un error. Tampoco sé el endianness. Parece que el GMC-4 es big endian, pero no estoy seguro. Si alguien posee un GMC-4 y puede verificar esto / dime la resistencia del GMC-4, lo agradecería mucho.


3

C, 48 bytes

void f(int b){while(printf(""))Sleep(60000/b);}
                            ^ literal 0x07 here

Una solución solo para Windows (función Sleep (), para ser específicos).

También (ab) usé el hecho de que printf () devuelve el número de caracteres impresos para usarlo como condición de bucle infinito.

Hay un carácter entre comillas dobles en la llamada printf (), pero no se muestra aquí por alguna razón. En caso de duda, copie y pegue en Sublime Text 2 o Notepad ++, el carácter se mostrará comoBEL .

Esto comenzó como una solución de C ++, pero cayó en el subconjunto C de C ++ (porque, ya sabes, Sleep()es un poco más corto que std::this_thread::sleep_for(std::chrono::milliseconds())) y printf()es más corto que std::cout<<).


3

AppleScript 94 bytes

Sé que llego bastante tarde, y esta es mi primera publicación aquí, pero lo que sea.

muestra el cuadro de diálogo "" respuesta predeterminada ""
establezca x en 60000 / se devuelve el texto del resultado
repetir
bip
retraso x
fin

Sin golf:

muestra el cuadro de diálogo "" respuesta predeterminada ""
establece x en 60000 / (se devuelve el texto del resultado)
repetir
    bip
    retraso x
final repetir

Hola, nuevas respuestas :) Desafortunadamente no puedo probar tu publicación a menos que no tenga Mac;) - pero muchas gracias
PEAR

@PEAR De nada. :)
Usted

Bienvenido a Programming Puzzles y Code Golf. Esta es una buena respuesta, +1. ¡Por favor sigue respondiendo!
wizzwizz4

2

VBScript, 113 66 bytes

a=InputBox("")
Do
WScript.Echo(Chr(7))
WScript.Sleep(60000/a)
Loop

Este programa es lo suficientemente simple; toma entrada, hace eco del carácter BEL y espera. ¡Gracias a Niel por reducir casi la mitad del programa!


¿Qué tiene de malo WScript.Echo CHR(7)? Además, ¿quisiste decir 60000?
Neil

@Neil Ah, yes. forgot about those.;
Conor O'Brien

2

Ruby, 37 33 bytes

m=->b{loop{puts"\7"
sleep 6e1/b}}

Pretty straightforward.

This is a lambda function. If you wanted 60 bpm, you'd do: m[60].


Theoretically $><<?\a should also work for the beep. And no need to give a name for your proc (all JavaScript solutions with fat arrow function also leave it unassigned), you can call it anonymously too: ->b{loop{$><<?\a;sleep 6e1/b}}[60].
manatwork

@manatwork I only have Ruby 2.x, so I couldn't test the ?\a; do you have Ruby 1.x? If so, can you test that this works?
Justin

Well, I have a Ruby 1.9.3 and the code raises no error with it. But I have another problem with the testing: no beep on my machine. Neither Ruby nor anything else. Set something once, no idea what.
manatwork

2

Japt, 30 bytes

6e4/U i`?w Au¹o('../1').play()

The ? should be the literal byte 9A. Test it online! (Sorry about the pop-up delaying the first few beats; this will be removed soon.)

How it works

6e4/U i"new Audio('../1').play()  // Implicit: U = input bps
6e4/U                             // Calculate 60000 / U.
      i                           // Set a timed event every that many milliseconds,
       "new Audio('../1').play()  // running this code every time.
                                  // ../1 is the path to the file used in my JS entry.

2

Mumps, 18 bytes

R I F  H 60/I W *7

Read the BPM into variable I, then F {with two spaces after} is an infinate loop. Halt for 60 seconds / BPM, then write $CHR(7) {Ascii: BEL} to standard output, giving the audio output required, then restart at the infinite loop.


2

Java, 321 chars

Sounds very good. Works only on systems with MIDI support.

import javax.sound.midi.*;import java.util.*;class A{public static void main(String[] a) throws Exception{int d=new Scanner(System.in).nextInt();Synthesizer b=MidiSystem.getSynthesizer();b.open();MidiChannel c=b.getChannels()[0];c.programChange(116);while(true){c.noteOn(0,100);Thread.sleep((int)(d/.06));c.noteOff(0);}}}

.


Looks nice, but this does not work for me: pastebin.com/0CbGYkU0
PEAR

@PEAR fixed. I forgot a cast.
username.ak

@PEAR and an import
username.ak

@PEAR, i had swapped some ops because of no sound
username.ak

2

ChucK, 90 bytes

White noise that is turned on and off every two ticks.

60./Std.atoi(me.arg(0))*1000=>float s;while(1){Noise b=>dac;s::ms=>now;b=<dac;s::ms=>now;}

Explanation

60./Std.atoi(me.arg(0)) //Convert the input to an int and divide 60 by it
*1000                   //Multiply by 1000 (in order to avoid s::second)
=>float s;              //Store it as a float in variable s
while(1)                //Forever,
{Noise b=>dac;          //Connect a noise generator b to the audio output
s::ms=>now;             //Wait for s milliseconds
b=<dac;                 //Disconnect b from the audio output
s::ms=>now;}            //Wait for s milliseconds

This is made to turn on the sound on a beat, then turn it off on the beat after.

98 93 byte version (fancier)

White noise played for 10 milliseconds per tick.

60./Std.atoi(me.arg(0))*1000-9=>float s;while(1){Noise b=>dac;10::ms=>now;b=<dac;s::ms=>now;}

This is made to be a click instead of constant noise being turned on and off.


2

Perl 5, 36 bytes

{{$|=print"\a";sleep 60/$_[0];redo}}

A subroutine; use it as

sub{{$|=print"\a";sleep 60/$_[0];redo}}->(21)

sleep is in seconds, so you can't have more than 60 beeps per minute, not sure if that's a requirement. Also, you can probably keep the same byte count but have a full program by doing something like: $|=<>;{print"\a";sleep 60/$|;redo} (can't test it right now).
ChatterOne

@ChatterOne, according to its documentation, you're right about sleep. But it worked for me.
msh210

1

Jolf, 7 bytes, noncompeting

I added sounds after this very fine challenge was made.

TΑa/Αaj
T       set an interval
 Αa      that plays a short beep (Α is Alpha)
   /Αaj  every 60000 / j (the input) seconds. (Αa returns 60000)

If you so desire to clear this sound, take note of the output. Say that number is x. Execute another Jolf command ~CP"x", and the interval will be cleared.


1

Zsh, 32 bytes

<<<$'\a'
sleep $[60./$1]
. $0 $1

Based on the leading bash answer, but sources instead of execs. The TIO link sources $0:a because of how the original file is executed, but it will work without it.

Try it online!


You're late to the party but this looks like really fine solution!
PEAR

I know I'm late, but I just felt like golfing today. Decided to check on the music tag for fun, and found this challenge. Good one, btw!
GammaFunction

0

Bash + bc + ><>, 44 bytes

Playing on the fact that the ><> interpreter lets you define a tick time :

python fish.py -t $(bc -l<<<"2/$1/60") -c 7o

The ><> code is 7o and should output the BEL character, producing a system beep. It will loop until interrupted.
The -t value is set to (2 / RPM ) / 60 so that the whole code is played RPM * 60 times per second.


Thanks a lot for a new answer after some amount of time after publishing. Doesn't work for me :( Not sure if a problem of my system or something else. I downloaded the fish.py from GitHub and executed your commad (openSUSE). Got this error: (standard_in) 1: syntax error usage: fish.py [-h] (<script file> | -c <code>) [<options>] fish.py: error: argument -t/--tick: expected one argument
PEAR

Have you got bc installed? It looks like the $(bc -l<<<"2/$1/60") did not produce any output. I'll add it to the list of languages of the answer. I haven't been able to fully test my answer yet, so there might be some kind of error too.
Aaron

0

SmileBASIC, 26 bytes

INPUT B$BGMPLAY@8T+B$+"[C]

It can play any general midi instrument, though anything above 9 will use more bytes.


0

Stax, 17 bytes

ü7»♥O╚⌂╥☻≈OyM╜Δ∩`

or, unpacked:

4|A48*x/W2|A]pc{| }*

The program outputs bytes that, when fed through the command line tool aplay with default setting, produce a metronome noise. The input is used as bpm

example:

example-stax-interpreter metronome.stax -i "60" | aplay

You should hear a horrible beeping noise at the desired bpm

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.