15
\$\begingroup\$

What's the Binary Time?

Everybody knows what the normal time is. It's up there in the top-right (or wherever you put it) of your screen. But a question people rarely seem to ask themselves is this: What's the binary time?

Binary Time

Binary Time (True Binary Time) works by first reading the most significant bit (MSB) of the number. If that number is 0, the time expressed is before noon. If that number is 1, the time expressed is after noon. The next bit splits the half of the day the first bit expressed into two more equal halves, this time of 6 hours. The following bit splits into 3 hours, the next 90 minutes, and so on. Times like 12:00:00, where it seems it should be neither, become 1.

I can only understand this strange system of timing, so I need a program to convert to that for me. But as binary numbers are Base-2, and 2 is a small number, your program must be as short as possible.

Requirements

  • Your program should take a time (as 24-hour-time) as input and output the corresponding binary time number.
  • The output number should have 16-bit precision (the number should be 16 digits long).
  • You cannot use a builtin that does all of that conversion for you.
  • You should floor if it needs to be rounded.

Rules

Test Cases

00:00:00 ==> 0000000000000000
12:00:00 ==> 1000000000000000
01:30:00 ==> 0001000000000000
10:33:06 ==> 0111000010001101
09:57:30 ==> 0110101000111000
06:00:00 ==> 0100000000000000
18:00:00 ==> 1100000000000000

Scoring

To win, as I mentioned earlier, you must have the least bytes.

Submissions

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

Leaderboard

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

/* Configuration */

var QUESTION_ID = 81057; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 53406; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    if (/<a/.test(lang)) lang = jQuery(lang).text();
    
    languages[lang] = languages[lang] || {lang: a.language, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang > b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<div id="language-list">
  <h2>Winners by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

\$\endgroup\$
9
  • 3
    \$\begingroup\$ Can I input as [hour, minute, second]? We don't like restricting input format. \$\endgroup\$
    – Leaky Nun
    Jun 1, 2016 at 9:51
  • 2
    \$\begingroup\$ How does 09:57:30 make 0110110000000000? \$\endgroup\$
    – Leaky Nun
    Jun 1, 2016 at 10:11
  • 2
    \$\begingroup\$ 16 bits can only represent 65536 values. There are 86400 seconds in a day. How should we represent anything that does not exactly match a binary representation? \$\endgroup\$ Jun 1, 2016 at 10:11
  • \$\begingroup\$ Can we return the result as a list of 16 numbers? \$\endgroup\$
    – Adám
    Jun 1, 2016 at 10:19
  • \$\begingroup\$ @Adám Yes, you can. \$\endgroup\$
    – user53406
    Jun 1, 2016 at 10:32

11 Answers 11

5
\$\begingroup\$

CJam, 20 bytes

l':/60b9m<675/2bG0e[

Test suite.

Explanation

Makes use of the fact that 65536 (216) over 86400 (the number of seconds in a day) simplifies to 512 over 675.

l     e# Read input.
':/   e# Split around ':', so we get ["hh" "mm" "ss"].
60b   e# Interpret as base-60 digits, which computes hh*60^2 + mm*60 + ss,
      e# i.e. it computes the total number of seconds. Note that this implicitly
      e# converts all three strings to integers.
9m<   e# Bitwise left-shift by 9 positions, which is the same as multiplying by
      e# 2^9 = 512.
675/  e# Divide by 675, flooring the result.
2b    e# Convert to binary.
G0e[  e# Left-pad with zeros to 16 digits.
\$\endgroup\$
3
\$\begingroup\$

Pyth, 31 27 bytes

.[\016.Bs*512cisMcQ\:60 675

Test suite.

Converts the input into number of seconds passed, multiply by a factor of 2^16 / 24*60*60, and then floor and convert to 16-bit binary.

Saved 4 bytes by simplifying 65536/86400 into 512/675 (stupid me).

Input/output

00:00:00    0000000000000000
11:00:00    0111010101010101
12:00:00    1000000000000000
01:30:00    0001000000000000
10:33:06    0111000010001101
09:57:30    0110101000111000
06:00:00    0100000000000000
18:00:00    1100000000000000
23:59:59    1111111111111111
\$\endgroup\$
6
  • \$\begingroup\$ Can you justify "and then floor"? \$\endgroup\$ Jun 1, 2016 at 10:08
  • \$\begingroup\$ @PeterTaylor What should I do instead? \$\endgroup\$
    – Leaky Nun
    Jun 1, 2016 at 10:15
  • 4
    \$\begingroup\$ Wait until the spec has been disambiguated before posting an answer. \$\endgroup\$ Jun 1, 2016 at 10:16
  • \$\begingroup\$ @PeterTaylor The right way of rounding is apparent by 10:33:06. \$\endgroup\$
    – Adám
    Jun 1, 2016 at 11:45
  • \$\begingroup\$ @Adám, not really, because that gives the same output with floor and round-to-nearest. \$\endgroup\$ Jun 1, 2016 at 12:01
3
\$\begingroup\$

TSQL(sqlserver 2012), 103 bytes

DECLARE @d datetime = '10:33:06'

DECLARE @ char(16)='',@x INT=cast(@d as real)*131072WHILE
len(@)<16SELECT @x/=2,@=concat(@x%2,@)PRINT @

Try it online

Ungolfed

DECLARE @d datetime = '10:33:06'

DECLARE @ char(16)='',
        @x INT=cast(@d as real)*131072
WHILE len(@)<16
SELECT @x/=2,@=concat(@x%2,@)
PRINT @

TSQL(sqlserver 2012), 119 106 bytes

Also included a different version without the variable @x, however it was a few bytes longer. Including the ungolfed version for those interested:

DECLARE @d datetime = '23:59:59'

DECLARE @ varchar(16) =''
WHILE LEN(@)<16
SET @+=LEFT(CAST(@d as decimal(9,9))*2*POWER(2,LEN(@))%2,1)
PRINT @
\$\endgroup\$
4
  • \$\begingroup\$ That doesn't look golfed. Can't you remove a lot of whitespace? \$\endgroup\$
    – Adám
    Jun 1, 2016 at 15:35
  • \$\begingroup\$ @Adám it is very goolfed, I used different methods than the standard to make the script shorter and even tried a different method. I just had an accidental whitespace put in when coping my answer into codegolf(only one extra). I wanted to put a linebreak there, but decided to put it after WHILE instead. Removing the space and wondering if you really downvoted me for that single extra space \$\endgroup\$ Jun 1, 2016 at 16:14
  • \$\begingroup\$ @Adám and if you are looking at the second method, it is not golfed(except the character count), since it is not my actual answer. Just a different more calculating method of solving it \$\endgroup\$ Jun 1, 2016 at 16:21
  • 3
    \$\begingroup\$ No, I didn't downvote. It was probably someone who has a principle to downvotes all answers that are posted before the OP clarifies outstanding rule questions. All but the very newest answer has exactly one downvote. (It was probably Peter Taylor, because he was last here just before that post, and he has been complaining about this.) You can see this when you get enough rep. Here, have some! \$\endgroup\$
    – Adám
    Jun 1, 2016 at 17:36
2
\$\begingroup\$

JavaScript (ES6), 72 76 bytes

Edit 4 bytes save thx @Neil

Still unclear about the rounding. This one truncates and that's ok.

t=>(t.split`:`.map(v=>t=+v+60*~~t),t*512/675|65536).toString(2).slice(1)

Test

f=t=>(t.split`:`.map(v=>t=+v+60*~~t),t*512/675|65536).toString(2).slice(1)

function test() {
  var v=I.value
  R.textContent=f(v)
}

test()


;`00:00:00 ==> 0000000000000000
12:00:00 ==> 1000000000000000
01:30:00 ==> 0001000000000000
10:33:06 ==> 0111000010001101
09:57:30 ==> 0110101000111000
06:00:00 ==> 0100000000000000
18:00:00 ==> 1100000000000000`
.split('\n').forEach(t=>{
  [i,k]=t.split(' ==> ')
  r=f(i)
  ok=r==k
  O.textContent += (ok ? 'OK ':'KO ')+ i + ' -> ' + r + (ok? '\n' : ' Expected '+k+'\n')
})
<input id=I value='12:34:56' oninput=test()>
<span id=R></span>
<pre id=O></pre>

\$\endgroup\$
6
  • \$\begingroup\$ am trying to figure out why this was downvoted \$\endgroup\$ Jun 1, 2016 at 14:01
  • \$\begingroup\$ t=>([h,m,s]=t.split`:`,(+h+m/60+s/3600)*8192/3|65536).toString(2).slice(1) saves you 2 bytes, but reduce goes one byte further: t=>(t.split`:`.reduce((n,m)=>+m+n*60)*512/675|65536).toString(2).slice(1) \$\endgroup\$
    – Neil
    Jun 1, 2016 at 19:06
  • \$\begingroup\$ Downvote without a comment is not cool, upvoted \$\endgroup\$ Jun 1, 2016 at 19:46
  • \$\begingroup\$ @Neil thank you very much! And with .map 1 more byte saved \$\endgroup\$
    – edc65
    Jun 1, 2016 at 20:12
  • \$\begingroup\$ Huh, I was wondering where you were going to get the 0 from for the map... \$\endgroup\$
    – Neil
    Jun 1, 2016 at 20:52
1
\$\begingroup\$

MATL, 15 bytes

YOtk-KWW*k16&YB

Uses a builtin for converting a string representing time to a serial date/time number, which is allowed by the challenge.

Try it online!

Explanation

YO       % Input time string. Convert to serial date/time. Time is fractional part
tk-      % Duplicate, round down, subtract. This keeps fractional part only
KWW      % 34, 2 raised to, 2 raised to (`16W` would require an extra space)
*        % Multiply
k        % Round down
16&YB    % Convert to binary string with 16 digits. Display
\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog), 24 21 bytes

The rules have now been clarified.

Prompts for time as 3-element list.

(16/2)⊤⌊512×675÷⍨60⊥⎕

Edit: Updated () to match new result for 10:33:06.

Try it online!

 prompt for input

60⊥ evaluate in base-60

675÷⍨ divide by 675

512× multiply by 512

 floor

()⊤ convert to (mnemonic: upside-down base is anti-base) the following number system:

16/2 replicate 2 sixteen times (i.e. 16-bit binary)   

\$\endgroup\$
0
0
\$\begingroup\$

Q, 32 Bytes

48_0b\:_(512%675)*60/:"I"$":"\:

Test

   t "00:00:00"
0000000000000000b
   t "12:00:00"
1000000000000000b
   t "01:30:00"
0001000000000000b
   t "10:33:06"
0111000010001101b
   t "09:57:30"
0110101000111000b
   t "06:00:00"
0100000000000000b
   t "18:00:00"
1100000000000000b
  • In order to reduce display cluttering, i assume a slight modification to the original expression, that gives name t to the lambda

  • b suffix indicates binary

Explanation

NOTE.- read left to right, evaluates right to left

Reads as: 48 drop from binary representation of floor of 512 divideb by 675 and multiplied by 60 scalarFromVector over integer cast from splits at ":" original string

Evaluation:

":"\:x splits string x (implicit arg of the lambda) at ":" character (Q uses "" to denote char)

"I"$x cast string(s) x to int(s) -> hours, minutes, seconds

60/:x uses base 60 to calculate a single value from a sequence of ints -> seconds total

(512%675)*x calculates ratio 512%675 (% is divide) and multiplies seconds. 512%675 is the simplified form of the fraction (totalSecondsPerDay%64K)

_ x indicates floor of float x

0b\:x calculates binary representation of x (64 bits)

48_ x drop first 48 bits, so we have our 16 bits representation

Example (x="01:30:00"). NOTE.- "/" indicates comment to end of line

":"\:"01:30:00" /-> ("01";"30";"00") "I"$ /-> 1 30 0 60/: /-> 5400 (512%675)* /-> 4096.0 _ /-> 4096 0b\: /-> 0000000000000000000000000000000000000000000000000001000000000000b 48_ /-> 0001000000000000b

\$\endgroup\$
0
\$\begingroup\$

Ruby, 75 bytes

h,m,s=t.split(':').map &:to_i;((h*3600+m*60+s<<9)/675).to_s(2).rjust 16,'0'

I feel like there must be a shorter method of converting the time to seconds, but this is all I could think of.

\$\endgroup\$
0
\$\begingroup\$

Python, 45 bytes

lambda h,m,s:bin((s+m*60+h*3600)*512/675)[2:]

Came up with the 512/675 factor myself, then saw others did it the same.

\$\endgroup\$
0
\$\begingroup\$

C, 91 bytes

f(h,m,s,n,i){i=0;n=(s+m*60+h*3600)*512/675;while(i<16)printf((n&32768)?"1":"0"),n<<=1,i++;}
\$\endgroup\$
0
\$\begingroup\$

PHP, 47 46 43 bytes

Uses IBM-850 encoding.

printf(~┌Ø,strtotime($argn.UTC,0)*512/675);

Run like this:

echo "18:00:00" | php -nR 'printf(~┌Ø,strtotime($argn.UTC,0)*512/675);';echo

Tweaks

  • Saved a byte by using IBM-850 encoding.
  • Saved 3 bytes by using $argn
\$\endgroup\$

Your Answer

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