# Enigmatic Code

Programming Enigma Puzzles

## Puzzle #30: Sticking in a pin

Sachin tells me that the four-digit PIN that he uses for his credit card has an unusual property. When he enters his PIN into a calculator and squares it, the last four digits of the answer are also his PIN. He tells me that exactly one of the digits in his PIN is a zero, but he won’t tell me which position it is in.

What is Sachin’s PIN?

[puzzle#30]

### 8 responses to “Puzzle #30: Sticking in a pin”

1. Jim Randell 16 November 2019 at 8:53 am

We have encountered Automorphic Numbers before. See: Enigma 49, Enigma 1736.

We can solve this puzzle using the [[ SubstitutedExpression() ]] solver from the enigma.py library.

The following run file executes in 155ms.

Run: [ @repl.it ]

#!/usr/bin/env python -m enigma -r

SubstitutedExpression

--distinct=""
--invalid=""

"pow(ABCD, 2, 10000) = ABCD"

"(A, B, C, D).count(0) = 1"

Solution: The PIN is 0625.

Without the final condition we see that there are four candidate 4-digit PINs: 0000, 0001, 0625, 9376, but only one of these has exactly one zero digit.

As noted in Enigma 49, when typed using a phone keypad the word ZERO uses the digits 9376, which would be a sneaky way for the PIN to include ZERO, but it doesn’t fit with the wording for this particular puzzle.

2. arthurvause 16 November 2019 at 10:42 pm

The puzzle is so popular that it also appeared in Sunday Times Teaser 2982, Pin Head

3. GeoffR 17 November 2019 at 9:09 am

I found that I had to represent the PIN as a string and an integer to preserve the leading zero digit when the four permutation integers are converted to a 4-digit integer.

The [[ SubstitutedExpression() ]] solver obviously solves this issue too i.e. of preserving leading zero digits.

from time import perf_counter_ns
start = perf_counter_ns()

from itertools import product

for a, b, c, d in product(range(10),repeat=4):
s = set([a, b, c, d])
if len(s) == 4 and 0 in s:
# form pin number and its square
abcd = str(a) + str(b) + str(c) + str(d)
num = 1000*a + 100*b + 10*c + d
num2 = num ** 2
# compare Pin with last 4 digits of PIN^2
if abcd == str(num2)[-4:]:
print("Sachin\'s Pin =", abcd)
print("Square of Pin =", num2)
print(f"{(perf_counter_ns() - start) / 1e6:.3f} ms")

# Sachin's Pin =  0625
# Square of Pin = 390625
# 9.369 ms

• Jim Randell 17 November 2019 at 9:21 am

Yes. In the [[ SubstitutedExpression() ]] solver the [[ --invalid ]] option controls what values the symbols can take on. The default is to disallow leading zeroes, but by setting it to an empty value any of the symbols can take on any of the values.

• Jim Randell 19 November 2019 at 9:42 am

@geoff: We can find the four 4-digit numbers with the required property fairly easily:

>>> list(n for n in range(10000) if pow(n, 2, 10000) == n)
[0, 1, 625, 9376]

And we can output them using a format specifier of [[ "{n:04d}" ]] if we want to see the leading zeros, so:

for n in range(10000):
if pow(n, 2, 10000) == n:
s = f"{n:04d}"
if s.count('0') == 1:
print(f"PIN = {s}")

I noticed your program enforces the condition that all the digits in the PIN are different, which is not required, and obviously won’t find the potential PINs 0000, 0001.

4. John Crabtree 2 March 2020 at 6:13 am

P^2 – P = 10,000 * n = (16 * x) * (625 * y)
By inspection P = 0000 or 0001, both of which are invalid.
Or 16 * x = 625 * y +/- 1
For 16 * x = 625 * y + 1, y = 15, x = 586 which gives P = 9376
For 16 * x = 625 * y – 1, y = 1, x = 39, which gives P = 0625
…y = 17, x = 664 is the next solution, but n > 10,000 (P = 10625)

This site uses Akismet to reduce spam. Learn how your comment data is processed.