Let Computer Conquer ABCDE * 4 = EDCBA, Step by Step
Your kids need something more fun than video games
Hal understood the problem ABCDE * 4 = EDCBA very well. So he brought up TextEdit, probably would try something there.
“Let’s play with it in Xcode, inside a test file. And we have fix-width font by default at least. Maybe we’ll try some program solution too.”, I suggested.
“Sure”, Hal got used to unit test already.
He created a file MathTests.swift with a single function.
func testMath() {}
Then I put the problem there and said: “OK, go ahead to give it a try manually.”
func testMath() {
/* ABCDE * 4 = EDCBA */
}
“Do you get any idea?” I asked a few minutes later.
“Eh…”
“No worry. Let’s see if computer can help us. Please type …” I said. He followed my instruction and key in
let x = 256
Then I continued: “Try to print out the ones place digit 6.” Followed was a long silence. “Need some hint? Remember we used an operator % before?” I had to give him a hand.
“Oh yeah, to get the remainder”, he seemed to be enlightened.
let x = 256
let onesPlace = x % 10
print(onesPlace)
He ran it and got 6.
“Now take the 5 out”, I moved on to the next step.
let x = 256
let onesPlace = x % 10
let tensPlace = x % 100 - onesPlace
print(onesPlace)
print(tensPlace)output:
6
50
“It works”, he said without thinking too much.
“What? You think it works?! We need the single digit 5 in tens place”, my voice went louder.
“Oh Oh, I got it”, he said, and murmur to himself: “How to get rid of the 0? I need to get rid of the 0 …”
let x = 256
let onesPlace = x % 10
let tensPlace = (x % 100 - onesPlace) / 5
print(onesPlace)
print(tensPlace)output:
6
10
I knew he must be sleepy or tired.
“Ah, my bad”, he realized that his mind was somehow distracted, and corrected immediately with
let x = 256
let onesPlace = x % 10
let tensPlace = (x % 100 - onesPlace) / 10
print(onesPlace)
print(tensPlace)output:
6
5
“Are you sleepy?”, I asked.
“Kind of. I had a 2-hour basketball class this evening.” he answered.
“Understandable, understandable. Please hold on for a while.” I believed that he could get somewhere before his mind stopped working.
“What about printing the 2 digits in one row, instead of two, separated by a comma? We’ll have multiple digits to add.” I said.
Hal used a print with format
print("\(onesPlace), \(tensPlace))output:
6, 5
“Do you think we really need the minus onesPlace part? What if we remove it?” I said.
“Oh yes the decimal part may be dropped automatically”, he said but was not quite sure.
“Delete it and give it a try”, I said. He could always try and check when in doubt.
He modified that line to
let tensPlace = x % 100 / 10
and made sure it worked as before.
“Pretty good Hal. Even though there is no need for a pair of parentheses here it’s still a good idea to make our intention clear”, I introduced some good practice here. So that line became
let tensPlace = (x % 100) / 10
Time for the hundreds place. Easy. Hal wrote
let hundredsPlace = x % 100
and got 2 out quickly, without realizing he just dug a hole for himself.
“Now put the 3 digits back to re-build the original number. Note that we need an actual number, not 3 digits printed together.” I guessed Hal could do it on his own.
“Do we make it in the opposite order?” he asked. I was very happy with what he said, and of course what was in his mind.
“Let’s just build the original number and compare with the initial x”, I was confident with what he could do with his digits.
Hal went on with
let y = hundredsPlace * 100 + tensPlace * 10 + onesPlace * 1
print(y)output:
256
“Keep going to try some 5-digit number”, I pushed him towards our original math problem, the final goal.
He added 1 and 0 in front of 256 and deleted 0 immediately. Maybe he disliked 0 because it might introduce some unknown trouble. I stopped him and said: “0 is good. We don’t have 0 yet so better to include it for testing”.
As soon as he arrived at the thousands place he caught the bug of hundredsPlace and fixed it in no time.
let hundredsPlace = (x % 1000) / 100
I pointed out: “we call this new solution generic because it is future proof, while your previous one only works for 3-digit numbers”.
“Yes, I got it”, he said, and continued typing in
let x = 10256
let onesPlace = x % 10
let tensPlace = (x % 100) / 10
let hundredsPlace = (x % 1000) / 100
let thousandsPlace = (x % 10000) / 1000
let tenThousandsPlace = (x % 100000) / 10000print("\(onesPlace), \(tensPlace), \(hundredsPlace), \(thousandsPlace), \(tenThousandsPlace)")let y = tenThousandsPlace * 10000 + thousandsPlace * 1000 + hundredsPlace * 100 + tensPlace * 10 + onesPlace * 1
print(y)output:
10256
“OK, create a constant z to hold the 5-digit number with each digit in reversed order”, we were closer and closer.
let z = onesPlace * 10000 + tensPlace * 1000 + hundredsPlace * 100 + thousandsPlace * 10 + tenThousandsPlace * 1
print(z)
Notice the little thing times one “* 1” in the code above? It’s so cool.
I guessed his mind must be active, or hot at that moment. Sleepy? no way.
“With everything we tried here, can we let the computer help us solve the original math problem now?” I asked.
“I think so. Maybe just let it check each number one by one stupidly”, he said.
“It makes sense to check one by one”, I didn’t think anything else, other than checking one by one.
Then he started to write a for loop. However he hesitated after typing in “for i in 0 ..< 10000” and tried to delete those text. He worried about the performance: “This might be too stupid. It could bog the machine down”.
“Looping 10000 times is nothing. It’ll take a tiny fraction of a second to finish.” I said. Then he wrote the following working code in a single shot.
for i in 0 ..< 100000 {
let x = 10000 + i
let onesPlace = x % 10
let tensPlace = (x % 100) / 10
let hundredsPlace = (x % 1000) / 100
let thousandsPlace = (x % 10000) / 1000
let tenThousandsPlace = (x % 100000) / 10000
let y = tenThousandsPlace * 10000 + thousandsPlace * 1000 + hundredsPlace * 100 + tensPlace * 10 + onesPlace * 1
let z = onesPlace * 10000 + tensPlace * 1000 + hundredsPlace * 100 + thousandsPlace * 10 + tenThousandsPlace * 1
if y * 4 == z {
print("\(y), \(z)")
}
}
This is the output:
21978, 87912
0, 0
Hal launched the calculator on mac and double checked the answer.
“That’s great! It works! Don’t forget that some part of the code can still be improved, e.g. x and i can be merged, and it’s a waste to try all the way up to 99999, etc.” I said before we got disconnected.