Back in 2018, there has been introduced new law in Poland to ban trading on sundays, but certain exceptions have been made (listed below). The task today is to determine, can one trade on the sunday provided by the user (according to these rules).

# Rules

You can trade only if one of the following is satisfied:

• The day is the last sunday of 1st, 4th 6th and 8th month.
• The day is one of the two sundays preceding Christmas.
• The day is the sunday preceding Easter

## Simplifications

Obviously one can't trade on certain holidays, but you can omit the check for them in your code. The only exclusion to this rule is Easter or Christmas (for obvious reasons).

For example, if the rules above allowed trading on 6th of January and albeit in reality you can't trade due to a holiday, you don't need to take that on the account (and assume that one can trade on 6th of January).

## I/O rules

You can take the date in any reasonable format - "DDMMYYYY", "MMDDYYYY" and so on. The output should be a truthy or falsy value (answering the question - can you trade on this sunday?)

You can assume the input date to always be a sunday.

## Examples

A few examples:

• You can trade on 27 January of 2019, due to rule 1.
• You can't trade on 13 January of 2019.
• You can't trade on 21 April of 2019 - it's Easter.
• You can trade on 14 April of 2019, due to rule 3.
• You can trade on 28 April of 2019, due to rule 1.
• You can trade on 15 December of 2019, due to rule 2.
• You can trade on 22 December of 2019, due to rule 2.

## Obvious clarifications

• You'll have to calculate the date of Easter and Christmas in the process.
• Your program has to work correctly with any other year than 2019.
• You MUST take on the account that you can't trade on Easter or Christmas, even if the conditions are satisfied.
• You don't need to check for other holidays.

# Scoring criterion

The shortest code (in bytes) wins.

• Because it's Poland, that's why the law is complex. If they banned all sundays, citizens would simply take the politicians out on a wheelbarrow from the Parliament. Commented May 17, 2020 at 13:52
• Seems a complicated enough problem just to calculate easter
– mkst
Commented May 17, 2020 at 14:45
• Mathematica has Default, GovernmentBond, NASDAQ, NERC, NYSE calendars for United States, but, unfortunately, only a normal-ish calendar for Poland :( Commented May 17, 2020 at 15:31
• streetster is correct - this is a chameleon challenge unless we can accept two dates: the date of the Sunday to check; and the date of Easter Sunday on that same year. Commented May 17, 2020 at 16:39
• Chameleon challenge is a challenge where one of it's parts is nearly as hard as the challenge itself. In this case, simply calculating the date of Easter is considerably easier than solving the challenge above. You've literally got a formula for this, it spans around 4 lines, what's hard in this? I can't seem to understand the problem with the challenge Commented May 17, 2020 at 16:56

# JavaScript (ES6),  173  172 bytes

Takes input as (year, month, day). Returns 0 or 1.

As anticipated by @streetster, computing Easter is the biggest part.

(y,m,d)=>169>>--m&(D=new Date(y,m,d+7)).getMonth()!=m|m>10&(d+3)/14|+D==+new Date(y,2,56-(c=(y%19*351-~((b=(a=y/25>>2)>>2)+a*29.32+13.54)*31.9)/33%29|0)-~(a-b+c-24-y/.8)%7)


Try it online!

## How?

### Last Sunday

We use the binary mask 0b10101001 (or 169 in decimal) to encode the 0-indexed months for which it's allowed to trade on the last Sunday. We make sure that m-1 is one of these months and that adding 7 days brings us to the next month.

169 >> --m & (D = new Date(y, m, d + 7)).getMonth() != m


### Christmas

We simply test whether the month is December and the day is more than 10 and less than 25.

m > 10 & (d + 3) / 14


All possible cases are summarized in the following table:

 Mo Tu We Th Fr Sa | Su | Mo Tu We Th Fr Sa | Su | Mo Tu We Th Fr Sa | Su | Mo Tu We
-------------------+----+-------------------+----+-------------------+----+----------
8  9[10]11 12 13 | 14 | 15 16 17 18 19 20 | 21 | 22 23 24[25]26 27 | 28 | 29 30 31
7  8  9[10]11 12 | 13 | 14 15 16 17 18 19 | 20 | 21 22 23 24[25]26 | 27 | 28 29 30
6  7  8  9[10]11 | 12 | 13 14 15 16 17 18 | 19 | 20 21 22 23 24[25]| 26 | 27 28 29
5  6  7  8  9[10]| 11 | 12 13 14 15 16 17 | 18 | 19 20 21 22 23 24 |[25]| 26 27 28
4  5  6  7  8  9 |[10]| 11 12 13 14 15 16 | 17 | 18 19 20 21 22 23 | 24 |[25]26 27
3  4  5  6  7  8 |  9 |[10]11 12 13 14 15 | 16 | 17 18 19 20 21 22 | 23 | 24[25]26
2  3  4  5  6  7 |  8 |  9[10]11 12 13 14 | 15 | 16 17 18 19 20 21 | 22 | 23 24[25]

### Easter

We test whether D (computed above) is equal to Easter. The algorithm was taken from this page (function ShortGregorianEaster1). It returns a day in March which may be greater than 31, in which case Date() quietly converts into a day in April.

+D == +new Date(y, 2, some_long_and_boring_formula)


# Python 2 + dateutil, 163 157 bytes

Possibly could be golfed some more. Even using a library function, calculating the date for Easter still takes up almost half of the code.

-6 bytes thanks to @Arnauld

from dateutil.easter import*
y,m,d=input()
e=easter(y)
print(e.month==m)*((e.day==d+7)-(e.day==d)*(m*d>99))+m/12*(d<25)*(d>10)+(m in[4,6])*d/24+(m%7==1)*d/25


Try it online!

Accepts input in the form YYYY, (M)M, (D)D. Returns 1 if trading is allowed, 0 otherwise.

• @Arnauld Thanks! I was able to use the same trick in a couple more places too Commented May 18, 2020 at 17:04

# 05AB1E, 109103 101 bytes

т÷©>3*4÷DV¹19%DU19*15O®8*13+25÷-30%DX11÷+29÷-23+DY-¹D4÷++7%(91O31‰R»9bS30+6ÝδαεŽ5ÂNèδ»}˜12ÐÝ+sδ»«sª²å


Input as year, day\nmonth (multi-line string).

(68 bytes are used to calculate Easter Sunday.)

Explanation:

Calculate the week before Easter Sunday, using @PeterTaylor's formula in his GolfScript answer here:

т÷             # Integer-divide the (implicit) input-year by 100
©            # Store it in variable ® (without popping)
>              # Increase it by 1
3*            # Multiply it by 3
4÷          # Integer-divide it by 4
DV        # Store a copy in variable Y
¹19%           # Push the input-year modulo-19
DU         # Store a copy in variable X
19*            # Multiply the year-modulo-19 by 19
15          # Push 15
O         # Sum the three values on the stack together:
#  year/100*3/4 + year%19*19 + 15
®8*            # Push variable ® and multiply it by 8
25÷      # Integer-divide it by 25
-     # Subtract it from the earlier calculated number
30%  # Modulo-30
D # Duplicate it
X11÷           # Push X integer-divided by 11
+          # Add it to top copy
29÷       # Integer-divide it by 29
-      # Subtract it from the other copy
D  # Duplicate it
Y-             # Subtract Y from the top copy
¹D           # Push the input-year two times
4÷         # Integer-divide to top year by 4
+        # Add it to the year
+       # Add it to the earlier number
7%     # Modulo-7
(    # Negate it
#  day 1-based; subtracts 7 since we want the week before Easter Sunday)
O            # Sum the three values on the stack
31‰          # Divmod it by 31 to extract the 1-based month and day
»         # And join those by newlines


Calculate all the other dates that could potentially be a truthy Sunday:

9              # Push 9
bS            # Convert it to a binary-list: [1,0,0,1]
30+         # Add 30 to each: [31,30,30,31]
6Ý       # Push list [0,1,2,3,4,5,6]
δ      # Apply double-vectorized:
α     #  Take the absolute difference
# [[31,30,29,28,27,26,25],[30,29,28,27,26,25,24],[30,29,28,27,26,25,24],[31,30,29,28,27,26,25]]
ε              # Map each to:
Ž5Â           #  Push compressed integer 1468
Nè         #  Index the map-index into it
δ»       #  And join it to each individual day with a newline delimiter
}˜             # After the map: flatten the list
12Ð          # Push 12 three times to the stack
Ý         # Pop one, and push list [0,1,2,3,4,5,6,7,8,9,10,11,12]
+        # Add each to 12: [12,13,14,15,16,17,18,19,20,21,22,23,24]
s       # Swap so the third 12 is at the top of the stack
δ»     # Join it to each individual day with a newline delimiter
«    # And merge these to the earlier flattened list


Merge it together to a single list:

sª             # Add the earlier calculated Easter Sunday - 7 to the list


I.e. for the year 2019, we now have the following dates that are potentially a truthy Sunday:

["31\n1","30\n1","29\n1","28\n1","27\n1","26\n1","25\n1", # January 31 to 25
"30\n4","29\n4","28\n4","27\n4","26\n4","25\n4","24\n4", # April 30 to 24
"30\n6","29\n6","28\n6","27\n6","26\n6","25\n6","24\n6", # June 30 to 24
"31\n8","30\n8","29\n8","28\n8","27\n8","26\n8","25\n8", # August 31 to 25
"12\n12","13\n12","14\n12","15\n12","16\n12","17\n12","18\n12","19\n12","20\n12","21\n12","22\n12","23\n12","24\n12",
# December 12 to 24
"24\n3"]                                                 # Sunday week before Easter


And we check if the second input is in this list to complete the program:

  ²å           # And check if the second input-string is in this list
# (after which the result is output implicitly)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ž5Â is 1468.