12
\$\begingroup\$

Seems like we do not have this one yet, so here we go:

The Challenge

Write a program or function that takes a date as input and outputs the day number of the year. You may not use any builtins for that!

Rules

  • As usual you may write a full program or a function.
  • The format of the input is up to you, but it has to contain a year, a month and a day. Make clear which one your solution uses!
  • No date-related builtins allowed! You gotta do the work by yourself. Builtins which are not related to date operations are fine.
  • Base for the calcultion is the gregorian calendar.
  • You have to take account of leap-years.
  • You only need to handle years in the range [1, 9999]
  • Standard loopholes are forbidden.
  • Lowest byte count wins!

Testcases

Input format here is YYYY/MM/DD

2016/07/05 -> 187
2000/03/28 -> 88
0666/06/06 -> 157
6789/10/11 -> 284
0004/04/04 -> 95
1337/07/13 -> 194

Happy Coding!

\$\endgroup\$
3
  • \$\begingroup\$ Can we use builtins for days since a certain date? What about for whether a year is a leap year? \$\endgroup\$
    – lirtosiast
    Jan 28, 2016 at 22:19
  • \$\begingroup\$ @Thomas No date-related builtins allowed. Gonna clarify that in the challenge, thanks for the comment! :) \$\endgroup\$
    – Denker
    Jan 28, 2016 at 22:22
  • \$\begingroup\$ @DenkerAffe Why did you forbid all built-ins? \$\endgroup\$
    – aloisdg
    Jul 17, 2016 at 18:07

9 Answers 9

7
\$\begingroup\$

JavaScript ES6, 81 69 bytes

(y,m,d)=>d+parseInt("03479cehkmpr"[--m],36)+m*28-(y%(y%25?4:16)&&m>1)

Assuming months are 1-based, otherwise I could save 2 bytes.

Edit: Saved 12 bytes using @user81655's tip.

\$\endgroup\$
3
\$\begingroup\$

C, 96 102 89 61 bytes

g(y,m,d){printf("%d",m/2*31+--m/2*30-(y%(y%25?4:16)?2:1)+d);}
\$\endgroup\$
0
2
\$\begingroup\$

Pyth, 31 bytes

+s<X1+L28jC"3Ȕ"4!%|F_jQ*TT4tEE

Thanks to @Dennis and @Jakube for the leap year portion. Input is YYYY, MM, DD on separate lines.

+                          add [day] to
  s <                      sum of first [month]-1 values in the list
      X                    add 1 to
        1                  the second element (January)...
        +L                 \
           28              |
           j               }   lengths of all the months
             C "3Ȕ"       | 
             4             /
        ! %                ... if the year is a leap year; that is, 4 divides...
            |F _ j         fold logical OR over reversed
                   Q       the year
                   *TT     converted to base 100
            4
      t E                 [month]-1
  E                       [day]

Test suite.

\$\endgroup\$
2
\$\begingroup\$

Python 3, 152 148 150 bytes

m,d,y=map(int,input().split());n=[0,31,(59,60)[(y%4==0 and y%100!=0)or y%400==0]]
for i in range(m):n+=[n[-1]+(31,30)[i in[1,3,6,8]]]
print(n[-4]+d)

Takes dates in the format "M D YYYY".

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You should use Python 2, unless you need specific features from Python 3. Because then you don't need brackets in your prints which allows you to save one byte by wrinting your print as print n[m-1]+d \$\endgroup\$
    – Denker
    Jan 29, 2016 at 9:37
  • \$\begingroup\$ In the first line, you could write y%4==0and y%100!=0, I think \$\endgroup\$
    – univalence
    Jul 16, 2016 at 8:38
2
\$\begingroup\$

Python 2, 100 82 bytes

A Python port of @Neil's answer:

lambda d,m,y:d+int("03479cehkmpr"[m-1],36)+(m-1)*28-(y%(4if y%25 else 16)and m>2)

As with the previous answer, adding 17 bytes (99 bytes total) will yield a full program:

print(lambda d,m,y:d+int("03479cehkmpr"[m-1],36)+(m-1)*28-(y%(4if y%25 else 16)and m>2))(*input())

Previous answer:

As an anonymous lambda:

lambda d,m,y:d+sum(31-(n in(3,5,8,10))for n in range(m-1))-(3if y%4 or(y%400!=0and y%100==0)else 2)

Can be converted to a named lambda for a 2 byte penalty. Alternatively, a full program (taking input in the format D,M,Y) can be achieved for 117 bytes:

print(lambda d,m,y:d+sum(31-(n in(3,5,8,10))for n in range(m-1))-(3if y%4 or(y%400!=0and y%100==0)else 2))(*input())
\$\endgroup\$
1
  • \$\begingroup\$ A few small golfs gets 76 bytes \$\endgroup\$
    – squid
    Jun 12, 2019 at 17:07
1
\$\begingroup\$

Nibbles, 28 bytes

+-=@`\:0.``@1370+30$+?-@2- 2%+.::4 100 400^0%_$~0

Attempt This Online!

Takes the year, month and day as command-line arguments.

Edit: Care to explain why this was downvoted?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Re downvote: probably for the same reason that all the other 8 answers except for the awk one were downvoted. Only the downvoter knows the reason, and nobody knows for sure who he/she is. Although it is somewhat intriguing that the author of the awk answer has placed 9 downvotes this week... \$\endgroup\$ Oct 6, 2023 at 13:17
  • \$\begingroup\$ @DominicvanEssen Interesting observation. Hmmm… \$\endgroup\$
    – xigoi
    Oct 6, 2023 at 14:53
0
\$\begingroup\$

Python 3, 125 bytes

print((lambda d,m,y:sum([3,not(y%400 and not y%100 or y%4),3,2,3,2,3,3,2,3,2,3][:m-1])+m*28-28+d)(*map(int,input().split())))

An another approach to this problem. The code takes advantages of the Python's boolean algebra execution priorities and since not is the last operation, conversion to boolean is automatic. When summation is done, the boolean is treated as 1 or 0. Input format is "YY MM DDDD" string. Input system inspired by @SteveEckert's similar one.

Another form as a function, 91 bytes

def f(d,m,y):return sum([3,not(y%400 and not y%100 or y%4),3,2,3,2,3,3,2,3,2,3][:m])+m*28+d

In this case input is three integers, the month being between 0-11. This would work in Python 2 also.

\$\endgroup\$
0
\$\begingroup\$

Excel, 106 bytes

=AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100))))+30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1

Takes input in three cells A1 = Year, B1 = Month, C1 = Day.


AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100))))

1 if LeapYear, else 0

30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1

Multiple of 30, CHOOSE for additional days, plus days in month


Evolution:

=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+CHOOSE(B1,0,31,59,90,120,151,181,212,243,273,304,334,365)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+CHOOSE(B1-1,31,59,90,120,151,181,212,243,273,304,334,365)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+30*(B1-1)+CHOOSE(B1,0,1,-1,0,0,1,1,2,3,3,4,4,5)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+30*B1-30+CHOOSE(B1,0,1,-1,0,0,1,1,2,3,3,4,4,5)+C1
=IF(AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100)))),1,0)+30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1
=AND(C1>2,OR(MOD(A1,400)=0,AND(MOD(A1,4)=0,MOD(A1,100))))+30*B1-31+CHOOSE(B1,1,2,0,1,1,2,2,3,4,4,5,5,6)+C1
\$\endgroup\$
0
\$\begingroup\$

Scala, 126 bytes

Port of @Neil's Javascript answer in Scala.


Golfed version. Try it online!

(y,m,d)=>d+Integer.parseInt("03479cehkmpr".toSeq(m-1).toString,36)+(m-1)*28-(if ((y%(if (y%25==0)16 else 4)!=0)&&m>1)1 else 0)

Ungolfed version. Try it online!

object Main {
  def dayOfYear(y: Int, m: Int, d: Int): Int = {
    val monthOffsets = "03479cehkmpr".toList
    d + Integer.parseInt(monthOffsets(m - 1).toString, 36) + (m - 1) * 28 - (if ((y % (if (y % 25 == 0) 16 else 4) != 0) && m > 1) 1 else 0)
  }

  def main(args: Array[String]): Unit = {
    println(dayOfYear(2016, 07, 05))  // 187
    println(dayOfYear(2000, 03, 28))  // 88
    println(dayOfYear(0666, 06, 06))  // 157
    println(dayOfYear(6789, 10, 11))  // 284
    println(dayOfYear(0004, 04, 04))  // 95
    println(dayOfYear(1337, 07, 13))  // 194
  }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.