You are right that I could increase the constraint to 24 but I would prefer to

stick with the least common multiple of the number of rows and columns as this

is the most obvious immediate constraint. It would improve the speed of the code

very slightly to add the additional constraint of even column sums but this won’t

change to results as this is already guaranteed by the code. This teaser seems

hard manually and using 24 rather than 12 here might help quite a lot in allowing

steps of 24 rather than 12 in checking the overall prime sum values.

I suspect that this does not affect the operation of the program – but perhaps the 12 in line 51 could be replaced by 24?

]]>Assuming you are right that it doesn’t meet the column constraint, the calendar you illustrate IS a solution to this modified teaser but IS NOT a solution to the original teaser. So I simply do not understand why you think the two solution spaces are the same.

This situation is not unusual in teasers and it also happened recently in teaser 3029 where it was easy to find a possible answer but hard to show that the jigsaw layout was actually possible.

]]>Normally, each additional constraint in the Teaser statement reduces the solution space. It is not the case here.

For example in a calendar with equal rows such as:

[3, 5, 7, 47, 101, 107] 270

[67, 37, 71, 41, 11, 43] 270

[73, 13, 79, 17, 29, 59] 270

[83, 19, 53, 23, 61, 31] 270

There is no possible arrangement of the numbers in the rows giving equal column sums. But the Teaser solution is the same as if both row and column sums were equal such as occurs in the outputs of the above programs.

]]>This is true for some row arrangements but not for others. If the programs are changed to allow multiple solutions, this shows that there are row sums for prime sums of 1080 (and higher) that do not allow equal sum columns. And this means that, in arriving at a solution, it is necessary to find an arrangement which provides both equal row and equal columns sums – finding equal row sums doesn’t necessarily provide equal column sums.

]]>Any thoughts?

]]>My efforts at removing elements from lists could be more elegant.

I changed exactly one line in my code after seeing Brian’s – see the comment below.

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 |
#teaser 3037 from itertools import combinations from number_theory import is_prime def findrows(ps24, row_sum, rows= []): if len(ps24) == 6: yield rows + [list(ps24)] else : for rowt in combinations(ps24, 6): if sum(rowt) == row_sum: yield from findrows(ps24 - set(rowt), row_sum, rows + [list(rowt)]) def findcols(adv_cal, col_sum, cols = []): if len(adv_cal[0]) == 0: yield cols else: a = adv_cal[0][0] # initially, the above line was 'for a in adv_cal[0]:' Changing it to the # current code turbocharged performance. This is the one change I made after # seeing Brian's code for b in adv_cal[1]: for c in adv_cal[2]: for d in adv_cal[3]: if (a + b + c + d) == col_sum: yield from findcols([list(set(adv_cal[0]) - {a}), list(set(adv_cal[1]) - {b}), list(set(adv_cal[2]) - {c}), list(set(adv_cal[3]) - {d})], col_sum, cols + [[a, b, c, d]]) def main_body(cho): # generate primes in range 3 -- 107 (not including 107) # exclude 2 as a possible prime because it would give an odd sum ps = [i for i in range(3, 107) if is_prime(i)] if cho: # change order of primes (out of curiosity) in the second run ps = reversed(ps) print ("\nPrimes list order is reversed") else: print("Number of primes",len(ps)+1) for pss in combinations(ps, 23): # pss increases monotonically in value (fortuitously) in the first run # so no coding effort is required to ensure the rule: # "...the sum of all the prime numbers is as small as it can be." sum_ps = sum(pss) + 107 # sum_ps must be divisible by 4 (columns) and 6 (rows); lcm(4,6) = 12 if sum_ps % 12 == 0: for adv_calr in findrows(set(pss + (107,)), sum_ps // 4): for adv_calc in findcols(adv_calr, sum_ps // 6): print("Sum of advent calendar primes",sum_ps) print("\nCalendar by rows (provisional)") for a in(adv_calr): print(a, sum(a)) print ("\nCalendar by columns") for b in (adv_calc): print(b, sum(b)) print("-" * 50) print("Days 20-23:",* sorted(pss)[-4:]) return # run program twice changing primes order on second run for i in range(2): main_body(i) |

1 2 3 |
prms = Primes().tuple(1, max_prime ) |

The current situation gives 107 twice in ps at line 53.

]]>