How far is the Sun?

20

4

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

insertusernamehere

Posted 2016-01-25T09:28:51.680

Reputation: 4 551

What should programming languages do that cannot access the current time? Like BF etc? – flawr – 2016-01-25T09:52:34.447

3I 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. – grc – 2016-01-25T10:06:38.120

@grc I've fixed the error in my example - thanks for pointing me to it. – insertusernamehere – 2016-01-25T16:52:45.053

@flawr You can get the time as an input to your program. The question is updated accordingly. – insertusernamehere – 2016-01-25T16:58:15.220

This challenge was discussed on meta. It's back with some improvements now.

– insertusernamehere – 2016-01-25T16:58:20.537

I think your estimate of the length of a year is slightly high. – SuperJedi224 – 2016-01-25T17:09:10.447

What formats are allowed for the time input, for languages that cannot query the current time? – Mego – 2016-01-25T17:46:26.113

What do we do on leap years? – lirtosiast – 2016-01-25T18:15:25.893

@ThomasKwa Not much I'd say, the year has just 366 days then. – insertusernamehere – 2016-01-25T18:31:01.023

Can I use an alternate, more accurate formula? – busukxuan – 2016-01-26T06:31:33.317

@busukxuan Yes you can. I'd like to see another approach. Do you want to use Kepler's equation? If you add an answer, it would be great to explain how it works or differ from this approach as well – so that everybody learns something. Your answer will not be competitive though as it will differ from the rules of the challenge. This means you can receive upvotes for your answer but you can't win, even if you have the lowest byte count. – insertusernamehere – 2016-01-26T09:59:04.557

@insertusernamehere I just posted my answer. The formula I used is basically the same as yours, only with different constants in the cos, and seconds rather than days. Is it still non-competing? If it is, I will strikethrough the "(probably)" in the title. – busukxuan – 2016-01-26T11:02:53.983

@busukxuan Ah I see how you solved it. You adjusted the values to get a more accurate value I think this is fine. :) – insertusernamehere – 2016-01-26T12:14:39.247

@insertusernamehere Oh ok thank you. I guess now I will strikethrough "(probably) non-" instead :-) – busukxuan – 2016-01-26T12:29:22.430

Are six digits of accuracy sufficient? – lirtosiast – 2016-01-26T23:52:53.807

1I bet Mathematica has a built-in for it! – sergiol – 2018-04-11T13:27:04.573

Answers

5

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.

lirtosiast

Posted 2016-01-25T09:28:51.680

Reputation: 20 331

Now this is short. Kudos! – insertusernamehere – 2016-01-27T22:39:01.840

5

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

Robert Benson

Posted 2016-01-25T09:28:51.680

Reputation: 1 339

1Nice. Couldn't 1.0 become 1? And can you remove the leading 0 from 0.01672 and 0.9856? – insertusernamehere – 2016-01-25T19:43:04.460

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. – Robert Benson – 2016-01-25T19:45:53.760

Why System.err? – SuperJedi224 – 2016-01-25T21:31:46.463

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 :) – Robert Benson – 2016-01-25T22:13:25.463

Hmm... the conversion to radians could be combined with the constant .9856 to give 0.0172019651, but how much precision is required? – Robert Benson – 2016-01-25T22:23:30.787

2I'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 – Robert Benson – 2016-01-26T14:17:27.307

4

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π)

pacholik

Posted 2016-01-25T09:28:51.680

Reputation: 490

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. – wizzwizz4 – 2016-01-26T17:10:54.677

I get 107 for the byte count. – Morgan Thrapp – 2016-01-26T21:10:48.110

Right, I've included the last newline. – pacholik – 2016-01-27T07:53:24.440

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. – PurkkaKoodari – 2016-01-27T08:00:47.683

Also true, with all of that PEP I've forgotten it is possible :) – pacholik – 2016-01-27T08:06:36.083

3

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.

Toby Speight

Posted 2016-01-25T09:28:51.680

Reputation: 5 058

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. – Robert Benson – 2016-01-27T13:11:20.037

1Thanks, @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! – Toby Speight – 2016-01-27T13:13:47.710

Yep, been there, done that. I always forget which is which. – Robert Benson – 2016-01-27T14:52:11.260

2

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

Roujo

Posted 2016-01-25T09:28:51.680

Reputation: 353

1

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.

njpipeorgan

Posted 2016-01-25T09:28:51.680

Reputation: 2 992

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? – busukxuan – 2016-01-26T12:52:12.760

@busukxuan I have multiplied the coefficient to the formula. – njpipeorgan – 2016-01-26T13:18:30.283

Oh sry I missed it. Didn't expect it to be in 4 significant figures. – busukxuan – 2016-01-26T13:25:17.827

2Alternatively, Dynamic[Round[PlanetData["Earth", "DistanceFromSun"]~QuantityMagnitude~"Kilometers"]] – 2012rcampion – 2016-01-27T01:24:49.463

1

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.

busukxuan

Posted 2016-01-25T09:28:51.680

Reputation: 2 728

1

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.

linkian209

Posted 2016-01-25T09:28:51.680

Reputation: 51

Can you remove .0 from 864.0 and 100.0 to save a few bytes? – insertusernamehere – 2016-01-27T13:51:51.010

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. – linkian209 – 2016-01-28T19:10:21.907

0

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);}
}

samt1903

Posted 2016-01-25T09:28:51.680

Reputation: 1

3

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! =)

– Roujo – 2016-01-27T18:31:37.420