//---------------------------------------------------------------------- // enigma1366.c (c) 2005 by Charles Petzold // // "Done in Half the Time" by Susan Denham, New Scientist, 12 November 2005, page 62 // // You look at your watch 9 times over a two-day period, always at an // exact number of minutes past the hour. Each time, the angle between // the hour hand and the minute hand is half what it was previously. // // What's the last time you look at your watch? // // Measuring angles in degrees clockwise (of course) from the stroke of 12, // // Angle of Minute hand = 6 * Minutes // Angle of Hour hand = 30 * Hour + Minutes / 2 // // The difference is always a multiple of 0.5 degrees. Is 0.5 degrees // actually the angle between the two hands seen on the 9th time the // watch is observed? // // If so, the other eight angles are (working backwards) 1, 2, 4, 8, 16, // 32, 64, and 128. The next angle would be 256, but that would probably // be interpreted as 104, so we have the 9 angles. // // The hour and minute hand are separated by each of these 9 angles only // twice during every 12-hour period, as shown in the following table: // // Angle Times // ----- ------------- // 128 5:04 & 6:56 // 64 3:28 & 8:32 // 32 4:16 & 7:44 // 16 2:08 & 9:52 // 8 1:04 & 10:56 // 4 5:28 & 6:32 // 2 3:16 & 8:44 // 1 4:22 & 7:38 // 0.5 2:11 & 9:49 // // If you're looking at your watch within a two-day period (Saturday and // Sunday are mentioned in the text of the puzzle) then the last time // must be 9:49 PM, which is the solution. // // The code shown below solves the problem as well. All angles are // doubled so they can be represented as integers. //---------------------------------------------------------------------- #include // This function calculates the angle between the hour hand and the // minute hand for a particular time. Actually, as the name of the // function implies, it calculates TWICE that angle. int TwiceAngleDifference(int hour, int min) { int angleMin = 12 * min; int angleHour = 60 * hour + min; int angleDiff = angleHour - angleMin; // Reflect around 0 if (angleDiff < 0) angleDiff = -angleDiff; // NOrmalize to between 0 and 720 while (angleDiff > 720) angleDiff -= 720; // Reflect around 360 if (angleDiff > 360) angleDiff = 720 - angleDiff; return angleDiff; } // This function determines the time when twice the angle between // the hour hand and minute hand equals the third argument. // // Notice that the arguments are pointers. Thus, the values on // entry to the function indicate a start time, and the values // when the function returns indicate the determined time. // // The hour can go up to 48. Values above 12 are PM. Values above // 24 are the second day. // // The function returns 0 if it can't find a time, but I don't use that. int FindTimeAtAngle(int * pHour, int * pMin, int angle) { for ( ; *pHour < 48; (*pHour)++) { for ( ; *pMin < 60; (*pMin)++) { if (angle == TwiceAngleDifference(*pHour, *pMin)) return 1; } *pMin = 0; } return 0; } // Entry point int main(void) { int hour = 0, min = 0, angle = 256; // actually twice the angle while (angle > 0) { // Find the time at the specified angle FindTimeAtAngle(&hour, &min, angle); // Print the angle and the time printf("%3i/2: %2i:%02i %s\n", angle, 1 + (hour + 11) % 12, min, hour % 24 < 12 ? "AM" : "PM"); // Half the angle for the next time through angle /= 2; } return 0; }