Costruire un metronomo


36

introduzione

Alcuni giorni fa avevo bisogno di un metronomo per qualcosa. Non ne avevo a disposizione, quindi ho scaricato un'app dall'App Store. L'app aveva una dimensione di 71 MB !!!
71 MB per creare tic-toc ...?!
Così mi è venuto in mente il code-golf e mi chiedevo se qualcuno di voi potesse migliorare.

Sfida

Golf del codice che emette del suono. È abbastanza irrilevante che tipo di suono. Se necessario, creare un file audio ... ma anche un segnale acustico di sistema farà il lavoro. ( Ecco un po 'di suono che ho creato ... niente di speciale. )

Input : I battiti al minuto emettono il metronomo.

Esempio

Questa è una versione Java non giocata a golf! È solo per mostrarti il ​​compito.

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!");

    }
  }
}

Regole

Non è possibile utilizzare librerie esterne, sono ammessi solo strumenti della lingua stessa.
Conta solo i byte del codice sorgente ... non il file audio.

Questo è , quindi vince l'invio con il minor numero di byte!

MODIFICARE:

Esempio di output: quindi qualcosa del genere sarebbe l'output per 120 bps : link


1
Puoi aggiungere alcuni esempi di I / O (registrare un po 'di suono e caricarlo, pubblicare qui i collegamenti)?
Addison Crump,

2
Domanda: quando dici "librerie esterne", includono le librerie suggerite con la lingua? (Non userò questo, ma un esempio è in Vitsy in cui posso accedere alla shell o JS (ma JS è incorporato))
Addison Crump

3
Puoi aggiungere uno snippet di classifica ?
Addison Crump,

1
Ho il sospetto che la maggior parte dell'app che hai scaricato sia piuttosto grafica ed effetti sonori. È come quelle app della torcia che non fanno altro che girare lo schermo tutto bianco ma riescono comunque a utilizzare in qualche modo decine di MB ...
Darrel Hoffman

1
Qual è il requisito sulla precisione? Nel tuo esempio, entrambi beep()e l'output della console non sono esattamente IIRC istantanei. Nessuno dei due sleep()è noto per essere accurato.
Num Lock,

Risposte:


19

Mathematica, 26 byte

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

Doè normalmente usato come un ciclo "for" nel senso più stretto: ripeti questo pezzo di codice per ciascuno ida xa y... o addirittura ripeti questo pezzo di codice nvolte. Invece di un numero n, possiamo dargli l'infinito per creare un ciclo infinito. Il corpo del loop è Pause[Beep[];60/#]che è solo un modo da golf per scrivere Beep[];Pause[60/#]dove# trova l'argomento funzione.

Se alla fine è ammissibile che la soluzione esploda lo stack di chiamate, possiamo salvare un byte con una soluzione ricorsiva:

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

Non sapevo che ~Do~∞fosse possibile. Un Forloop mi ha portato solo a 29 byte. (Inoltre, credo personalmente che la versione a 26 byte sia l'unica valida.)
LegionMammal978

@ LegionMammal978 Sfortunatamente, ~Do~∞non sembra funzionare quando proviene da una variabile. (Ho provato a usarlo quando
Martin Ender il

1
Attributes[Do]include HoldAll, quindi la mia ipotesi è che _~Do~∞ha un modello di valutazione speciale.
LegionMammal978,

@ LegionMammal978 Sembra più simile alle variabili, perché il messaggio di errore per Do[...,a]dove adetiene l'infinito mostra effettivamente la chiamata come Do[...,{a}].
Martin Ender,


8

JavaScript, 36 45 42 41 34 byte

Salvato 1 byte grazie a @RikerW

Salvato 1 byte grazie a @ETHproductions

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

Questa è una funzione

Se uso `\7`, SpiderMonkey lamenta che i letterali ottali sono deprecati.

Alternativa, 31 byte

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

Il problema è che gli stampabili non vengono stampati ma questo dovrebbe funzionare.


Accidenti, stavo per pubblicare qualcosa del genere. Lo pubblicherò ancora (perché utilizza il nodo e tutti) perché utilizzo un approccio diverso.
Addison Crump,

Se lo guardi dal modo in cui ho posto la domanda, la soluzione ricorsiva non sarebbe possibile. I metronomi sono fatti per lavorare e lavorare ... non per crash dopo un po 'di tempo.
PERA

@PEAR questo non dovrebbe andare in crash perché nessuna variabile è in fase di incremento. L'unica cosa che potrebbe causarne l'arresto anomalo è il buffer del terminale, tranne sui computer moderni che potrebbero richiedere> 50-100 anni, credo
Downgoat,

In quale ambiente funziona? Ho provato Chrome e Node.js, ma non riesco a farlo funzionare.
starbeamrainbowlabs

@starbeamrainbowlabs utilizza la shell JavaScript (SpiderMonkey)
Downgoat

8

Bash, 53 55 41 byte

Grazie a @Dennis per la rasatura di 14 byte 1

Ok, ora della verità: sono terribile a giocare a golf. Qualsiasi aiuto sarebbe molto apprezzato.

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

1 merda santa. Non c'è da stupirsi che nessuno possa superare Dennis.


È while 1possibile?
PERA

@PEAR Nupe - già provato.
Addison Crump,

while printf \\aForse?
Neil,

Questo non funziona poiché bash usa la divisione intera. Dovrai usare bc.
uno spaghetto il

1. Il personaggio BEL non è speciale per Bash, quindi non hai bisogno delle virgolette. 2. Se leggi l'input come CLA, non è necessario read. 3. echoesiste con il codice 0, quindi puoi usare quell'istruzione invece di true.
Dennis,

7

JavaScript ES6 (browser), 43 byte

Questo potrebbe allungare le regole:

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

Assegna a questa funzione un nome (ad es. F=x=>...) E inseriscilo nella console del browser in questa pagina . Quindi chiama la funzione con i tuoi bps, ad esempio F(60), e attendi che avvenga la magia. :-)

Perché funziona? Bene, b.htmlè nella stessa cartella di un file chiamato1 , che è il file audio di esempio dall'OP. Non sono sicuro che questo rientri nelle regole (immagino che sia come la versione della shell; deve essere eseguito in un ambiente specifico), ma valeva la pena provare.

Versione più sicura, 57 byte

Se il codice sopra non è consentito per qualche motivo, prova questo:

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

Funziona su qualsiasi pagina!


Questa è una soluzione interessante. È ancora più breve quando si scarica e si rinomina il file, non è vero?
PEAR

@PEAR Sarebbe più breve, ma avrebbe bisogno di una propria pagina web con il file audio nella stessa cartella per funzionare.
ETHproductions

Oh, è JavaScript xD ... hai ragione
PEAR

@PEAR Ecco, l'ho fatto. Questa nuova soluzione rientra nelle regole?
ETHproductions

Huh. You could specify that it is JS with the certain webpage. It's a preexisting interpreter, so it's a valid language.
Addison Crump

6

05AB1E, 31 bytes

Code:

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

If I had a built-in for waiting N seconds, this could have been 11 bytes. Unfortunately, this is not the case. Here is the explanation:

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

Uses the ISO 8859-1 encoding.


This must be one of the first 05AB1E answers o.Ô It looks very weird to see the time.sleep and .pop() in the middle of the code like that. ;)
Kevin Cruijssen

6

osascript, 39 bytes

on run a
repeat
beep
delay 60/a
end
end

There is literally a command called beep? Sweeeet!

Runnable only on Mac OS X due to restricted license, but to run, do:

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

6

Python, 68 67 57 bytes

Saved 1 byte thanks to @FlagAsSpam

Saved 9 bytes thanks to @Adnan

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

Also it took 2 bytes less after converting line endings to UNIX format.

Older version, that actually takes bpm as command line argument (66 bytes):

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

4
Can't you do print"\7";? I'm not sure, but I'm pretty sure that works.
Addison Crump

@Andan No, input() requests input from user. I don't know if that's considered a valid input. Also conversion to number is needed anyway.
webwarrior

1
How about a=input() and a replacing int(sys.argv[1])? I've always thought that Python 2 automatically evaluates input and therefore doesn't need the int conversion, but I may be wrong.
Adnan

@Andan input() actually does auto evaluate. I forgot about that feature. It's rather unpythonic though - probably a legacy from old times.
webwarrior

Can time.sleep(60./a) be replaced with time.sleep(60./input()), while completely removing a=input()?
clap


4

Vitsy, 14 bytes

a6*r/V1m
<wVO7

Verbose mode (interpreter coming soon):

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;

Basically, I use the w operator to wait a certain number of seconds as specified by bpm/60, wrapped in an infinite loop. Then, I make noise with the terminal output of ASCII character 7 (BEL).


Looks nice, but how can I test this? :)
PEAR

@PEAR You'll have to download the interpreter (forgot to link it in the title). Save it in a file and run it with 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();}}

Basic solution.


Why not print ASCII char 7?
Addison Crump

@FlagAsSpam It's longer: The system beep uses System.Console.Beep();, and printing the character uses System.Console.Write('<\a character>');.
LegionMammal978

Woah. That's a lot to write a character.
Addison Crump

4

Java, 103 82 bytes

Thanks to @Justin for shaving off 21 bytes!

Oh, geez.

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

Method and golfed version of the sample program.


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. I've always thrown errors on that (when using double quotes). My mistake. Thanks! :D
Addison Crump

3

GMC-4 Machine Code, 21.5 bytes

The GMC-4 is a 4-bit computer by a company called Gakken to teach the principles of assembly language in a simplified instruction set and computer. This routine takes input in data memory addresses 0x5D through 0x5F, in big-endian decimal (that is, one digit per nibble).

The algorithm is basically adding the input to memory and waiting 0.1s, until it's at least 600, and then subtracting 600 and beeping, in an infinite loop. Since the GMC-4 has a bunch of register swap functions but no register copy functions, this is done the hard way.

In hex (second line is position in memory):

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

In assembly:

    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

Disclaimer:

I don't actually own a GMC-4. I've meticulously checked this program with documentation from online, but I may have made a mistake. I also don't know the endianness. It looks like the GMC-4 is big-endian, but I'm not sure. If anyone owns a GMC-4 and can verify this/tell me the endianness of the GMC-4, I'd much appreciate it.


3

C, 48 bytes

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

A Windows-only solution (Sleep() function, to be specific).

I also (ab)used the fact that printf() returns the number of characters printed to use it as infinite loop condition.

There IS a character between double-quotes in printf() call, but it is not displayed here for some reason. If in doubt, copy and paste into Sublime Text 2 or Notepad++, the character will be displayed as BEL.

This started as a C++ solution but it kinda fell into the C-subset of C++ (because, you know, Sleep() is a bit shorter than std::this_thread::sleep_for(std::chrono::milliseconds())) and printf() is shorter than std::cout<<).


3

AppleScript 94 bytes

I know I'm pretty late, and this is my first post here, but whatever.

display dialog""default answer""
set x to 60000/result's text returned
repeat
beep
delay x
end

Ungolfed:

display dialog "" default answer ""
set x to 60000 / (result's text returned)
repeat
    beep
    delay x
end repeat

Hey, new answers :) Unfortunatly I'm unable to try your post unless I have no Mac ;) - but thanks a lot
PEAR

@PEAR You're welcome. :)
You

Welcome to Programming Puzzles and Code Golf. This is good answer, +1. Please keep answering!
wizzwizz4

2

VBScript, 113 66 bytes

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

This program is simple enough; it takes input, echoes the BEL character, and waits. Thanks to Niel for shaving off almost half the program!


What's wrong with WScript.Echo CHR(7)? Also, did you mean 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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.