I have deleted your earlier version as you requested. I have also taken the liberty of reformatting lines 76..80 as this suggests to me that there are bugs in line 80.

There is always a balance that has to be struck between the amount of manual analysis and the amount of code used in any teaser solution. I think your preliminary analysis is neat but I can’t help wondering whether on this occasion the effort to exploit this in your code has made an already long program significantly longer than it really needs to be! The use of a subroutine to convert digits sequences into numbers would make sense since you do this several times in your code.

]]>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
''' The repeated digit can not be 3 because the sum of 1..6 + 3 = 24 which means all three numbers would be divisible by three violating the different prime factors < 10 rule. One of the six digits is repeated: 1123456 1223456 1233456 1234456 1234556 1234566 6543211 6543221 6543321 6544321 6554321 6654321 * * * * * * The above shows that the central digit must be 3 or 4. So G = 3 or 4 and the largest and smallest numbers have the same central digit regardless of the repeated digit. All the smallest numbers end in 6 and are divisible by 2. Neither can be divisible by 3 because then all would be divisible by 3 by the sum of digits rule. To be divisible by 5 a number must end in 5 or 0. The largest number always ends in 1 so it is not divisible by 5. The remaining prime less than 10 is 7 so the largest number is divisible by 7. ROYGBIV must therefore be divisible by 5 meaning V = 5 this leaves us to determine R O Y X B I 5 once the smallest and largest numbers have been found, where X is the central digit. ''' from itertools import permutations # determine the number of prime factors less than 10 in "x" # also return a prime factor < 10 (used if pflt10 == 1) def pf(x): ii, pflt10 = 0, 0 for i in (2, 3, 5, 7): if x % i == 0: pflt10 += 1 ii = i # return the number of prime factors < 10 and the last/first one found return pflt10, ii # consider repeated digit for rd in range(1, 7): smallest = [1, 2, 3, 4, 5, 6] smallest.insert(rd - 1, rd) largest = [6, 5, 4, 3, 2, 1] largest.insert(6 - rd, rd) SMALLEST = 0 LARGEST = 0 # convert list of digits into number for i in range(7): SMALLEST = SMALLEST * 10 + smallest[i] LARGEST = LARGEST * 10 + largest[i] # check number of primes factors < 10 SN, SF = pf(SMALLEST) LN, LF = pf(LARGEST) if SN == 1 and LN == 1 and SF != LF: print("smallest", SMALLEST, "factor", SF, "largest", LARGEST, "factor", LF) rdd = rd # repeated digit # Determine ROYGBIV V = 5 # last digit of ROYGBIV # Central digit common to all 3 numbers G = smallest[3] # or largest[3] RO = [] ROYGBIVl = [] # numbers to try for rainbow: all digits + repeated digit but not # 5 or central digit ntt = [1, 2, 3, 4, 6, rdd] ntt.remove(G) # Consider ROY-BI- (V and G are determined above) for R, O, Y, B, I in permutations(ntt): # apply the rule that only the central digit is common if ( R != smallest[0] and R != largest[0] and O != smallest[1] and O != largest[1] and Y != smallest[2] and Y != largest[2] and B != smallest[4] and B != largest[4] and I != smallest[5] and i != largest[2] ): ROYGBIV = (((((((R * 10) + O) * 10 + Y) * 10 + G) * 10 + B) * 10) + I) * 10 + V RN, RF = pf(ROYGBIV) if RN == 1 and RF != SF and RF != LF: # print(R,O,Y,G,B,I,V) ROYGBIVl.append((R, O, Y, G, B, I, V)) RO.append((R, O)) # Print results for i in range(len(RO)): if RO.count(RO[i]) == 1: print("ROYGBIV:", *ROYGBIVl[i]) print("indigo:", ROYGBIVl[i][5]) |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
from collections import defaultdict from itertools import permutations from functools import reduce # convert a sequence of digits into a number dg2n = lambda s: reduce(lambda x, y: 10 * x + y, s) # if a number has one (maybe repeated) prime factor # less than 10, return it; otherwise return None def dspf(n): spf = {p for p in (2, 3, 5, 7) if n % p == 0} return spf.pop() if len(spf) == 1 else None # the duplicated digit for d in range(1, 7): # the seven digits d7 = list(range(1, 7)) + [d] # form the minimum and maximum numbers that these digits # can make and find their prime factors less than ten df, dr = sorted(d7), sorted(d7, reverse=True) minv, maxv = dg2n(df), dg2n(dr) mnpf, mxpf = dspf(minv), dspf(maxv) # these values have different primes but the same central digit if not (mnpf and mxpf) or mnpf == mxpf or df[3] != dr[3]: continue # collect possible 'rainbow' numbers indexed on their first two digits ro2rbl = defaultdict(set) for rbwd in permutations(d7): rbwn = dg2n(rbwd) rbpf = dspf(rbwn) # the central digits of the three numbers must match and they # must have three different prime factors if rbwd[3] == df[3] and rbpf and len({mnpf, rbpf, mxpf}) == 3: # other than at the central position, digits at the same # positions in the three numbers don't match if (sum(x == y for x, y in zip(df, rbwd)) == sum(x == y for x, y in zip(dr, rbwd)) == 1): ro2rbl[rbwn // 100000].add(rbwn) # ... and then index unique rainbow numbers on the value of indigo ind2rb = defaultdict(list) for k, vl in ro2rbl.items(): if len(vl) == 1: v = vl.pop() ind2rb[(v // 10) % 10].append(v) # output the solutions for k, v in ind2rb.items(): t = tuple(sorted(v)) print(f"min/max: ({minv}/{maxv}), rainbows: {t}, indigo: {k}") |