HHC 2018 Programming Contests
|
10-01-2018, 06:37 AM
Post: #44
|
|||
|
|||
RE: HHC 2018 Programming Contests
My take on elegance is a simple and concise program. That's what I present here; it contains several pre-calculated 'magic' numbers generated from the functions given in the challenge. It's probably not immediately obvious from the code exactly how they are derived, but that's what comments are for. So let's start with the general idea.
Each of the three functions has two extrema in their cycle, a maximum at a quarter of the cycle length and a minimum at three quarters of the cycle length. For the functions which don't have a cycle length evenly divisible by four, the example shows me that the rounded result of the division by four is enough. Experimentation has confirmed that, and it has also confirmed that the surrounding days are far enough away to yield function values with an absolute value of at most 99, which means we don't have to deal with extrema spanning more than a single day. From these observations we can easily calculate for each function the first few days on which it is at an extremum. For the 'physical' function (henceforth known as P): maximum at 5.75 (rounded to 6), minimum at 17.25 (rounded to 17), repeating every 23 days - Maxima (first 33): 6, 29, 52, 75, 98, 121, 144, 167, 190, 213, 236, 259, 282, 305, 328, 351, 374, 397, 420, 443, 466, 489, 512, 535, 558, 581, 604, 627, 650, 673, 696, 719, 742 - Minima (first 33): 17, 40, 63, 86, 109, 132, 155, 178, 201, 224, 247, 270, 293, 316, 339, 362, 385, 408, 431, 454, 477, 500, 523, 546, 569, 592, 615, 638, 661, 684, 707, 730, 753 For the 'emotional' function (henceforth known as E): maximum at 7, minimum at 21, repeating every 28 days - Maxima (first 33): 7, 35, 63, 91, 119, 147, 175, 203, 231, 259, 287, 315, 343, 371, 399, 427, 455, 483, 511, 539, 567, 595, 623, 651, 679, 707, 735, 763, 791, 819, 847, 875, 903 - Minima (first 33): 21, 49, 77, 105, 133, 161, 189, 217, 245, 273, 301, 329, 357, 385, 413, 441, 469, 497, 525, 553, 581, 609, 637, 665, 693, 721, 749, 777, 805, 833, 861, 889, 917 For the 'intellectual' function (henceforth known as I): maximum at 8.25 (rounded to 8), minimum at 24.75 (rounded to 25), repeating every 33 days - Maxima (first 28): 8, 41, 74, 107, 140, 173, 206, 239, 272, 305, 338, 371, 404, 437, 470, 503, 536, 569, 602, 635, 668, 701, 734, 767, 800, 833, 866, 899 - Minima (first 28): 25, 58, 91, 124, 157, 190, 223, 256, 289, 322, 355, 388, 421, 454, 487, 520, 553, 586, 619, 652, 685, 718, 751, 784, 817, 850, 883, 916 For every pair of functions (P and E, P and I, E and I) there is a number of days where they meet at 0 again and both ascend towards +100, just like they do at birth. That is, the pattern produced by drawing both functions of a pair repeats, and so do their extrema as well as the points where both have an extremum on the same day. The length of this repeating pattern is the product of lengths of the two functions' cycles. (Technically it should be the LCM (lowest common multiple), but since the cycles lengths don't have any common factor, that equates to the same number.) The next pre-processing task is therefore to find for each pair of functions the days on which they both have an extremum. For P and E the repeating pattern is 23 28 *, i.e. 644 days long, during which P goes through 28 cycles and E goes through 23. Looking at the first 28 maxima and minima of P as well as the first 23 maxima and minima of E, we find the common days 63 (minimum of P, maximum of E, the example), 259 (maximum of both), 385 (minimum of both), and 581 (maximum of P, minimum of E). For P and I the repeating pattern is 23 33 *, i.e. 759 days long, during which P goes through 33 cycles and I goes through 23. Looking at the first 33 maxima and minima of P as well as the first 23 maxima and minima of I, we find the common days 190 (maximum of P, minimum of I), 305 (maximum of both), 454 (minimum of both), and 569 (minimum of P, maximum of I). For E and I the repeating pattern is 28 33 *, i.e. 924 days long, during which E goes through 33 cycles and I goes through 28. Looking at the first 33 maxima and minima of E as well as the first 28 maxima and minima of I, we find the common days 91 (maximum of E, minimum of I), 371 (maximum of both), 553 (minimum of both), and 833 (minimum of E, maximum of I). With this data, the challenge can be rewritten like this: Given a number (representing the age in days, which is calculated as the difference between the birthdate and now), find the lowest number higher than the given number that is either: - equal to one of 63, 259, 385, 581, all modulo 644, or - equal to one of 190, 305, 454, 569, all modulo 759, or - equal to one of 91, 371, 553, 833, all modulo 924. The found number needs to be converted back to a date by adding it to the current date, of course. With this rewritten challenge in mind (or on hand), the code becomes relatively straight-forward. The input and output for this program are performed through the stack. This way the program blends in with normal calculator commands, and it's much less messy than the code for e.g. an input form. As a bonus, it even respects system flag 42 (date format mm.ddyyyy or dd.mmyyyy). Code: \<< Tests: A baby born last Friday (Sep 28, 2018), should have its first extrema date when it is 63 days old, which will happen on Nov 30, 2018. This is the example given in the challenge, and the graphs given there make it easy to tell if the function values are in the vicinity of the correct results. For input 28.092018 (my 50G has system flag 42 set, so that is the correct format) on stack level 1 my program outputs 30.112018 on stack level 2, and {P:(-100.) E:100. I:(-54.)} on stack level 1. Looks good so far, except for these weird parentheses around tagged negative numbers when they are on stack levels that get rendered in multiline mode. (I've set mine to only render level 1 in multiline mode.) Non-multiline stack levels have extra spaces at various places instead. Anyway, the data is fine. A baby born on Jan 1, 2018 has passed its first four extrema dates already. The next one should happen when it is 305 days old, i.e. on Nov 2, 2018. For input 1.012018 on stack level 1 my program outputs 2.112018 on stack level 2, and {P:100. E:(-62.) I:100.} on stack level 1. Yay, correct date. It appears my program can actually handle cases where the first result in the lists is not the best one. Now for some stress testing. After 23 28 33 * * days (that's 21252 days) all three functions are at their starting value of 0 again. A person who is exactly that much older than the baby from last Friday should therefore get the exact same output as the baby. 21252 days before Sep 28, 2018 is July 22, 1960 according to my 50G. (Enter 28.092018 -21252. DATE+ to confirm.) For input 22.071960 on stack level 1 my program outputs 30.112018 on stack level 2, and {P:(-100.) E:100. I:(-54.)} on stack level 1. Yaaay! It works with larger numbers too! ... So I can conclude that it does indeed work. |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 1 Guest(s)