/* BrainTwister #75: Letters and numbers in Picat. BrainTwister #75: Letters and numbers: https://enigmaticcode.wordpress.com/2025/05/29/braintwister-75-letters-and-numbers/ """ From New Scientist #3545, 31st May 2025 Let each letter have a value, where the vowels A, E, I, O and U have value zero and all other letter values are whole numbers greater than zero. The value of a word is the sum of the values of its letters. A word that represents a number is “self-describing” if its value is that number. For example, ONE is self-describing if ONE = 1, for which we must have N = 1. If TWO and THREE are also self-describing, which other letters can we find the values of? If we continue with FOUR, etc., being self-describing and retain all deduced letter values, which is the first number word that cannot be self-describing? What further letter values can we find, following the same rules, skipping over those number words that aren’t self-describing but keeping all earlier letter deductions, up to the word TWENTY? """ The First not self describing number if 9 (NINE). Here is the progression of the numbers 1..20 (ONE..TWENTY): 1 = one x = [a = 0,e = 0,i = 0,n = 1,o = 0,u = 0] 2 = two x = [a = 0,e = 0,i = 0,n = 1,o = 0,t = 1,u = 0,w = 1] 3 = three x = [a = 0,e = 0,h = 1,i = 0,n = 1,o = 0,r = 1,t = 1,u = 0,w = 1] 4 = four x = [a = 0,e = 0,f = 3,h = 1,i = 0,n = 1,o = 0,r = 1,t = 1,u = 0,w = 1] 5 = five x = [a = 0,e = 0,f = 3,h = 1,i = 0,n = 1,o = 0,r = 1,t = 1,u = 0,v = 2,w = 1] 6 = six x = [a = 0,e = 0,f = 3,h = 1,i = 0,n = 1,o = 0,r = 1,t = 1,u = 0,v = 2,w = 1] 7 = seven x = [a = 0,e = 0,f = 3,h = 1,i = 0,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2] 8 = eight x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2] 9 = nine Solution: We can continue up to 8 (EIGHT): 9 (NINE) is the first non self-describing number. And then the following numbers up to 100 (ONEHUNDRED) are also self-describing: 11 = eleven x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2] 12 = twelve x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2] 20 = twenty x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 21 = twentyone x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 22 = twentytwo x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 23 = twentythree x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 24 = twentyfour x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 25 = twentyfive x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 26 = twentysix x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 27 = twentyseven x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 28 = twentyeight x = [a = 0,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 100 = onehundred x = [a = 0,d = 48,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] And, after some testing and tweeking of the interval: 1000000 = onemillion x = [a = 0,d = 48,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,m = 999982,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] 1000100 = onemilliononehundred x = [a = 0,d = 48,e = 0,f = 3,g = 6,h = 1,i = 0,l = 8,m = 999982,n = 1,o = 0,r = 1,s = 4,t = 1,u = 0,v = 2,w = 1,x = 2,y = 16] The "final" assignments are a = 0 d = 48 e = 0 f = 3 g = 6 h = 1 i = 0 l = 8 m = 999982 n = 1 o = 0 r = 1 s = 4 t = 1 u = 0 v = 2 w = 1 x = 2 y = 16 Note that this is done without solve/1, i.e. "pure constraints". This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> garbage_collect(400_000_000), NumNs = 10_000_000, OK = [], NotOK = [], Alpha = (0'a..0'z).map(chr), AlphaMap = new_map([Alpha[I]=I : I in 1..Alpha.len]), X = new_array(Alpha.len), X :: 0..NumNs, foreach({I,V} in zip(1..Alpha.len,Alpha)) if membchk(V,"aeiou") then X[I] #= 0 else X[I] #> 0 end end, foreach(I in 1..NumNs, (I <= 100 ; membchk(I,[1_000_000,1_000_100]))) N = english(I), if self_describing(N,I,X,AlphaMap) then println(I=N), println(x=[Alpha[J]=X[J] : J in 1..26, fd_size(X[J]) == 1] ), OK := OK ++ [I=N] else NotOK := NotOK ++ [I=N] end end, nl, println("First non self-describing number"=NotOK.first), println("Assignments:"), foreach(I in 1..Alpha.len, fd_size(X[I]) == 1) println(Alpha[I]=X[I]) end, nl. go => true. % % Ensure that the string N is a self-describing number, i.e. totals to itself % self_describing(N,I,X,AlphaMap) => sum([X[AlphaMap.get(V)] : V in N ]) #= I. % Convert the integer N to English string % From english.pi (and euler17.pi) english(N) = English => Divs = [1000000000, 1000000, 1000, 100], Divnames = ["billion", "million", "thousand", "hundred"], Prefixes = ["0", "twen", "thir", "for", "fif", "six", "seven", "eigh", "nine"], _Ordinals = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth","fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth"], Cardinals = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"], Sstr = "", Printed = 0, if N < 0 then Sstr := "minus" ++ Sstr, N := -N end, foreach(I in 1..Divs.length) D = N div Divs[I], N := N mod Divs[I], if D != 0 then Sstr := Sstr ++ english(D) ++ Divnames[I], Printed := 1 end end, if N > 0, Printed = 1 then Sstr := Sstr ++ "and" end, if N == 0 then 1 == 1 % dummy elseif N > 19 then D = N div 10, N := N mod 10, Sstr := Sstr ++ Prefixes[D] ++ "ty" ++ english(N) else Sstr := Sstr ++ Cardinals[N] end, English = Sstr.