//------------------------------------------------------------------- // enigma1347.c (c) 2005 by Charles Petzold (www.charlespetzold.com) // // "Fair and Square" from New Scientist, 2 July 2005, page 50. // // For a particular word, the "score" is the sum of numeric values for // each of its letters. // // Begin with A=1, B=2, etc. The problem observes that the score of // SQUARE (which is 81) is square, PRIME (61) is prime, EVEN (46) is // even, and ODD (23) is odd. // // Now shuffle the values of three letters. SQUARE is still square, // etc, but the scores differ in various ways stated in the problem. // (See below in the 'for' loops.) //------------------------------------------------------------------ #include // This function calculates a score for a particular string. If the // last three arguments are 0, it's the "normal" score for A=1, B=2, etc. // Otherwise, the last three arguments indicate the three letters // being shuffled. For example, for a shuffling where B=3, C=7, G=2, // the arguments are 2, 3, 7. // // Because arguments of 3, 7, 2 and 7, 2, 3 produce the same results // as 2, 3, 7, the convention later on is that i1 is always the lowest // number of the three. int Score(char str[], int i1, int i2, int i3) { int i = 0; int scr = 0; char ch; while (0 != (ch = str[i++])) { ch -= 'A'; if (ch == i1) ch = i2; else if (ch == i2) ch = i3; else if (ch == i3) ch = i1; scr += ch + 1; } return scr; } // Returns 1 if argument is prime. int IsPrime(int i) { int j = 2; if (i < 2) return 0; while (j * j <= i) { if (i % j == 0) return 0; j += 1; } return 1; } // Returns 1 if argument is square. int IsSquare(int i) { int j = 1; while (j * j <= i) { if (j * j == i) return 1; j++; } return 0; } // Odd and Even macros. #define IsOdd(i) ((i) & 1) #define IsEven(i) (!IsOdd(i)) int main(void) { // These variables store the "normal" scores. int scrSQUARE = Score("SQUARE", 0, 0, 0); int scrPRIME = Score("PRIME", 0, 0, 0); int scrODD = Score("ODD", 0, 0, 0); int scrEVEN = Score("EVEN", 0, 0, 0); // Shuffled letters are arguments to Score. int i1, i2, i3; // Notice that i1 is always the lowest, and it can't exceed 'X'. // i2 and i3 can go all the way to 'Z'. for (i1 = 0; i1 < 24; i1++) for (i2 = i1; i2 < 26; i2++) for (i3 = i1; i3 < 26; i3++) { // Now calculate new scores. int newscrSQUARE = Score("SQUARE", i1, i2, i3); int newscrPRIME = Score("PRIME", i1, i2, i3); int newscrODD = Score("ODD", i1, i2, i3); int newscrEVEN = Score("EVEN", i1, i2, i3); // Eliminate invalid shufflings. if (i2 == i3) continue; // Problem states new SQUARE score isn't the same as original score. if (!IsSquare(newscrSQUARE) || newscrSQUARE == scrSQUARE) continue; // Problem states new PRIME score is less than original score if (!IsPrime(newscrPRIME) || newscrPRIME >= scrPRIME) continue; if (!IsEven(newscrEVEN) || !IsOdd(newscrODD)) continue; // Problem states at least one of these new scores is different. if (newscrEVEN == scrEVEN && newscrODD == scrODD) continue; // Print the values of the three shuffled letters. printf("%c = %i, %c = %i, %c = %i\n", i1 + 'A', i2 + 1, i2 + 'A', i3 + 1, i3 + 'A', i1 + 1); } return 0; }