The alphametic
MANY + MANY = THANKS
has no solutions in base 10. How many more "MANYs" must I add before it has a solution?
Puzzling Stack Exchange is a question and answer site for those who create, solve, and study puzzles. It only takes a minute to sign up.
Sign up to join this communityThe alphametic
MANY + MANY = THANKS
has no solutions in base 10. How many more "MANYs" must I add before it has a solution?
From
1814400
possible permutations of letters AHKMNSTY
and digits 0-9 (P(10,8)
), just
759
are valid for the problem n * MANY = THANKS
. This is, just those were THANKS/MANY
is an integer.
After removing those solutions where T=0 (THANKS <= 99999)
, there are 727 left from which the minimum n is
17 (3 solution already given in another answer: (8567, 8569, 8576))
BONUS:
The maximum n
is 7815 for MANY=0123
. If M=0 or MANY <= 999
is not valid, the maximum will be n=935
for MANY=1027
csv files with solutions:
M or T = 0
non_zeros.csvM or T = 0
with_zeros.csvI think you need (in base ten):
15 more manys (17 all together)
There are three solutions:
A=5 H=4 K=3 M=8 N=6 S=9 T=1 Y=7 because $8567\times17=145639$,
A=5 H=4 K=7 M=8 N=6 S=3 T=1 Y=9 because $8569\times17=145673$, and
A=5 H=4 K=9 M=8 N=7 S=2 T=1 Y=6 because $8576\times17=145792$.
Or
Zero more:
$7493\times2=014986$
A=4 H=1 K=8 M=7 N=9 S=6 Y=3 T=0
$8746\times2=17492$
A=7 H=1 K=9 M=8 N=4 S=2 Y=6
The question was already answered by @Duck, but here is a (not very well-crafted or efficient) C program which tests increasing numbers of MANY until a solution (in fact three) is found.
Program output:
x * MANY = THANKS
17 * 8567 = 145639
17 * 8569 = 145673
17 * 8576 = 145792
3 results found
Took ~ 0.37 seconds
#include <stdio.h>
#include <time.h>
int used[10];
int result;
int rep = 2;
int M, A, N, Y, T, H, K, S, AN;
void check(int many)
{
for(T=1; T<10; T++) {
if(used[T] == 0) {
used[T] = 1;
int Tval = T * 100000;
for(H=0; H<10; H++) {
if(used[H] == 0) {
used[H] = 1;
int Hval = Tval + H * 10000;
for(K=0; K<10; K++) {
if(used[K] == 0) {
used[K] = 1;
int Kval = Hval + K * 10;
for(S=0; S<10; S++) {
if(used[S] == 0) {
if(Kval + AN + S == many) {
printf("%d * %d%d%d%d = %d%d%d%d%d%d\n", rep,
M,A,N,Y, T,H,A,N,K,S);
result++;
}
}
}
used[K] = 0;
}
}
used[H] = 0;
}
}
used[T] = 0;
}
}
}
int main(void)
{
clock_t tstart = clock();
printf("x * MANY = THANKS\n");
while(result == 0) {
for(M=1; M<10; M++) {
used[M] = 1;
int Mval = M * 1000;
for(A=0; A<10; A++) {
if(used[A] == 0) {
used[A] = 1;
int Aval = Mval + A * 100;
for(N=0; N<10; N++) {
if(used[N] == 0) {
used[N] = 1;
int Nval = Aval + N * 10;
AN = (A * 10 + N) * 100; // for "thanks"
for(Y=0; Y<10; Y++) {
if(used[Y] == 0) {
used[Y] = 1;
check((Nval + Y) * rep);
used[Y] = 0;
}
}
used[N] = 0;
}
}
used[A] = 0;
}
}
used[M] = 0;
}
rep++;
}
printf("%d results found\n", result);
double elapse = (double)(clock() - tstart) / CLOCKS_PER_SEC;
printf("Took ~ %.2f seconds\n", elapse);
return 0;
}
So the answer is
15
I also coded this out, running it in python (you can even use change the words for other similar puzzles, they're global variables, I used "CAT" and "DOG" to test the logic worked for trivial examples.
I would be very interested in a rigorous proof, but given how complex the setup is to express in mathematical logic I suspect there isn't an easy one.
import math as maths
import sys
def build_coding(iter_num):
return_coding = {}
for i,char in enumerate(word[0]):
return_coding[char] = iter_num%10
iter_num -= iter_num%10
iter_num = int(iter_num/10)
return return_coding
def attempt_codings(iteration_number,multi_number):
first_coding = build_coding(iteration_number)
num[0] = word_to_num(first_coding,word[0])#aka get word 0 as a num (num 0)
if len(str(num[0])) != len(word[0]):
return ""
num[1] = num[0]*(multi_number)#word 1, as a num (num 1)
if len(str(num[1])) != len(word[1]):
return ""
second_coding = {}
for i,char in enumerate(str(num[1])):#build second coding by matching letters in word 1 to num 1
second_coding[word[1][i]] = int(char)
for quay in first_coding.keys():
if quay in second_coding.keys():
if first_coding[quay] != second_coding[quay]:#if a key in one exists in either
return ""
end_coding = {}
for quay in first_coding.keys():
if quay in end_coding:#if this key is double-coded
if end_coding[quay] != first_coding[quay]:#and the double doesn't match
return ""
end_coding[quay] = first_coding[quay]
for quay in second_coding.keys():
if quay in end_coding:#if this key is double-coded
if end_coding[quay] != second_coding[quay]:#and the double doesn't match
return ""
end_coding[quay] = second_coding[quay]
uniquevals = []
for quay in end_coding.keys():
if end_coding[quay] in uniquevals:#if we already have a match for this value
return ""
else:
uniquevals.append(end_coding[quay])
return end_coding
def word_to_num(coding,word):
num = 0
for i,char in enumerate(word):
num += maths.pow(10,len(word)-i-1)*coding[char]
return int(num)
word = ["",""]
word[0] = "MANY"
word[1] = "THANKS"
num = ["",""]
for i in range(10000):#ways of coding the first word, including invalid ones like '00010'
for j in range(20):#number of the first word to add (aka multiplication)
coding = attempt_codings(i,j)
if coding != "":
print("~~~A SOLUTION:")
print("CODING IS :: {}".format(coding))
print("{} becomes :: {}".format(word[0],word_to_num(coding,word[0])))
print("{} becomes :: {}".format(word[1],word_to_num(coding,word[1])))
print("{} * {} = {}".format(word_to_num(coding,word[0]),j,word_to_num(coding,word[1])))
sys.exit("Solution found")
```