12
\$\begingroup\$

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

| improve this question | | | | |
\$\endgroup\$
  • \$\begingroup\$ Related. \$\endgroup\$ – Arnauld Jan 8 at 19:35
  • 2
    \$\begingroup\$ This looks like a chameleon challenge combining the one @Arnauld noted and this one: Related \$\endgroup\$ – Xcali Jan 8 at 21:25
  • 1
    \$\begingroup\$ @JL2210 I'm not sure that I understand the question but please feel free to try it. \$\endgroup\$ – ElPedro Jan 8 at 21:32
  • 1
    \$\begingroup\$ 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... :/ \$\endgroup\$ – Arnauld Jan 9 at 13:06
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – ElPedro Jan 9 at 13:38

17 Answers 17

10
\$\begingroup\$

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$$

| improve this answer | | | | |
\$\endgroup\$
  • 2
    \$\begingroup\$ It doesn' matter how long I hang out here, I will never understand your APL answers :) +1 \$\endgroup\$ – ElPedro Jan 8 at 19:48
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – Adám Jan 8 at 19:49
  • \$\begingroup\$ 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 :) \$\endgroup\$ – ElPedro Jan 8 at 19:52
  • 2
    \$\begingroup\$ @FryAmTheEggman Yes, fixing now. \$\endgroup\$ – Adám Jan 8 at 20:14
9
\$\begingroup\$

Perl 6, 33 bytes

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

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.

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ Awesome but why 24? My Perl is not so good. Sorry. \$\endgroup\$ – ElPedro Jan 8 at 21:12
  • \$\begingroup\$ @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 \$\endgroup\$ – Jo King Jan 8 at 21:26
  • \$\begingroup\$ Very smart idea. Unfortunately I can only upvote once. \$\endgroup\$ – ElPedro Jan 8 at 23:05
9
\$\begingroup\$

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!

| improve this answer | | | | |
\$\endgroup\$
  • 1
    \$\begingroup\$ as.double is shorter than as.integer by a whopping one byte. \$\endgroup\$ – Giuseppe Jan 8 at 20:39
  • 2
    \$\begingroup\$ sum the first x integers instead -- 39 bytes. \$\endgroup\$ – Giuseppe Jan 8 at 21:31
  • 1
    \$\begingroup\$ @Giuseppe impressive! I didn’t know : coerced from string. \$\endgroup\$ – Nick Kennedy Jan 8 at 22:27
  • 3
    \$\begingroup\$ 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). \$\endgroup\$ – Robin Ryder Jan 8 at 23:48
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Giuseppe Jan 9 at 16:41
6
\$\begingroup\$

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
| improve this answer | | | | |
\$\endgroup\$
5
\$\begingroup\$

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}\$.

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ Your explanations are always well good to read. Care to give one for this because I have no idea what is happening here :-/ \$\endgroup\$ – ElPedro Jan 8 at 20:24
  • 1
    \$\begingroup\$ @ElPedro Done. :) \$\endgroup\$ – Arnauld Jan 8 at 23:34
4
\$\begingroup\$

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.

| improve this answer | | | | |
\$\endgroup\$
4
\$\begingroup\$

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.

| improve this answer | | | | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Alternative 19s: •Σ₁t•ºS₂+IšI£O7/îLO (swapped inputs) or •ë˜¿•ºS₂+I£O+7÷3-LO. \$\endgroup\$ – Grimmy Jan 16 at 15:59
3
\$\begingroup\$

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.

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – ElPedro Jan 8 at 21:19
  • \$\begingroup\$ @ElPedro Sorry, don't understand. The function returns the number of ACUs as stated. \$\endgroup\$ – Noodle9 Jan 8 at 21:22
  • \$\begingroup\$ Sorry also. When I go to TIO it shows True for each input. Sorry if I am missing something. \$\endgroup\$ – ElPedro Jan 8 at 21:24
  • \$\begingroup\$ @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. \$\endgroup\$ – Noodle9 Jan 8 at 21:25
  • \$\begingroup\$ @ElPedro Ok, they now print the returned value and the expected value. \$\endgroup\$ – Noodle9 Jan 8 at 21:29
2
\$\begingroup\$

Perl 5 -ap -MTime::Local -MTime::Piece, 61 bytes

$_=($w=(gmtime timegm 0,0,0,$F[0],$F[1]-1,24)->week)*($w+1)/2

Try it online!

| improve this answer | | | | |
\$\endgroup\$
2
\$\begingroup\$

Ruby, 42 bytes

A function that takes the month and date.

Time#yday returns the day of the year.

->m,d{k=1+~-Time.gm(4,m,d).yday/7;k*-~k/2}

Try it online!

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ Nice. I need to get into Ruby. I went the Python way. \$\endgroup\$ – ElPedro Jan 8 at 23:02
2
\$\begingroup\$

PowerShell, 48 bytes

Thanks to @mazzy

(1..(((Date|% DayOfYear)/7)+1)|measure -sum).sum

Try it online!

Originally 76 bytes

[Linq.Enumerable]::Sum([Linq.Enumerable]::Range(1,(Get-Date).DayOfYear/7+1))

Try it online!

| improve this answer | | | | |
\$\endgroup\$
2
\$\begingroup\$

C (gcc), 34 32 38 34 32 bytes

g(n){n=n/604800-2607;n=n*-~n/2;}

Takes as input the number of seconds since January 1st, 1970 (the Unix epoch) at 0:00 AM UTC time.

Explanation:

n=n/604800-2607;

Divide by number of seconds in a week and subtract the number of weeks from Jan 1 1970 to Jan 1 2020 minus one so we don't have to increment later.

n=n*-~n/2;

Return the n'th triangle number. This is equivalent to the ACU calculation but without any builtin language constructs or loops. Due to TIO's calling convention I can assign to the first argument instead of using return.

-2 bytes thanks to Arnauld!
+6 bytes thanks to Arnauld and ElPedro! (:P)
-4 bytes thanks (indirectly) to ceilingcat!
-2 more bytes thanks to ceilingcat!

Try it online!

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ (n+1) can be turned into -~n. That said, I don't think this input format complies with it must be a date. \$\endgroup\$ – Arnauld Jan 9 at 12:52
  • \$\begingroup\$ @Arnauld It seems that the OP disagrees, unless you're implying that I need a date structure in which case my language doesn't provide one. \$\endgroup\$ – S.S. Anne Jan 9 at 13:04
  • 2
    \$\begingroup\$ There's no need to use a structure. Other answers that are not using date built-ins are just taking the day, the month and the year as separate arguments (like here, here, here, etc.) It is perfectly fine to ignore the year, though. \$\endgroup\$ – Arnauld Jan 9 at 13:41
  • \$\begingroup\$ @Arnauld Alright, revised solution. \$\endgroup\$ – S.S. Anne Jan 9 at 15:42
  • \$\begingroup\$ @ceilingcat Argh, forgot to change the TIO link. Fixed and I can squeeze a few more bytes out. \$\endgroup\$ – S.S. Anne Jan 11 at 0:16
2
\$\begingroup\$

PHP, 67 59 57 bytes

<?=(($d=(int)(date(z,strtotime($argv[1]))/7+1))+$d*$d)/2;

Try it online!

| improve this answer | | | | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | | | | |
\$\endgroup\$
1
\$\begingroup\$

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

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

Try it online!

| improve this answer | | | | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | | | | |
\$\endgroup\$
0
\$\begingroup\$

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.
| improve this answer | | | | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Looks good but can you add a link to an online interpreter so we can see the results? \$\endgroup\$ – ElPedro Jan 10 at 16:18
  • \$\begingroup\$ @ElPedro I added a link to try it online. \$\endgroup\$ – Nic.Star Jan 13 at 12:30
  • \$\begingroup\$ 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 \$\endgroup\$ – Jo King Jan 13 at 22:37
  • \$\begingroup\$ Can you either fix your answer or delete it until you have done so? \$\endgroup\$ – Jo King Jan 24 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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