Next Friday the 13th

15

What is the shortest program that can predict the next time Friday will fall on the 13th day of the month?

  • Must be an complete functioning program (not just a function/subroutine)
  • Must print out date in the following format: YYYY-MM-DD
  • Allow user to provide a start date either as a command line argument or through STDIN
  • If user provides no start date, use today as the start date.
  • If the start date is a Friday the 13th, the program should find the next Friday the 13th.

If I were to run the program today (Feb 16 2011) I should get the following output.

$ ./fr13th 2013-05-09
2013-09-13
$ ./fr13th 2007-06-29
2007-07-13
$ ./fr13th 2007-07-13
2008-06-13
$ ./fr13th
2011-05-13

Daniel Standage

Posted 2011-02-16T15:21:46.937

Reputation: 634

Would a 2013-9-13 output be ok for the first example? – J B – 2011-02-16T16:05:11.590

Do you mean we can decide whether we want to take the date as an argument or from STDIN or that we need to support both? – sepp2k – 2011-02-16T16:58:05.210

@sepp2k You can decide, you don't need to support both, the user just needs a way to input a date. – Daniel Standage – 2011-02-16T18:06:00.600

@JB Yeah, since there are several other solutions that do address all of the requirements, I wouldn't accept your response as the solution even if it was the shortest. That doesn't mean your response wasn't informative...but yeah, dealing with an inconsistent date format would be frustrating. – Daniel Standage – 2011-02-16T20:50:48.383

Well this one is not really possible with golfscript because it doesn't know today's date. It also doesn't have a date library so would likely be quite a large answer anyway. (you can use ruby eval to get it, but then might as well use ruby date lib too) – gnibbler – 2011-02-16T21:21:16.557

@Daniel Standage: my question predates those, so that makes for a weak argument; but the decision is acceptable on its own nonetheless. – J B – 2011-02-16T22:40:07.660

Answers

6

Windows PowerShell, 74

for($d="date $args"|iex;($d+='1').day*$d.dayofweek-65){}'{0:yyy-MM-d}'-f$d

Fairly straightforward. One perhaps confusing bit is the use of "Get-Date $args" | Invoke-Expression to get either the current date (if $args is empty) or the date specified in $args without raising an error.

72-byte variant:

for($d="date $args"|iex;($d+=9).day*$d.dayofweek-65){}'{0:yyy-MM-d}'-f$d

Takes ages, though ... this doesn't increment the datetime by a whole day each iteration but instead only 900 nanoseconds. But two bytes shorter.

67-byte variant:

for($d="date $args"|iex;($d+='1').day*$d.dayofweek-65){}'{0:d}'-f$d

This is a bit locale-sensitive; if it fails on your machine, try setting your date format to ISO-8601 beforehand. :-)

Oh, and it can be made into 65 bytes just like the 72-byte version.

History:

  • 2011-02-17 00:33 (92) First attempt.
  • 2011-02-17 00:35 (85) Improved getting an initial date.
  • 2011-02-17 00:37 (79) Compared the product instead of day and day of week individually. Admittedly stolen from Ventero.
  • 2011-02-17 00:40 (76) Pulled the first line into the for. Comparison just as subtraction instead of -eq which saves another two bytes.
  • 2011-02-17 00:53 (75) Unix date format string is a bit shorter.
  • 2011-02-17 11:42 (74) Reverted to the default date pattern but yyy-MM-d suffices (since the year is always longer than three characters and the day is always 13. Thanks to Ty Auvil for this.

Joey

Posted 2011-02-16T15:21:46.937

Reputation: 12 260

Why are you passing "date $args" to iex? Try just (date $args) instead. – Iszi – 2013-12-11T00:26:17.520

@Iszi: This is used to implement the "If user provides no start date, use today as the start date." rule. If you pass an empty array or $null to Get-Date you'll get an error, not the current date. "date $args"|iex however, resolves to either the date given in $args or the current date, which is just what we want here. – Joey – 2013-12-11T07:05:40.293

4

Ruby, 96 75 characters

require"date"
d=Date.parse(gets||"thu")+1
d+=1 while d.wday*d.day!=65
$><<d

Takes the date from stdin. To not specify a date press ctrl-d.

Thanks very much for Ventero's help.

Ungolfed:

require "date"
# Date.parse("thu") will return this week's thursday
date = Date.parse(gets || "thu")+1
date += 1 while d.wday * d.day != 5 * 13
$stdout << date

Sample IO:

$ ruby fr13th.rb
2013-05-09
2013-09-13
$ ruby fr13th.rb
2007-06-29
2007-07-13
$ ruby fr13th.rb
2007-07-13
2008-06-13
$ ruby fr13th.rb
2011-05-13

sepp2k

Posted 2011-02-16T15:21:46.937

Reputation: 1 679

1d.wday*d.day==65 is 4 characters shorter. And you should be able to replace Date.today.to_s with "thu" – Ventero – 2011-02-16T19:30:16.613

Actually using a loop instead of an iterator shortens the code to 76 characters: require"date";d=Date.parse($*[0]||"thu")+1;d+=1 while d.wday*d.day!=65;$><<d. And you could read the date from stdin with gets instead of $*[0] to save another character (enter EOF to get the default behavior). – Ventero – 2011-02-17T00:06:21.127

@Ventero: Very nice, thanks. – sepp2k – 2011-02-17T06:11:41.000

4

bash, 75

until set `date +%F -d$1+day`
date -d$1|grep -q '^F.* 13'
do :
done
echo $1

This is a bit locale-sensitive; if it fails on your machine, try exporting LC_ALL=C beforehand.

$ bash fri13th.sh 2013-05-09
2013-09-13                                             
$ bash fri13th.sh 2007-06-29
2007-07-13                                             
$ bash fri13th.sh 2007-07-13
2008-06-13
$ bash fri13th.sh
2011-05-13

J B

Posted 2011-02-16T15:21:46.937

Reputation: 9 638

3

C#, 185

Based on Andrew Koester's C# solution, but heavily modified along the way. I eventually arrived at a solution similar to my PowerShell solution:

using System;class
P{static void
Main(string[]a){var
n=a.Length>0?DateTime.Parse(a[0]):DateTime.Now;for(;(n=n.AddDays(1)).Day*(int)n.DayOfWeek!=65;);Console.Write("{0:yyy-MM-d}\n",n);}}

Joey

Posted 2011-02-16T15:21:46.937

Reputation: 12 260

2

R, 113 characters

f="%Y-%m-%d";o=format;a=c(as.Date(scan(,""),f),Sys.Date())[1];repeat{a=a+1;if(o(a,"%w%d")==513)break};cat(o(a,f))

Example runs:

> f="%Y-%m-%d";o=format;a=c(as.Date(scan(,""),f),Sys.Date())[1];repeat{a=a+1;if(o(a,"%w%d")==513)break};cat(o(a,f))
1: 2007-06-29
2: 
Read 1 item
2007-07-13

> f="%Y-%m-%d";o=format;a=c(as.Date(scan(,""),f),Sys.Date())[1];repeat{a=a+1;if(o(a,"%w%d")==513)break};cat(o(a,f))
1:
Read 0 items
2013-12-13

> f="%Y-%m-%d";o=format;a=c(as.Date(scan(,""),f),Sys.Date())[1];repeat{a=a+1;if(o(a,"%w%d")==513)break};cat(o(a,f))
1: 2013-12-13
2: 
Read 1 item
2014-06-13

plannapus

Posted 2011-02-16T15:21:46.937

Reputation: 8 610

2

Perl 6, 69 bytes

$_=Date.new(@*ARGS[0]//Date.today);.++while .day*.day-of-week-65;.say

Try it online!

Thanks to @ASCII-only for -5

Ven

Posted 2011-02-16T15:21:46.937

Reputation: 3 382

Invalid, needs to handle the case when the user does not provide an argument, also day-of-week==5 – ASCII-only – 2019-03-01T10:47:27.930

@ASCII-only fixed – Ven – 2019-03-01T10:51:36.237

Oh yeah, it also has to be a complete program, not a function – ASCII-only – 2019-03-01T10:55:56.847

Might want to link to this (even better, go there, esc -> s -> g for a nicely formatted post)

– ASCII-only – 2019-03-01T10:57:08.443

@ASCII-only done, ty – Ven – 2019-03-01T11:01:16.630

Really wish Perl 6 had Str.date so I could use a coercer... – Ven – 2019-03-01T11:02:33.493

Yeah, this is unusually ungolfy for Perl :/ – ASCII-only – 2019-03-01T11:03:17.663

170 using the powershell answer – ASCII-only – 2019-03-01T11:04:36.183

69 – ASCII-only – 2019-03-01T11:08:07.543

Beautiful. Updated. – Ven – 2019-03-01T11:09:16.367

Let us continue this discussion in chat.

– ASCII-only – 2019-03-01T11:58:23.320

you don't have to delete answers especially if it's a radically different approach to others in the same language, fixed 22 for max thing (EDIT: wait wtf. it's now tying with the other one)

– ASCII-only – 2019-03-01T11:58:51.010

@ASCII-only well, it was outgolfed in the same language, so... – Ven – 2019-03-01T12:01:07.393

outgolfed in the same language doesn't matter :P (in fact, it's encouraged - there really isn't enough intra-language competition, mostly since there's usually only one really competitive method) what matters is the best for each approach that anyone thinks is viable – ASCII-only – 2019-03-01T12:02:04.037

2

Perl (and others), 114

for(($y,$m,$d)=(shift//`date +%F`)=~/\d+/g,$d>12&&$m++;$m
>12&&($y++,$m=1),`cal $m $y`!~/14$/m;$m++){}say"$y-$m-13"

Perl 5.10 or later, run with -E 'code here' or -M5.010 file. Needs date (from coreutils for Linux) and cal (from util-linux)

Sample run:

$ perl -M5.010 fr13.pl 2013-05-09
2013-9-13
$ perl -M5.010 fr13.pl 2007-06-29
2007-07-13
$ perl -M5.010 fr13.pl 2007-07-13
2008-6-13
$ perl -M5.010 fr13.pl
2011-5-13

I'm not sure when the leading zero for months before October is kept. It's obviously lost when the year rolls over; it seems to be kept when the answer is just next month. Let's call that undefined behavior--hey, this is golfing!

J B

Posted 2011-02-16T15:21:46.937

Reputation: 9 638

2

PHP - 103

(brute force)

<?for($d=date_create(@$argv[1]);$d->modify('next fri')&&$d->format(@d)-13;);die($d->format("Y-m-d\n"));

Ungolfed:

<?
$d = new DateTime(@$argv[1]);
while ($d->modify('next fri')) {
        if ($d->format('d') == 13) {
                die($d->format("Y-m-d\n"));
        }
}

Test:

$ php 979.php 2013-05-09
2013-09-13
$ php 979.php 2007-06-29
2007-07-13
$ php 979.php 2007-07-13
2008-06-13
$ php 979.php 
2011-05-13

Arnaud Le Blanc

Posted 2011-02-16T15:21:46.937

Reputation: 2 286

1You can save up 1 character by changing != to -. Also you can save up 2 characters by moving up the $d->modify('next fri') in the increment section of the loop. – HoLyVieR – 2011-02-16T19:25:48.733

I need to modify to next friday before the loop, in case the given date is already a friday 13 :-) (or even just 13) – Arnaud Le Blanc – 2011-02-17T13:20:53.417

Use -r and You don´t need the tag. Use the default config with -n and You don´t need @. \n is unnecessary. echo instead of die saves another byte. strtotime instead of Date class can save one or two more. – Titus – 2017-03-01T21:15:51.357

2

BASH

#!/bin/bash
from=$1
if [ "$from" = "" ]; then
from=`date +%Y-%m-%d`
fi
i=1
while [ "$isFri" = "" ] || [ "$is13" = "" ]
do
isFri=`date -d "${from} ${i} days" | grep Fri`
is13=`date -d "${from} ${i} days" +%Y-%m-%d | grep "\-13"`
((i++))
done
((i--))
date -d "${from} ${i} days" +%Y-%m-%d

CONCEPT USED:

$ date -d "2011-02-16 2 days" +%Y-%m-%d
2011-02-18

SAMPLE I/O

:~/aman> ./fr13th.sh
2011-05-13
:~/aman> ./fr13th.sh 2013-05-09
2013-09-13
:~/aman> ./fr13th.sh 2007-06-29
2007-07-13
:~/aman> ./fr13th.sh 2007-07-13
2008-06-13

Aman ZeeK Verma

Posted 2011-02-16T15:21:46.937

Reputation: 609

2

Python - 166 chars

Reads from stdin, so you need to feed a blank line if you want todays date

from datetime import*
D=datetime
e=timedelta(1)
I=raw_input()
d=e+(I and D.strptime(I,"%Y-%m-%d")or D.now())
while(d.weekday()+1)*d.day-65:d+=e
print d.strftime("%F")

gnibbler

Posted 2011-02-16T15:21:46.937

Reputation: 14 170

Unless I'm missing something this does not address the 4th requirement (if no date is provided, start from today). – Daniel Standage – 2011-02-16T21:06:21.100

@Daniel, missed that one. 26 strokes later... – gnibbler – 2011-02-16T21:16:09.590

Blast from the past sorry :) If we join our solutions, we get to a collaborative 144 chars (see below!) :) – Roberto – 2013-12-12T02:00:16.977

2

C#

240 characters. C# needs a "run inside of a function only" mode!

using System;class P{static void Main(string[] a){var n=DateTime.Now;if(a.Length>0)DateTime.TryParse(args[0],out n);while(true){n=n.AddDays(1);if((n.Day==13)&&(n.DayOfWeek==(DayOfWeek)5))break;}Console.WriteLine(n.ToString("yyyy-MM-dd"));}}

Un-golfed:

using System;

class P
{
    static void Main(string[] a)
    {
        var n = DateTime.Now;
        if (a.Length > 0) DateTime.TryParse(args[0], out n);
        while (true)
        {
            n = n.AddDays(1);
            if ((n.Day == 13) && (n.DayOfWeek == (DayOfWeek)5)) break;
        }
        Console.WriteLine(n.ToString("yyyy-MM-dd"));
    }
}

Test output

\Debug> f13.exe 2013-05-09
2013-09-13

\Debug> f13.exe 2007-06-29
2007-07-13

\Debug> f13.exe 2007-07-13
2008-06-13

\Debug> f13.exe
2011-05-13

Jess

Posted 2011-02-16T15:21:46.937

Reputation: 121

2

D: 227 Characters

import std.datetime,std.stdio;void main(string[]a){auto d=a.length<2?cast(Date)(Clock.currTime()):Date.fromISOExtendedString(a[1]);for(;d.dayOfWeek!=DayOfWeek.fri||d.day!=13;d+=dur!"days"(1)){}writeln(d.toISOExtendedString());}

More Legibly:

import std.datetime, std.stdio;

void main(string[] a)
{
    auto d = a.length < 2 ? cast(Date)(Clock.currTime()) : Date.fromISOExtendedString(a[1]);

    for(; d.dayOfWeek != DayOfWeek.fri || d.day != 13; d += dur!"days"(1)) {}

    writeln(d.toISOExtendedString());
}

The fun part is that while D's std.datetime makes this sort of code very easy to write, it's also incredibly verbose - due primarily to the precise (and therefore long) function names. So, the usability and maintainability of the code is very high, but it's code golfability is rather low.

Jonathan M Davis

Posted 2011-02-16T15:21:46.937

Reputation: 705

2

C#, 206 194 characters

Update

This is a slightly different take on the problem, so I left my other attempt here in full.

using System:class p{static void Main(string[]a){var n=a.Length>0?DateTime.Parse(a[0]):DateTime.Now;for(;(n=n.AddDays(5-(int)n.DayOfWeek).AddDays(7)).Day!=13;);Console.Write("{0:yyy-MM-d}",n);}}

Here, I'm finding the "current" week's Friday and then incrementing by 7 until I find one that's a 13. I also used Joey's for loop and output formatting to shave a few characters.

Ungolfed:

using System;
class p
{
    static void Main(string[] a)
    {
        var n = a.Length > 0 ? DateTime.Parse(a[0]) : DateTime.Now;

        for (; (n = n.AddDays(5 - (int)n.DayOfWeek).AddDays(7)).Day != 13; ) ;

        Console.Write("{0:yyy-MM-d}", n);
    }
}

Original:

This is similar to Andrew's above, but there were enough differences I decided to post a separate answer rather than comment and suggest edits.

using System;class p{static void Main(string[]a){var n=a.Length>0?DateTime.Parse(a[0]):DateTime.Now;do n=n.AddDays(1);while(!(n.Day==13&&n.DayOfWeek+""=="Friday"));Console.Write(n.ToString("yyyy-MM-dd"));}}

Ungolfed:

using System;
class p
{
    static void Main(string[] a)
    {
        var n = a.Length > 0 ? DateTime.Parse(a[0]) : DateTime.Now;
        do
        {
            n = n.AddDays(1);
        } while (!(n.Day == 13 && n.DayOfWeek + "" == "Friday"));

        Console.Write(n.ToString("yyyy-MM-dd"));
    }
}

Steve

Posted 2011-02-16T15:21:46.937

Reputation: 671

2

SQLite, 374 characters

(Line breaks added here for readability; not included in the count.)

Requirement to "Allow user to provide a start date either as a command line argument or through STDIN" omitted due to technical limitations.

CREATE TABLE R(N UNIQUE);
INSERT INTO R VALUES(0);
INSERT INTO R VALUES(1);
REPLACE INTO R SELECT A.N*2048|B.N*1024|C.N*512|D.N*256|E.N*128|F.N*64|
G.N*32|H.N*16|I.N*8|J.N*4|K.N*2|L.N FROM
R A,R B,R C,R D,R E,R F,R G,R H,R I,R J,R K,R L;
CREATE TABLE F AS SELECT DATE('2000-01-13','+'||N||'months') AS D
FROM R WHERE STRFTIME('%w',D)='5';
SELECT MIN(D) FROM F WHERE D>DATE('now');

The first 4 statements create a table (R) with a single column containing all the integers from 0 to 4095.

The 5th statement builds a table (F) of all Friday the 13ths between 2000-10-13 and 2340-12-13.

The 6th statement simply returns the first Friday the 13th after the current (UTC) date.

dan04

Posted 2011-02-16T15:21:46.937

Reputation: 6 319

The Gregorian calendar has a 400-year cycle, not 340 years. Or am I missing something here? – Joey – 2011-02-17T17:27:55.750

It doesn't handle years outside the range 2000-2340. That was just an arbitrary choice. – dan04 – 2011-02-18T03:54:10.547

1

Another Javascript, 153

I post another javascript answer because I can't comment the first...

a=new Date(process.argv[2]||Date.now());for(b=1;b;b=a.getDate()!=13||!/^F/.test(a))a.setTime(a.getTime()+864e5);console.log(a.toISOString().substr(0,10))

Execute with nodeJS :

$ node fr13th
2013-12-13

$ node fr13th 2007-06-29
2007-07-13

$ node fr13th 2013-05-09
2013-09-13

guy777

Posted 2011-02-16T15:21:46.937

Reputation: 153

1

Python 3.3, 166 characters

import datetime as d
t=input()
t=d.date(*map(int,t.split()))if t!=""else d.date.today()
while 1:
 t+=d.timedelta(1)
 if t.day==13and t.weekday()==4:
  print(t);break

Input is in the format 2013 1 1,

>>> ================================ RESTART ================================
>>> 
2013 1 1
2013-09-13

or just press enter to use today's date (would be 2013/12/11 for this output)

>>> ================================ RESTART ================================
>>> 

2013-12-13

(there is actually a mix of my solution and @gnibbler 's that counts 144 chars)

import datetime as d
t=input()
t=d.date(*map(int,t.split()))if t!=""else d.date.today()
while t.day*t.weekday()-65:
 t+=d.timedelta(1)
print(t)

The very nice line while t.day*t.weekday()-65: is from @gnibbler's solution.

Roberto

Posted 2011-02-16T15:21:46.937

Reputation: 761

1

Japt, 35 bytes

ÐUªKs3 ¯A
@e ¶5©D¶Uf}a@f1Uf Ä
s3 ¯A

-8 bytes thanks to @ASCIIOnly!

Try it!

dana

Posted 2011-02-16T15:21:46.937

Reputation: 2 541

Invalid output format... – ASCII-only – 2019-03-01T10:06:40.440

136? – ASCII-only – 2019-03-01T10:08:19.707

Yeah, I'm working on it :) Apparently toISOString converts to UTC which changes the date – dana – 2019-03-01T10:08:43.593

How does it change the date? Does K store time as local time? – ASCII-only – 2019-03-01T10:14:54.487

Depending on your timezone, this will be different: https://ethproductions.github.io/japt/?v=1.4.6&code=0FWqSylqCjFvNTAwXyo4NjRlNX0p5l890ForVSlaZSC2NalaZiC2RArQVStWKXMz&input=IjIwMDEtMDEtMDEi - but anyways, I think you nailed it!

– dana – 2019-03-01T10:17:48.607

1

Fixed, 39 (well, kinda. It outputs the correct result for today at UTC (AFAICT) and that's good enough for me. Don't want to mess with timezones more than I already am)

– ASCII-only – 2019-03-01T10:19:27.777

37 – ASCII-only – 2019-03-01T10:30:29.943

Now we just have to wait for Shaggy to shave another 5 bytes off :P – ASCII-only – 2019-03-01T10:36:55.253

I actually think through 36 byte solution works. There must be something different between setDate and the date constructor. – dana – 2019-03-01T10:37:08.560

Let us continue this discussion in chat.

– ASCII-only – 2019-03-01T10:37:40.547

32 if you want to use the old 36-byter – ASCII-only – 2019-03-01T10:44:03.200

@ASCII-only, I have 23 bytes at the moment ;) – Shaggy – 2019-03-01T12:04:31.403

@Shaggy :| ok i mustn't have been looking hard enough i'll be back in a few years with that 23-byter. also, it works correctly? (doesn't return the wrong date because of conversion to ISO time?) – ASCII-only – 2019-03-01T12:05:19.117

@ASCII-only ... huh ... so it does :\ 24 bytes, so. – Shaggy – 2019-03-01T12:08:39.273

Ah, wait, I missed the optional input. Back to the drawing board! – Shaggy – 2019-03-01T12:13:34.470

1

Swift 4, 310 bytes

import Foundation
let (u,f)=(Calendar.current,DateFormatter())
f.dateFormat="yyyy-MM-dd"
var t={(x:Date)->Int in let c=u.dateComponents([.weekday,.day],from:x);return c.weekday!*c.day!},d=readLine().map{f.date(from:$0)!} ?? Date()
while t(d) != 65{d=u.date(byAdding:.day,value:1,to:d)!}
print(f.string(from:d))

Try it online!

-4 thanks to TagTaco.

Alas...:

  • needs Foundation for Date/Calendar.
  • Swift doesn't allow Ints to be used as Bool.
  • The shorthand enum syntax is helpful, though not that much.
  • Space is required around ??.
  • != also needs spacing, lest it's interpreted as an unwrapping.

Ven

Posted 2011-02-16T15:21:46.937

Reputation: 3 382

1

Javascript

F13=function(x){
    z=function(x){return (''+x).replace(/^(.)$/,'0$1')}
    D=x?new Date(x):new Date(),Z=864e5,X=D.getDay()%7,X+=+D+(X?Z*(5-X):0);
    do{
        X+=Z*7;
        D=new Date(X);
    }while(D.getDate()!=13)
    return D.getFullYear()+"-"+z(D.getMonth()+1)+"-"+z(D.getDate());
}

ps: yeah, I know, I broke the first rule (couldn't be just a function)

Tests on javascript shell

F13("2013-05-09") // 2013-09-13
2013-09-13
F13("2007-06-29") // 2007-07-13
2007-07-13
F13("2007-07-13") // 2008-06-13
2008-06-13
F13() //2011-05-13
2011-05-13

YOU

Posted 2011-02-16T15:21:46.937

Reputation: 4 321

+1 Fight the elitist general purpose language favoring STDIN rule. – mootinator – 2011-02-17T17:22:22.230

1

T-SQL 359 285 253 Characters

CREATE PROCEDURE f13(@d DateTime=null)AS
SET @d=ISNULL(@d,GETDATE())
;WITH d AS
(SELECT @d+1 d
UNION ALL SELECT d+1 FROM d
WHERE DATEPART(dw,d)<>6 OR DAY(d)<>13)SELECT CAST(d AS DATE) FROM d
WHERE DATEPART(dw,d)=6 AND DAY(d)=13
OPTION (MAXRECURSION 999)

I just wanted to lay the smack down on the SQLite solution with my non-clever verbose date function using T-SQL procedure.

Update: My original fear that doing a day increment would take more space than a month increment was very incorrect.

Test results (SSMS):

f13 '2013-05-09';
GO

f13 '2007-06-29';
GO

f13 '2007-07-13';
GO

f13;
GO
--

d
----------
2013-09-13

d
----------
2007-07-13

d
----------
2008-06-13

d
----------
2011-05-13

mootinator

Posted 2011-02-16T15:21:46.937

Reputation: 1 171

0

Java 8, 200 197 bytes

interface M{static void main(String[]a){java.time.LocalDate z=null,r=a.length<1?z.now():z.parse(a[0]);for(;(r=r.plusDays(1)).getDayOfWeek().getValue()*r.getDayOfMonth()!=65;);System.out.print(r);}}

Explanation:

Try it here (remove the argument to use the current date).

interface M{                        // Class
  static void main(String[]a){      //  Mandatory main-method
    java.time.LocalDate z=null,     //   LocalDate to reduce bytes when using static calls
     r=a.length<1?                  //   If no argument is given:
        z.now()                     //    Start at the current date
       :                            //   Else:
        z.parse(a[0]);              //    Start at the date of the first argument
    for(;(r=r.plusDays(1))          //   Before every iteration, go to the next day
                                    //   Loop as long as:
         .getDayOfWeek().getValue()
                                    //    the 1-indexed day of the week (Friday = 5)
         *r.getDayOfMonth()         //    multiplied by the day of the month
        !=65;                       //    is not 65
                                    //    (5 and 13 are primes, so only 5*13 results in 65)
    );                              //   End of loop
    System.out.print(r);            //   Print the result Friday the 13th
  }                                 //  End of main-method
}                                   // End of class

NOTE: Java's default format when printing is already yyyy-MM-dd.

Kevin Cruijssen

Posted 2011-02-16T15:21:46.937

Reputation: 67 575

0

VB.net (96c*)

Entry

Function NextFridayThe13th(d As Date) As Date
  While d.DayOfWeek<>DayOfWeek.Friday
    d=d.AddDays(1)
  End While
  While d.Day<>13
    d=d.AddDays(7)
  End While
  Return d
End Function
  • I think the CodeGolf count for vb.net shouldn't include the function signature, closing end function and the return. So it just makes it about the internal implementation.

So my scoring is broken down as so

While d.DayOfWeek<>DayOfWeek.Friday    '35c
d=d.AddDays(1)                         '13c  48c
End While                              ' 9c  57c
While d.Day<>13                        '15c  72c
d=d.AddDays(7)                         '14c  86c
End While                              ' 9c  95c
Return d                               ' 1c  96c

Adam Speight

Posted 2011-02-16T15:21:46.937

Reputation: 1 234

0

05AB1E, 141 bytes

gĀi'-¡ëžežfžg)}V[Y`2ô0Kθ4ÖUD2Qi\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝVY`UÐ3‹12*+>13*5÷s3‹Xα©т%D4÷®т÷©4÷®·()O7%6QYн13Q*#}YRεDgi0ì]'-ý

05AB1E doesn't have any builtins for Date objects or calculations. The only builtin regarding dates it has is today's year/month/day/hours/minutes/seconds/microseconds.

So because of that, almost all of the code you see are manual calculations to go to the next day, and calculating the day of the week.

Mostly derived from my 05AB1E answer in The Work Day Countdown challenge (which is why I edited that one about an hour ago when I came across a bug..)

Input is a string in the format dd-MM-yyyy (but output is in the format yyyy-MM-dd, since it's one of the rules of the challenge).

Try it online or verify all test cases.

Explanation:

gĀi        # If an input is given:
   '-¡    '#  Split it by "-"
  ë        # Else:
   že      #  Push today's day
     žf    #  Push today's month
       žg  #  Push today's year
         ) #  Wrap them into a single list
  }V       # After the if-else statement: pop and store it in variable `Y`
[          # Start an infinite loop
 Y`2ô0Kθ4ÖUD2Qi\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝV
           #  Go to the next day
           #  (see my linked The Work Day Countdown answer for an explanation)
 Y`UÐ3‹12*+>13*5÷s3‹Xα©т%D4÷®т÷©4÷®·()O7%
           #  Calculate the day of the week (0 = Saturday, 1 = Sunday, ..., 6 = Friday)
           #  (see my linked The Work Day Countdown answer for an explanation)
 6Q        #  Check if the day of the week is a Friday
 Yн        #  Push the days of the current date
   13Q     #  Check if it's the 13th
 *         #  And if both checks are truthy:
  #        #   Stop the infinite loop
}YR        # After the infinite loop: push the resulting date-list, and reverse it
ε          # Map each value to:
 Dgi       #  If it's only a single digit:
    0ì     #   Prepend a leading "0"
]          # Close both the if-statement and map
 '-ý      '# Join the result by "-"
           # (and output the result implicitly)

Kevin Cruijssen

Posted 2011-02-16T15:21:46.937

Reputation: 67 575

0

Rebol, 136

d: any[do system/script/args now]until[d: d + 1 all[d/day = 13 d/weekday = 5]]print format/pad[4"-"-2"-"-2]reduce[d/year d/month d/day]

Ungolfed:

d: any [do system/script/args  now]

until [
    d: d + 1 
    all [d/day = 13 d/weekday = 5]
]

print format/pad [4 "-" -2 "-" -2] reduce [d/year d/month d/day]

Example usage:

$ rebol friday13th.reb 2013-05-09
2013-09-13
$ rebol friday13th.reb
2014-06-13

draegtun

Posted 2011-02-16T15:21:46.937

Reputation: 1 592