How next_c.tc works On Friday Jan 13, 2017 I became intrigued by the question "When's the next Friday the 13th?" After about four iterations I finally arrived at a solution (which worked for any day, not just Friday the 13th). Mine is in tiny-C (perl has date smarts that tiny-C lacks). The source code is at http://primepuzzle.com/tc/next_c.tc. The basic idea is to hop from month to month, driven by the length of each month. In a simple case, to go from Sun March 12 2017 to Wed April 12 2017 we hop 31 days (the number of days in March). The day of week advances by 3 (because 31%7=3). We keep hopping till the sum of the numbers equals 0 (modulo 7). ```31 30 31 30 31 31 30 31 Mar Apr May Jun Jul Aug Sep Oct Nov 3 + 2 + 3 + 2 + 3 + 3 + 2 + 3 = 21 = 0 (modulo 7) Sun Wed Fri Mon Wed Sat Tue Thu Sun ``` If you start on a day number that doesn't occur in every month (e.g. 30) hops may cross over month boundaries so we can't stop our hopping because we'll be sitting on a day number that's not our required day number. Also, if we start in a late month (e.g. Nov or Dec) it's likely we'll cross a year boundary and we may be running into a leap year (or we may have been in a leap year and will be entering a non-leap year). For these reasons, after a while it occurred to me that I should "compile" a 3-year list of month lengths, and make sure the 29th of Feb (if any) was where it belonged. For example: ``` 2018 2019 2020 31 28 31 30 31 30 31 31 30 31 30 31 31 28 31 30 31 30 31 31 30 31 30 31 31 29 31 30 31 30 31 31 30 31 30 31 ``` Key variables in the logic were the four input variables (dow, month, day, year), two arrays that hold month lengths, index (a month "pointer"), and work_day (a day of week recorder). How to initialize them and how to update them was finally worked out. The main loop fell into place. ``` index=month+1;work_day=dow;verbose=1 if verbose printf "%c%d %d",10,month,work_day while 1 [ work_day=(work_day+da(index-1))%7 if verbose printf "%c%d %d",10,index,work_day if work_day==dow // needs to be right day of week if (da(index)>=day) break // needs to be a legal month index=index+1 ] printf "%c%s %d%c",10,month_n(index%12),(year+index/12),10 ``` Here's a sample run:```D:\Tom Gibson\tiny-c-master>tc SamplePrograms\next_c_try.tc *** TINY-C VERSION 1.0, COPYRIGHT 1977, T A GIBSON *** This C version copyright 2017, T A Gibson next_c.tc - 6/6/19 - lrb dow (0=Sunday, 1=Monday, etc.) : 4 month (0=January, 1=February, etc.) : 5 day (1..31) : 6 year (e.g. 2019) : 2019 Thu Jun 6 5 4 6 6 7 2 8 5 9 0 10 3 11 5 12 1 13 4 Feb 2020 done D:\Tom Gibson\tiny-c-master>```