Every computer program is a solution to some problem - not the only solution and not necessarily the best solution. Before programmers begin writing code, they must understand the problem and know how to solve it - knowing how to solve a problem is not the same as knowing how to write the program. Simple problems are often solved directly with basic programming operations, but solutions for more complex problems require a sequence of operations. Together, these operations form an algorithm or recipe for solving a specific problem. Some well-known problems have well-known algorithmic solutions, but computer scientists must often develop specialized algorithms for smaller, unique problems.
The palindrome-number problem is a puzzle with three parts or subproblems. Two parts are simple, but solving the third requires developing a new algorithm. This section uses the puzzle to demonstrate how to solve a problem and represent the solution.
Problem:
Find the smallest positive integer that, when squared, produces a palindrome of at least six digits in length: abccba or abcdcba (where a is not 0).
Solution Outline:
A palindrome-number problem decomposition:
Generate a consistent list of candidate numbers that might solve the problem. To avoid skipping a potential solution, count sequentially. End the search when a candidate satisfies all the requirements.
Set the first candidate number to 1. (It is more efficient to start the candidate at ⌊√ 100000 ⌋1 = (int)sqrt(100000), but starting it at 1 helps motivate a programming organization described below.)
Increment the candidate number: number = number + 1
Square the number.
Convert the squared number into a string. Although the solution begins with a numeric value, it converts it to a string. The tests (IV.i, IV.ii, and IV.iii) are easier to implement with string functions than by isolating individual digits.
Test the squared number s, ensuring it satisfies the puzzle's three requirements. Sequencing the tests from the easiest/fastest to the hardest/slowest demonstrates a programming technique called case analysis. Beginning the candidate search at 1 highlights the value of this organization:
The squared number is at least six digits long.
The squared number does not begin or end with a '0'. Numbers converted to strings rarely have leading zeros, rendering part of the test superfluous. The examples include the test for a leading zero to enhance the string demonstrations.
The digits of the squared number form a palindrome - identifying a palindrome requires a new algorithm.
Palindrome-number problem statement and solution outline.
The Roman numerals synchronize the logic diagram elements with the solution outline. Programs can implement most of the solution outline steps with a few statements. The test highlighted in blue is the exception that requires a more intricate algorithm.
Identifying A Palindrome: Developing An Algorithm
A palindrome is "a word, verse, or sentence ... or a number ... that reads the same backward or forward." Consequently, digits and characters are significant when determining if a string is a palindrome, but not spaces, punctuation, or character case (upper or lower). Although the potential palindromes arising in the palindrome-number problem contain only digits, imposing three preconditions on potential palindromes allows developers to design a general palindrome-checking algorithm. A precondition means that a client program must suitably prepare the palindrome candidate before invoking the algorithm:
All letters must be the same case (it doesn't matter if they are upper or lower case)
The string must not contain punctuation characters
The string must not contain spaces
Jonassen2 asserts that "Problem solving requires the mental representation of the situation in the world. That is, human problem solvers construct a mental representation (or mental model) of the problem, known as the problem space... Problem solving requires manipulation of the problem space, be it an internal mental representation or an external physical representation" (p. 65). How we represent a problem influences the algorithm we design. Two different algorithms, each beginning with a distinct representation, demonstrate this phenomenon. Although each representation leads to a different algorithm, the implementing programs contain remarkably similar code fragments.
Algorithm 1: The Finger Method
The first representation imagines the potential palindrome written on paper. This representation limits how we can "manipulate the problem space." Moving the individual characters by erasing and rewriting them eventually damages the paper. If the string is long, copying a manipulated version is cumbersome and error-prone. These observations suggest a static representation - static in the sense that the string remains unchanged and the algorithm selects pairs of characters for comparison. With the candidate palindrome written on paper, I can imagine pointing at and comparing the characters at each end. I would keep moving my fingers together as long as the characters matched. The candidate is a palindrome if I reach the middle without any mismatches. If the candidate has an odd number of characters, the middle character is irrelevant and skipped. Seeing a picture helps clarify this process.
Identifying a palindrome with the finger algorithm.
While each pair of characters matches, the algorithm continues move the fingers together.
The first pair of characters match, but we cannot yet conclude that the candidate is a palindrome, as the next pair may not match.
Moving our fingers closer together, we find another matching pair, but still can't classify the candidate as a palindrome.
Moving our fingers together again yields another match. If the candidate has an even number of characters, the algorithm ends with our fingers adjacent; if the candidate has an odd number of characters, the algorithm ignores the middle character because it doesn't affect the results. Finding no mismatched characters, the algorithm concludes the candidate is a palindrome.
The algorithm must also identify when a candidate is not a palindrome.
Identifying a non-palindrome with the finger algorithm.
While each pair matches, the algorithm continues moving the fingers together.
With the first mismatched pair of characters, the algorithm concludes that the candidate is not a palindrome, and the algorithm ends. Although the algorithm could continue to the middle, it's more efficient to end the test at the first mismatched pair, saving computational time. Furthermore, if it continued comparing characters, the next pair might match, potentially creating a false positive.
Algorithm 2: The Reverse Method
For the next example, we change our representation of the problem and how we manipulate it by imagining that a program stores the candidate palindrome in computer memory as a string. This representation allows a more dynamic solution by avoiding the limitations imposed by physically maintaining the candidate as written text on paper. The definition of a palindrome is a string "that reads the same backward or forward." The second algorithm, based on the definition, copies the candidate stored in a string, reverses the copy, and compares the two strings. If the two strings are the same (i.e., equal), the candidate string is a palindrome; if the two strings are not the same, the candidate is not a palindrome.
Identifying a palindrome with the reverse algorithm.
The initial candidate string s
Copy s to a second string r
Reverse r
Compare strings s and r; if they are equal, the original string is a palindrome
Again, it is essential that the algorithm correctly identifies a non-palindrome.
Identifying a non-palindrome with the reverse algorithm.
The operations are the same as in the previous example, but the input differs, resulting in a different outcome.
The initial candidate string s
Copy s to a second string r
Reverse r
Compare strings s and r. In this example, the strings are not the same, implying the original string is not a palindrome
The L-shaped symbols are the floor function, which returns the largest integer not greater than the argument - it truncates its argument, so it has the same effect as casting a value to an integer.
Jonassen, D. H. (2000). Toward a design theory of problem solving. Educational Technology, Research and Development, 48(4), 63-85.