20
\$\begingroup\$

Introduction

tl;dr

Continuously output the current distance from the Earth to the Sun.


Simplified, the orbit of the Earth around the Sun is an ellipse. So the actual distance between both is constantly changing. This distance can be calculated for any given day using this formula:

d/AU=1-0.01672 cos(0.9856(day-4))

The equation can be split into the following parts2:

  • 1 represents 1 AU (astronomical unit), equals 149,597,870.691 km
  • 0.01672 is the orbital eccentricity between the Earth and the Sun
  • cos is of course the cosine function, but with argument in degrees rather than radians
  • 0.9856 is 360° / 365.256363 days, a full rotation in one year, where 365.256363 is the length of a sidereal year, in mean solar days
  • day is the day of the year [1-365]
  • 4 represents the offset to the perihelion, which is between 4th and 6th of January

The formula takes a whole day but for the purpose of this challenge – a continuously output – you have to be more accurate; or nothing much will happen till the next day. Simply add the percentage of the past time to the current day, like1:

day + (h * 3600 + m * 60 + s) / 864 / 100

A few Examples:

  • 1 January, 23:59:59 1.99998842592593
  • 1 January, 18:00:00 1.75
  • 1 January, 12:00:00 1.50
  • 1 January, 06:00:00 1.25

Input

This challenge has no input.


If your language can't get the current time, you can get it as an input to your program. Valid inputs are timestamps or complete date-time strings that suits the language best. Passing the current day alone (like 5 for 5th January or 5.25 for the same day at 6 o'clock) is not allowed.

Output

Output the current distance from the Earth to the Sun:

  • Output the value in km.
  • Update the value at least every second.

Example output:

152098342

If it doesn't increase your byte count, you can also pretty print the result:

152,098,342
152,098,342 km

Requirements

  • You can write a program or a function. If it is an anonymous function, please include an example of how to invoke it.
  • This is so shortest answer in bytes wins.
  • Standard loopholes are disallowed.

Example implementation

I've prepared an example implementation in JavaScript. It's neither competitive nor golfed.

// dayOfYear from http://stackoverflow.com/a/8620357/1456376
Date.prototype.dayOfYear = function() {
    var j1= new Date(this);
    j1.setMonth(0, 0);
    return Math.round((this-j1)/8.64e7);
}

// vars
var e = document.getElementById('view'),
    au = 149597870.691,
    deg2rad = Math.PI/180,
    date = now = value = null;

// actual logic
function calculate() {
    date = new Date();
    now = date.dayOfYear() + (date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()) / 864 / 100;
    value = 1 - 0.01672 * Math.cos(deg2rad * 0.9856 * (now - 4));
    // supported in Firefox and Chrome, unfortunately not in Safari
    e.innerHTML = Math.round(value * au).toLocaleString('en-US') + ' km';

    setTimeout(calculate, 1000);
}

// let's do this
calculate();
<div id="view"></div>


1 To not unreasonably increase complexity, you don't have to convert your local time to UTC. If you use UTC please add a note to your answer.

2 For more details see "Earth-Sun distance on a given day of the year" over at Physics

\$\endgroup\$
  • \$\begingroup\$ What should programming languages do that cannot access the current time? Like BF etc? \$\endgroup\$ – flawr Jan 25 '16 at 9:52
  • 3
    \$\begingroup\$ I believe your example is incorrect, since Math.cos uses radians. And since this formula seems very approximate, you'll have to be clear on how answers are to be verified. \$\endgroup\$ – grc Jan 25 '16 at 10:06
  • \$\begingroup\$ @grc I've fixed the error in my example - thanks for pointing me to it. \$\endgroup\$ – insertusernamehere Jan 25 '16 at 16:52
  • \$\begingroup\$ @flawr You can get the time as an input to your program. The question is updated accordingly. \$\endgroup\$ – insertusernamehere Jan 25 '16 at 16:58
  • 1
    \$\begingroup\$ I bet Mathematica has a built-in for it! \$\endgroup\$ – sergiol Apr 11 '18 at 13:27
5
\$\begingroup\$

TI-BASIC, 38 bytes

Disp 25018086(59.8086-cos(5022635.4⁻¹checkTmr(83761
prgmA

For a TI-84+ series calculator. Name this prgmA. Note that this overflows the stack after a few thousand iterations; use a While 1:...:End instead if this is a problem, for two extra bytes.

This uses the perihelion on January 1, 1997, 23:16 UTC for reference, and is accurate to within a few dozen kilometers (about 7 digits of accuracy) for the next few years.

\$\endgroup\$
  • \$\begingroup\$ Now this is short. Kudos! \$\endgroup\$ – insertusernamehere Jan 27 '16 at 22:39
5
\$\begingroup\$

Java - 185 180 bytes

static void d(){while(true){System.err.println(149597870.691*(1-.01672*Math.cos(Math.toRadians(.9856*(Calendar.getInstance().get(6)+LocalTime.now().toSecondOfDay()/8.64e4-4)))));}}

This uses the fact that there are 86,400 seconds in a day and is using local time, not GMT. Output happens much more than once per second. Not sure if import statements should be included in byte count.

To include a 1 second delay adds about 26 bytes e.g.

static void d(){try{while(true){System.err.println(149597870.691*((1-.01672*Math.cos(Math.toRadians(.9856*(Calendar.getInstance().get(6)+LocalTime.now().toSecondOfDay()/8.64e4-4)))));Thread.sleep(1000L);}}catch(Exception e){}}

Java definitely isn't the most golfable language. :)

Removed a few bytes thanks to @insertusernamehere

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice. Couldn't 1.0 become 1? And can you remove the leading 0 from 0.01672 and 0.9856? \$\endgroup\$ – insertusernamehere Jan 25 '16 at 19:43
  • \$\begingroup\$ Very true, that's what I get for copy-paste from the question :p I could drop some more bytes if I used import static but that might be "cheating"... I'm still rather new here. \$\endgroup\$ – Robert Benson Jan 25 '16 at 19:45
  • \$\begingroup\$ Why System.err? \$\endgroup\$ – SuperJedi224 Jan 25 '16 at 21:31
  • \$\begingroup\$ I used System.err so there would be no buffering. I know the println is supposed to print immediately anyway, but it doesn't always seem to do that. Of course it could be converted to System.out without changing the byte count :) \$\endgroup\$ – Robert Benson Jan 25 '16 at 22:13
  • 2
    \$\begingroup\$ I've noticed that many people are forgetting to convert from degrees to radians. I'd comment on them, but I'm a newbie with too little rep :p \$\endgroup\$ – Robert Benson Jan 26 '16 at 14:17
4
\$\begingroup\$

Python, 101 bytes

import time,math
a=149597870.691
while 1:print(a-a*.01672*math.cos((time.time()-345600)/5022635.53))

345600 = 4*24*3600 (four days)

5022635.53 ≌ (365.256363*24*3600)/(2π) (seconds in year/2π)

\$\endgroup\$
  • \$\begingroup\$ Welcome to Programming Puzzles and Code Golf. This is a good solution, +1. However, it may improve the answer if you added an ungolfed and commented version, explaining what you have done, or even just added a simple comment before the code. \$\endgroup\$ – wizzwizz4 Jan 26 '16 at 17:10
  • \$\begingroup\$ I get 107 for the byte count. \$\endgroup\$ – Morgan Thrapp Jan 26 '16 at 21:10
  • \$\begingroup\$ Right, I've included the last newline. \$\endgroup\$ – pacholik Jan 27 '16 at 7:53
  • \$\begingroup\$ You can save 7 bytes by combining the imports: import time,math. Also, if you use Python 2 you can drop the parenthesis from print. \$\endgroup\$ – PurkkaKoodari Jan 27 '16 at 8:00
  • \$\begingroup\$ Also true, with all of that PEP I've forgotten it is possible :) \$\endgroup\$ – pacholik Jan 27 '16 at 8:06
3
\$\begingroup\$

Bash/coreutils/bc, 101 bytes

#!/bin/bash
bc -l <<<"149597870.691*(1-.01672*c((`date +%s`-`date -d 4-Jan +%s`)/5022635.5296))"
sleep .5
exec $0

This computes the offset from the 4th of January in seconds, so uses a corresponding constant to convert to radians. Half a year converts to roughly pi:

$ bc -l <<<"(365.256363/2*86400)/5022635.5296"
3.14159265361957033371

The rest of the calculation is straight from the question.

\$\endgroup\$
  • \$\begingroup\$ Nice job. I wondered if bc might be useful for this. I noticed that you have dc in your header, but use bc in the code. I often confuse the two myself. \$\endgroup\$ – Robert Benson Jan 27 '16 at 13:11
  • 1
    \$\begingroup\$ Thanks, @Robert - I've fixed the title. I started off looking at dc, then realised I needed bc's mathlib, so had both calculators in my mind at the wrong moment! \$\endgroup\$ – Toby Speight Jan 27 '16 at 13:13
  • \$\begingroup\$ Yep, been there, done that. I always forget which is which. \$\endgroup\$ – Robert Benson Jan 27 '16 at 14:52
2
\$\begingroup\$

F#, 178 bytes

open System
Seq.initInfinite(fun _->
let n=DateTime.Now
(1.-0.01672*Math.Cos(0.0172*((n-DateTime.Today).TotalDays+float(n.DayOfYear-4))))*149597870.691)|>Seq.iter(printfn"%f")

This is an F# script that runs well in F# Interactive. For simplicity's sake, the "continuous output" requirement is taken to literal levels, although I did lose a byte to make the output print on a new line every iteration so that it wasn't too bad. =P

Ungolfed and explained:

Seq.initInfinite (fun _ ->            // Create an infinite sequence, with each element being defined by the following function
    let n = DateTime.Now
    let dayOffset = n.DayOfYear - 4   // Day of year returns the day as a number between 1 and 366
    let today = n - DateTime.Today    // Extract the current day, so the hours, minutes and all
    let partialDay = today.TotalDays  // Get the value of 'today' as a floating point number of days
                                      // so between 0 and 1 in this case - exactly what I needed
    // And now, the formula - note that 0.9856 has been combined with the conversion from degrees to radians, giving 0.0172
    (1. - 0.01672 * Math.Cos (0.0172 * (partialDay + float dayOffset))) * 149597870.691
)
|> Seq.iter (fun i -> printfn "%f" i) // For each of the (infinity of) numbers, print it
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 97 bytes

Dynamic[1496*^5-2501*^3Cos[.9856#&@@Now~DateDifference~{DateValue@"Year",1,4}],UpdateInterval->1]

Explanation

{DateValue@"Year",1,5} represents 5th of January this year, and ...~DateDifference~... gives the temporal distance.

Dynamic[...,UpdateInterval->1] update the expression once per second.

\$\endgroup\$
  • \$\begingroup\$ Just to remind you, you need to output the answer in km, not AU. I suppose Mathematica has built-in converters so you could save some bytes for the unit conversion, yes? \$\endgroup\$ – busukxuan Jan 26 '16 at 12:52
  • \$\begingroup\$ @busukxuan I have multiplied the coefficient to the formula. \$\endgroup\$ – njpipeorgan Jan 26 '16 at 13:18
  • \$\begingroup\$ Oh sry I missed it. Didn't expect it to be in 4 significant figures. \$\endgroup\$ – busukxuan Jan 26 '16 at 13:25
  • 2
    \$\begingroup\$ Alternatively, Dynamic[Round[PlanetData["Earth", "DistanceFromSun"]~QuantityMagnitude~"Kilometers"]] \$\endgroup\$ – 2012rcampion Jan 27 '16 at 1:24
1
\$\begingroup\$

Pyth, 51 bytes

#*149597870.691-1*.01672.t*c-.dZ86400 31558149*2.nZ1

Alternate formula

d/AU = 1 - 0.01672 cos ( 2π [time since perihelion]/[orbital period] )
This formula is essentially the same as the OP's formula, except it is generalized to be able to use any perihelion as a reference date.

The OP's formula has [time since perihelion] as ( day - 4 ) and has ( 2π rad / [orbital period] ) pre-calculated as 0.9856deg/day.

In my solution I am using the perihelion closest to the Unix epoch, 2nd January 1970.

The code

Hand-compiled to pythonic pseudocode:

#                        while 1:
  *149597870.691             print( 149597870.691 * (                 # implicit print
    -1                           1 - (
      *.01672                        0.1672 * (
        .t                               trigo(
          *                                  multiply(
            c                                    divide(
              -.dZ86400                              unixTime-86400,
              31558149                               31558149
                                                 ),
            *2.nZ                                2*pi
                                             ),
          1                                  1                        # 1 means cos
                             )))))

This is essentially just turning the following formula into code:
d = ( 1 - 0.01672 cos ( 2π (t - 86400)/31558149 ) ) * 149597870.691
where t is the Unix time.

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

Python 2.4 - 158 bytes

import time,math
while 1:t=time.localtime();print(int(149597870.691*(1-.01672*math.cos(math.radians(.9856*(t[7]+(t[3]*3600+t[4]*60+t[5])/864.0/100.0-4))))))

Takes the local time and spits out the distance. time.localtime() returns a tuple and can be referenced here.

\$\endgroup\$
  • \$\begingroup\$ Can you remove .0 from 864.0 and 100.0 to save a few bytes? \$\endgroup\$ – insertusernamehere Jan 27 '16 at 13:51
  • \$\begingroup\$ The only thing I am worried about with doing that is that it will no longer be a floating point division. I kept the .0 so they would be floating point and not integer. \$\endgroup\$ – linkian209 Jan 28 '16 at 19:10
0
\$\begingroup\$

C, 338

#include <stdio.h>
#include <time.h>
#include <math.h>
int main ()
{
  time_t rt;
  struct tm * ti;
  while(1) {
  time(&rt);
  ti = localtime(&rt);
  double d = 1.0 - .01672*cos(0.0174533 * .9856*((ti->tm_yday + (ti->tm_hour * 3600.0 + ti->tm_mday * 60.0 + ti->tm_sec) / 86400.0) - 4));
  printf ("%f\n", d * 149598000.0);}
}
\$\endgroup\$
  • 3
    \$\begingroup\$ Welcome to Programming Puzzles and Code Golf! While this looks like a correct answer, it doesn't seem to be golfed very much. For questions with the [code-golf] tag, answers need to make an effort at reducing their size as much as possible to be considered on-topic - see the help center. I'll be looking forward to seeing the golfed version! =) \$\endgroup\$ – Roujo Jan 27 '16 at 18:31

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.