最後に日付がnで割り切れたのはいつですか?


24

日付は、YYYYMMDDなどの符号なし整数で表すことができます。必要なことは、指定された数値n(今日の日付を含む)で割り切れる最新の日付を計算し、その日付を上記の形式で返す最短のプログラムまたは関数を作成することです。指定した整数で割り切れる日付(00000101から今日まで)が一度もなかった場合は、-1を返す必要があります。

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

入力

STDINから読み取るか、関数の引数を取るか、入力が変数に格納されることを期待することもできます。入力は符号なし整数になります。

出力

日付を表す整数をYYYYMMDD形式で返すか、STDOUTに書き込むか、変数に保存します。

制限事項

言語が提供する標準ライブラリを使用できます。標準の抜け穴が適用されます。

勝利条件

これはなので、最小のプログラム(バイト単位)が勝ちます。同点の場合は、投票数が最も多い答えが勝ちです。


4
日付00000101は存在しません。1.によって年カウントが開始en.wikipedia.org/wiki/0_%28year%29
edc65

1
@ edc65それが存在するふりをすることはできますか?
オーバーアクター14

3
2月29日はどうですか?有効な日付を確認するために、うるう年の完全な規則を適用する必要がありますか?en.wikipedia.org/wiki/Leap_year
デジタル外傷14

6
ユリウス・グレゴリオ暦の切り替えにより失われた日はどうですか?それとも、私たちはずっとグレゴリオに行きますか? en.wikipedia.org/wiki/Gregorian_calendar
デジタル外傷

1
入力/出力仕様はかなり緩やかです。たとえば、「入力が変数に格納されることを期待する」では、Cのような言語の変数宣言をカウントする必要がありますか?あなたは「プログラムを書く」と言いますが、「関数の引数を取る」と言います-それは完全なプログラムではなく関数だけを書くことができるということですか?
ボブ14

回答:


16

Mathematica、93 60バイト

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

入力がに格納されることを期待していnます。

縦線は「分割」のUnicode文字であり、3バイト(UTF-8)としてカウントしていることに注意してください。

編集:肥大化DateStringとフォーマットの仕様を避けるための巧妙なトリックを見つけました:)。

編集:-1要件を完全に忘れました。修正されました。

ここに説明があります

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. *)

Unicodeはモノスペースを乱しているため、説明では|なく代わりに使用していることに注意してください


+ 1.Unicode文字を3バイトとして数える必要があることを指摘するリンクはありますか?
ベリサリウス博士14

2
@belisarius OPは、このゴルフは文字ではなくバイトでカウントされると述べました(これは、タグwikiで述べられているデフォルトでもあります)。
マーティンエンダー14

wikiの最後まで読んだことがありません:)ありがとう!
ベリサリウス博士14

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

days =を削除する提案をしてくれた@ chill0rに感謝します。また、tryブロックを1行に減らすことができるというヒントを提供してくれたJason Sに感謝します。


はい。それは標準的な操作手順です;)。タブは貼り付け後にスペースに変換されます。
ベクトル化

あなたは削除することができますdays=ではt-=d.timedelta(days=1)。これも正常に動作します(少なくともpython3で)
chill0r 14

@bitpwnerああ、ああ、気にしないで。
マーティンエンダー14

1
さらに節約できます:(1)使用int(t.strftime("%Y%m%d"))してドロップre、(2)必要なのは1行tryだけt-=d.timedelta(1)なので、1行を使用します。
ジェイソンS 14

1
@bitpwner strftime古い日付のを確認、のpython3で動作し、私はpython2でエラー得るか
ジェイソンS

5

C#136

改訂された仕様では、unsigned intを受け取り、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文字

緩やかな入出力要件を利用して、入力は変数に格納されn(現在、整数リテラルを除くすべての文字をカウントします)、出力には変数が提供されます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";}}}

STDIN / STDOUTを含む204文字:

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

1
本当に、下票ですか?これは問題を正しく解決しませんか?説明してください。他のC#の回答を複製したと思う人がいたら、実際に他の回答の1時間前にこれを書き、宣言式にC#6.0使用することを検討しました。少し脇道になったため、回答が遅れて投稿されました。それでも、それは下票のかなり薄っぺらな理由です。
ボブ14

4

T-SQL(2012)-148

n値を持つ自由変数@nがあると仮定します。

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

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)

ルアのないバージョンは、

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)

2
ここでテストn = 20140699出力20140699
William Barbosa

@WilliamBarbosa:修正; 20140699は-1を返します。
カイルカノス14

4

MATLAB:61

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

除数がに格納されてnいると仮定します。結果はと呼ばれる変数に保存されますans


コメント版:

-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

結果が見つからない場合はエラーを生成しますが、それでも変数の回答は利用可能です。


余分な2文字のコストでエラーを回避できます。

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

@MartinBüttnerうーん、その問題は解決しましたが、今では解決策は最小文字数に限定されています。改善点はありますか?
デニスジャヘルディン14

1
いいえ、頭の上からではありません。しかし、あなたが私を打ち負かすのを支援する私の動機は少し限られています。;)
マーティン・エンダー14

4

PHP(92 = 85 + 7)

入力がに保存されることを期待し$nます。

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

PHPがもう好きではなくなった理由を思い出しただけです=)

編集:仕様の-1も実装されました。


いいえ、チェックしただけです。エコーするとき、$ dは1つ低くなります。「偽造した」とはどういう意味ですか?(申し訳ありませんが、英語ネイティブ=)
flawr 14

ああ、私はその仕様を見ませんでした、もちろんこれを追加する必要があります、ありがとう!
flawr 14

3

JavaScript(ES6)115

変数nに数値を期待し、結果を変数rに格納します。毎日がチェックされ、現在の日付から始まり、デクリメントされます-より良い方法がなければなりません。
さらに、標準のjavascript日付関数を使用すると、すべての日付が1年目までのグレゴリオ暦になります(グレゴリオ暦の改革以前はうるう年が間違っていました)。

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

3

C#-144(またはLINQPadでは124)+各桁に1 n

これは、入力が変数にあることを想定していますn。実行が終了するまでに、目的の値は変数になりますr00010101ただし、日付00000101は存在しないため、これは最初の日付と見なされます。改善の提案はいつでも歓迎します。

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バージョン:

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

3

グルービー- 301の 300文字

Joda Timeを使用しているという事実を隠すトリックはなく、非常にシンプル(かつ遅い)です。

ゴルフ:

@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

実行例(2014年7月30日):

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

ゴルフをしていない:

@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

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

うまくいかない日付で幸運を。microbenchmark15日前に戻るには約0.5秒かかります。2014年7月31日の時点で-1、少なくとも封筒の裏によれば、これには2,000万秒(約23日)程度の時間がかかります。

編集:コメント内のいくつかのショートカット


!dより短いd==F!z%%nよりz%%n==0。また、as.numeric(gsub("-","",...)関数にすると、文字数も減ります。それでも、いい仕事だ!
plannapus

ああ、as.real多くの場合、より良い、より短い代替as.numericです。
plannapus 14

残念ながらas.real、R 3.0.0の時点では機能していません。しかし、まだas.double1文字短くなっています。
シャドウトーカー14

ああ、私はまだR 2.14を使用しているのでそれを知りませんでした
plannapus 14

1
私は管理者権限のあるコンピューターで作業していないので、それは本当に私次第ではありません。しかし、私はすでにpaste0私の.Rprofile自然にあります:)
plannapus 14

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

アンゴルフド:

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

編集:私はそれを少し最適化することができましたが、@ DennisJaheruddinはここで本当の解決策を持っています


これはまだかなりゴルフすることができます、私はそれを更新します。
デニスJaheruddin 14

@DennisJaheruddin このメタ投稿に基づいて編集を拒否しました。コメントで改善点を提案してください。そうすれば、OPは回答を修正する前にそれらを確認できます。
マーティンエンダー14

文字をさまざまな方法で保存できることに注意してください:関数ではなくスクリプトを使用し、物をansに割り当て、低から高へループを実行し、各結果が前の結果を上書きするようにして、ループを中断する必要がないようにします。-もちろん、ベクトル化も役立ちます回答を参照しください。
デニスJaheruddin 14

ここでは67文字の短いループベースのバージョンがある:-1,for s=str2num(datestr(1:now,'YYYYmmDD'))',if~mod(s,n),+s,end,end
デニスJaheruddin

@MartinBüttnerコメントありがとうございます。あなたが言ったようにエラーがありました。これで大丈夫です。
スコット14

3

Python 3-151 148バイト、ジェネレーター

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)

import*提案をありがとう@ nyuszika7h



2

Java:373文字

これはGroovyの回答の移植版であり、Joda Timeを使用しています。

ゴルフ:

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

サンプルの実行(クラスパスでjoda-time-2.4.jarを使用:

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

ゴルフをしていない:

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

3
ありますjava.time.*最新バージョンのJavaに。
ntoskrnl 14

2

Bash + coreutils(8.21)、67バイト

seq -f-%gday $[9**9]|date -f- +[pq]sp[_1pq]sq%Y%m%ddA1=qd$1%%0=p|dc
  • seq1〜9 9の整数を1 行に1つずつ生成し、次のようにフォーマットします。-<x>day
  • これ管date -f各行を解釈しにフォーマット日付出力するdcような式[pq] sp [_1pq] sq 20140728 d A1 =q d 7% 0=p(読みやすくするために追加スペースを)
    • [pq] スタックの先頭を印刷するマクロを定義してから終了します
    • sp レジスタpにマクロを保存します
    • [pq] -1をプッシュするマクロを定義し、スタックの先頭を出力してから終了します
    • sq レジスターqにマクロを保存する
    • 20140728 埋め込み日付整数
    • d スタックの最上部を複製
    • A1 101をプッシュ(00000101)
    • =q上位2つのスタック値をポップします。日付と101を比較しq、等しい場合はマクロを呼び出します
    • 7 プッシュディバイダー
    • % デバイダーとdividee、デバイドと残りをプッシュ
    • 0 プッシュ0
    • =p上位2つのスタック値をポップします。剰余と0を比較しp、等しい場合はマクロを呼び出します
    • d スタックの最上部を複製
    • マクロpが呼び出されます:日付整数を出力し、dc完全に終了します
  • dc式はdc評価のためにパイプされます。いったんdcプリント正しい値して終了、パイプラインの残りの部分が取り壊されます

出力:

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

このプログラムは1〜9 9の整数を生成するため、100万年先まで有効です。この制限が受け入れられることを望みます;-)


-1のリターンを短縮してくれた@ WumpusQ.Wumbleyに感謝します。


わーい!今では、19バイトのペナルティがあります:)
デジタル外傷14

空の出力を-1に変換するより短い方法:|grep .||echo -1パイプラインの最後に追加するか、zshを使用して次のような展開をネストできますecho ${$(cmd):-1}(他の場所にバックスラッシュがかかります...)

@ WumpusQ.Wumbleyどうしてそんなことを考えなかったの?ありがとう!
デジタル外傷14

1
ちなみに、これはcoreutilsのバージョンの影響を受けやすいようです。私(8.15)は、「日前」の仕様で1901年以前に戻ることを拒否しています。

1
sizeof time_tそれが壊れる境界は1970年1月1日の2 ** 31秒前であるため、実際には問題のようです。私の古いインストールも哀れな32ビット

2

パイソン:134バイト

現在のリーダーを打ち負かすことはできませんし、Pythonの最良の答えよりもそれほど良くはありませんが、私は最高のPythonソリューションを投稿することにしました。

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

ゴルフをしていない:

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

実際には138バイトです。のfrom datetime import*代わりにimport datetime as d、のtimedelta(1)代わりにd.timedelta(1)およびのyield代わりにを使用して、4バイトを節約できますreturn
nyuszika7h

ランダムなオンラインバイトカウンターを使用していますが、より良いオプションはありますか?
RageCage 14


これとこれとの違いは何ですか?bytecount.bluebus112.com
RageCage

その1は、改行をカウントしない、プラスそれはカウント文字は、バイトではありません。ASCIIテキストの場合、この2つは同じであるため、後者では違いはありません。では、コードゴルフ OPはそう言っていない限り、あなたは、通常の文字を数えます。(また、私がリンクしたのは、ここでの「バイトカウント」の Googleでの最初の結果です。)
nyuszika7h 14

2

JavaScript(ES5)-94

変数の入力を想定しx、出力をに配置しますo

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

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]}

これは、最初に思いついた最初のアルゴリズムによる最初のカットです。パフォーマンスと長さの両方でより良いことが可能だと確信しています。

このバージョンは「今日」の部分をハードコードします(これが.z.D)です。それを日付リテラル(yyyy.mm.dd)またはq日付システム(2000年1月1日からの日数)の整数に変更して、テストケースを実行します。(qは18世紀初頭より前の日付リテラルを解析しないため、それより前の日付については、値を計算し、適切な整数を直接使用する必要があります。であることが-730457機能コードで使用され、7月28 AD 5、最後のテストケースから、であることが判明しました-728450。)

指定されたテストケース:

  {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

編集:

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

これは、分割演算子を見つけるか、1/1/0000境界を超えるまで、収束演算子の1つを使用して日付を減分する別のアプローチです。また、日付から整数への変換も少し異なります。

テストケース、今回は一度にすべて:

  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

1

VBA 343バイト(モジュール)

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

これは、頻繁にまで凝縮させることができる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 Sub139バイトのために
テイラー・スコット

1

PowerShell-76

これは、変数に格納されている数値に依存します$n

try{@(0..$n|%{'{0:yyyyMMdd}'-f(date).AddDays(-$_)}|?{!($_%$n)})[0]}catch{-1}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.