30
\$\begingroup\$

Program the shortest code that will calculate the average BPM (Beats per Minute) using 8 data points of time passed. This is my first post, and I haven't seen a question similar to this. Since I am a fan of rhythm games, it would be nice to have a small handy tool to calculate BPM using your own keyboard and your own sense of rhythm (if you have one...)

Challenge

  • All inputs must be singular. (i.e. Only pressing "enter" as "input")
  • Your program must take at least 9 inputs. (To create 8 data points of time passed.)
  • Your program should output the BPM of the keypresses rounded at 2 decimal points. (i.e. 178.35)
  • Timing starts at first input. Not start of program

This is , so the shortest answer wins.

Example Input and Output

Provide at least one example input and output. Make sure they match your own description of what the input should look like.

Input:

> [Enter-Key]
# User waits 1 second
...  7 more inputs
> [Enter-Key] 

Output:

> 60

Current winner is KarlKastor at 22 Bytes using Pyth

Even though the winner was using Pyth, the Matlab answer was a notable answer.

\$\endgroup\$
4
  • 5
    \$\begingroup\$ Ha! Interesting, welcome to PPCG; for future reference we also have a sandbox where you can get feedback on your challenges before posting them. This is pretty well done though. \$\endgroup\$ Commented Jul 24, 2017 at 20:25
  • \$\begingroup\$ How do we compute the BPM? Do we start timing on the first keypress or when the code starts running? Do we divide by 7 or 8 before extrapolating? \$\endgroup\$
    – xnor
    Commented Jul 24, 2017 at 20:27
  • \$\begingroup\$ Hmm.. So timing should start on the first keypress. As for division, I will change it to do 9 inputs (so you divide by 8) \$\endgroup\$ Commented Jul 24, 2017 at 20:28
  • \$\begingroup\$ Cool question! Good luck \$\endgroup\$ Commented Jul 24, 2017 at 20:34

16 Answers 16

9
\$\begingroup\$

MATLAB/Octave, 58 56 55 bytes

Thanks @LuisMendo for -1 byte!

input('');tic;for k=1:7;input('');end;fix(48e3/toc)/100

You have to press enter 9 times. (Also works in Octave.)

Here you see it in action, left MATLAB, right Octave:

\$\endgroup\$
2
  • \$\begingroup\$ D'oh! but is round(.,2) does not work, or does it in the newer versions? \$\endgroup\$
    – flawr
    Commented Jul 25, 2017 at 18:00
  • \$\begingroup\$ Oh, it only works in Matlab \$\endgroup\$
    – Luis Mendo
    Commented Jul 25, 2017 at 18:35
7
\$\begingroup\$

JavaScript (ES6), 77 74 bytes

(i=8,n=Date.now,t)=>onclick=_=>(t=t||n(),i--||alert((48e6/(n()-t)|0)/100))

Creates an onclick event on the global window object. Send beats by clicking anywhere in the window.

Test Snippet

let f=
(i=8,n=Date.now,t)=>onclick=_=>(t=t||n(),i--||alert((48e6/(n()-t)|0)/100))

f()
document.write("Running... click anywhere here")
*{user-select:none}

\$\endgroup\$
1
  • \$\begingroup\$ 632.41! quite a good calc :) +1 \$\endgroup\$ Commented Jul 26, 2017 at 8:54
6
\$\begingroup\$

Python 3, 93 92 81 bytes

Saved 11 bytes thanks to Felipe.

import time
a,*l,b=[input()or time.time()for i in' '*9]
print(round(480/(b-a),2))
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 81 bytes \$\endgroup\$ Commented Jul 25, 2017 at 13:59
  • \$\begingroup\$ i tried print('%.2f'%(480/(b-a))) and print(f'{480/(b-a):.2f}') (python3.6+), but both have the same bytecount \$\endgroup\$ Commented Jul 25, 2017 at 14:35
5
\$\begingroup\$

Bash + common Linux utilities, 58

script -tt -c'sed -n 9q'
sed '1c2k0
s/ 2/+/;$a480r/p' t|dc
\$\endgroup\$
5
\$\begingroup\$

Javascript, 100, 84 thanks to Powelles, 82 bytes thanks to Justin Mariner

z=>{(a=alert)();i=0;s=(n=Date.now)();while(i++<8)a();a((48e4/(n()-s)).toFixed(2))}

(z=>{(a=alert)();i=0;s=(n=Date.now)();while(i++<8)a();a((48e4/(n()-s)).toFixed(2))})();

\$\endgroup\$
5
  • 1
    \$\begingroup\$ You should be able to use Date.now() instead of new Date().getTime() and 48e4 instead of 480000. \$\endgroup\$
    – powelles
    Commented Jul 25, 2017 at 17:26
  • \$\begingroup\$ Also you can alert the result back instead of returning it and assign alert to a variable like (a=alert)() for your first usage and then later use a(). \$\endgroup\$
    – powelles
    Commented Jul 25, 2017 at 17:49
  • \$\begingroup\$ Ah thanks a lot, I'd never thought of 48e4, and instanciate AND call alert together : (a=alert)(). \$\endgroup\$
    – Serge K.
    Commented Jul 26, 2017 at 7:22
  • 1
    \$\begingroup\$ You can also switch s to use Date.now(), and drop the .getTime() later. And then you can alias Date.now to a shorter name. And the initial z= isn't needed since you aren't calling the function recursively. Down to 69 bytes here \$\endgroup\$ Commented Jul 26, 2017 at 10:24
  • \$\begingroup\$ Oh, and your solution doesn't round to 2 decimal places like the challenge asks for. \$\endgroup\$ Commented Jul 26, 2017 at 10:30
4
\$\begingroup\$

Java 1.5+, 345 339 361 337 bytes

-34 bytes thanks to Michael for pointing out I forgot to fix my imports

import java.awt.event.*;class B{public static void main(String[]a){new java.awt.Frame(){{addKeyListener(new KeyAdapter(){long x=System.currentTimeMillis();int b=0;public void keyPressed(KeyEvent e){if(e.getKeyChar()==' '&&b++==9){System.out.println(Math.round(6000000.0*b/(System.currentTimeMillis()-x))/100.0);}}});setVisible(1>0);}};}}

Listens to the user as they press the space bar. Then, when the user has pressed it 9 times, prints back to the user the current BPM:

enter image description here

Image has debug messages not present in golfed code.


Ungolfed:

import java.awt.event.*;

class B {
    public static void main(String[] a) {
        new java.awt.Frame() {
            {
                addKeyListener(new KeyAdapter() {
                    long x = System.currentTimeMillis();
                    int b = 0;

                    public void keyPressed(KeyEvent e) {
                        if (e.getKeyChar() == ' ' && b++ == 9) {
                            System.out
                                    .println(Math.round(6000000.0 * b
                                            / (System.currentTimeMillis() - x)) / 100.0);
                        }
                    }
                });
                setVisible(1 > 0);
            }
        };
    }
}

Kinda fun to try and get a highscore...

KEY PRESS0 AT 250ms.
KEY PRESS1 AT 343ms.
KEY PRESS2 AT 468ms.
KEY PRESS3 AT 563ms.
KEY PRESS4 AT 672ms.
KEY PRESS5 AT 781ms.
KEY PRESS6 AT 880ms.
KEY PRESS7 AT 989ms.
485
\$\endgroup\$
11
  • \$\begingroup\$ I made a minor change and that I wanted 9 inputs so you could have 8 data points for input instead of 7. (should just be a small change.) \$\endgroup\$ Commented Jul 24, 2017 at 20:53
  • \$\begingroup\$ Missed a space: String[]a) {new java \$\endgroup\$
    – Stephen
    Commented Jul 24, 2017 at 20:56
  • \$\begingroup\$ Another thing is, I put a requirement that says "It should output the BPM of the keypresses rounded at 2 decimal points." Does this round to 2 decimal places? \$\endgroup\$ Commented Jul 24, 2017 at 21:13
  • 1
    \$\begingroup\$ @xNinjaKittyx does now. \$\endgroup\$ Commented Jul 24, 2017 at 21:22
  • 1
    \$\begingroup\$ record is 2027.03 BPM xD slightly modified the code for some better benchmarking \$\endgroup\$ Commented Jul 25, 2017 at 9:22
3
\$\begingroup\$

C# (.NET Core), 193 206 189 186 155 143 137 bytes

-47 bytes thanks to TheLethalCoder
-4 bytes thanks to Nazar554
-16 bytes thanks to Luc
-2 bytes thanks to Kamil Drakari

_=>{var x=new long[9];for(int i=0;i<9;){Console.ReadKey();x[i++]=DateTime.Now.Ticks;}return Math.Round(48e8/(x[8]-x[0]),2);}

Also added to byte count:

using System;

Whole program:

namespace System
{
    class A
    {
        static void Main()
        {
            Func<int, double> f = _ =>
            {
                var x = new long[9];
                for (int i = 0; i < 9; )
                {
                    Console.ReadKey();
                    x[i++] = DateTime.Now.Ticks;
                }
                return Math.Round(48e8 / (x[8] - x[0]), 2);
            };
            Console.WriteLine(f(0));
        }
    }
}
\$\endgroup\$
18
  • 1
    \$\begingroup\$ It would be shorter to have two variables have one outside the loop after the first key press for start time and then overwrite another in the loop. I don't think you need to format the output value so just +"" or even returning the double would be fine. namespace System.Diagnostics{} is probably shorter but you only use Diagnostics on the w so fully qualifying that is probably shorter too. Note that you should include using System; in your byte count for the Console call. \$\endgroup\$ Commented Jul 25, 2017 at 8:33
  • 2
    \$\begingroup\$ replace 540000.0 with 5.4e5 \$\endgroup\$
    – Nazar554
    Commented Jul 25, 2017 at 9:18
  • 1
    \$\begingroup\$ Well you'd do something like (end-start).Milliseconds and set end and start to DateTime.Now. \$\endgroup\$ Commented Jul 25, 2017 at 10:39
  • 1
    \$\begingroup\$ I think you've got an error in your calculation. If you replace ReadKey with Thread.Sleep(100), you should get a bit less than 600 BPM, but your code gives more than that (around 670 BPM). The formula should be "60sec * 1000ms / (deltaMs / 8points)" which translates to "48e8 / deltaMs". Also, you can return$"{48e8/(d[8]-d[0]).Ticks:n2}" fo -20 ;-) \$\endgroup\$
    – Luc
    Commented Jul 25, 2017 at 13:59
  • 1
    \$\begingroup\$ I think you should be able to save some bytes by doing 8/TimeSpan.TotalMinutes instead of 54e4/TimeSpan.TotalMilliseconds. Also, by a quick check using 'Math.Round(value,2)' instead of value.ToString("n2") seemed to save a few characters, partially because it needed fewer parentheses \$\endgroup\$ Commented Jul 25, 2017 at 18:37
2
\$\begingroup\$

C++, 150 bytes

#include<iostream>
#include<ctime>
#define G getchar()
void f(){G;auto s=clock();G;G;G;G;G;G;G;G;std::cout<<round(6000/(double(clock()-s)/8000))/100;}
\$\endgroup\$
7
  • \$\begingroup\$ You could save 5 bytes if you remove the #define and instead do void f(){for(int i=0,auto s=clock();i++<9;){getchar();}std::cout<<round(6000/(double(clock()-s)/8000))/100;} \$\endgroup\$
    – DJMcMayhem
    Commented Jul 25, 2017 at 15:10
  • \$\begingroup\$ No, because if i do that, timing will start before the first input, while it's said Timing starts at first input. Not start of program \$\endgroup\$ Commented Jul 25, 2017 at 16:25
  • \$\begingroup\$ Would it be possible to change line 3 to #define G;getchar() and then changing clock();G to clock()G? \$\endgroup\$
    – Adalynn
    Commented Jul 30, 2017 at 20:53
  • \$\begingroup\$ @Zacharý I get syntax errors \$\endgroup\$ Commented Jul 30, 2017 at 21:01
  • \$\begingroup\$ For some reason, my compiler complains about round. \$\endgroup\$
    – Adalynn
    Commented Jul 30, 2017 at 21:07
2
\$\begingroup\$

Python + curses, 122 bytes

import curses as C,time as T
s=C.initscr()
C.cbreak()
t=0
exec's.getch();t=t or T.time()'*9
print'%.2f'%(540/(T.time()-t))

Requires the curses module to be loaded.

-9 bytes thanks to Felipe Nardi Batista

\$\endgroup\$
7
  • \$\begingroup\$ What's the curses module do? Curse you? \$\endgroup\$ Commented Jul 24, 2017 at 21:05
  • \$\begingroup\$ @MagicOctopusUrn Of course that's certainly what it does. \$\endgroup\$
    – hyper-neutrino
    Commented Jul 24, 2017 at 21:10
  • \$\begingroup\$ time() needs to start at first input and not at program execution. \$\endgroup\$ Commented Jul 24, 2017 at 21:34
  • \$\begingroup\$ @xNinjaKittyx fixed; thanks \$\endgroup\$
    – hyper-neutrino
    Commented Jul 24, 2017 at 22:28
  • \$\begingroup\$ @MagicOctopusUrn Jokes aside, it's a terminal-based GUI library. \$\endgroup\$
    – Kroltan
    Commented Jul 25, 2017 at 10:05
2
\$\begingroup\$

vba, 57

msgbox"":x=timer:for i=1to 8:msgbox"":next:?480/(timer-x)

press enter, or click on the OK in the message box.

\$\endgroup\$
2
\$\begingroup\$

Python 3, 74 bytes

from timeit import*;print('%.2f'%(480/timeit('input()',input(),number=8)))

Try it online!

This will give you silly numbers in TIO since it runs all the inputs at once but it does work. timeit() returns the execution time of the statement 'input()' in seconds excluding the setup parameter input(). TIO with a 1s delay per input for validation.

\$\endgroup\$
1
\$\begingroup\$

Pyth, 22 bytes

 wJ.d0 mw8.Rc480-.d0J2

(yes there's a leading space)

Input is 'enter' presses.

If additional output is allowed I can remove the spaces and get a score of 20 bytes.

example execution

explanation

 wJ.d0 mw8.Rc480-.d0J2
 w                      # take the first input
                        # (space) throw the result away
  J.d0                  # store the current system time in J
       mw8              # take 8 inputs and throw the result away
                 -.d0J  # difference of current time and J
             c480       # divide 480 by this
           .R         2 # round to 2 decimal places 
\$\endgroup\$
1
\$\begingroup\$

Java 8, 180 135 bytes

-45 bytes thanks to @SocraticPhoenix suggesting to use System.in directly.

x->{System.in.read();long t=System.nanoTime(),i=0;for(;i++<8;System.in.read());System.out.printf("%.2f",4.8e11/(System.nanoTime()-t));}

An anonymous lambda function with an unused argument that must be assigned to a functional interface method that throws an Exception (example below). Reads from console; beats are sent by pressing enter.

Ungolfed w/ Surrounding Test Code

public class A {
    interface F{void f(Object x) throws Exception;}

    public static void main(String[]a) throws Exception {
        F f =

        x->{
            System.in.read();
            long t=System.nanoTime(),i=0;
            for(;i++<8;System.in.read());
            System.out.printf("%.2f",4.8e11/(System.nanoTime()-t));
        }

        ;
        f.f(null);
    }
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Would it be shorter to just read directly from System.in? \$\endgroup\$ Commented Jul 25, 2017 at 2:06
  • \$\begingroup\$ @SocraticPhoenix I've never actually tried that, but it seems to work; just using System.in.read() to block until input is received. Thanks! Will update answer. \$\endgroup\$ Commented Jul 25, 2017 at 2:14
  • \$\begingroup\$ 25559105.43 bpm with this lol \$\endgroup\$ Commented Jul 26, 2017 at 8:58
1
\$\begingroup\$

C#, 117 bytes

There's already a C# (.NET Core) answer that this one builds on. Added interpolated string (that .NET Core seems to lack) for output and shaved some bytes by using long array instead of DateTime.

_=>{var d=new long[9];for(var i=0;i<9;){Console.ReadKey();d[i++]=DateTime.Now.Ticks;}return$"{48e8/(d[8]-d[0]):n2}";}

Humane version

class Program
{
    static void Main()
    {
        Func<int, string> f = _ =>
        {
            var d = new long[9];
            for (var i = 0; i < 9;)
            {
                Console.ReadKey();   // Switch these two to "automate" key presses.
                //Thread.Sleep(100); 

                d[i++] = DateTime.Now.Ticks;
            }
            return $"{48e8 / (d[8] - d[0]):n2}";
        };

        var result = f(1);
        Console.WriteLine();
        Console.WriteLine(result);
        Console.ReadKey(true);
    }
}
\$\endgroup\$
1
\$\begingroup\$

R, 79 84 bytes

scan();s=Sys.time;x=s();replicate(8,scan());cat(round(60/as.numeric((s()-x)/8),d=2))

Only works when using enter, since that will end scan immediately. Explicitly uses print for its digits argument, handling the rounding.

> scan();s=Sys.time;x=s();replicate(8,scan());cat(round(60/as.numeric((s()-x)/8),d=2))
1: 
Read 0 items
numeric(0)
1: 
Read 0 items
1: 
Read 0 items
1: 
Read 0 items
1: 
Read 0 items
1: 
Read 0 items
1: 
Read 0 items
1: 
Read 0 items
1: 
Read 0 items
[[1]]
numeric(0)

[[2]]
numeric(0)

[[3]]
numeric(0)

[[4]]
numeric(0)

[[5]]
numeric(0)

[[6]]
numeric(0)

[[7]]
numeric(0)

[[8]]
numeric(0)

[1] 439.47
\$\endgroup\$
2
  • \$\begingroup\$ Does this also round correct with a CPM greater than 1000? \$\endgroup\$ Commented Jul 25, 2017 at 21:11
  • \$\begingroup\$ @RomanGräf woops, nope. Edited. \$\endgroup\$
    – JAD
    Commented Jul 26, 2017 at 8:47
0
\$\begingroup\$

Ruby, 58 bytes

gets;t=Time.now;8.times{gets};p (480/(Time.now-t)).round 2
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.