Leap for Leap Seconds!

28

1

Since today marks the occasion of the 26th leap second ever to occur, your challenge will be to output the date and time of every leap second in GMT or UTC that has occurred so far, as well as the one to occur today.

Input

There is no input.

Output

1972-06-30 23:59:60
1972-12-31 23:59:60
1973-12-31 23:59:60
1974-12-31 23:59:60
1975-12-31 23:59:60
1976-12-31 23:59:60
1977-12-31 23:59:60
1978-12-31 23:59:60
1979-12-31 23:59:60
1981-06-30 23:59:60
1982-06-30 23:59:60
1983-06-30 23:59:60
1985-06-30 23:59:60
1987-12-31 23:59:60
1989-12-31 23:59:60
1990-12-31 23:59:60
1992-06-30 23:59:60
1993-06-30 23:59:60
1994-06-30 23:59:60
1995-12-31 23:59:60
1997-06-30 23:59:60
1998-12-31 23:59:60
2005-12-31 23:59:60
2008-12-31 23:59:60
2012-06-30 23:59:60
2015-06-30 23:59:60

Rules

Since I doubt there are many built-ins that allow leap-seconds, I'll allow them.

Standard loopholes are disallowed.

Shortest code wins.

Date format must have a zero-padded month and a 4-digit year, as well as military time and a space separating the time from the date. Putting UTC at the end is optional. Your choice of dashes or slashes.

EDIT: Yep as predicted, this became an encoding challenge. If only encoding could fix the leap second problem, ...then all our code would be much more practical. Maybe we need some ideas for more fun challenges with practical uses?

mbomb007

Posted 2015-06-30T19:21:07.493

Reputation: 21 944

Is the output required to have that exact distribution, or it can have any distribution as long as the 26 dates are there? – Ismael Miguel – 2015-07-01T14:17:43.283

2@IsmaelMiguel They need to be in this order. – mbomb007 – 2015-07-01T16:21:26.890

Off topic, but looking at the list, I'm left wondering why we need fewer leap seconds these days than we did in the previous century. – Mr Lister – 2015-07-05T06:12:29.583

@MrLister View the linked Wikipedia article. I think it has to do with Earth's changing rotational speed. – mbomb007 – 2015-07-06T16:58:41.377

Answers

25

CJam, 72 70 69 64 bytes

26,"~g¼K&Béx¸¦­Ø"240bFbf{<1b2md\1972+'-@6X$4*-'-Z3$" 23:59:60"N}

Try it online in the CJam interpreter.

Idea

We start by encoding each leap second as 2 * (Y - 1972) + D, where D is 1 if it occurs in December and 0 otherwise.

The array of all encoded leap seconds is:

[0 1 3 5 7 9 11 13 15 18 20 22 26 31 35 37 40 42 44 47 50 53 67 73 80 86]

Let's call this array L.

Since the array is in ascending order, we can store the consecutive differences instead of the actual numbers:

[1 2 2 2 2 2 2 2 3 2 2 4 5 4 2 3 2 2 3 3 3 14 6 7 6]

Treating this array as the digits of a base 15 number, we obtain the integer

19238985373462115979359619336

which digits in base 240 (cast to characters) are

~g¼K&Béx¸¦­Ø

Code

26,             e# Push I := [0 ... 25].
"~g¼K&Béx¸¦­Ø"   e# Push the string from above.
240bFb          e# Convert from base 250 to base 15 to push L.
f{              e# For each J in I:
                e#   Push L.
  <             e#   Replace L with L[:J].
  1b            e#   Push the sum S of the integers in L[:J].
  2md           e#   Push (S / 2) and (S % 2).
  \1972+        e#   Add 1972 to (S / 2).
  '-@           e#   Push '-' and rotate (S % 2) on top.
  6X$4*-        e#   Compute (6 - 4 * (S % 2)).
  '-Z           e#   Push '-' and 3.
  3$            e#   Push a copy of (S % 2).
  " 23:59:60"   e#   Push that string.
  N             e#   Push a linefeed.
}

Dennis

Posted 2015-06-30T19:21:07.493

Reputation: 196 637

28That feeling when you have a built in that almost entirely solves the problem and yet the manual solution in CJam is shorter. – Alex A. – 2015-06-30T21:54:50.810

9@AlexA. There are some built-ins in Mathematica which I can reimplement in fewer bytes in Mathematica. – Martin Ender – 2015-07-02T15:53:02.163

@MartinBüttner: Brutal. – Alex A. – 2015-07-02T15:54:52.617

35

R, 78 75 bytes

Built-ins, you say? Well...

message(paste(as.Date(.leap.seconds)-1,"23:59:60\n"),"2015-06-30 23:59:60")

R has an automatic variable .leap.seconds which contains the date and time of each leap second insertion, given in the system's local time. As of R version 3.2.0, this does not include today, so I've added that manually.

Ungolfed + explanation:

# Convert the datetime values to UTC dates. These will be a day past the
# expected output, so we can subtract 1 to get what we want.
dates <- as.Date(.leap.second) - 1

# Paste the UTC time and a newline onto the end of each date
datetimes <- paste(dates, "23:59:60\n")

# Print each time, including today, on its own line
message(datetimes, "2015-06-30 23:59:60")

You can try it online!

Alex A.

Posted 2015-06-30T19:21:07.493

Reputation: 23 761

if you can assign "23:59:60" to a variable, you might save some chars – Not that Charles – 2015-07-01T03:23:08.107

1@NotthatCharles: I had thought about that, but R's method of combining strings is not concise enough to make constructing today's date and time shorter. Thanks for the input though! – Alex A. – 2015-07-01T03:26:29.230

24

HTML, 594 bytes

1972-06-30 23:59:60<br>1972-12-31 23:59:60<br>1973-12-31 23:59:60<br>1974-12-31 23:59:60<br>1975-12-31 23:59:60<br>1976-12-31 23:59:60<br>1977-12-31 23:59:60<br>1978-12-31 23:59:60<br>1979-12-31 23:59:60<br>1981-06-30 23:59:60<br>1982-06-30 23:59:60<br>1983-06-30 23:59:60<br>1985-06-30 23:59:60<br>1987-12-31 23:59:60<br>1989-12-31 23:59:60<br>1990-12-31 23:59:60<br>1992-06-30 23:59:60<br>1993-06-30 23:59:60<br>1994-06-30 23:59:60<br>1995-12-31 23:59:60<br>1997-06-30 23:59:60<br>1998-12-31 23:59:60<br>2005-12-31 23:59:60<br>2008-12-31 23:59:60<br>2012-06-30 23:59:60<br>2015-06-30 23:59:60

¯\_(ツ)_/¯

vijrox

Posted 2015-06-30T19:21:07.493

Reputation: 471

6@Vioz- This question is tagged [tag:kolmogorov-complexity] and so this is a perfectly legal answer. Not likely to win though... – Digital Trauma – 2015-06-30T20:34:48.290

But how about a curl command to extract the answer from this page? – mlepage – 2015-07-01T06:13:17.700

10@mlepage That's one of the "standard loopholes". – Jacob Raihle – 2015-07-01T07:54:39.257

4@Voitcus save in file, open in a browser. It's a working html code – edc65 – 2015-07-01T08:00:16.810

1@edc65 Just because some browsers make it work, doesn't make it valid. According the W3C validation tool, this is not valid. – Antony D'Andrea – 2015-07-01T08:34:32.820

9@AntonyD'Andrea Yeah, so what? Vailidity is not requested in code golf challenges. – edc65 – 2015-07-01T08:45:24.783

You could replace <br> with \n. You'll need to view source, but it does save bytes. And the validness depends on which htmlversion you use. There are versions where this is valid – Martijn – 2015-07-01T10:02:55.747

Technically, you are hardcoding the output which is one of the loopholes! – Mhmd – 2015-07-01T10:43:56.630

4@Mhmd basically everybody is hardcoding the output, except the R solution, which uses a built-in function, which some might also consider a loophole. – Peter Olson – 2015-07-01T11:04:34.090

1

According to the META (http://meta.codegolf.stackexchange.com/a/2073/14732), this is not a programming language since it failt on Point 4.

– Ismael Miguel – 2015-07-01T14:15:04.420

3@PeterOlson: Built-ins in this case were explicitly allowed by the OP. And since this is [tag:kolmogorov-complexity], hard-coding the output is pretty much expected. – Alex A. – 2015-07-01T14:21:03.007

2@Voitcus The smallest HTML5 document that validates is <!DOCTYPE html><title>x</title>. There is no need for a <body>, <head> or even an <html>. – Ismael Miguel – 2015-07-01T17:31:20.313

1It most definitely is HTML, just not valid HTML. Also, using the <pre> element would have saved some characters. – zzzzBov – 2015-07-01T21:01:16.280

@JacobRaihle I see that now after checking the rules. :-) – mlepage – 2015-07-02T14:05:50.510

-1: "program" size is larger than expected output - this is not fun for [kolmogorov-complexity] – anatolyg – 2015-07-02T20:22:14.763

5@anatolyg YOU'RE not fun for [kolmogorov-complexity] – vijrox – 2015-07-02T20:23:50.750

@Voitcus This is Code Golf not Code Review... The code doesn't need to be valid. – Derek 朕會功夫 – 2015-07-03T21:06:31.437

I still don't understand this answer. Save the question text with normal returns as a plain text file, you can still open it in a browser, and you would save 75 bytes. Anyway, Voitcus has quite some rep in the PHP tag in SO, so I can only assume he knows about optional start tags. Ergo he's trolling. – Mr Lister – 2015-07-04T14:32:15.017

@MrLister I was not trolling, I'm sorry if you took me wrong. I am quite new on this site and maybe did not understand something - please excuse me. I have deleted all my comments in this thread. – Voitcus – 2015-07-04T19:35:07.643

Why the hell is this at +23? It's not even funny. – lirtosiast – 2015-07-05T04:57:03.780

1@ThomasKwa TIL humor is objective – vijrox – 2015-07-05T16:36:01.580

@VijayRamamurthy You're right, but if the votes for this started at +0/-2 I guarantee you we'd all be piling downvotes on it. – lirtosiast – 2015-07-05T16:41:34.717

Yeah, you're right... I too am surprised at the feedback this answer got – vijrox – 2015-07-05T16:44:38.713

11

C, 160 146 141 140 bytes

First time posting, not sure what "standard loopholes" are. I have printf warnings of course.

160 bytes:

The original idea is to encode leap seconds using two bits per year: one for June and one for December. The encoding is consumed one bit at a time by the inner while loop. Without a 128-bit integer, the outer while loop is necessary. The rest is all bookkeeping and math. :-)

int main(){long long X=0x2495288454AAAB,Y=1972,Z=1;while(Y<2000){while(X){if(X&1)printf("%d-%02d-%d 23:59:60\n",Y,6*(2-Z),31-Z);Y+=Z^=1;X>>=1;}X=0x104082000;}}

141 bytes:

Applying the suggested tips gets it down to 146 bytes. Then I found a way to simplify the outer while condition (from Y<2000 to just Z), bringing it down to 141 bytes. So close to a tweet!

main(Z){long long X=0x2495288454AAAB,Y=1972;while(Z){while(X)X&1?printf("%d-%02d-%d 23:59:60\n",Y,12-6*Z,31-Z):1,Y+=Z^=1,X/=2;X=4362608640;}}

140 bytes:

I noticed the dash in the date could be eliminated by making the day negative. Can't do it with the month as well due to leading zero in June. But at least it fits in a tweet now!

main(Z){long long X=0x2495288454AAAB,Y=1972;while(Z){while(X)X&1?printf("%d-%02d%d 23:59:60\n",Y,12-6*Z,Z-31):1,Y+=Z^=1,X/=2;X=4362608640;}}

Pretty version:

main(Z) {
    long long X = 0x2495288454AAAB, Y = 1972;
    while (Z) {
        while (X)
            X&1 ? printf("%d-%02d%d 23:59:60\n", Y, 12-6*Z, Z-31) : 1,
            Y += Z ^= 1,
            X /= 2;
        X = 4362608640;
    }
}

Bonus version:

I eliminated the outer loop by bit-shifting one 64-bit integer into another, but it's 150 bytes, due to the rather long "unsigned long long"; if I could use something like "uint64" it would be 138 bytes.

main(Z) {
    unsigned long long Y = 1972, X = 0x2495288454AAAB, W = 8520720;
    while (X)
        X&1 ? printf("%d-%02d-%d 23:59:60\n", Y, 12-6*Z, 31-Z) : 1,
        Y += Z^= 1,
        X = X/2 | (W>>=1)<<63;
}

mlepage

Posted 2015-06-30T19:21:07.493

Reputation: 231

4

Welcome to PPCG. "Standard loopholes" refers to this post, but generally it just means "use common sense and don't cheat". :)

– Martin Ender – 2015-07-01T08:10:40.750

1

I think using a for loop will save some bytes. BTW, int main() --> main(). You might find this very helpful.

– Spikatrix – 2015-07-01T08:38:14.153

Also: X>>=1 is the same as X/=2, 6*(2-Z) is the same as 12-6*Z, and 4362608640 is one byte shorter than 0x104082000. The int in front of main() is unnecessary, and if you change main() to main(Z) then you can remove the declaration Z=1. – r3mainer – 2015-07-01T08:47:48.387

Really nice solution- another thing to think about- you can change if(X&1)printf(...); with X&1?printf(...):1; which saves 1 byte – euanjt – 2015-07-01T08:53:41.663

and rather than while(X){...} use commas so you can remove the braces- while(X)X&1?printf("%d-%02d-%d 23:59:60\n",Y,6*(2-Z),31-Z):1,Y+=Z^=1,X>>=1; saving another 2 bytes – euanjt – 2015-07-01T08:56:02.007

Thanks for all those tips. I wondered about things like ternary and commas but it was late and I was happy just to get it working. I will check out the links. – mlepage – 2015-07-01T16:10:07.653

on most 64-bit Unix-like systems you can use just long instead of long long – phuclv – 2015-07-02T05:20:32.380

9

Python 3, 91

Uses the encoding and string formatting by Sp3000, but stores the values in a Python 3 bytes object rather than a magic number.

for n in b'()+-/1357:<>BGKMPRTWZ]kqx~':print('%d-%02d-3%d 23:59:60'%(1952+n/2,n%2*6+6,n%2))

The encoding only needs 86 of the 256 possible values of a bytes, so a range of printable characters is used to make it look nicer.

xnor

Posted 2015-06-30T19:21:07.493

Reputation: 115 687

7

Brainfuck, 806

++++++++[>++++++>+++++++>+++++++>++++++>++++++>++++++>+++++++>++++++>++++++>++++++>++++>++++++>++++++>+++++++>+++++++>+++++++>+++++++>+++++++>++++++>+<<<<<<<<<<<<<<<<<<<<-]>+>+>->++>--->>-->--->+++>>>++>+++>++>--->+>++>-->>++[<]>[.>]<[<]>>>>>>+>---->>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>+>-------->>->++++>>>-[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>++[<]>[.>]<[<]>>>>++>>+>---->>>+[<]>[.>]<[<]>>>>++[<]>[.>]<[<]>>>+>---------[<]>[.>]<[<]>>>>++>>->++++>>>-[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+[<]>[.>]<[<]>>>>+>>+>---->>>+[<]>[.>]<[<]>>>>++>>->++++>>>-[<]>[.>]<[<]>>>>+>>+>---->>>+[<]>[.>]<[<]>+>--------->--------->---[<]>[.>]<[<]>>>>+++[<]>[.>]<[<]>>>+>------>>->++++>>>-[<]>[.>]<[<]>>>>+++[<]>[.>]

You can run it on this online interpreter.

Peter Olson

Posted 2015-06-30T19:21:07.493

Reputation: 7 412

6

Python 2, 111 104 bytes

n=0x6697f252225354422533333330;y=1972
while n:print'%d-%02d-3%d 23:59:60'%(y,n%2*6+6,n%2);y+=n/2%8;n/=16

Base encoding and more base encoding.

Sp3000

Posted 2015-06-30T19:21:07.493

Reputation: 58 729

5

GNU sed+date: 112

Common Linux distributions have the leap seconds built-in, too. Using GNU sed and date:

sed -n 's/^\([0-9]\+\).*/1899-12-31 \1sec/p' /usr/share/zoneinfo/leap-seconds.list|date -f- +"%Y-%m-%d 23:59:60"

GNU sed+date: 90

Safing a few characters by cutting the path:

sed -n 's/^\([0-9]\+\).*/1899-12-31 \1sec/p' /u*/s*/z*/leap*|date -f- +'%Y-%m-%d 23:59:60'

GNU sed+date tuned by Toby Speight: 84

Deeply golfed version proposed in the comments:

sed -nr 's/^([0-9]+).*/date -d "1899-12-31 \1sec" "+%F 23:59:60"/ep' /u*/s*/z*/leap*

Jens Erat

Posted 2015-06-30T19:21:07.493

Reputation: 261

Thanks for teaching me where to find the leap-seconds data. Unfortunately, my date (GNU 8.23) displays those as the first second of the next minute. What are you using that understands the 60-second minute? – Toby Speight – 2015-07-01T08:32:12.570

With GNU coreutils, I got it down to 76, shaving bytes with the -r flag, substituting date in with the s///e modifier, and replacing %Y-%m-%d with %F in date: TZ=UTC sed -nr 's/^([0-9]+).*/date -d "1900-1-1 \1sec" "+%F %T"/ep' /u*/s*/z*/leap* – Toby Speight – 2015-07-01T08:50:44.603

I knew I missed something. Seems there is no way around specifying this manually, at least not worse than most of the other solutions do. Let's see if somebody comes up with some date library to fiddle the numbers properly supporting those seconds. – Jens Erat – 2015-07-01T08:50:52.603

I got there by using 1899-12-31 \1sec for the date, and hardcoding 23:59:60 as the time: sed -nr 's/^([0-9]+).*/date -d "1899-12-31 \1sec" "+%F 23:59:60"/ep' /u*/s*/z*/leap* – Toby Speight – 2015-07-01T09:53:10.333

3

JavaScript (ES6) 125

The newline inside `` is significant and counted.

To test, run the snippet below (being EcmaScript 6, Firefox only)

alert([..."09:;=DEFIX[01234567?ABGJQS"].map((c,i)=>c.charCodeAt()+1924+(i>10?'-12-31':'-06-30')+' 23:59:60').sort().join`
`)

edc65

Posted 2015-06-30T19:21:07.493

Reputation: 31 086

2

PHP, 198 bytes

foreach([.5,1,2,3,4,5,6,7,8,9.5,10.5,11.5,13.5,16,18,19,20.5,21.5,22.5,24,25.5,27,34,37,40.5,43.5] as$d){$h=(int)$d-ceil($d);echo date("Y-m-d 23:59:60",mktime(0,0,0,-6*$h,31+$h,(int)$d+1972))."\n";}

Unfortunately, I don't know if I can insert \n in the date function. If so, this is 3 bytes less because of ."".

Voitcus

Posted 2015-06-30T19:21:07.493

Reputation: 755

You can strip both (int) and remove some whitespace. Date throws an error, if the default timezone is not set, silence it with an @. 187 bytes: foreach([.5,1,2,3,4,5,6,7,8,9.5,10.5,11.5,13.5,16,18,19,20.5,21.5,22.5,24,25.5,27,34,37,40.5,43.5]as$d){$h=$d-ceil($d);echo@date("Y-m-d 23:59:60",mktime(0,0,0,-6*$h,31+$h,$d+1972))."\n";} – Octfx – 2015-07-02T07:39:27.567

2

8086 machine code + DOS, 92 bytes

Hexdump of the code:

BE 3A 01 B1 57 D1 E0 75 03 AD EB F9 72 09 50 BA
47 01 B4 09 CD 21 58 BB 50 01 81 77 FC 01 04 80
37 01 80 3F 31 74 10 83 EB 05 4B FE 07 80 3F 3A
75 05 C6 07 30 EB F3 E2 CC C3 AA 2A 77 B5 6A DD
DF B6 BE FF 7D BF 31 39 37 32 2D 30 36 2D 33 30
20 32 33 3A 35 39 3A 36 30 0D 0A 24

To run, write the 92 bytes into a com-file and run under 32-bit Windows or DOSBox.

The code uses a bitmap with 87 bits, one per half a year. The bits are arranged into groups of 16, starting from MSB.

Decoding the bitmap:

                 ; when the program starts, ax=0 (tested on DOSBox)
myloop:
    shl ax, 1    ; shift the MSB left into the carry flag
    jnz mywork   ; if some bits are left in the register, work normally
    lodsw        ; if all bits were shifted out, load the next 16 bits
    jmp myloop   ; and check the MSB again

Because of the code's structure, some bits are lost during decoding, so I had to repeat them. This repeating doesn't bloat the bitmap because I had to pad 87 bits to 96 bits anyway.

After printing (or not printing) the leap second, the code increases the date by half a year, using manipulations on the ASCII codes of the output message.

Source code (can be assembled with tasm):

    mov si, offset mydata
    mov cl, 57h ; number of iterations

myloop:
    shl ax, 1   ; shift the MSB left into the carry flag
    jnz mywork  ; if some bits are left in the register, work normally
    lodsw       ; if all bits were shifted out, load the next 16 bits
    jmp myloop  ; and check the MSB again
mywork:
    jc myinc_date ; shifted bit 1? - skip printing the message

    push ax
    mov dx, offset mymsg
    mov ah, 9
    int 21h     ; print the message
    pop ax

myinc_date:
    mov bx, offset mymsg + 9 ; pointer to the middle of the message
    xor word ptr [bx - 4], 401h ; change month 06<->12
    xor byte ptr [bx], 1 ; change day 30<->31
    cmp byte ptr [bx], '1'
    je myloop_end ; if 31 December, no need to increase the year
    sub bx, 5 ; pointer beyond the last digit of the year

myinc_year:
    dec bx
    inc byte ptr [bx] ; increase the digit
    cmp byte ptr [bx], '0' + 10
    jne myloop_end ; if the digit was less than 9, done
    mov byte ptr [bx], '0' ; set the digit to 0
    jmp myinc_year ; continue increasing other digits

myloop_end:
    loop myloop
    ret ; terminate the program

; In the following bitmap, the spaces before some LSBs
; show that the least significant 1-bit and all
; following 0-bits are lost during decoding.
mydata:
    dw 02aaah ; 00101010101010     10
    dw 0b577h ; 101101010111011    1
    dw 0dd6ah ; 11011101011010     10
    dw 0b6dfh ; 101101101101111    1
    dw 0ffbeh ; 11111111101111     10
    dw 0bf7dh ; 101111110111110    1

mymsg:
    db '1972-06-30 23:59:60',13,10,'$'

anatolyg

Posted 2015-06-30T19:21:07.493

Reputation: 10 719

I would like to test this, but I can't seem to find a single editor anywhere that allows you to paste hex and save it to a binary file. – Mr Lister – 2015-07-04T17:10:39.813

@MrLister any normal hex editor should do that for you. – TheDoctor – 2015-11-22T16:44:35.717

1

Python 2, 123 121 116 114 111

I've managed to get it pretty short, but I'm not sure how much shorter it can get. I tried using exec, but the formatting gets to be too costly.

I used a base 16 encoding of the table from the linked Wikipedia page.

Edit: Using hex encoding is shorter than base 36 (see the less golfed version.)

Try it here

n=0x410208002495288454aaab
for i in range(88):
    if n%2:print"%d-%02d-3%d 23:59:60"%(1972+i/2,i%2*6+6,i%2)
    n/=2

Less golfed:

s=bin(int('WELD24ZDGIMBWWLFM',36))[2:]
for i in range(44):
    t,s=int(s[0]),s[1:]
    if t:print"%d-06-30 23:59:60"%(i+1972)
    t,s=int(s[0]),s[1:]
    if t:print"%d-12-31 23:59:60"%(i+1972)

mbomb007

Posted 2015-06-30T19:21:07.493

Reputation: 21 944

1

Pyth - 88 84 bytes

Converts to char to compress the data and saves the 06-30 versus 12-31 data as binary number.

jbm++-2047ed?"-06-30"hd"-12-31"" 23:59:60"C,j33678243 2CM"KKJIHGFEDBA@><:9765421*'# 

(there is a space there at the end)

Try it here online.

Maltysen

Posted 2015-06-30T19:21:07.493

Reputation: 25 023

1

Python, 204 201

e,g,h=0,1972,0
for i in range(1,27):e,g,h={2:1,9:2,10:1,12:2,15:1,16:2,17:1,20:2,21:1,22:7,23:3,24:4,25:3}.get(i,e),g+e,(h,1-h)[i in[2,10,14,17,20,21,22,25]];print`g`+("-06-30","-12-31")[h]+" 23:59:60"

You can play with it on repl.it.

Edit: Thoroughly beaten! The compression answers are amazingly short.

sudo rm -rf slash

Posted 2015-06-30T19:21:07.493

Reputation: 1 076

Surprisingly, my PHP anwser is shorter, using similar algorithm. I've always expected Python be more compact. Maybe you could golf it a little more?

– Voitcus – 2015-07-01T08:30:47.463

I'll take a look. I think the best route is compression though, and others have already done that – sudo rm -rf slash – 2015-07-01T10:25:50.917

1

q/kdb+, 95 94 93 bytes

asc 1_" "0:([]raze("DEFGHIJKSUV[^eh";"DMNOQXYZ]lo"){("d"$"m"$-12*95-6h$x)-y}'1 185;`23:59:60)

Explanation

For each year + 1, encode for years since 1905 as an ASCII character, e.g.:

1972 -> 1973 -> 68 -> D

6h$x turns "D" back to 68. Since q's date epoch is 2000.01.01, we subtract 95 and perform the integers-to-date conversion "d"$"m"$-12*95-6h$x.

The reason we + 1 above is to subtract the number of days from the start of next year to get the actual year's 31st December or 30th June, namely 1 or 185 days. Therefore, "DEFGHIJKSUV[^eh" represents the years with a leap second in December, and "DMNOQXYZ]lo" for those in June. The pairing-subtraction is done via (a;b){x-y}'(c;d), where a and b are years that will be subtracted by c and d number of days respectively.

" "0:([]...) prepares the results to give us the correct formatting, with a small caveat that a column header will be generated. 1_ drops that header and finally apply asc to get the ordering correct.

edit: 're-base' to subtracting 95 years instead of 100 (saving 1 character).

edit 2: re-ordering the operands' positioning inside the integers-to-date conversion function.

h.j.k.

Posted 2015-06-30T19:21:07.493

Reputation: 589

1

C, 155 149 147 bytes

Here's another approach in C, using strings and run length encoding. Not quite as terse as my other C solution, but maybe it can be improved?

155 bytes:

Using a string to hold the month/day.

main(Y){Y=1972;char*M="06-3012-31",*B="#@DGCDF7D3daTdS#!",b,c;while(b=*B++-33){c=b>>1&7;while(c--)printf("%d-%.5s 23:59:60\n",Y++,M+b%2*5);Y+=(b>>4&7)-1;}}

149 bytes:

Eliminating the month/day string.

main(Y){Y=1972;char*B="#@DGCDF7D3daTdS#!",b,c;while(b=*B++-33){c=b>>1&7;while(c--)printf("%d-%02d-%d 23:59:60\n",Y++,6+b%2*6,30+b%2);Y+=(b>>4&7)-1;}}

147 bytes:

Eliminating the year initialization.

main(Y){char*B="#@DGCDF7D3daTdS#!",b,c;while(b=*B++-33){c=b>>1&7;while(c--)printf("%d-%02d-%d 23:59:60\n",1971+Y++,6+b%2*6,30+b%2);Y+=(b>>4&7)-1;}}

144 bytes:

If I reencoded the buffer to make the skip count apply before (not after) the run, then I could reorder the statements in the outer while loop, use the comma operator, and eliminate the braces, saving 2 bytes.

I can save another byte by making the day negative (as in my other solution).

Pretty:

main(Y) {
    char *B = "#@DGCDF7D3daTdS#!", // buffer of bytes encoding runs
         b, // current byte
         c; // current count
    while (b = *B++-33) { // get byte
        c = b>>1&7; // get count
        while (c--) printf("%d-%02d-%d 23:59:60\n", 1971+Y++, 6+b%2*6, 30+b%2); // run
        Y += (b>>4&7)-1; // skip years
    }
}

Explanation:

Runs are encoded in bytes. Each byte has one bit to say whether it's June or December, 3 bits for a length count, 3 bits for a skip count, and 1 unused high bit.

The skip count is the number of years to skip after a run; it's offset by -1 to allow for two leap seconds in 1972. The length is how many years in a run; it probably could be offset by +1 but it isn't currently.

So a byte means: "Do LENGTH years of JUNE (or DECEMBER) years of leap seconds, then skip SKIP-1 years" before moving to the next byte.

The bytes are offset by 33 to make them readable and avoid fancy encoding.

This means although we have enough skip bits to cover 1998-2005, we're out of ASCII range, so we have an extra zero length run. Also, 1979 appears on its own because the length 1972-1979 is one too long.

There's enough bits in the bytes, so those issues might be fixable ultimately.

mlepage

Posted 2015-06-30T19:21:07.493

Reputation: 231

0

Python, 221 217

def d(x):
 q=x%10
 if x%2==0:
  p,r=q/2,"06-30"
 else:
  p,r=(q-1)/2,"12-31"
 return"%d%d-%s 23:59:60"%(p+197,x/10,r)
for x in [20,21,31,41,51,61,71,81,91,12,22,32,52,73,93,5,24,34,44,55,74,85,57,87,28,58]:print(d(x))

Some Insights

Basically, d(x) decompresses a vector of 3 integers from a single 2-digit integer. d(x) is constructed as the inverse function (over the 26 leap seconds datetimes) of c(v), which in turn is a compression function that turns a 3-uple such as (1998,12,31) into a number like 85. To derive the list [20,21...28,58] I designed another algorithm to verify that the compression function is bijective over the domain. That is, I made sure that the following program doesn't produce duplicates, and I used its output as the list of the program above.

dates = [(1972,06,30),
    (1972,12,31),
    (1973,12,31),
    (1974,12,31),
    (1975,12,31),
    (1976,12,31),
    (1977,12,31),
    (1978,12,31),
    (1979,12,31),
    (1981,06,30),
    (1982,06,30),
    (1983,06,30),
    (1985,06,30),
    (1987,12,31),
    (1989,12,31),
    (1990,12,31),
    (1992,06,30),
    (1993,06,30),
    (1994,06,30),
    (1995,12,31),
    (1997,06,30),
    (1998,12,31),
    (2005,12,31),
    (2008,12,31),
    (2012,06,30),
    (2015,06,30)]

def c(v):
    x = (v[0] % 10) * 10
    x += v[2] % 30
    x += 2 * (int(v[0] / 10) - 197)
    return x

for v in dates:
    print(c(v))

The compression function c(v) was designed to be bijective by using a very simple scheme. Let's take as an example (1998,12,31).

  • The expression (v[0] % 10) * 10 selects the units of the year (e.g. 1 9 9 8 --> 8) and makes it the tenths digit of the output (now x=80).
  • There are only two month-day combination in which the leap second thing happens, so I decided to use the day component to distinguish between the 06,30 case and the 12,31 case. The expression v[2] % 30 is 0 if the day is 30, and is 1 if the day is 31. In our example, we add 1 to x (hence, now x=81).
  • Finally, I observed that this puzzle involves only 5 decades; hence if I map the first decade (the seventies) to 0 and the last decade (the 2010s) to 4 I can do cool stuff. More specifically, if instead of mapping to 0,1,2,3,4 I map to 0,2,4,6,8 I can add this value to the units of x, which due to the previous rule is either 0 or 1. So in the end we have that also this last step doesn't screw the bijection, and we get that the units of a 06,30 case are one of 0,2,4,6,8 and that the units of a 12,31 case are one of 1,3,5,7,9. Hence the bijection is obvious. In our example, 1998 is in the third decade (70s->0, 80s->1, 90s->2) so we add 2*2=4. So we get x=85.

I wrote the program to verify that this is true, and then I defined d(x) as the inverse of c(v). In our example, c((1998,12,31)) is 85 and d(85) correctly prints 1998-12-31 23:59:60.

damix911

Posted 2015-06-30T19:21:07.493

Reputation: 121

1

Remove q=x%10 and replace q with x%10 everywhere. It's shorter. I also give a helpful description of some additional golfing on your program here. I recommend viewing the Tips for Golfing in Python page.

– mbomb007 – 2015-07-01T21:03:53.463

This is code-golf, so you should try to shorten the length of your code in any way possible. – mbomb007 – 2015-07-06T16:50:05.487

0

PHP, 164 bytes

foreach([.5,1,2,3,4,5,6,7,8,9.5,10.5,11.5,13.5,16,18,19,20.5,21.5,22.5,24,25.5,27,34,37,40.5,43.5]as$d){echo(ceil($d)+1971).($d%2?'-12-31':'-06-30')." 23:59:60\n";}

This is just a few modification on @Voitcus's idea

pranzer

Posted 2015-06-30T19:21:07.493

Reputation: 1

-1

gzip, 114 bytes

Hexdump:

1f8b080853f9975502006c006dd04b0a80300c84e1bde01dbc40218fa6697aff8309e2a6fa6f3f86cc10adb426a3b95ce62b6a0d398f07d59aeb8e4ed80983701026e1242cc0a9307e1aa11306615211b59710527b3961270cba9994fc7fc944829092faeedc313e7803993cfafb20020000

Create a file with the bytes described above.

Extract using gunzip or another decompression program to get a new file named "l". This file contains the desired output.

Stef Heyenrath

Posted 2015-06-30T19:21:07.493

Reputation: 107