Big Ben goes BONG

45

6

Your task is to create a program that is to mimic Big Ben (Twitter).

Task

Whenever a new hour has begun (according to your computer's local time or UTC), you have to output BONG repeated hour times (with a space between the words). For example, when it's 3 o' clock, you have to output BONG BONG BONG. The time format follows the 12-hour time format, ie after 12 o' clock, we have 1 and not 13. The program/function must run forever.

Example:

don't output stuff inside the brackets

(start: 00:34 for example)
BONG               (01:00)
BONG BONG          (02:00)
(...)
BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG (12:00)
BONG               (01:00 again)
(...)
(it continues forever)

Rules

  • Each series of BONGs must be separated by a newline
  • Leading/trailing newlines are allowed
  • However leading/trailing spaces are not allowed
  • The submission must run forever
  • Your output may be printed ±3 seconds from the beginning of the hour
  • You may not assume the program to be run at any specific hour

This is , so the program with the shortest bytecount wins!

user41805

Posted 2016-12-25T15:11:09.203

Reputation: 16 320

6Testing these submissions is going to be fun... :D – FlipTack – 2016-12-25T15:16:59.243

1Can we assume starting the program exactly on midnight? – JAD – 2016-12-25T15:21:53.377

1@JarkoDubbeldam No, the program can be started from any hour – user41805 – 2016-12-25T15:22:30.990

@KritixiLithos Damn, that would've saved a bit. – JAD – 2016-12-25T15:24:44.873

Can you clarify "any hour"? Does that mean that the program can start at ±3 seconds from an exact hour or can be started at any time no matter whether it is a whole hour or not? – ElPedro – 2016-12-25T17:08:50.157

1@ElPedro The program can be started at any time from 00:00 to 23:59 – user41805 – 2016-12-25T17:10:01.247

@ETHproductions You can use whichever you prefer – user41805 – 2016-12-25T18:47:10.677

3for 12/24 do we print 0 bongs or 12 bongs? – Maltysen – 2016-12-25T22:42:46.227

6+1 for a challenge which isn't easily dominated by dedicated code-golfing languages. – Philipp – 2016-12-25T22:59:13.093

2How should the program behave if the system clock is wound back to before 1859? – Amani Kilumanga – 2016-12-26T06:47:48.557

2@Maltysen You need to print out 12 BONGs for 12/24 – user41805 – 2016-12-26T09:49:42.343

1Does it have to work across summertime changes? – Ben – 2016-12-26T12:12:30.277

1@BenAston No, there is no need to worry about that. – user41805 – 2016-12-26T12:13:28.153

3

For testing one can use LD_PRELOAD hack overriding time functions: https://github.com/vi/timeskew . TIMESKEW="60 1" makes minutes flow like seconds.

– Vi. – 2016-12-26T18:46:56.253

Answers

2

05AB1E, 43 bytes

3600žcžb60*+->Lvw}["BONG "ža<12%>×,5°36*.W]

Try it online! (lol this won't work, it will timeout in 60 seconds. Download the 05AB1E interpreter for this)

Explanation:

3600žcžb60*+->                          # Get amount of seconds (plus one) until next hour
              Lvw}                      # Wait said amount of seconds
                  [                     # Infinite loop start
                   "BONG "ža<12%>×,     # Print "BONG " multiplied by the amount of hours (12-hour clock)
                               5°36*.W  # Wait an hour (3600000 milliseconds)
                                      ] # Infinite loop end  

This took me a while to golf! I might be able to golf it a little more, but it beats *><>, so that's cool :)

Quick version:

1Uw["BONG "X<12%>×,wX>U]

Will wait one second on start, and one second between BONGs

Okx

Posted 2016-12-25T15:11:09.203

Reputation: 15 025

Sorry for the delay, I finally got to running your program locally. Well done, this is particularly good for an esolang! – user41805 – 2017-04-28T19:01:14.153

18

Bash, 71, 70, 69 bytes

EDITS:

  • Optimized the sleep interval computation a bit, -1 byte;
  • Replaced backticks with xargs, -1 byte (Thanks @jrtc27 !).

Golfed

sleep `date +3600-%s%3600|bc`;yes BONG|sed $(date +%I)q|xargs;exec $0

Explained

#Compute the number of seconds left in the current hour and wait.
sleep `date +3600-%s%3600|bc`; 

#Print "hour" (1-12) worth of "BONG" strings, one per line,
#use xargs to merge them into a single space-separated string.
yes BONG|sed $(date +%I)q|xargs

#Re-execute itself (in the same process).
exec $0

Test Version

Works with minutes instead of hours

sleep `date +60-%s%60|bc`;yes BONG|sed $(date +%I)q|xargs;exec $0

zeppelin

Posted 2016-12-25T15:11:09.203

Reputation: 7 884

2@zeppeIin I joined this community with the primary goal of worshipping you. Your solution is so full of sneaky tricks I'm still reeling from the awesomeness - especially yes BONG|sed 12q – neonzeon – 2016-12-26T19:21:51.083

@neonzeon wow :) – zeppelin – 2016-12-27T20:03:02.973

You can shave 1 byte off the echo by piping to xargs, which calls echo by default. 1 for pipe + 5 for xargs - 2 for backticks - 4 for echo - 1 for space = -1 byte. – jrtc27 – 2017-01-31T13:14:09.470

@jrtc27 That's an excellent advice! Thank you ! – zeppelin – 2017-01-31T18:31:01.297

8

*><>, 48 47 44 bytes

>s?um?uhc%:?!c21.O
v$o" GNOB"oooo$1-:?!
\aofS

Try it here! (or this version which does it every minute for testing)

This outputs a number of BONGs separated by spaces based on what hour it is (and 13 is 1, etc). There are no trailing space after the final BONG, and there is a trailing newline.

Technically this doesn't run forever (but it basically does). It leaks ~28 bytes per day (ignoring interpreter overhead ...). It would take ~105062 years for it to leak 1GiB.

Approximating for interpreter overhead, the stack is just a slice of float64s on the Golang interpreter. So I simply did 28*8 to come up with 224 bytes per day. I divided this number by the number of bytes in a gibibyte (1073741824) then 365 to approximate that it would take 13132.85 years to leak 1 GiB.

Note about the interpreters

The online interpreter is in Javascript. The page must be open and visible for it to check the time it currently is and output the BONGs. The Golang interpreter has no such limitation.

Explanation

Main loop:

s?um?u          O     if seconds == 0 && minutes == 0:
      hc%               push hours % 12 (bongs) to the stack
         :?!c           if bongs is 0, push 12 to the stack
             21.        jump to "output bongs" coords (2, 1)


Output bongs:

Begins at `"` because of the jump.

   " GNOB"            push "BONG " to the stack
          oooo        output "BONG"
              $1-     subtract 1 from bongs
v                :?!  if bongs == 0, move to "newline and sleep"
 $o                   output " "


Newline and sleep:

\                     mirror the IP to the right
 ao                   output a newline
   fS                 sleep for 1.6s
\                     mirror to main loop

redstarcoder

Posted 2016-12-25T15:11:09.203

Reputation: 1 771

What is the local timezone for the language's interpreter online? Because when a new hour struck for me, it didn't output anything – user41805 – 2016-12-30T07:53:38.283

@KritixiLithos, unfortunately for the online interpreter the page must be open and visible for it to work. I think this is a Javascript/browser limitation. You don't need to worry about it being online or not as the interpreter itself is in Javascript, you could download it yourself if you wanted! The Golang interpreter works regardless of anything though. Sorry for the inconvenience, I'll edit the answer to make that clear. – redstarcoder – 2016-12-30T12:24:48.203

1Congratulations on winning this challenge! This is the only golfing-lang to have completed this challenge and that's impressive :) – user41805 – 2017-01-07T12:03:40.987

@KritixiLithos thanks!! This is the first challenge I've won at all :D – redstarcoder – 2017-01-07T14:58:32.560

7

JavaScript (ES6), 99 93 bytes

f=_=>setTimeout('alert("BONG ".repeat(new Date/36e5%12|0||12).trim(f()))',36e5-new Date%36e5)

This uses UTC time (which lines up with the actual thing). Due to the untestable nature of the code, you can try the following which does the same thing, but every 60 seconds:

f=_=>setTimeout('alert("BONG ".repeat(new Date/36e5%12|0||12).trim(f()))',6e4-new Date%6e4)

f()

Here's a bonus 99-byte version which uses local time:

f=_=>setTimeout('alert("BONG ".repeat(new Date().getHours()%12||12).trim(f()))',36e5-new Date%36e5)

ETHproductions

Posted 2016-12-25T15:11:09.203

Reputation: 47 880

This (the snippet) alerts every minute for me (but the number of BONGs is correct), but the program is supposed to output every hour only – user41805 – 2016-12-25T19:06:42.547

@KritixiLithos "Due to the untestable nature of the code, you can try the following which does the same thing, but every 60 seconds:" ;-) – ETHproductions – 2016-12-25T19:07:50.093

6

JavaScript(ES6), 125 123 117 115 bytes

Thanks to @Flp.Tkc for saving 5 bytes!

Thanks to @BenAston for saving 2 more bytes!

a=eval(b=`(new Date).getHours()`);setInterval(w=>eval(b)!=a?console.log(Array(++a%12+1).join`BONG `.trim()):"",1e3)

Snack Snippet

a=eval(b=`(new Date).getHours()`);setInterval(w=>eval(b)!=a?console.log(Array(++a%12+1).join`BONG `.trim()):"",1e3)

user41805

Posted 2016-12-25T15:11:09.203

Reputation: 16 320

1@BenAston Thanks for noticing that :) – user41805 – 2016-12-25T16:41:36.813

1@BenAston It doesn't work without the first semi-colon – user41805 – 2016-12-25T16:43:45.520

5

Batch, 142 bytes

@timeout/t>nul 1
@if not %time:~3,5%==00:00 %0
@set/ah=-%time:~0,2%%12
@set s=............
@call set s=%%s:~%h%%%
@echo %s:.=BONG %
@%0

Since the file runs as an infinite loop, I start with a 1s delay, as I need one anyway after the bongs, and this saves CPU cycles. The >nul is positioned carefully to save a byte (1>nul would cause the 1 to be eaten by the redirection). We then loop until both minutes and seconds are zero. The bongs are constructed by taking the negative hour modulo 12, and asking for the last h characters from a 12-character string. When h is zero this actually gives us the whole string, therefore 12 bongs. It then suffices to replace the characters with the word BONG. When run it looks something like this (note that the image does not loop, so you'll need to force-reload to see the animation again):

Sample Output

Neil

Posted 2016-12-25T15:11:09.203

Reputation: 95 035

Could you provide a gif of it running and outputting? – user41805 – 2016-12-26T09:36:10.657

1@KritixiLithos Not sure what you're looking for here; I can take screenshots from before and after the hour and add a delay of up to 11 minutes in an animated GIF but I don't see how that proves anything. – Neil – 2016-12-26T13:58:24.120

I am asking for a gif because I can't test it on my computer (it's a mac) – user41805 – 2016-12-26T13:59:34.940

@KritixiLithos Something like this OK? – Neil – 2016-12-26T14:21:03.763

Good enough, I'll take your word for it :) – user41805 – 2016-12-26T14:21:39.910

Every time I see @ before every line, I feel compelled to suggest @echo off instead -- but it's shorter the way you have it. Stupid code golf. :( – Fund Monica's Lawsuit – 2016-12-26T15:54:22.823

@QPaysTaxes Indeed, usually I have at least one label which saves me an additional byte as it doesn't require an @. No such luck here! – Neil – 2016-12-26T16:10:37.630

5

Bash + Linux crontab, 90

I was hoping this would be shorter than the other shell answers. Still, I think it's an interesting approach:

for i in {0..11};{
s+=\ BONG
echo "0 $i,$[i+12] * * * echo$s>/proc/$PPID/fd/1"
}|crontab -

The script runs once, populates the crontab, then exits. However, the output from the cronjobs is sent to the terminal from which the script was run. I think this satisfies the submission must run forever requirement.

Warning - this will clear out any existing crontab entries, so make sure you have existing ones backed up.

This works on Ubuntu 16.04, which is using Vixie cron by default.

Digital Trauma

Posted 2016-12-25T15:11:09.203

Reputation: 64 644

I ran it and got some "mail". When I checkout out the mail, there was one more BONG than necessary. – user41805 – 2016-12-30T07:03:23.450

@KritixiLithos Thats odd. Which Linux distro are you using? Which cron are you using? – Digital Trauma – 2016-12-30T16:27:19.447

I'm on a mac, wait, that's not Linux – user41805 – 2016-12-30T16:32:18.467

@KritixiLithos Yup ;-). This answer relies on Linux /proc/<PID>/fd/<N>. – Digital Trauma – 2016-12-30T16:33:17.433

3

Ruby, 112 99 Bytes

loop{sleep 2;n=Time.now;if(n.min==0);puts ('BONG '*n.strftime('%I').to_i).chop;sleep 60-n.sec end}

Old Version

loop{sleep(2);n=Time.now; if(n.min.zero?) then puts ('BONG ' * n.strftime('%I').to_i).chop;sleep(60-n.sec) end}

Thanks to QPaysTaxes for the tips

Jatin Dhankhar

Posted 2016-12-25T15:11:09.203

Reputation: 141

@Flp.Tkc Oh yes, nice catch! Forgot to delete the last character – Jatin Dhankhar – 2016-12-25T16:02:09.263

I don't know ruby, but the program must output within 3 seconds of the start of the new hour. I don't think sleep(60) makes that happen – user41805 – 2016-12-25T16:02:27.620

@KritixiLithos We can make the program sleep for every 3 seconds and then do the caculation

Loop -> Wake every 3 Seconds ; Check time and do stuff ? – Jatin Dhankhar – 2016-12-25T16:06:39.083

@JatinDhankhar Or you can make it sleep for 2 seconds (just to give some breathing space) – user41805 – 2016-12-25T16:07:53.173

@KritixiLithos Yes, making the change to 2 seconds than Thanks – Jatin Dhankhar – 2016-12-25T16:12:59.830

This is 81 bytes. And when I ran this program, there was a leading space. Could you fix this? – user41805 – 2016-12-25T19:03:44.753

Will this only print out one set of bongs per hour? It looks like it will print until the end of the minute – Blue – 2016-12-25T21:37:13.453

@muddyfish you are correct, also the code needs one space not to throw NoMethodError. – Borsunho – 2016-12-25T23:08:33.897

@OP if you fix this ping me and I'll change to an upvote – Blue – 2016-12-25T23:19:25.517

@muddyfish Fixing this

Here is my algorithm now Start Loop Sleep for 2 seconds Check Time, store it in a variable If minute is zero ; BONG the time and sleep for remaining time until next minute turns up (60 - time.sec)

If time was captured at 15 sec then we do the BONG then make it sleep for (60 - 15) = 45 secs and wake it again

Is it okay ? Updated the answer but it – Jatin Dhankhar – 2016-12-26T06:19:41.747

@KritixiLithos I ran the program and there is no leading space. Also I used wc to calculate byte size. Can you point me where I am wrong ? – Jatin Dhankhar – 2016-12-26T06:23:17.997

@JatinDhankhar It works now :) – user41805 – 2016-12-26T11:13:03.540

Use ; in place of then, get rid of every space after a ; or close-paren, use ==0 instead of .zero?, Get rid of the spaces around *, use .hour instead of that .strftime nonsense, remove the parens around the argument to sleep (put a space before them instead). – Fund Monica's Lawsuit – 2016-12-26T18:09:52.703

@QPaysTaxes Thanks for the tip. I wanted to use hour but it gives output in 24 hour format but question asks for hour in 12 hour format and then I would have to use conditions and mod. – Jatin Dhankhar – 2016-12-27T05:52:23.840

(n.hour%12+1) is shorter than n.strftime("%I").to_i. Also, you don't need the parens around the condition to if. Finally, I'm not sure that the sleep 60-n is doing anything except making your program more efficient, and this is code golf, so we don't care about that. If you can get rid of that, you can turn the condition into an inline if, which gets rid of the end. – Fund Monica's Lawsuit – 2016-12-27T14:20:15.627

@QPaysTaxes (n.hour%12 + 1) is not correct. If time is 20:XX hours which is 8 PM should BONG 8 times but (20%12+1) is 9 if we remove it would for all cases except when time is 12:00 as (12%12+1) will give 1 whereas (12%12) will give 0. You are right about sleep 60-n times but if this program runs for say infinite time but if we don't allow it to sleep it may print BONG continuously for about a minute. If time is 20:00:00 if condition is triggerred and will BONG then will continue to do so unitl minute changes to 1. Are there any more approaches around it ? – Jatin Dhankhar – 2016-12-27T14:40:07.113

3

Python 2, 105 106 bytes

import time
h=0
while 1:
 l=time.localtime();c=l[3]%12
 if l[4:6]==(0,0)and h!=c:print('BONG '*c)[:-1];h=c

Edit

Added one byte by changing < to != after feedback from @pinkfloydx33. Good spot.

Tested as much as possible locally but doesn't work on TIO as it (obviously) exceeds the 60 second execution limit. Please feel free to test locally :-)

btw, losing that pesky trailing space cost me 7 bytes otherwise this would have been under 100.

In the absence of TIO here is output after waiting an hour. Prog was started at 15:27 with extra debug code to show the time of the print (12 hour format).

python bigben.py
time is 4:0:0
BONG BONG BONG BONG
time is 5:0:0
BONG BONG BONG BONG BONG

Pretty straightforward but here is an explanation for anyone who is interested.

import time                 #Import the time module
h=0                         #Create a variable to store the hour that has just been printed
while 1:                    #Loop forever
 l=time.localtime()         #Get the local time from the time module
 c=l[3]%12                  #Set a variable to the current hour in 12 hour format
 if l[4:6]==(0,0)and h!=c:   #If minutes=0 and hours=0 and the last hour that was printed is not the current hour
  print "time is "+`c`+":"+`l[4]`+":"+`l[5]`    #Debug code to show hour
  print('BONG '*c)[:-1]     #Print 'BONG '*number of hours and lose the space from the end 
  h=c                       #Update the last hour that was printed

ElPedro

Posted 2016-12-25T15:11:09.203

Reputation: 5 301

1You can just check if the minutes are 0: l[4]==0and h<c. – Carra – 2016-12-25T18:51:22.817

Now that I think of it, there's the small problem that it doesn't work if you start the timer on 20:00:01. Minutes will be zero, seconds not and it will print the bongs – Carra – 2016-12-25T19:04:39.727

This doesn't output anything when I ran it locally – user41805 – 2016-12-26T11:10:20.847

@KritixiLithos No idea why you get no output. I'm on Ubuntu 14 and Python 2.7.9. Want to take this to chat to discuss further? – ElPedro – 2016-12-26T16:04:42.737

2Does this work from 11h->12h. (12%12=0)? Seems that 11>0, so h>c or am I missing something? – pinkfloydx33 – 2016-12-27T10:40:04.717

3

Python 3 - 100 97 92 bytes

from time import*
while 1:x=3600;sleep(x-time()%x);print(('BONG '*int(strftime("%I")))[:-1])[:-1])

Explanation:

import time;
while 1:
 t=time;x=3600;
 t.sleep(x-t.time()%x);#sleep for the remaining seconds until the next hour
 print(('BONG '*int(t.strftime("%I")))[:-1])#strftime("%")=nr of hours (1-12). Print the bongs and remove the last char

Carra

Posted 2016-12-25T15:11:09.203

Reputation: 301

from time import*<NL>while 1:x=3600;sleep(x-time()%x);print(('BONG '*int(strftime("%I")))[:-1]) is 93 bytes – Roman Gräf – 2016-12-27T11:32:08.657

I don't think you need the semicolon at the end of the first line. – Fund Monica's Lawsuit – 2016-12-27T14:20:49.730

Removed the trailing ; – Carra – 2016-12-29T15:43:50.647

92 bytes if you do from time import*, like this

– FlipTack – 2016-12-30T12:30:37.010

Thanks for the tip, I've added it. Learning new things about Python every day :) – Carra – 2016-12-30T14:24:11.533

3

Ruby, 82 81 bytes

loop{l=Time.new
puts ("BONG "*(l.hour%12+1)).chop if(l+1).hour!=l.hour
sleep 1}

Every second we check whether it's last second of the hour, and BONG accordingly. Could probably be golfed further with some dirty tricks, but I don't know too many. Also it works differently than the other Ruby answer.

One byte saved thanks to courtesy of QPaysTaxes.

Borsunho

Posted 2016-12-25T15:11:09.203

Reputation: 261

Need to get into Ruby. It seems a bit less verbose than Python for golfing. – ElPedro – 2016-12-26T14:50:40.997

Do you need the space immediately after if? – Fund Monica's Lawsuit – 2016-12-26T16:04:11.723

@QPaysTaxes I don't, thank you. I was so mad about space after puts I forgot about that one. – Borsunho – 2016-12-26T18:03:21.907

3

Cheddar v1.0.5, 162 bytes

Cheddar has no built-in time reader/cmd output reader, so I had to improvise!

Golfed:

var f=->{IO.exec("time/t>c");(String::IO.read("c")).split(":")};var a=f()[0];for(;1;){var b=f();if(b[0]!=a){var c=Number::(a=b[0]);print("BONG "*c).head(5*c-1);}}

Ungolfed:

var f=->{
    IO.exec("time/t>c");
    (String::IO.read("c")).split(":")};
var a=f()[0];
for(;1;){
    var b=f();
    if(b[0]!=a){
        var c=Number::(a=b[0]);
        print("BONG "*c).head(5*c-1);
    }
}

Explanation:

Due to Cheddar's limited standard library, I had to use cmd to generate the time. I did this by saving the output of "time /t", which prints the time in 12-hour format, to a file named "c". IO.read returns a buffer which I casted to a string and split by ":" which ensured the hour is always in index zero. I saved that whole operation into a lambda expression which saved me 44 bytes. After that point it goes into the logic of "if stored hour doesn't equal current hour, set previous hour to current and print BONG n times, trim off the trailing space."

Cheddar may not be the least verbose language but it can be fun to find workarounds like this!

Sadly this is a Windows-only solution.

Edit 1: Saved two bytes by replacing "0<1" in the for-condition to "1" I didn't expect 1 to evaluate to true in this language!

Zavada

Posted 2016-12-25T15:11:09.203

Reputation: 189

2

C, 238 bytes

#include<time.h>
#include<unistd.h>
i,j;f(){time_t t=time(0);struct tm l=*localtime(&t);for(;;){t=time(0),l=*localtime(&t),j=l.tm_hour;sleep(1);if(!(l.tm_min+l.tm_sec)){j=j%12?j<12?j:j-12:12;for(i=0;i<=j;i++)printf("BONG%c",i^j?32:10);}}}

I'm not sure if this works correctly, and I'm mobile, and my phone doesn't have a C compiler. (Only works on UNIX-like systems)

betseg

Posted 2016-12-25T15:11:09.203

Reputation: 8 493

This produced infinite output (newlines) when I tried it – user41805 – 2016-12-25T19:01:49.007

@KritixiLithos yes, I forgot to remove the part that I don't use anymore. Can you test in 7 minutes? :) – betseg – 2016-12-25T19:53:38.927

f instead of main? How is this supposed to work? – Thomas Padron-McCarthy – 2016-12-26T13:10:14.823

1@ThomasPadron-McCarthy I'm fairly sure that providing a function, as opposed to a full program, is fine. – Fund Monica's Lawsuit – 2016-12-26T15:55:37.610

2

sh, 66 bytes

yes 'echo `yes BONG|sed $(date +%I)q`'|sh -s|awk '$0!=a&&a;{a=$0}'

Explained

#Pipe a command into a subshell repeatedly
yes 'some command'|sh -s

#Print "hour" (1-12) worth of "BONG" strings, one per line,
#use backticks to merge them into a single space-separated string.
#(stolen from zeppelin's answer)
echo `yes BONG|sed $(date +%I)q`

#Print every time the output changes
awk '$0!=a&&a;{a=$0}

Rainer P.

Posted 2016-12-25T15:11:09.203

Reputation: 2 457

This prints immediately once the program is run, it should not do that. The program must only output when a new hour has began – user41805 – 2016-12-26T17:11:17.857

The same problem still appears – user41805 – 2016-12-26T17:22:20.423

@KritixiLithos My bad. I had only updated explanation and byte count, not the actual code. – Rainer P. – 2016-12-26T17:32:03.377

Now all that is remaining is for me to test it at the hour – user41805 – 2016-12-26T17:33:23.057

@KritixiLithos Replace %I with %M and it works for minutes. – Rainer P. – 2016-12-26T17:34:25.337

1

R, 104 105 bytes

f=format;repeat{Sys.sleep(1);q=Sys.time();if(f(q,"%M%S")=="0000")print(rep("BONG",as.double(f(q,"%I"))))}

Each second, it will (should) test whether we are at the end of an hour, then print that amount of BONGs.

JAD

Posted 2016-12-25T15:11:09.203

Reputation: 2 898

When will this program output when the program is run at 12:00:01? – user41805 – 2016-12-25T15:25:29.363

I don't know R, but the program must output within 3 seconds of the start of the new hour. I am not really sure if Sys.sleep(60) makes that happen – user41805 – 2016-12-25T16:04:21.647

You can replace while(1) by repeat. – plannapus – 2016-12-25T18:10:26.527

The sleep interval must be shorter than the grace period after the hour for correctness. How about Sys.sleep(2) ? – newcoder – 2016-12-26T05:35:44.627

Come to think of it, why sleep at all? – newcoder – 2016-12-26T05:38:46.073

Oh, I missed the seconds requirement. I'll change the solution when I get back to my pc. – JAD – 2016-12-26T13:45:15.493

@KritixiLithos Woops, fixed now. – JAD – 2016-12-27T12:07:38.950

1@newcoder Each loop it sleeps for 1 second now, because otherwise it would print BONG for 1 second, instead of just once. This is to ensure it only checks once per second. – JAD – 2016-12-27T12:09:07.647

1

JavaScript ES2015, 100 99 98 96 94 88 bytes

h=_=>new Date/36e5%12|0,p=h();for(;;)h()!=p&&(p=h(),alert('BONG '.repeat(p||12).trim()))

Explanation:

h is a function that gets the 12-hour-based hour of the day using the remainder operator (%12). 36e5 is the number of milliseconds in one hour using the exponential syntax to save characters. The new operator does not require that parentheses are used with functions if there are no arguments, hence new Date. JavaScript only has floating point arithmetic, the | bitwise OR operator forces the number to be an integer because JS bitwise operators work with the integer subset of the numbers represented by IEEE 754 floating point.

The comma delineates sub-expressions. p is initialized to the current hour (p=h()).

for(;;) is used to check repeatedly whether any BONGs should be alerted. Checking is performed as rapidly as the runtime will allow.

If the hour has changed (h()!=p), then we update p and then alert the BONGs. The logical AND operator is used as a guard (it short-circuits if h()===p) to determine if the BONGs are output.

String.prototype.repeat is new in ES2015 and saves some characters over using something like ES5's Array.prototype.join.

h returns zero for exact multiples of 12 (i.e. 12pm, 12am), so we change it to 12 using the logical OR p||12.

With thanks to Kritixi Lithos and ETHProductions for ideas.

Ben

Posted 2016-12-25T15:11:09.203

Reputation: 111

I think you can remove the last semi-colon – user41805 – 2016-12-26T09:42:37.210

1

C, 198 bytes

#import<time.h>
h,i;f(){time_t t=time(0);struct tm l=*localtime(&t);for(h=l.tm_hour;;t=time(0),l=*localtime(&t))if(h-l.tm_hour%12){h=l.tm_hour%12;for(i=h?h%12:12;--i;)printf("BONG ");puts("BONG");}}

Steadybox

Posted 2016-12-25T15:11:09.203

Reputation: 15 798

1

Javascript ES6 87 bytes

Edit: Shamelessly borrowed @ETHProductions' new Date/36e5%12|0||12 code to save 6 bytes

setInterval('Date().match`:00:00`?alert("BONG ".repeat(new Date/36e5%12|0||12)):5',1e3)

Kuilin Li

Posted 2016-12-25T15:11:09.203

Reputation: 421

1

Excel VBA, 143 Bytes

Code Outputs to the VBE Immediates Window

Sub b:Do:n=Now
If Minute(n)=0 Then:s="":For i=1To Hour(n) Mod 12:s=s &"BONG ":Next:Debug.?Trim(s):Application.Wait n+#0:1#:End If:Loop:End Sub

Fun version, 143 Bytes (Non-Competing)

While it would be rather difficult to get excel to go BONG, it is pretty straight forward to get excel to go Beep. The Beep call produces a beeping sound, and the code below uses this to produce beeps indicating the hour, on the hour, separated by 1 second pauses.

As with above, it this code makes excel appear unresponsive and adding a :DoEvents call to the end of the first line is recommended as it improves the user experience, however, this is not necessary for correct code execution.

Sub b:Set a=Application:Do:n=Now
If Minute(n)=0 Then:For i=1To Hour(n) Mod 12:Beep:a.Wait(Now+#0:0:1#):Next:a.Wait(n+#0:1#):End If:Loop:End Sub

Ungolfed Version

Public Sub BigBen()
    Dim i As Byte
    Dim n As Date
    Dim w As Worksheet
    Dim a As Excel.Application
    Set a = Application
    Set w = a.ThisWorkbook.Sheets(1)
    Let w.Name = "Big Ben"

    Let w.[A1] = Now
    w.Columns("A:A").AutoFit

    Do
        DoEvents
        Let n = Now
        If Minute(n) = 0 Then

            ''  Print BONG
            Let s = ""
            For i = 1 To Hour(n) Mod 12 Step 1
                Let s = s & "BONG "
            Next i
            Debug.Print Trim(s)

            ''  Go Beep
            For i = 1 To Hour(n) Mod 12 Step 1
                Beep
                a.Wait (Now + #12:00:01 AM#) ''  <- #0:0:1# resolves to #12:00:01 AM#
            Next i

            ''  Keep Ticking After Going BONG
            While Now < n + #12:01:00 AM#    ''  <- #0:1# resolves to #12:01:00 AM#
                Let w.[A1] = Now
                Let a.StatusBar = IIf(Second(Now) Mod 2, "Tick", "Tock")
                DoEvents
            Wend
        End If

        ''  Tick Tock until its time to Go BONG again
        Let a.StatusBar = IIf(Second(n) Mod 2, "Tick", "Tock")
        Let w.[A1] = Now
    Loop

End Sub

Taylor Scott

Posted 2016-12-25T15:11:09.203

Reputation: 6 709

Is it possible to test this on a non-Windows computer? If not, could you provide a gif of the output when a new hour begins? – user41805 – 2016-12-27T14:21:42.403

To be entirely honest, I am not immediately sure. It will not be possible to test this code on a linux machine, but it should function properly on a Mac.

However, it may be that the Beep or DoEvents Calls do not function properly on mac machines. – Taylor Scott – 2016-12-27T14:24:16.380

0

C# 234 Bytes

I'm not planning on winning any prizes here, but a C# implementation is compulsory.

using System;
using System.Linq;namespace B{class P{static void Main(){Func<int> h=()=>DateTime.Now.Hour % 12;var p=h();while (true){var t=h();if (t!=p)Console.WriteLine(string.Concat(Enumerable.Repeat("BONG",t== 0?12:t)));p=t;}}}}

Ungolfed with comments:

using System;
using System.Linq;

namespace B
{
    class P
    {
        static void Main()
        {
            Func<int> h = () => DateTime.Now.Hour % 12; // h(): the hour in the range [0, 11], making this a lambda saves a few chars
            var p = h(); // p: Previous time
            while (true)
            {
                var t = h(); // t: Current time
                if (t != p) // If current hour is different to previous hour
                    Console.WriteLine(string.Concat(Enumerable.Repeat("BONG", t == 0 ? 12 : t))); // Print "BONG" t times (also correcting t = 0 to 12)
                p = t; // Current time is now previous time
            } // Repeat ad nauseum
        }
    }
}

Pharap

Posted 2016-12-25T15:11:09.203

Reputation: 195

1Use for(;;), change h=()=>1+(DateTime.Now.Hour-1)%12; (note no whitespace either) and then Enumerable.Repeat becomes ("BONG",t) (saves you either two or three) then get rid of extra whitespace ie if(...) Also note this will print all the bongs concatenated, probably take those byte savings to turn concat into join with a space as its first argument. – pinkfloydx33 – 2016-12-27T11:16:53.117

0

Groovy, 72 bytes

{x={new Date().getHours()};y=x();while(1){if(y!=(y==x()){print "BONG "*y}}​}​​​

How?

Store a method to get current hours.

x={new Date().getHours()};

Store initial hours.

y=x();

While true, if current hour not equal previous hour, output current hour multiplied by "BONG " to output current hour of bongs.

while(1){if(y!=(y==x()){print "BONG "*y}}

+3 bytes %12 for non-military bongs.

Magic Octopus Urn

Posted 2016-12-25T15:11:09.203

Reputation: 19 422

0

QBIC, 82 bytes

X=$left$|(_d,2){Y=left$$|(_d,2)~Y<>X|x=!Y!%12~x=0|x=12]B=C[x|B=B+@BONG |]?_tB|]X=Y

Really need to change the token for code literals ($) and implement a substring feature (left$(x,y) can be shorter).

The inner workings:

In the first part, we want to set X$ to the hour-component
of our system's time. The DATE is implemented in QBIC, but
Substring (LEFT$, RIGHT$ and MID$ in QBasic) is not (yet).
We need to use the QBasic LEFT$ function, and QBIC can do 
that using a 'code literal': everything from '$' to '|'
is not parsed by QBIC but passed on to QBasic.
X=               Set X$ to
$left$|(         the leftmost (note the '$' and '|' for the code literal)
_d,2)            2 characters of TIME$ (hh:mm format)
{                DO - infinite loop
Y=left$$|(_d,2)  Set Y$ in the same way
~Y<>X            If Y$ is not equal to X$ the hour has changed
|x=!Y!%12        THEN set x to the modulo 12 of Y$ cast to number
~x=0|x=12]       If Y% happens to be divisible by 12, set x to 12
B=C              Clear B$ (c$ never gets assiged a value)
[x|B=B+@BONG |]  For the given number of hours, add "BONG " to B$
?_tB|            Print B$, trim the trailing space
]                end if
X=Y              Update X$
<DO LOOP is implicitly closed>

Update (NC): The $ is no longer used in QBICs instruction set, so it can now be used freely as code for QBasic without the need for code literals. In this case, it saves 4 bytes, bringing QBIC to 78 bytes:

X=left$(_d,2){Y=left$(_d,2)~Y<>X|x=!Y!%12~x=0|x=12]B=C[x|B=B+@BONG `]?_tB|]X=Y

steenbergh

Posted 2016-12-25T15:11:09.203

Reputation: 7 772

0

perl, 60 bytes

Update

Replaced " " with $", removed CORE::, corrected count.

Golf

say join$",(BONG)x(time/3600%12||12)while sleep -time%3600+1

This needs to be run with perl -E.

Remarks

  • In perl, x while y is equivalent to while(y){x} (where x is a single statement) but does not need the brackets. sleep is executed the first time before anything is printed.
  • time uses UTC. The original Big Ben is on summer time (British Summer Time, BST) from the end of March until the end of October.
  • One second is added to the wait time in order to ensure that the program waits for at least one second. This means that the BONGs will always be printed one second late, which is legal according to the rules. Let's say you're standing on Westminster Bridge, ca. 300 m away from Big Ben. On the plus side, this also means that the program will print the correct amount of BONGs if it is started at exactly the beginning of an hour (instead of waiting 3600 seconds).
  • sleep returns the number of seconds waited. This will always be true.

cfaerber

Posted 2016-12-25T15:11:09.203

Reputation: 1

12 things. 1, I'm pretty sure the -E flag is +1 byte (there's a page somewhere about measuring flags...). 2, I'm not sure how to run this as perl -E golf.pl appears to terminate immediately. – redstarcoder – 2016-12-30T16:44:45.620

0

SmileBASIC, 74 67 bytes

WAIT 61TMREAD OUT H,M,S?("BONG"+" BONG"*((H+11)MOD 12))*!(M+S)EXEC.

Outputs large amounts of "trailing" line breaks ;)

Edit: saved 7 bytes with a better 24->12 hour algorithm.

12Me21

Posted 2016-12-25T15:11:09.203

Reputation: 6 110

0

PHP, 63 bytes

I could save two more bytes with extended ASCII. But I am currently too lazy for that.

for(;;sleep(1))+date(is)?:print str_pad("
",5*date(h),"BONG ");

prints the BONGs with a leading linebreak precisely at the full hour. Run with -nr.

Titus

Posted 2016-12-25T15:11:09.203

Reputation: 13 814

You have to include the flags in your bytecount – user41805 – 2017-01-31T07:28:23.280

@KritixiLithos No I don´t. -n is kind of implicit (ignore php.and fall back to default config values); -r tells PHP to run code from a command line parameter instead of from a file.

– Titus – 2017-01-31T07:36:16.930

Ah, my bad, I don't know PHP. – user41805 – 2017-01-31T09:15:08.140

0

C, 152

int a=0,i,L=25;main(){char s[9];for(i=-1;++i<48;){sprintf(s,"%02i:00:00",i);if(!strcmp(s,__TIME__)&&i!=L)a=L=i,i=-1;printf(a-->0?"BONG ":"\n");}main();}

Readable:

int a=0,i,L=25;

main(){
    char s[9];
    for(i=-1;++i<48;){
        sprintf(s,"%02i:00:00",i);
        if(!strcmp(s,__TIME__)&&i!=L)
            a=L=i,i=-1;
        printf(a-->0?"BONG ":"\n");
    }
    main();
}

Albert Renshaw

Posted 2016-12-25T15:11:09.203

Reputation: 2 955