When was the last time the date was divisible by n?

24

3

A date can be represented by an unsigned integer as such: YYYYMMDD. What you need to do, is write the shortest program or function that figures out the most recent date whose number was divisible by a given number n (including today's date) and then returns that date in the format showed above. If there has never been a date (between 00000101 and today inclusive) divisible by the given integer, you should return -1.

Examples

Current Date     Input     Output

30 July, 2014      4       20140728
30 July, 2014      7       20140729
28 July, 2014      4       20140728
28 July, 2014      7       20140722
28 July,    5    90000     -1

Input

You can read from STDIN or take a function argument or even expect the input to be stored in a variable. The input will be an unsigned integer.

Output

Write to STDOUT or return (or save in a variable) the integer representing the date in the format YYYYMMDD.

Restrictions

You may use any standard library your language offers. Standard loopholes apply.

Winning conditions

This is a , so smallest program (in bytes) wins. In case of a tie, the answer with the most votes wins.

overactor

Posted 2014-07-30T14:30:49.307

Reputation: 3 500

4

Date 00000101 does not exist. Year count starts by 1. http://en.wikipedia.org/wiki/0_%28year%29

– edc65 – 2014-07-30T14:35:52.450

1@edc65 can we pretend it does exist? – overactor – 2014-07-30T14:37:08.987

3

What about Feb 29th? Do we need to apply full leap year rules to check for valid dates? http://en.wikipedia.org/wiki/Leap_year

– Digital Trauma – 2014-07-30T14:52:42.257

6

What about the days lost due to the Julian-Gregorian calendar switch? Or are we going Gregorian all the way? http://en.wikipedia.org/wiki/Gregorian_calendar

– Digital Trauma – 2014-07-30T14:56:38.423

1Your input/output specs are rather loose. For example, should the "expect the input to be stored in a variable" count the variable declaration in a language like C? You say "write a program", yet you say "take a function argument" - does that mean we can write just a function rather than a full program? – Bob – 2014-07-30T16:43:01.813

@Bob, yes, thanks for pointing that out, you CAN just write a function. – overactor – 2014-07-30T16:49:42.337

What calendar is used ? – Emmanuel – 2014-07-31T09:11:20.787

1

@edc65 "ISO 8601 prescribes, as a minimum, a four-digit year [YYYY] to avoid the year 2000 problem. It therefore represents years from 0000 to 9999, year 0000 being equal to 1 BC and all others AD." from Wikipedia http://en.wikipedia.org/wiki/ISO_8601

So year 0000 exists in ISO 8601. Which year it really means is a bit unclear though.

– Ahlqvist – 2014-07-31T11:39:19.150

Answers

16

Mathematica, 93 60 bytes

For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n∣r,];r~Max~-1

Expects the input to be stored in n.

Note that the vertical line is the unicode character for "divides", which I've counted as 3 bytes (UTF-8).

Edit: Found a neat trick to avoid the bloated DateString and format specification :).

Edit: Totally forgot about the -1 requirement. Fixed now.

Here is an explanation

For[i=0,            i--                        ,];         (* i is the number of days AFTER
                                                              today. Hence, we decrement 
                                                              it. *)
For[i=0,   DatePlus@i--                        ,];         (* If no reference date is
                                                              provided, DatePlus will add
                                                              the given number of days to
                                                              today's date. The result is a 
                                                              list of 3 integers, luckily 
                                                              in order {year,month,day} *)
For[i=0,   DatePlus@i--~FromDigits~100         ,];         (* Interpret these as the digits
                                                              of a base 100 number. The 
                                                              beauty is that FromDigits
                                                              doesn't care about digits 
                                                              greater than the base and 
                                                              just carries them over. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)        ,];         (* Store the number in r. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0      ,];         (* Make sure it's positive. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n|r,];         (* And keep going while n does 
                                                              not divide r. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n|r,];r~Max~-1 (* Clamp result to -1. *)

Note that I've used | instead of in the explanation, because the Unicode one messes with monospacing.

Martin Ender

Posted 2014-07-30T14:30:49.307

Reputation: 184 808

+1.Do you have a link pointing out that you should count unicode chars as 3 bytes? – Dr. belisarius – 2014-07-30T18:21:12.200

2@belisarius The OP stated that this code golf is counted by bytes and not characters (this is also the default as stated in the tag wiki). – Martin Ender – 2014-07-30T18:24:01.480

I never got to read thru the end of the wiki :) Thanks! – Dr. belisarius – 2014-07-30T18:29:48.160

6

Python 2 - 150

import datetime as d,re
def f(n):
 t=d.date.today()
 while t:
    c=int(re.sub("-","",str(t)))
    if c%n<1:return c
    try:t-=d.timedelta(1)
    except:return-1

Thanks @chill0r for suggestion to remove days=, and Jason S for tip that the try block can be reduced to one line.

Vectorized

Posted 2014-07-30T14:30:49.307

Reputation: 3 486

Yes. That is a standard operating procedure ;). The tabs get converted to spaces after pasting. – Vectorized – 2014-07-30T15:06:08.183

You can remove the days= in t-=d.timedelta(days=1). This works fine too (at least in python3) – chill0r – 2014-07-30T15:20:08.827

@bitpwner ah I see, never mind then. – Martin Ender – 2014-07-30T15:27:20.053

1You can save more: (1) use int(t.strftime("%Y%m%d")) and drop re, (2) use a one-line try because only t-=d.timedelta(1) needs to be in it. – Jason S – 2014-07-31T04:33:01.307

@JasonS Sorry for late reply... was busy with other stuff. Thx for the tip. Seems like strftime would give the following for a large n like 9000: ValueError: year=1899 is before 1900; the datetime strftime() methods require year >= 1900 – Vectorized – 2014-07-31T08:09:43.123

1@bitpwner strftime on older dates works in python3, checked and I do get an error in python2 – Jason S – 2014-07-31T08:17:28.490

5

C# 136

With the revised specs, a function that takes an unsigned int and returns an int.

int F(uint n){var d=System.DateTime.Now;int i;try{while((i=int.Parse(d.ToString("yyyMMdd")))%n>0)d=d.AddDays(-1);}catch{i=-1;}return i;}

152 characters with variable input/output

Taking advantage of the loose input/output requirements, input is to be stored in the variable n (currently counting all characters except the integer literal), and output is provided with the variable s.

class P{static void Main(){var n=4;var d=System.DateTime.Now;string s;try{while(int.Parse(s=d.ToString("yyyMMdd"))%n>0)d=d.AddDays(-1);}catch{s="-1";}}}

204 characters with STDIN/STDOUT:

using System;class P{static void Main(){int n=int.Parse(Console.ReadLine());var d=DateTime.Now;string s;try{while(int.Parse(s=d.ToString("yyyMMdd"))%n>0)d=d.AddDays(-1);}catch{s="-1";}Console.Write(s);}}

Bob

Posted 2014-07-30T14:30:49.307

Reputation: 844

1

Really, a downvote? Does this not solve the problem correctly? Please explain. If anyone thinks I duplicated the other C# answer, I actually wrote this about an hour before the other one, and even looked into using C# 6.0 for the declaration expressions. Got a bit sidetracked, which resulted in posting the answer late. Even then, that's a rather flimsy reason for a downvote.

– Bob – 2014-07-30T17:25:17.940

4

Golflua 90 86

n=I.r()d="%Y%m%d"i=O.d(d)+0j=0@i>0?i%n==0w(i)O.q()$j=j+1i=O.d(d,O.t()-j*86400)+0$w(-1)

An ungolfed Lua version would be,

n = io.read()
d = "%Y%m%d"
i = os.date(d)+0   -- implicitly casts os.date(d) to int
j = 0
while i>0 do
   if i % n == 0 then
      print(i)
      os.exit()
   end
   j = j+1
   i = os.date(d,os.time()-j*86400)+0
end
print(-1)

Kyle Kanos

Posted 2014-07-30T14:30:49.307

Reputation: 4 270

2

Tested here n = 20140699 outputs 20140699

– William Barbosa – 2014-07-30T14:50:54.467

@WilliamBarbosa: Fixed; 20140699 returns -1. – Kyle Kanos – 2014-07-30T17:36:53.660

4

PHP (92=85+7)

Expects input to be stored in $n.

for($d=date("Ymd");!($d%$n==0&checkdate($d/100%100,$d%100,substr($d,0,4))|$d<0);$d--);echo$d

I just remembered why I do not like PHP anymore=)

EDIT: Now the -1 of the specifications is implemented too.

flawr

Posted 2014-07-30T14:30:49.307

Reputation: 40 560

No, just checked it, $d will be one too low when echo-ing. What do you mean by 'you've forge'? (Sorry, no english native=) – flawr – 2014-07-30T16:05:42.413

Oh, I didn't see that spec, of course this has to be added, thanks! – flawr – 2014-07-31T12:31:04.900

4

T-SQL (2012) - 148

Assumes there is a free variable @n with the n value.

declare @ date=getdate()while convert(char,@,112)%@n>0 and'00010101'<@ set @=dateadd(d,-1,@)print iif(convert(char,@,112)%@n=0,convert(char,@),'-1')

Michael B

Posted 2014-07-30T14:30:49.307

Reputation: 1 551

4

MATLAB: 61

-1,s=str2num(datestr(1:now,'YYYYmmDD')),d=s(~mod(s,n)),d(end)

Assumes the divisor is stored in n. The result will be stored in a variable called ans.


Commented version:

-1                                     % Store -1 in ans in case we don't find anything
s=str2num(datestr(1:now,'YYYYmmDD'))   % Make a list of date numbers
d=s(~mod(s,n)),                        % Select only those who are dividable and prepend -1
d(end)                                 % Store last found value in ans, if anything is found

Will generate an error if no result is found, but the answer is still available in the variable despite that.


Error could be avoided at the cost of 2 extra chars:

s=str2num(datestr(1:now,'YYYYmmDD')),d=[-1;s(~mod(s,n))],d(end)

Dennis Jaheruddin

Posted 2014-07-30T14:30:49.307

Reputation: 1 848

@MartinBüttner Hmm, solved that problem but now the solution is only tied for minimum chars. Can you see any improvements? – Dennis Jaheruddin – 2014-07-31T11:54:14.350

1No, not off the top of my head. But my motivation to help you beat me is a bit limited. ;) – Martin Ender – 2014-07-31T12:11:03.663

3

JavaScript (ES6) 115

Expects number in variable n, result stored in variable r. Each day is checked, starting with current date and decrementing - there must be a better way.
Moreover, using standard javascript date functions, all dates are gregorian down to year 1 (with leap years accordingly wrong before gregorian reform).

for(z=new Date,t=n+1;t>n&&t%n;)
  d=z.getDate(),
  t=z.getFullYear()*1e4+(z.getMonth()+1)*100+d,
  z.setDate(d-1);
r=t>n?t:-1

edc65

Posted 2014-07-30T14:30:49.307

Reputation: 31 086

3

C# - 144 (Or 124 in LINQPad) + 1 for each digit in n

This expects the input to be in the variable n. By the end of the execution the desired value will be in the variable r. This considers 00010101 as the first date, though, because the date 00000101 does not exist. Suggestions for improvement are always welcome.

class P{static void Main(){int n=7,r;var d=System.DateTime.Now;try{for(;(r=int.Parse(d.ToString("yyyMMdd")))%n>0;d=d.AddDays(-1));}catch{r=-1;}}}

LINQPad version:

int n=7,r;var d=System.DateTime.Now;try{for(;(r=int.Parse(d.ToString("yyyMMdd")))%n>0;d=d.AddDays(-1));}catch{r=-1;}r.Dump();

William Barbosa

Posted 2014-07-30T14:30:49.307

Reputation: 3 269

3

Matlab 104

function d=f(v);for d=fix(now):-1:1 d=str2num(datestr(d,'YYYYmmDD'));if~mod(d,v)return;end;end;d=-1;end

Ungolfed :

function d = f(v)
   for d=fix(now):-1:1
       d = str2num(datestr(d,'YYYYmmDD'));
       if ~mod(d,v)
          return; 
       end
   end
   d = -1;
end

EDIT: I managed to optimise it a bit, but @DennisJaheruddin has the real solution here

Scott

Posted 2014-07-30T14:30:49.307

Reputation: 31

This can still be golfed quite a bit, I will update it. – Dennis Jaheruddin – 2014-07-31T10:28:41.767

@DennisJaheruddin I have rejected your edit based on this meta post. Please suggest your improvements in a comment, so the OP can review them before modifying his answer.

– Martin Ender – 2014-07-31T10:40:39.597

Note that you can save chars in various ways: Use a script rather than a function, let things get assigned to ans, do the loop from low to high and let each result overwrite the previous one so you don't need to break the loop. -- Of course vectorization can also help, see my answer.

– Dennis Jaheruddin – 2014-07-31T12:11:57.337

Here is a shorter loop based version of 67 chars: -1,for s=str2num(datestr(1:now,'YYYYmmDD'))',if~mod(s,n),+s,end,end – Dennis Jaheruddin – 2014-07-31T12:47:47.200

@MartinBüttner Thanks for the comment. There was an error as you said. Now it should be okay. – Scott – 2014-07-31T12:53:00.883

@DennisJaheruddin I saw your solution. Quite a good one. I'll leave you this one :P. – Scott – 2014-07-31T13:03:52.513

@Scott At least improve your solution a bit. Seeing you assign the number 1 to a variable really hurts. It also appears that it currently always returns d=-1. – Dennis Jaheruddin – 2014-07-31T13:08:50.477

3

Groovy - 301 300 chars

Very simple (and slow), with no tricks to hide the fact that it uses Joda Time.

Golfed:

@Grab(group='joda-time', module='joda-time', version='2.3')
import org.joda.time.*
import org.joda.time.format.*
f={DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(it)) as int}
n=args[0] as int;b=0;x=-1;c=0
while(!b){if(f(c++)%n==0){x=f(--c);b=1};if(f(0)-c<=101){b=1}}
println x

Example run (on 7/30/2014):

$ groovy D.groovy  7
20140729
$ groovy D.groovy  16
20140720
$ groovy D.groovy  90000
-1

Ungolfed:

@Grab(group='joda-time', module='joda-time', version='2.3')

import org.joda.time.*
import org.joda.time.format.*

f = { DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(it)) as int }

n = args[0] as int
b = 0 
x = -1
c = 0

while (!b) {
    if(f(c++)%n==0) { x=f(--c); b=1}
    if(f(0)-c<=101){b=1}
}

println x

Michael Easter

Posted 2014-07-30T14:30:49.307

Reputation: 585

3

Python 3 - 151 148 bytes, generators

from datetime import*
t=date.today()
f=lambda n:next((y for y in(int((t-timedelta(o)).strftime("%Y%m%d"))for o in range(t.toordinal()))if y%n<1),-1)

Thanks @nyuszika7h for import* suggestion

Jason S

Posted 2014-07-30T14:30:49.307

Reputation: 371

3

R, 146 139

D=function(n){
z=as.double(gsub("-","",y<-Sys.Date()))
d=F
while(z>100&!d){
y=y-1 
z=as.double(gsub("-","",y))
d=!z%%n}
ifelse(z>100,z,-1)}

Good luck with a date that doesn't work. microbenchmark reports it takes about half a second to go back 15 days. As of July 31, 2014, this will take something like 20 million seconds (~23 days) to spit out -1, at least according to the back of the envelope.

edit: some shortcuts in the comments

shadowtalker

Posted 2014-07-30T14:30:49.307

Reputation: 461

!d is shorter than d==F and !z%%n than z%%n==0. Also, making as.numeric(gsub("-","",...) into a function should reduce the character count as well. Still, nice job! – plannapus – 2014-07-31T11:26:05.483

Oh and as.real is often a good, shorter alternative to as.numeric. – plannapus – 2014-07-31T11:32:42.720

Unfortunately as.real is defunct as of R 3.0.0. But we still have as.double which is one character shorter. – shadowtalker – 2014-07-31T12:25:45.127

Oh I didn't know that as I'm still using R 2.14 – plannapus – 2014-07-31T12:26:23.690

You should upgrade! Huge quality of life improvements came out in the last couple of years... paste0 comes to mind. And unfortunately making a separate function for as.numeric(gsub("-","",...) is actually longer because of the =function(x) part – shadowtalker – 2014-07-31T12:29:36.363

1I'm not working on a computer i have administration rights on, so it's not really up to me. But I already have paste0 in my .Rprofile naturally :) – plannapus – 2014-07-31T12:33:01.977

2

Ruby 103

require'date'
f=->{d=Date.today 
(s=d.strftime('%Y%m%d').to_i
return s if s%n<1
d-=1)while d.year>0
-1}

Input

Expects the divisor value to be present in variable n.

Output

The return value of the f function

Online example: http://ideone.com/LoYxG4

Cristian Lupascu

Posted 2014-07-30T14:30:49.307

Reputation: 8 369

2

Bash+coreutils (8.21), 67 bytes

seq -f-%gday $[9**9]|date -f- +[pq]sp[_1pq]sq%Y%m%ddA1=qd$1%%0=p|dc
  • seq generates integers from 1 to 99, one per line, and formats it as -<x>day
  • pipe this to date -f which interprets each line and outputs the date formatted into a dc expression such as [pq] sp [_1pq] sq 20140728 d A1 =q d 7% 0=p (spaces added for readability)
    • [pq] define a macro to print the top of stack, then quit
    • sp save macro in register p
    • [pq] define a macro to push -1, print the top of stack, then quit
    • sq save macro in register q
    • 20140728 embedded date integer
    • d duplicate top of stack
    • A1 push 101 (00000101)
    • =q pop top 2 stack values: compare date and 101, and call macro q if equal
    • 7 push divider
    • % pop divider and dividee, the divide and push the remainder
    • 0 push 0
    • =p pop top 2 stack values: compare remainder and 0, and call macro p if equal
    • d duplicate top of stack
    • macro p is called: prints date integer and quits dc entirely
  • dc expressions are piped to dc for evaluation. Once dc prints the right value and quits, the rest of the pipeline is torn down

Output:

$ ./lastdivdate.sh 4
20140728
$ ./lastdivdate.sh 7
20140729
$ ./lastdivdate.sh 123456
17901120
$ ./lastdivdate.sh 77777
19910912
$ ./lastdivdate.sh 7777777
-1
$ 

Since this program generates integers from 1 to 99, it will be valid up to just over 1 million years into the future. I hope this limitation is acceptable ;-)


Thanks @WumpusQ.Wumbley for shortening the return of -1.

Digital Trauma

Posted 2014-07-30T14:30:49.307

Reputation: 64 644

@MartinBüttner Curses! Now it does, with a 19 byte penalty :) – Digital Trauma – 2014-07-31T00:51:35.090

Shorter ways to convert empty output to -1: add |grep .||echo -1 to the end of the pipeline, or use zsh where you can nest expansions like echo ${$(cmd):-1} (this will cost you a backslash elsewhere...) – None – 2014-07-31T13:01:01.777

@WumpusQ.Wumbley Why didn't I think of that? Thanks! – Digital Trauma – 2014-07-31T16:52:33.060

1By the way, this seems to be sensitive to the coreutils version. Mine (8.15) refuses to go back before 1901 with the "days ago" specification. – None – 2014-07-31T17:02:52.103

@WumpusQ.Wumbley I was wondering about that. I'm using coreutils 8.21 (ubuntu 14.04). I've noted this in the title. – Digital Trauma – 2014-07-31T17:21:39.427

1Actually it seems to be a sizeof time_t issue, since the boundary where it breaks is 2**31 seconds before 1/1/1970. My older installation is also pathetically 32-bit – None – 2014-07-31T17:25:35.450

2

Java : 373 chars

This is a port of the Groovy answer, and uses Joda Time.

Golfed:

import org.joda.time.*;
import org.joda.time.format.*;
public class D {
static int f(int i){return Integer.parseInt(DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(i)));}
public static void main(String[] args){
int n=Integer.parseInt(args[0]);int b=0,c=0,x=-1;
while(b!=1){if(f(c++)%n==0){x=f(--c);b=1;};if(f(0)-c<=101){b=1;}}
System.out.println(x);}}

Sample runs (with joda-time-2.4.jar on classpath:

$ java D 7
20140729
$ java D 4
20140728
$ java D 16
20140720
$ java D 90000
-1

Ungolfed:

import org.joda.time.*;
import org.joda.time.format.*;

public class D {
    static int f(int i) {
        return Integer.parseInt(DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(i)));
    }

    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        int b = 0,c = 0,x = -1;

        while(b!=1) {
            if(f(c++)%n==0) { x=f(--c);b=1; }
            if(f(0)-c<=101) { b=1; }
        }

        System.out.println(x);
    }
}

Michael Easter

Posted 2014-07-30T14:30:49.307

Reputation: 585

3There's also java.time.* in the latest version of Java. – ntoskrnl – 2014-07-31T10:26:03.750

2

JavaScript (ES5) - 94

It expects the input in variable x, and places the output in o.

for(i=Date.now();i>-7e13&&(o=(new Date(i)).toISOString().replace(/-|T.*/g,''))%x;i-=864e5)o=-1

Ben

Posted 2014-07-30T14:30:49.307

Reputation: 131

2

PYTHON: 134 bytes

Not going to be able to beat the current leader, and it's not that much better than the best Python answer, but I decided to post my best Python solution.

from datetime import*
def y(a,n):
 s=a.strftime("%Y%m%d")
 if int(s)%n==0:yield s
 try:x=y(a-timedelta(1),n)
 except:yield -1
 yield x

Ungolfed:

from datetime import *
def y(a, n):
    s=int(a.strftime("%Y%m%d"))
    if s%n==0:
        yield s
    try:
        x=y(a-timedelta(1), n)
    except:
        yield -1
    yield x

RageCage

Posted 2014-07-30T14:30:49.307

Reputation: 245

It's actually 138 bytes. You can save 4 bytes by using from datetime import* instead of import datetime as d, timedelta(1) instead of d.timedelta(1) and yield instead of return. – nyuszika7h – 2014-08-01T13:31:15.587

I'm using a random online byte counter, is there a better option? – RageCage – 2014-08-01T13:34:59.943

http://mothereff.in/byte-counter – nyuszika7h – 2014-08-01T13:36:02.160

What makes that one different from this one? http://bytecount.bluebus112.com/

– RageCage – 2014-08-01T13:40:52.393

That one doesn't count newlines, plus it counts characters, not bytes. For ASCII text, the two are the same, so the latter doesn't make a difference here. In [tag:code-golf], you usually count characters unless the OP says otherwise. (Also, the one I linked was the first result in Google for "byte count" here.) – nyuszika7h – 2014-08-01T13:41:47.180

I was using Bing, and the first result on Bing is the one I used. (don't ask why I was using Bing) – RageCage – 2014-08-01T13:44:37.157

In case I wasn't clear, your code at the latest revision before my comment was 138 bytes. I've now suggested an edit to correct it. – nyuszika7h – 2014-08-01T13:48:31.547

I accidentally pasted old code into the text box rather than the new code. – RageCage – 2014-08-01T13:57:58.907

2

k4 (84) (73)

f:{f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;.z.D];x]}

This is just an initial cut with the first algorithm that came to mind; I'm sure better is possible in both performance and length.

This version hardcodes the "today" part (that's the .z.D); change it to a date literal (yyyy.mm.dd) or an integer in the q date system (days since January 1, 2000) to run the test cases. (q won't parse date literals earlier than the early eighteenth century, so for dates before that, you'll need to work out the value and use the appropriate integer directly. January 1, "A.D. 0", from the spec, turns out to be -730457, which is used in the function code. July 28, A.D. 5, from the last test case, turns out to be -728450.)

The given test cases:

  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.30];x]}4
20140728
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.30];x]}7
20140729
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.28];x]}4
20140728
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.28];x]}7
20140722
  "d"$-728450
0005.07.28
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;-728450];x]}90000
-1

edit:

g:.,/$`\:`$$:;f:{$[Z=r:{(z>x)&.q.mod[g z]y}[Z:-730458;y]{x-1}/x;-1;g"d"$r]}

This is a different approach which uses one of the convergence operators to decrement the date until either it finds a divisible one or it crosses the 1/1/0000 boundary. It also does the conversion from date to integer slightly differently.

The test cases, this time all at once:

  g:.,/$`\:`$$:;{$[Z=r:{(z>x)&.q.mod[g z]y}[Z:-730458;y]{x-1}/x;-1;g"d"$r]}'[2014.07.30 2014.07.30 2014.07.28 2014.07.28,"d"$-728450;4 7 4 7 90000]
20140728 20140729 20140728 20140722 -1

Aaron Davies

Posted 2014-07-30T14:30:49.307

Reputation: 881

1

VBA 343 bytes (module)

Sub divD(i As Long)
a = Now()
b = Format(a, "yyyymmdd")
    Do While b / i <> Int(b / i)
    a = DateAdd("d", -1, a)
    b = Format(a, "yyyymmdd")
        If b = "01000101" Then
            MsgBox -1
            Exit Sub
        End If
    Loop
MsgBox b
End Sub

Alex

Posted 2014-07-30T14:30:49.307

Reputation: 369

This can be heavily condensed down to Sub d(i):a=Now:b=a:Do Until b/i=Int(b/i):a=DateAdd("d",-1,a):b=Format(a,"yyyymmdd"):If b="01000101"Then:b=-1:Exit Sub:Loop:Debug.?b:End Sub for 139 Bytes – Taylor Scott – 2017-06-05T18:21:23.180

1

PowerShell - 76

This depends on the number being stored in the variable $n.

try{@(0..$n|%{'{0:yyyyMMdd}'-f(date).AddDays(-$_)}|?{!($_%$n)})[0]}catch{-1}

Rynant

Posted 2014-07-30T14:30:49.307

Reputation: 2 353