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\$
16
  • \$\begingroup\$ What should programming languages do that cannot access the current time? Like BF etc? \$\endgroup\$
    – flawr
    Commented Jan 25, 2016 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
    Commented Jan 25, 2016 at 10:06
  • \$\begingroup\$ @grc I've fixed the error in my example - thanks for pointing me to it. \$\endgroup\$ Commented Jan 25, 2016 at 16:52
  • \$\begingroup\$ @flawr You can get the time as an input to your program. The question is updated accordingly. \$\endgroup\$ Commented Jan 25, 2016 at 16:58
  • 1
    \$\begingroup\$ I bet Mathematica has a built-in for it! \$\endgroup\$
    – sergiol
    Commented Apr 11, 2018 at 13:27

10 Answers 10

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\$
1
  • \$\begingroup\$ Now this is short. Kudos! \$\endgroup\$ Commented Jan 27, 2016 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\$
6
  • 1
    \$\begingroup\$ Nice. Couldn't 1.0 become 1? And can you remove the leading 0 from 0.01672 and 0.9856? \$\endgroup\$ Commented Jan 25, 2016 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\$ Commented Jan 25, 2016 at 19:45
  • \$\begingroup\$ Why System.err? \$\endgroup\$ Commented Jan 25, 2016 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\$ Commented Jan 25, 2016 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\$ Commented Jan 26, 2016 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\$
5
  • \$\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
    Commented Jan 26, 2016 at 17:10
  • \$\begingroup\$ I get 107 for the byte count. \$\endgroup\$ Commented Jan 26, 2016 at 21:10
  • \$\begingroup\$ Right, I've included the last newline. \$\endgroup\$
    – pacholik
    Commented Jan 27, 2016 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\$ Commented Jan 27, 2016 at 8:00
  • \$\begingroup\$ Also true, with all of that PEP I've forgotten it is possible :) \$\endgroup\$
    – pacholik
    Commented Jan 27, 2016 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\$
3
  • \$\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\$ Commented Jan 27, 2016 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\$ Commented Jan 27, 2016 at 13:13
  • \$\begingroup\$ Yep, been there, done that. I always forget which is which. \$\endgroup\$ Commented Jan 27, 2016 at 14:52
2
\$\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\$
4
  • \$\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
    Commented Jan 26, 2016 at 12:52
  • \$\begingroup\$ @busukxuan I have multiplied the coefficient to the formula. \$\endgroup\$ Commented Jan 26, 2016 at 13:18
  • \$\begingroup\$ Oh sry I missed it. Didn't expect it to be in 4 significant figures. \$\endgroup\$
    – busukxuan
    Commented Jan 26, 2016 at 13:25
  • 2
    \$\begingroup\$ Alternatively, Dynamic[Round[PlanetData["Earth", "DistanceFromSun"]~QuantityMagnitude~"Kilometers"]] \$\endgroup\$ Commented Jan 27, 2016 at 1:24
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\$

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\$
2
  • \$\begingroup\$ Can you remove .0 from 864.0 and 100.0 to save a few bytes? \$\endgroup\$ Commented Jan 27, 2016 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
    Commented Jan 28, 2016 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\$
1
  • 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
    Commented Jan 27, 2016 at 18:31
0
\$\begingroup\$

HP‑41C series, 78 Bytes

This program requires an HP‑41CX or an HP‑41C/CV with a time module plugged in. It works only correctly from October 15, 1582 through September 10, 4320. Ensure the display format allows for displaying 9 digits (e. g. FIX 4, the default setting). You may set flag 29 to enable the insertion of a thousands separator for every group of three digits in the integer part. Set flag 28 to use commas as thousands separators (as opposed to periods). Flag 28 and 29 set are the default setting.

01♦LBL⸆S           5 Bytes  global label requires 4 + (length of string) Bytes
02 DEG             1 Byte   ensure Degree mode is selected
─── get day number (zero-based) ────────────────────────────────────────────────
03 DATE            2 Byte   today’s date: has MM.DDYYYY or DD.MMYYYY format
04 ENTER↑          1 Byte   replicate value
05 ENTER↑          1 Byte   again because `ENTER↑` disables stack lift
   NULL            1 Byte   invisible Null byte before numbers
06 1 E6            3 Bytes  put 1,000,000 on top of stack
07 *               1 Byte   multiply so X = MMDDYYYY or DDMMYYYY
   NULL            1 Byte
08 1 E4            3 Bytes  put 1,000 on top of stack
09 MOD             1 Byte   isolate YYYY
   NULL            1 Byte
10 1 E6            3 Bytes
11 /               1 Byte   divide YYYY by 1,000,000
   NULL            1 Byte
12 1.01            4 Bytes
13 +               1 Byte   X = January 1, current year
14 X≷Y             1 Byte   swap X and Y so difference is positive
15 DDAYS           2 Bytes  difference of days – accounts for leap year
─── get fractional time of day ─────────────────────────────────────────────────
16 TIME            2 Bytes  obtain time in HH.MMSSss format
17 HR              1 Byte   convert HH.MMSSss into decimal hours format
   NULL            1 Byte
18 24              2 Bytes  24 hours
19 /               1 Byte
─── compose `day` as in specification ──────────────────────────────────────────
20 +               1 Byte   combine day number and time
   NULL            1 Byte
21 3               1 Byte   perihelion bias for zero-based day numbering
22 −               1 Byte
─── perform calculation ────────────────────────────────────────────────────────
   NULL            1 Byte
23 .9856           5 Bytes  use .985609113 for improved precision
24 *               1 Byte
25 COS             1 Byte
   NULL            1 Byte
26 −.01672         7 Bytes
27 *               1 Byte
   NULL            1 Byte
28 149,597,870.7  11 Bytes
29 +               1 Byte
30 PSE             1 Byte   delay execution for about one second
31 GTO⸆S           3 Bytes  `PSE` displays contents of X-register

NB: The actual calculator (in hardware) is too slow to perform all operations within one second. It needs roughly 3 seconds + 1 second for PSE. However, this is a circumstance outside the realm of the programming language.

\$\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.