Easter day challenge



#8

it will soon be easter. this year, easter sunday is on April 20.
the idea is to write an easter sunday calculation program valid for years 1900-2099 on the 25C (ie in 50 steps or less!).

to make it more interesting, i've already had a go, but my answer is incomplete. completely different approaches are allowed as long as they work!
i've managed to simplify a formula down to the following logic:

d =(204 - 11*(y%19))%30;
if (d < 28) ++d;
return d+27-(5*y/4+d)%7;

where `y' is the input year. the result `d' is the day number from march, where d > 31 implies april (d-31). after some struggle, i write:

sto0 1 9 / int 1 9 * rcl0 - 1 1 * 2 0 4 + sto1 3 0 / int 3 0 * sto-1 2 8 sto2 rcl1 x>=y? gto35 1 + rcl0 5 * 4 / int sto-2 + 7 / int 7 * rcl2 +

which works but always returns the answer + 1 :-)
be sure to test 1954 (which is April 18).

happy easter!


#9

i finally done this in 46 steps. wow, 3 steps to party!
but the program's about as vicious as a cornered rat.


#10

Did you scope out the algorithm at:

http://aa.usno.navy.mil/faq/docs/easter.html

Quoting here:


Computing the Date of Easter:


The rule is that Easter is the first Sunday after the first ecclesiastical full moon that occurs on or after March 21. The lunar cycles used by the ecclesiastical system are simple to program. The following algorithm will compute the date of Easter in the Gregorian Calendar system.

Please note the following: This is an integer calculation. All variables are integers and all remainders from division are dropped.


The algorithm uses the year, y, to give the month, m, and day, d, of Easter. The symbol * means multiply.


c = y / 100

n = y - 19 * ( y / 19 )

k = ( c - 17 ) / 25

i = c - c / 4 - ( c - k ) / 3 + 19 * n + 15

i = i - 30 * ( i / 30 )

i = i - ( i / 28 ) * ( 1 - ( i / 28 ) * ( 29 / ( i + 1 ) )

* ( ( 21 - n ) / 11 ) )

j = y + y / 4 + i + 2 - c + c / 4

j = j - 7 * ( j / 7 )

l = i - j

m = 3 + ( l + 40 ) / 44

d = l + 28 - 31 * ( m / 4 )

For example, using the year 2010,

y=2010,

c=2010/100=20,

n=2010 - 19 x (2010/19) = 15,

etc. resulting in Easter on April 4, 2010.

The algorithm is due to J.-M. Oudin (1940) and is reprinted in the Explanatory Supplement to the Astronomical Almanac, ed. P. K. Seidelmann (1992). See Chapter 12, "Calendars", by L. E. Doggett.


#11

hi glynn,

i had seen the oudin version. but it is way to large for 50 steps. instead i found a formular by Carter valid only for 1900-2099 then simplified it a bit more and tied that.

#12

Hugh,

I had a look at your original algorithm and ran a quick check of the values for d that are generated before the 'if' statement. Oddly enough, for years in the range 1900 to 2099, d never equals 27. So, your algorithm can be rewritten:

d =(204 - 11*(y%19))%30;
if (d < 27) ++d;
return d+27-(5*y/4+d)%7;


This leads to a simple change to your original HP-25C code - replace the '8' in step 28 with a '7' and now the result is no longer off by one.

I also experimented with storing some of the constants in the algorithm in memory registers. Doing this allowed me to free up about 10 lines of program space, which in turn allows an epilogue to your code to return the month in the X register and the day in the Y register.

Unfortunately, I don't have an actual HP-25C myself, but I was able to test the code on the HP-25C simulator at http://www.rskey.org/hp25.htm and it seems to work fine for all they years I threw at it. I've pasted the code below. Note that the registers need to be initialized with the values shown before the program is run for the first time. Since the program doesn't modify R3 to R7, they do not need to be initialized again for subsequent runs of the program.

Good challenge.

Eamonn.


Store the following values in registers R3 to R7:

R3 = 19
R4 = 204
R5 = 30
R6 = 27
R7 = 1.25

And here's the code, with some comments.

01 sto0 ; Store year in R0 for later
02 rcl3 ; R3 = 19
03 /
04 int
05 rcl3
06 *
07 rcl0
08 - ; X = -(year mod 19)
09 1
10 1
11 *
12 rcl4 ; R4 = 204
13 +
14 sto1 ; 204 - 11 * (year mod 19) stored in R1
15 rcl5 ; R5 = 30
16 /
17 int
18 rcl5
19 *
20 sto-1 ; d stored in R1
21 rcl6 ; R6 = 27
22 sto2 ; store 27 in R2 for later
23 rcl1 ; recalls d
24 x>=y? ; if d>=27 then ...
25 gto28 ; ... goto 27.
26 1 ; Add 1 to d
27 +
28 rcl0 ; Recall the year
29 rcl7 ; R7 = 5/4 = 1.25
30 * ; X = y * 5/4
31 int ; X = floor (y * 5/4)
32 sto-2 ; Store 27 - floor(y * 5/4) in R2
33 + ; X = d + floor(y * 5/4)
34 7
35 /
36 int
37 7
38 * ; X = 7 * floor( (d + (y * 5/4) ) / 7 )
39 rcl2 ; X = 28 - (y * 5/4)
40 + ; X = 28 - (y * 5/4) + 7 * floor( (d + (y * 5/4) ) / 7 ), the result from the original code.
41 3
42 1
43 x<y ; result > 31?
44 gto48 ; if so, then skip to line 48
45 Rv ; Place result back in X
46 3 ; Month is march
47 gto00 ; Done
48 - ; Subtract 31 from result
49 4 ; Month is April


#13

hey, i like it!

i didnt think of the 27 trick. you had seen how i had tried to reuse the same constant but out by 1.
also, the idea of storing some of the constants in registers and then using the space to discriminate march/april is a cool idea.
what i did in the end is recode the problem again using FRAC instead of INT. last time i tried this (which saves space) it got the wrong answer for certain cases.
you see frac(x/7)*7 is often wrong. but x - int(x/7)*7 is always right. this is due to small rounding errors.
here's my version:

sto1 1 9 / frac 2 0 9 * 2 0 4 - chs 3 0 / frac 3 1 * 2 8 x<>y x>=y? gto 29 1 + rcl1 5 * 4 / int sto2 + 7 / int 7 * rcl2 - + 1 -

the beauty is /30 then *31 which makes the number ever-so-slightly larger. later on the INT throws away the oversize part and there is no loss of bits.

but wait! i can use your 27 idea, because i do the -1 on the end here. this now gives me 5 spare steps. the question is, can i put in the month discriminator as well!

i'll try that later.


#14

Looks good Hugh, though I think you'll have difficulties getting the month and day displayed correctly with only five steps remaining. I both like and dislike the multiply by 31 trick - kinda ugly, but it gets the job done and it looks like it should work for all cases. Admittedly, when you have limitations such as having only 50 steps available, you sometimes have to resort to tricks like this. By the way, I really like the way you calculate the d+27-(5*y/4+d)%7 part of the algorithm. Not obvious, and it took a few minutes to write out the equations to understand what you were doing, but 100% correct.

With your changes bringing the program down to 44 steps, I'm guessing, you could store the constants 204 and 209 in registers, freeing up four steps and allowing the display of the month and date at the end. This is more efficient the five registers I used. Also, I see you only use two storage registers in your new code, compared to three in the original code.

It's going to be hard to beat that.


Possibly Related Threads...
Thread Author Replies Views Last Post
  An amazing day: Giving a talk at HP about their calculators Geir Isene 9 1,099 12-16-2013, 06:14 PM
Last Post: aurelio
  HHC 2013 Day 2 Highlights Eddie W. Shore 6 703 09-23-2013, 04:03 PM
Last Post: Kimberly Thompson
  HHC 2013: Day 1 Highlights Eddie W. Shore 28 1,956 09-23-2013, 03:22 PM
Last Post: Brad Barton
  Happy Mother's Day! Eddie W. Shore 1 274 05-12-2013, 11:35 AM
Last Post: Walter B
  happy fibonacci day 5/8/13 Allen 8 803 05-09-2013, 01:48 AM
Last Post: Gerson W. Barbosa
  HP 10s+ Easter Egg (Statistics) Eddie W. Shore 1 245 04-11-2013, 04:25 PM
Last Post: Andrew Feist
  Easter Sunday Basic Trigs (HP-12C) Gerson W. Barbosa 29 1,873 04-04-2013, 02:19 PM
Last Post: Gerson W. Barbosa
  Stupid idea of the day: 41-compatible watch bhtooefr 0 241 03-31-2013, 08:23 AM
Last Post: bhtooefr
  OT: Happy Pi Day! Eddie W. Shore 13 981 03-22-2013, 10:44 AM
Last Post: Les Koller
  Totally OT ... Pi Day for my car Maximilian Hohmann 18 1,206 03-10-2013, 01:15 PM
Last Post: chris smith

Forum Jump: