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\$
  • 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\$ – Magic Octopus Urn Jul 24 '17 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 Jul 24 '17 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\$ – xNinjaKittyx Jul 24 '17 at 20:28
  • \$\begingroup\$ Cool question! Good luck \$\endgroup\$ – Noah Cristino Jul 24 '17 at 20:34

16 Answers 16

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\$
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\$
  • \$\begingroup\$ D'oh! but is round(.,2) does not work, or does it in the newer versions? \$\endgroup\$ – flawr Jul 25 '17 at 18:00
  • \$\begingroup\$ Oh, it only works in Matlab \$\endgroup\$ – Luis Mendo Jul 25 '17 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\$
  • \$\begingroup\$ 632.41! quite a good calc :) +1 \$\endgroup\$ – V. Courtois Jul 26 '17 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\$
  • 1
    \$\begingroup\$ 81 bytes \$\endgroup\$ – Felipe Nardi Batista Jul 25 '17 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\$ – Felipe Nardi Batista Jul 25 '17 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\$
  • 1
    \$\begingroup\$ You should be able to use Date.now() instead of new Date().getTime() and 48e4 instead of 480000. \$\endgroup\$ – powelles Jul 25 '17 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 Jul 25 '17 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. Jul 26 '17 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\$ – Justin Mariner Jul 26 '17 at 10:24
  • \$\begingroup\$ Oh, and your solution doesn't round to 2 decimal places like the challenge asks for. \$\endgroup\$ – Justin Mariner Jul 26 '17 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\$
  • \$\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\$ – xNinjaKittyx Jul 24 '17 at 20:53
  • \$\begingroup\$ Missed a space: String[]a) {new java \$\endgroup\$ – Stephen Jul 24 '17 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\$ – xNinjaKittyx Jul 24 '17 at 21:13
  • 1
    \$\begingroup\$ @xNinjaKittyx does now. \$\endgroup\$ – Magic Octopus Urn Jul 24 '17 at 21:22
  • 1
    \$\begingroup\$ record is 2027.03 BPM xD slightly modified the code for some better benchmarking \$\endgroup\$ – XtremeBaumer Jul 25 '17 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\$
  • 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\$ – TheLethalCoder Jul 25 '17 at 8:33
  • 2
    \$\begingroup\$ replace 540000.0 with 5.4e5 \$\endgroup\$ – Nazar554 Jul 25 '17 at 9:18
  • 1
    \$\begingroup\$ Well you'd do something like (end-start).Milliseconds and set end and start to DateTime.Now. \$\endgroup\$ – TheLethalCoder Jul 25 '17 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 Jul 25 '17 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\$ – Kamil Drakari Jul 25 '17 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\$
  • \$\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 Jul 25 '17 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\$ – HatsuPointerKun Jul 25 '17 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\$ – Zacharý Jul 30 '17 at 20:53
  • \$\begingroup\$ @Zacharý I get syntax errors \$\endgroup\$ – HatsuPointerKun Jul 30 '17 at 21:01
  • \$\begingroup\$ For some reason, my compiler complains about round. \$\endgroup\$ – Zacharý Jul 30 '17 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\$
  • \$\begingroup\$ What's the curses module do? Curse you? \$\endgroup\$ – Magic Octopus Urn Jul 24 '17 at 21:05
  • \$\begingroup\$ @MagicOctopusUrn Of course that's certainly what it does. \$\endgroup\$ – HyperNeutrino Jul 24 '17 at 21:10
  • \$\begingroup\$ time() needs to start at first input and not at program execution. \$\endgroup\$ – xNinjaKittyx Jul 24 '17 at 21:34
  • \$\begingroup\$ @xNinjaKittyx fixed; thanks \$\endgroup\$ – HyperNeutrino Jul 24 '17 at 22:28
  • \$\begingroup\$ @MagicOctopusUrn Jokes aside, it's a terminal-based GUI library. \$\endgroup\$ – Kroltan Jul 25 '17 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\$

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\$
  • 1
    \$\begingroup\$ Would it be shorter to just read directly from System.in? \$\endgroup\$ – Socratic Phoenix Jul 25 '17 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\$ – Justin Mariner Jul 25 '17 at 2:14
  • \$\begingroup\$ 25559105.43 bpm with this lol \$\endgroup\$ – V. Courtois Jul 26 '17 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\$
  • \$\begingroup\$ Does this also round correct with a CPM greater than 1000? \$\endgroup\$ – Roman Gräf Jul 25 '17 at 21:11
  • \$\begingroup\$ @RomanGräf woops, nope. Edited. \$\endgroup\$ – JAD Jul 26 '17 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, privacy policy and cookie policy

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