Use xkcd's formula to approximate the world population

42

5

In xkcd 1047, Randall Munroe lists "slightly wrong" approximations of assorted quantities and numbers with varying precision and complexity, such as that the number of liters in a gallon is very close to 3 + π4. In the middle of the comic, he gives an intermission: a way to estimate the world (and United States) population based for a given year.

World and U.S. population formula, described below
(Cropped from xkcd: Approximations by Randall Munroe)

Your task is to write a program that implements these formulas to approximate the current world and U.S. populations, replicated as follows.

World population

  1. Take the last two digits of the current year.
  2. Subtract the number of leap years (including the current year) since Hurricane Katrina (2005). For these purposes, any year divisible by 4 is considered a leap year.
  3. Add a decimal point between the two numbers (the same as dividing by 10).
  4. Add 6. This gives the result in billions of people.

U.S. population

  1. Take the last two digits of the current year.
  2. Subtract 10.
  3. Multiply by 3.
  4. Add 10.
  5. Add 3 to the beginning (for this challenge, some numbers will be negative, so add 300 instead). Somehow I didn't notice that just concatenating wouldn't work because the program I used to generate the results just added 300.
  6. This gives the result in millions of people.

Details

This formula "should stay current for a decade or two," but you must be able to theoretically handle any year 2000–2039 inclusive. For some cases, the leap years since Katrina will have a negative or zero value.

You are free to simplify the formula in any way, as long as all outputs match the ones below.

For the year, use the year according to the computer's clock. It must work next year and any other year this century, so you cannot simply hardcode 2015. For convenience, you might want to include a way to specify the year as a variable or input to test other years.

The output should be the approximated world population (in billions of people), followed by some delimiter (e.g. space or comma), followed by the U.S. population (in millions of people). You may also write a function that returns or prints a string or an array of numbers or strings.

This is code golf, so shortest code in bytes wins. Tiebreaker is earliest post.

Test cases

This is a list of all possible years, followed by the two outputs.

Year   World  U.S.
2000    6.1   280
2001    6.2   283
2002    6.3   286
2003    6.4   289
2004    6.4   292
2005    6.5   295
2006    6.6   298
2007    6.7   301
2008    6.7   304
2009    6.8   307
2010    6.9   310
2011    7     313
2012    7     316
2013    7.1   319
2014    7.2   322
2015    7.3   325
2016    7.3   328
2017    7.4   331
2018    7.5   334
2019    7.6   337
2020    7.6   340
2021    7.7   343
2022    7.8   346
2023    7.9   349
2024    7.9   352
2025    8     355
2026    8.1   358
2027    8.2   361
2028    8.2   364
2029    8.3   367
2030    8.4   370
2031    8.5   373
2032    8.5   376
2033    8.6   379
2034    8.7   382
2035    8.8   385
2036    8.8   388
2037    8.9   391
2038    9     394
2039    9.1   397

NinjaBearMonkey

Posted 2015-09-12T19:23:15.597

Reputation: 9 925

1Do you have to round the numbers? – Blue – 2015-09-12T19:35:05.847

5@muddyfish I'm not sure I understand. If you follow the instructions in the comic exactly, there's technically no division going on, but the world population should be rounded to the nearest tenth. – NinjaBearMonkey – 2015-09-12T19:38:46.187

2I'm a little confused by the United States population one. If you're concatenating a 3, shouldn't 2040 give a population of 3100? 40 - 10 = 30, 30 * 3 = 90, 90 + 10 = 100, which would give "3" + "100" = 3100 – cole – 2015-09-12T20:01:26.700

Also, if the language we use cannot obtain the current year, should we hardcode it in, provided that the code without the hardcoded year will work for the range of inputs? – cole – 2015-09-12T20:06:07.373

2@Cole Good point, I'll make it so you only have to support years through 2039. About hardcoding the year, I don't want to allow hardcoding because that will almost always be shorter even languages that do support dates. – NinjaBearMonkey – 2015-09-12T20:09:35.453

@NinjaBearMonkey That's fair, I jumped the gun a bit and made a submission so I'll delete it. My apologies for doing so. – cole – 2015-09-12T20:16:15.063

8@NinjaBearMonkey I suggest that you change the description of "adding 3, thinking concatenation" to a literal "add 300" to cover all of the edge cases that occur when the previous result isn't a nice 2-digit positive number. (For example, year 2000 gives 280 as a result of -20+300=280 and not 3 . -20= "3-20") – PhiNotPi – 2015-09-13T05:15:00.197

Now we can make sure nobody hardcoded the year! – wizzwizz4 – 2016-01-09T10:25:44.497

If anyone's interested, I made an obfuscated solution for this in a cops/robbers challenge ;)

– FlipTack – 2016-11-18T22:48:12.183

Answers

23

Pyth, 21 20 bytes

-1 byte by Dennis

c/J-*3.d3C\ᙹ4T+33J

These have the same byte count but are ASCII-only:

c/J%*3.d3 523 4T+33J
c/-J%*3.d3*44T33 4TJ

I don't know Pyth, so still probably possibly golfable. Using the same algorithm:

TI-BASIC, 23 bytes

max(3getDate-5753
{.1int(Ans/4),Ans+33

getDate returns a list of three floats {YYYY,MM,DD} in some order depending on the date format setting (TI-84s don't have a true int datatype); the max( will be the year. Multiplying and subtracting inside the max( saves a close-paren.

lirtosiast

Posted 2015-09-12T19:23:15.597

Reputation: 20 331

1I think this is the first time I've seen a TI-BASIC answer here.... – The_Basset_Hound – 2015-09-13T21:43:04.727

8

@The_Basset_Hound TI-BASIC is the 28th most common language here at 140 answers; it's also won one major and a few smaller questions.

– lirtosiast – 2015-09-13T22:36:35.817

16

Javascript (ES6), 55 54 48 bytes

-~((n=Date().substr(13,2)*3+280)/4-9.1)/10+' '+n

Works in Firefox 33; theoretically supports all years from 2000 to 2099. If programs that dump the result onto the console are not allowed, use this 51-byte function:

(n=Date().substr(13,2)*3+280)=>-~(n/4-9.1)/10+' '+n

Full program, 55 bytes:

n=Date().substr(13,2)*3+280,alert(-~(n/4-9.1)/10+' '+n)

Getting the year was quite expensive, but after using the deprecated getYear() instead of getFullYear(), all of the numbers in the equation became smaller, saving a lot of bytes. EDIT: Thanks to an eeevil trick, I skipped new and getYear() altogether. >:D

Suggestions welcome!

ETHproductions

Posted 2015-09-12T19:23:15.597

Reputation: 47 880

10

Python 2, 80 bytes

from datetime import*
y=date.today().year%40
print int(61.55+.75*y)/10.,y*3+280

Now rounds!

Blue

Posted 2015-09-12T19:23:15.597

Reputation: 26 661

You have to round, as OP clarified a minute ago. ;-) – mınxomaτ – 2015-09-12T19:52:49.590

3year%100 is the same as year%40. – lirtosiast – 2015-09-12T22:31:51.157

10

Pyth, 30 bytes

.R+*.075J%.d3C\d6.105 1+*3J280

My first Pyth program!

Thanks @Jakube for some hints (I would never have thought of those!)

Blue

Posted 2015-09-12T19:23:15.597

Reputation: 26 661

3

Haven't read the question, but here are a few optimizations I immediately saw. Write everything on one line. Choose a different ordering of numbers and variables (+*3Z280 instead of +*Z3 280 for instance). C\d instead of 100 (saves spaces). Use J instead of Z (saves the =). Inline the assignment. Link

– Jakube – 2015-09-12T20:27:37.960

6

CJam, 28 bytes

et0=100%__4/(-Ad/6+S@3*280+

Try it online

To try years other than the current one, replace the et0= at the start with the literal value of the year.

Reto Koradi

Posted 2015-09-12T19:23:15.597

Reputation: 4 870

2Since 2000 is divisible by 40, and you only need 2000-2039, you can use 40% to save one byte. – Andrea Biondo – 2015-09-13T08:34:23.797

5

Python 3, 134 bytes

Works well but seems a bit long

from datetime import*
y=str(date.today().year)
z=int(y[2:])
m=str(60+(z-int((int(y)-2005)/4)))
print("%s.%s"%(m[0],m[1]),310+(z-10)*3)

Beta Decay

Posted 2015-09-12T19:23:15.597

Reputation: 21 478

To shorten this, use from time import*, y=strftime('%Y'). Or copy the other python answer :P – FlipTack – 2016-11-19T14:31:14.227

5

AutoIt - 60 58 56 bytes

$_=@YEAR-2e3
ClipPut(($_-Int($_/4-1))/10+6&' 3'&3*$_-20)

The rounding eats bytes (not anymore). I have now tweaked both formulas. Some sample outputs:

7.3 325 // 2015
7.3 328
7.4 331
7.5 334 // 2018
8.4 370 // 2030

They all seem to be accurate.

A tip: Order of execution saves bytes on parentheses. For example: (a-4)/4 = a/4-1 :-).

mınxomaτ

Posted 2015-09-12T19:23:15.597

Reputation: 7 398

4

PowerShell, 53 45 Bytes

$n=date -f yy;.1*[int](61.45+.75*$n);280+3*$n

Uses a similar rounding trick as muddyfish's Python 2 answer to simplify the world population calculation, since PowerShell implicitly Round()s when you cast from a [double] to an [int], rather than truncating.

For the output, we assume that "followed by some delimiter (e.g. space or comma)" can also mean "newline", so we execute one result and then the second. PowerShell implicitly writes out results, so we don't need to explicitly call any printing commands.

AdmBorkBork

Posted 2015-09-12T19:23:15.597

Reputation: 41 581

3

Mathematica, 50 bytes

n=Today["YearShort"];{.1*(61+n-Floor[n/4]),280+3n}

Note that this is dependent on having a Wolfram Engine with Version number 10+ (released 2014) due to dependence on DateObjects.

R, 64 bytes

n=as.numeric(format(Sys.time(),"%y"))
c(.1*(61+n-n%/%4),280+3*n)

Direct port of Mathematica code, think I had a shorter solution but dependent on packages whereas this works with base R.

Charlie Joey Hadley

Posted 2015-09-12T19:23:15.597

Reputation: 151

1(1/10) -> .1? – lirtosiast – 2015-09-13T17:32:48.763

1I think you also don't need parentheses around the .1. – lirtosiast – 2015-09-13T17:43:44.853

3

Java, 180 177 166 152 143 bytes

Thanks Thomas for helping a noob out :)

class D{public static void main(String[]a){int f=java.time.LocalDate.now().getYear();System.out.printf("%.1f %d\n",(3.*f-5755)/40,3*f-5720);}}

Ungolfed version:

class D {
  public static void main(String[]a) {
    int f = java.time.LocalDate.now().getYear();
    System.out.printf("%.1f %d\n",(3.*f-5755)/40,3*f-5720);
  }
}

Requires Java 8.

a spaghetto

Posted 2015-09-12T19:23:15.597

Reputation: 10 647

import java.time.*? 3.0->3.? You also don't need to print the year with the output. – lirtosiast – 2015-09-20T04:15:56.457

Oh, I didn't realize you didn't need the year printed out... :P – a spaghetto – 2015-09-20T14:35:20.647

3

JavaScript (ES6) 52

A function returning the output as an array.

(y=(new Date).getYear())=>[(y+~(y/4)-13)/10,y*3-20]

Just for testing purpose, the function accepts an input equals to current year - 1900 (e.g. 105 for 2015)

That's in the line of the ETHproductions' answer (the math is the math) but avoding the evil trick it is more portable in different locales. And as a function it's 1 byte shorter.

Test snippet:

f=(y=(new Date).getYear())=>[(y+~(y/4)-13)/10,y*3-20]

o=[];
for(a=2000;a<2050;a++)o.push(`<td>${a}</td><td>${f(a-1900)}</td>`);
document.write(`<table><tr>${o.join`</tr><tr>`}</tr></table>`)
td { text-align:right; font-family:monospace }

edc65

Posted 2015-09-12T19:23:15.597

Reputation: 31 086

3

Desmos, 140 Bytes

I'm counting a newline to be a signal for a new equation. Folders on the link are just for organization.

Golfed, 140 Bytes

Click add slider when prompted.

a=6+.1b-.1c
d=280+3b
c=\sum_{n=2005}^q\left\{0=\operatorname{mod}\left(n,4\right),0\right\}
b=100\left|\operatorname{floor}\left(.01q\right)-.01q\right|

Ungolfed, 261 Bytes

p_{world}=6+\frac{l_{astdig}-l_{eap}}{10}
p_{us}=310+3\left(l_{astdig}-10\right)
y_{ear}=2039
l_{eap}=\sum _{n=2005}^{y_{ear}}\left\{0=\operatorname{mod}\left(n,4\right),0\right\}
l_{astdig}=100\left|\operatorname{floor}\left(\frac{y_{ear}}{100}\right)-\frac{y_{ear}}{100}\right|

Conor O'Brien

Posted 2015-09-12T19:23:15.597

Reputation: 36 228

2

Ruby, 57 bytes

y=Time.now.year%40;puts "#{6+(y-(y-5)/4)*0.1} #{3*y+280}"

Unfortunately, Time.now.year really costs some characters.

PotatoOmeletteSandwich

Posted 2015-09-12T19:23:15.597

Reputation: 159

2

Glava, 77 bytes

i|f=java.time.LocalDate.now().getYear();F("%.1f %d\n",(3.*f-5755)/40,3*f-5720

A translation of my Java answer.

a spaghetto

Posted 2015-09-12T19:23:15.597

Reputation: 10 647

1

APL, 25 23 29 bytes

{(10÷⍨⌊⍵÷4),⍵+33}⊃¯5753+3×⎕TS

TryAPL

Yes, it's 29 bytes.

Shujal

Posted 2015-09-12T19:23:15.597

Reputation: 687

Save two chars: (÷∘40,+∘33)¯5753+3×⊃⎕TS – Adám – 2015-09-30T02:50:09.533

1

PHP, 45 bytes

The code:

echo(int)(($x=3*date(y)+247)/4)*.1," ",$x+33;

Because y (the argument of date()) is an undefined constant, PHP triggers a notice (that can be muted) and converts it to a string (as we need); this PHP courtesy allows saving 2 bytes.

In order to suppress the notice, the program needs to be run using the error_reporting=0 runtime directive, like this:

$ php -d error_reporting=0 -r 'echo(int)(($x=3*date(y)+247)/4)*.1," ",$x+33;'
7.3 325

For testing

By replacing the call to date(y) with $argv[1] (the first command line argument), the program length increases with 1 byte but it can get the year from the command line.

The expected argument is the year minus 2000; it also works for negative values (years before 2000) or values greater than 40 (after year 2040).

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 00
6.1 280

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 01
6.2 283

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 02
6.3 286

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 03
6.4 289

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 04
6.4 292

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 15
7.3 325

$ php -r 'echo(int)(($x=3*$argv[1]+247)/4)*.1," ",$x+33;' 39
9.1 397

axiac

Posted 2015-09-12T19:23:15.597

Reputation: 749