How many ACUs do I have?

Posted from sandbox

The Intro

What is an ACU? This challenge is based on the concept of money and since this is an international community, we all use different currencies, so in keeping with our spirit of inclusiveness, I have invented a new currency called Arbitrary Currency Units (ACUs) specifically for this challenge. In reality, the challenge is the same whether we are using Dollars, Pounds, Euros, Bitcoins, Lao Kip or Baked Beans.

The Idea

It's New Year. We all have ideas about how we can improve things in the coming year. Mine is to save some money but randomly putting money aside quickly becomes uninteresting so I am following up on something I read on a news site last year. Each week, I put the amount of ACUs equal to the week number into a tin and after 52 weeks I will have saved ACU 1378. That's enough for a nice golfing holiday somewhere in 2021!

The Problem

I need an incentive to keep me going with this so I need to know how much I have or will have in the tin on any given date during 2020. For example, if I enter a date before today I want to know how much was in the tin on that date. For a date after today I want to know how much I will have if I stay with the plan.

The Challenge

Write a program or function which will, when given any date in 2020 (apart from 30-31 Dec - see "The Details"), output the number of ACUs that are in my tin.

The Details

• Each week in 2020 consists of exactly 7 days.
• The first week of the year starts on 1 January 2020.
• We are considering only weeks that are completely within 2020. The last week ends on 2020-12-29 so there are exactly 52 weeks and 30/31 December are not included.
• Each week I will put a number of ACUs equal to the week number into my tin on the first day of the week, that is on the 1st January I will put 1 ACU into the tin, on the 8th January I will put 2 ACUs, etc. I will at no point take any ACUs out of the tin.

The Rules

• Program or function - your choice.

• Input in whatever convenient format but it must be a date. I have a feeling that accepting a day-of-year input may trivialise this challenge but I am open to other opinions on this.

• Output however you like but it must be a number of ACUs or a string representation of same.

• We are only talking about complete weeks in 2020 so you can assume that the input will not include 30 or 31 December. It's up to you how you deal with it if it does.

• Don't forget that in 2020 February has 29 days.

• Usual loopholes barred and this is code golf so the shortest program/function in each language will be the winner. All languages welcome and I will not be accepting an answer as per current consensus. Upvotes will decide who wins.

A small Python script that generates the expected output for each week is available here Try it online!. The output can also be printed to stick on the side of your tin if you decide to do the same :)

• Jan 8 '20 at 19:35
• This looks like a chameleon challenge combining the one @Arnauld noted and this one: Related Jan 8 '20 at 21:25
• @JL2210 I'm not sure that I understand the question but please feel free to try it. Jan 8 '20 at 21:32
• If accepting a number of seconds since 2020/01/01 is OK, the challenge basically becomes a dupe of this one, with just an additional division... :/ Jan 9 '20 at 13:06
• @Arnauld Hmm...very good point. This is why I initially said date only and not number of days. Sorry JL2210, in view of Arnaulds observation I am going to have to revert to date input only. Jan 9 '20 at 13:38

APL (Dyalog Extended), 20 19 bytesSBCS

Anonymous tacit prefix function taking [year,month,day] as argument.

2!∘⌊7÷⍨43816-⍨⌂days

Try it online!

⌂days calculate the number of days since 1899-12-31

43816-⍨ subtract 43816; days since 2019 12 18, i.e 14 days weeks extra

7÷⍨ divide by 7; weeks since 2019 12 18, i.e two weeks extra

floor; whole weeks since 2019 12 18, i.e two weeks extra

2! count the number of ways to choose 2 out of that many

In other words, if $$\d(x)\$$ is the number of days since 1899-12-31, then the answer is

$${\Big\lfloor{d(x)-43816\over7}\Big\rfloor\choose2}= {\Big\lfloor{d(x)-43823\over7}\Big\rfloor-1\choose2}= \sum_{n=1}^{\big\lfloor\frac{d(x)-43823}7\big\rfloor}n$$

• It doesn' matter how long I hang out here, I will never understand your APL answers :) +1 Jan 8 '20 at 19:48
• @ElPedro That's by staying here here on the main site, but if you start hanging out in the APL Orchard you'll understand very soon.
Jan 8 '20 at 19:49
• Thanks. I may well give that a try. Looking to learn something new. This may be it. I think I may need a new keyboard to find all of those strange symbols though :) Jan 8 '20 at 19:52
• @FryAmTheEggman Yes, fixing now.
Jan 8 '20 at 20:14

Perl 6, 33 bytes

{[+] 1..Date.new(24,|@_).week}

Try it online!

Takes input as month,day. This initialises a date in the year 24 (since that year starts on Monday and is a leap year), and calculates the sum of the range of 1 to the current week number.

• Awesome but why 24? My Perl is not so good. Sorry. Jan 8 '20 at 21:12
• @ElPedro I use the year 24 since the first week of that year starts on the first of January (assuming Monday is the first day of the week), and the year is a leap year
– Jo King
Jan 8 '20 at 21:26
• Very smart idea. Unfortunately I can only upvote once. Jan 8 '20 at 23:05

R, 56 34 bytes

function(d)sum(1:format(d-2,"%V"))

Try it online!

A function taking an R Date as its argument and returning a number. Works because 2019-12-30 was a Monday, strftime(,"%V") returns the ISO week number and then calculates the relevant triangular number.

Thanks to @Giuseppe for saving 17 bytes, and @RobinRyder a further 3!

• as.double is shorter than as.integer by a whopping one byte. Jan 8 '20 at 20:39
• sum the first x integers instead -- 39 bytes. Jan 8 '20 at 21:31
• @Giuseppe impressive! I didn’t know : coerced from string. Jan 8 '20 at 22:27
• You can use d-2 instead of d+1461 for -3 bytes. It works because the last 2 days of 2019 are counted as being in week 1 of 2020 (at least on my OS). Jan 8 '20 at 23:48
• Yes, : is weird; I don't think I've ever used it for its interaction between factors, but the docs say: Non-numeric arguments are coerced internally (hence without dispatching methods) to numeric—complex values will have their imaginary parts discarded with a warning. Jan 9 '20 at 16:41

JavaScript (ES6),  53  51 bytes

Takes input as (month)(day).

This is longer than my other answer but does not use any date built-in.

m=>g=d=>--m?g(d+31+~m%9%2-(m==2)):~(d=~-d/7)*~-~d/2

Try it online!

Commented version

m =>               // m = month
g = d =>           // g is a recursive function taking the day d
--m ?            // decrement m; if it's not equal to 0:
g(             //   do a recursive call:
d + 31       //     add 31
+ ~m % 9 % 2 //     subtract 1 if (m + 1) mod 9 is odd
//     to account for the August -> July transition
- (m == 2)   //     subtract 1 if m = 2, for February
)              //   end of recursive call
:                // else:
~(             //   compute the triangular number
d = ~-d / 7  //   using d' = (d - 1) / 7:
) *            //     -floor(d' + 1) *
~-~d           //     -floor(d' + 2)
/ 2            //     / 2

JavaScript (ES6),  61 50 49  47 bytes

Assumes that the system is set up to UTC time (as the TIO servers are)

Takes input as (month)(day).

m=>d=>(n=new Date(68,m-1,d+738)/6048e5|0)*-~n/2

Try it online!

How?

Given the month $$\m\$$ and the day $$\d\$$, we generate the corresponding date in $$\1968\$$ (the closest leap year before Epoch) with an additional offset of $$\738\$$ days.

new Date(68, m - 1, d + 738)

We implicitly coerce this value to a number of milliseconds and divide it by:

$$7\times24\times60\times60\times1000=604800000$$

We discard the decimal part of the result to turn it into a 1-based week index $$\n\$$ in $$\1970\$$ (Epoch's year) which is consistent with the week index in $$\2020\$$.

$$\738\$$ is the sum of:

• a leap year ($$\366\$$ days) to reach 1969
• a non-leap year ($$\365\$$ days) to reach 1970
• a week ($$\7\$$ days) to go from 0-indexed to 1-indexed

Finally, we return the $$\n\$$th triangular number $$\\dfrac{n(n+1)}{2}\$$.

• Your explanations are always well good to read. Care to give one for this because I have no idea what is happening here :-/ Jan 8 '20 at 20:24
• @ElPedro Done. :) Jan 8 '20 at 23:34

Red, 38 bytes

func[d][(t: pick d - 2 14)*(t + 1)/ 2]

Try it online!

Takes input as a date in any reasonable format: dd-mm-yyyy, yyyy-mm-dd, dd-MMM-yyyy. Red's date datatype fourteenth field holds the week nember.

05AB1E, 20 19 bytes

•Σ₁t•ºS₂+6šI£O+7÷LO

-1 byte thanks to @Arnauld.

Input in the order month, day, year (although the year is ignored).

Try it online.

Explanation:

•Σ₁t•                # Push compressed integer 5354545
º               # Mirror it: 53545455454535
S              # Convert it to a list of digits: [5,3,5,4,5,4,5,5,4,5,4,5,3,5]
₂+            # Add 26 to each: [31,29,31,30,31,30,31,31,30,31,30,31,29,31]
6š          # Prepend a 6: [6,31,29,31,30,31,30,31,31,30,31,30,31,29,31]
I£        # Leave the first month-input items of this list
O       # And sum those
+      # Add it to the (implicit) day-input
7÷    # Integer-divide it by 7
L   # Pop and push a list in the range [1,n]
O  # And sum that list
# (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why •Σ₁t• is 5354545.

• Alternative 19s: •Σ₁t•ºS₂+IšI£O7/îLO (swapped inputs) or •ë˜¿•ºS₂+I£O+7÷3-LO. Jan 16 '20 at 15:59

Python 3.8 (pre-release), 94 $$\\cdots\$$ 82 77 bytes

lambda d:(n:=(date(*d)-date(2020,1,1)).days//7+1)*-~n/2
from datetime import*

Try it online!

Function takes date as a (year, month, day) tuple and returns the number of ACUs. Tests ported from Arnauld's answer.

• I really do like the idea but "Output however you like but it must be a number of ACUs or a string representation of same". Upvoted before the change and won't retract. Jan 8 '20 at 21:19
• @ElPedro Sorry, don't understand. The function returns the number of ACUs as stated. Jan 8 '20 at 21:22
• Sorry also. When I go to TIO it shows True for each input. Sorry if I am missing something. Jan 8 '20 at 21:24
• @ElPedro Those are tests to see if the function returns the expected number of ACUs, If so True is printed, if not False would be printed. I'll change them to print output beside expected output. Jan 8 '20 at 21:25
• @ElPedro Ok, they now print the returned value and the expected value. Jan 8 '20 at 21:29

Try it online!

Jelly, 23 21 bytes

“¢(Y’b3+29ÄŻ⁸ị++6:7RS

Try it online!

A full program taking the date as three arguments: month, day, year. Alternatively a dyadic link taking the month as its left and day as its right argument. (The year is ignored in any case.) Jelly has no date type, so this needs to generate the cumulative month lengths.

C# (Visual C# Interactive Compiler), 44 bytes

x=>Enumerable.Range(1,x.DayOfYear/7+1).Sum()

Try it online!

TI-BASIC, 26 25 bytes

∑(X,X,1,1+int(7⁻¹(1+dbd(1.012,Ans

Hooray for built-ins!

Input is the compressed version of the end date in the form MM.DDYY or DDMM.YY where MM is the month (e.g. 01), DD is the day (e.g. 24) and YY is the year (in this case, 20).
Input is in Ans.

Output is the wanted result as specified in the challenge.

Update:

In my attempt to fix the code, I somehow made it shorter.

Explanation:

∑(X,X,1,1+int(7⁻¹(1+dbd(1.012,Ans

dbd(1.012,Ans  ;difference in days between 1Jan2020 and the
;  compressed input
1+               ;add one to allow 1Jan2020 to be an input
7⁻¹(                 ;multiply by 1/7
int(                     ;truncate
1+                         ;convert week index from 0-indexed to 1-indexed
∑(X,X,1, ...                       ;summation of X from 1 to the above
;implicit print of Ans

Examples:

1.2420:prgmCDGF28
6
2.2920:prgmCDGF28
36
1.3120:prgmCDGF28
10
1.0120:prgmCDGF28
1

Note: TI-BASIC is a tokenized language. Character count does not equal byte count.

Java, 24 characters/bytes

c->c.get(3)*-~c.get(3)/2

Try it online

• This is an instance of ToIntFunction as a Lambda function.
• c is a reference to a Calendar object.
• c.get(3) returns the week of year field (Calendar.WEEK_OF_YEAR == 3)
• x*-~x/2 is the triangle number calculation.
• Looks good but can you add a link to an online interpreter so we can see the results? Jan 10 '20 at 16:18
• @ElPedro I added a link to try it online. Jan 13 '20 at 12:30
• The calendar should be 2020, not 2019 (change the loop start to be 1, not 0). Additionally, your week won't be starting on 1st January, but the 28th of December
– Jo King
Jan 13 '20 at 22:37
• Can you either fix your answer or delete it until you have done so?
– Jo King
Jan 24 '20 at 11:10