# Send More Money

## Recommended Posts

Somebody set me a puzzle. I was to work out the values of each letter in this equation: "Send + More = Money".

I sat down with a pen and paper and worked it out, but then I wanted to write a script that could work it out through brute force and or guessing.

This is what I came up with:

```#cs
SEND
+MORE
MONEY
#ce
Global \$Array[2][10] = [["0", "1", "X", "X", "X", "X", "X", "X", "X", "X"],[0]]
\$Array[1][0] = 0
Global \$T1, \$Send, \$More, \$Money, \$R, \$Last
\$Solved = False
\$C = 1
\$T2 = TimerInit()
Do
\$E = _RandomizeNumbers()
\$Send = _RandomizeNumbers() & \$E & _RandomizeNumbers() & _RandomizeNumbers()
\$More = \$Array[0][1] & \$Array[0][0] & _RandomizeNumbers() & \$E
If \$Send + \$More = StringLeft(\$More, 2) & StringMid(\$Send, 3, 1) & \$E & 2 Then ;Dirty, dirty cheater...
\$Solved = True
ExitLoop
EndIf
\$C += 1
Global \$Array[2][10] = [["0", "1", "X", "X", "X", "X", "X", "X", "X", "X"],[0]]
Until \$Solved = True
\$T2 = TimerDiff(\$T2)
ConsoleWrite(@CRLF & "Time taken: " & Round(\$T2 / 1000, 2) & @CRLF & "Calculations:" & \$C & @CRLF & "Send: " & \$Send & @CRLF & "More: " & \$More & @CRLF & "Money: " & \$Send + \$More & @CRLF)
Exit

Func _RandomizeNumbers() ;Purpose, to generate a unique random number.
\$R = _Random()
If \$Array[0][\$R] = "X" Then
\$Array[0][\$R] = \$R
Else
_RandomizeNumbers()
EndIf
Return \$R
EndFunc   ;==>_RandomizeNumbers

Func _Random()
Return Random(0, 9, 1)
EndFunc   ;==>_Random

#cs Lots of boring, useless code...

\$T1 = Random(1, 9, 1) ;E
\$Send = Random(1, 9, 1) & \$T1 & Random(1, 9, 1) & Random(1, 9, 1)
\$More = 1 & Random(0, 9, 1) & Random(1, 9, 1) & \$T1

\$Y = StringMid(\$Send,4,1) + StringMid(\$More,4,1)
;If \$Send + \$More = StringLeft(\$More,2) & StringMid(\$Send,3,1) & Random(1, 9, 1)& \$T1 & StringMid(\$Send,4,1) + StringMid(\$More,4,1)

;\$C += 1
\$D += 1
If TimerDiff(\$T) < 5000 Then
If TimerDiff(\$T) > 1000 Then
ConsoleWrite("CPS: " & \$D & @CRLF)
;ConsoleWrite("TCE: " & \$C & @CRLF)
\$D = 0
;\$T = TimerInit()
EndIf
EndIf

Func _RandomizeNumbers()
Global \$T1 = Random(1, 9, 1) ;E
Global \$Send = Random(1, 9, 1) & \$T1 & Random(1, 9, 1) & Random(1, 9, 1)
Global \$More = Random(1, 9, 1) & Random(1, 9, 1) & Random(1, 9, 1) & \$T1
Global \$Money = \$Send + \$More
EndFunc   ;==>_RandomizeNumbers

Func _RandomizeNumbers()
If \$Array[1][0] = 9 Then Global \$Array [2][10] =[[0,0], [1,2,0,0,0,0,0]]
\$R = Random(0,9,1)
If not \$Array[0][\$R] = \$R Then
\$Array[0][\$R] = \$R
\$Array[1][0] +=1
Return \$R
Else
_RandomizeNumbers()
EndIf
EndFunc

Func _RandomizeNumbers()
If \$Array[1][0] = 10 Then Global \$Array[2][10]
;_ArrayDisplay(\$Array)
\$R = Random(0, 9, 1)
If Not \$Array[0][\$R] = \$R Then
ToolTip("Array:" & \$R)
\$Array[0][\$R] = \$R
\$Array[1][0] += 1

Return \$R
Else
For \$X = 0 To 9
If \$Array[0][\$X] = "" Then
ToolTip("Array:2" & \$X)
\$Array[0][\$X] = \$X
\$Array[1][0] += 1
Return \$X
EndIf
Next
EndIf
_ArrayDisplay(\$Array)
EndFunc   ;==>_RandomizeNumbers

M = 1
O = 0
N = 6
E = 5
Y = 2

D = 7, R = 8, and S = 9.

Func _RandomizeNumbers()
If \$Array[1][0] = 10 Then Global \$Array[2][10] = [["", "", "", "", "", "", "", "", ""],[0]]
\$R = Random(0, 9, 1)
If Not \$Array[0][\$R] = \$R and \$Array[0][\$R] = "" Then
\$Array[0][\$R] = \$R
\$Array[1][0] += 1
ConsoleWrite("New Random Number: " & \$Array[0][\$R]&@CRLF)
Else
ConsoleWrite("Old Random Number: " & \$R&@CRLF)
For \$X = 0 To 9
If \$Array[0][\$X] = "" Then
\$Array[0][\$X] = \$X
ConsoleWrite("New Random Number: " & \$Array[0][\$R]&@CRLF)
\$Array[1][0] += 1
\$R = \$X
ExitLoop
EndIf
Next
EndIf
;_ArrayDisplay(\$Array)
Return \$R
EndFunc   ;==>_RandomizeNumbers

If StringLen(StringMid(\$Send, 4, 1) + StringMid(\$More, 4, 1)) > 1 Then
\$Y = StringTrimLeft(StringMid(\$Send, 4, 1) + StringMid(\$More, 4, 1), 1)
Else
\$Y = StringMid(\$Send, 4, 1) + StringMid(\$More, 4, 1)
EndIf
#ce```

I'm really unhappy with it, I cheat, and it's not brute force. Can anybody push me in the right direction?

Wikipedia say that I could use mod to help me work it out, but my maths isn't so strong .

http://en.wikipedia.org/wiki/Verbal_arithmetic

Help me Obi Wan Kenobi,

You're my only hope.

Edited by BitByteBit

##### Share on other sites

Hi!

You can bruteforce all combinations for Send and More and than see if the result could match Money. To bruteforce Send and Money you will have to generate all possible numbers for s,e,n,d,m,o,y; which is less than 10^7 combinations. Example

```for \$s=0 to 9
for \$e=0 to 9
for \$n=0 to 9
...
for \$y=0 to 9
\$send=\$s*1000+\$e*100+\$n*10+\$d
same for \$more
\$money=\$send+\$more

and you check if the numbers for m,o,n,e match with those you've always generated and check if \$y is different from all other letters.```

also in the loops you need to make sure that the letters are different.

Good luck!

I ran. I ran until my muscles burned and my veins pumped battery acid. Then I ran some more.

##### Share on other sites

For a nice challenge you can make a script that would work for other challenges like this. I've started making one myself

Edit: And came up with this.

```#include <Array.au3>
\$script = _BuildScript("Send","More","Money")
\$array = _RunScript(\$script)
_ArrayDisplay(\$array)

; #FUNCTION# ====================================================================================================================
; Name...........: _BuildScript
; Description ...: Returns a script to evaluate possible values of the letters in 3 given strings
; Syntax.........: _BuildScript(\$sWord1, \$sWord2, \$sResult[, \$nBase = 10[, \$bUnique = True[, \$canbe0 = False]]])
; Parameters ....: \$sWord1 - The first string to evaluate
;   \$sWord2 - The second string to evaluate
;   \$sResult - The sum of \$sWord1 and \$sWord2
;   \$nBase - [optional] the system to use. (Default is 10, for decimal) !!!!not working yet!!!!
;   \$bUnique - [optional] Flag to indicate if numbers represent an unique number, or if doubles are allowed (Default is True, for unique numbers)
;   \$canbe0 - [optional] Flag to indicate if the first letter of each string can be 0 (Default is False, the fist letter has to be at least 1)
; Return values .: Success - Returns working script
;   Failure - Not so lucky
; Author ........: Tom
; Remarks .......: Proper errorchecking is not on the ToDo list
; Related .......: _RunScript(\$script)
; ===============================================================================================================================
Func _BuildScript(\$sWord1, \$sWord2, \$sResult, \$nBase = 10, \$bUnique = True, \$canbe0 = False)

If \$nBase <> 10 Then
MsgBox(0,"error","base" & \$nBase & " is not yet implemented.")
Return
EndIf

Local \$script, \$tabsstring, \$ScriptEnd
Local \$nWord1, \$nWord2, \$nResult
\$sWord1 = StringLower(\$sWord1)
\$sWord2 = StringLower(\$sWord2)
\$sResult = StringLower(\$sResult)
\$aLetters = _UniqueLetters(\$sWord1&\$sWord2&\$sResult)

;create the embedded For...To...Next loops
\$script = "Local \$Return, \$Word1, \$Word2, \$Result" & @CRLF
For \$i = 1 To \$aLetters[0]
\$tabsstring = ""
For \$i0 = 2 To \$i ;proper indentation because it's nice
\$tabsstring &= @TAB
Next
\$script &= \$tabsstring

;conditional based on the value of \$canbe0
Switch \$aLetters[\$i]
Case \$canbe0
\$script &= "For \$" & \$aLetters[\$i] & " = 0 To " & \$nBase-1 & @CRLF ;first letter is allowed to be 0
Case StringLeft(\$sWord1,1), StringLeft(\$sWord2,1), StringLeft(\$sResult,1)
\$script &= "For \$" & \$aLetters[\$i] & " = 1 To " & \$nBase-1 & @CRLF ;this is a first letter and not allowed to be 0
Case Else
\$script &= "For \$" & \$aLetters[\$i] & " = 0 To " & \$nBase-1 & @CRLF ;this is not a first letter
EndSwitch

;conditional based on the value of \$bUnique
;create a switch statement to "continueloop" if another letter already has this value.
If \$bUnique And (\$i > 1) Then
\$script &= \$tabsstring & @TAB
\$script &= "Switch \$" & \$aLetters[\$i] & @CRLF
\$script &= \$tabsstring & @TAB & @TAB
\$script &= "Case "
For \$i1 = 1 To \$i-1
\$script &= "\$" & \$aLetters[\$i1]
If \$i1 < \$i-1 Then
\$script &= ", "
Else
\$script &= @CRLF
EndIf
Next
\$script &= \$tabsstring & @TAB & @TAB & @TAB
\$script &= "ContinueLoop" & @CRLF
\$script &= \$tabsstring & @TAB
\$script &= "EndSwitch" & @CRLF
EndIf

;this creates a properly tabbed end of the script to be added when the script is complete.
\$ScriptEnd = \$tabsstring & "Next" & @CRLF & \$ScriptEnd
Next

;This is the code that checks if \$Word1 + \$Word2 = \$Result
;Convert Words to Numbers
;faster then Number(\$w&\$o&\$r&\$d)
For \$i = 1 To StringLen(\$sWord1)
\$nWord1 &= "\$" & StringMid(\$sWord1,\$i,1) & "*" & 10^(StringLen(\$sWord1)-(\$i*1))
If \$i < StringLen(\$sWord1) Then \$nWord1 &= "+"
Next
\$script &= \$tabsstring & @TAB
\$script &= "\$Word1 = " & \$nWord1 & @CRLF
For \$i = 1 To StringLen(\$sWord2)
\$nWord2 &= "\$" & StringMid(\$sWord2,\$i,1) & "*" & 10^(StringLen(\$sWord2)-(\$i*1))
If \$i < StringLen(\$sWord2) Then \$nWord2 &= "+"
Next
\$script &= \$tabsstring & @TAB
\$script &= "\$Word2 = " & \$nWord2 & @CRLF
For \$i = 1 To StringLen(\$sResult)
\$nResult &= "\$" & StringMid(\$sResult,\$i,1) & "*" & 10^(StringLen(\$sResult)-(\$i*1))
If \$i < StringLen(\$sResult) Then \$nResult &= "+"
Next
\$script &= \$tabsstring & @TAB
\$script &= "\$Result = " & \$nResult & @CRLF

;Compare Numbers
\$script &= \$tabsstring & @TAB
\$script &= "If \$Word1+\$Word2 = \$Result Then" & @CRLF
\$script &= \$tabsstring & @TAB & @TAB
\$script &= "\$Return &= \$Word1 & '+' & \$Word2 & '=' & \$Result & ','" & @CRLF
\$script &= \$tabsstring & @TAB
\$script &= "Endif" & @CRLF
\$script &= \$ScriptEnd
\$script &= "ConsoleWrite(\$Return)"
Return \$script
EndFunc
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _UniqueLetters
; Description ...: Returns an array of unique letters found in a string
; Syntax.........: _UniqueLetters(\$string)
; Parameters ....: \$string - The string to get the unique letters from
; Return values .: Success - A 1-based array of letters with \$array[0] containging the count
; Author ........: Tom
; Remarks .......: This function is used internally by _BuildScript.
; Related .......: _BuildScript
; ===============================================================================================================================
Func _UniqueLetters(\$string)
Local \$newstring, \$letter
For \$i = 0 To StringLen(\$string)
\$letter = StringMid(\$string,\$i,1)
If StringInStr(\$newstring,\$letter) Then ContinueLoop
\$newstring &= \$letter
Next
Return StringSplit(\$newstring,"")
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: _RunScript
; Description ...: Runs a script created by _BuildScript() and returns the output as an array
; Syntax.........: _RunScript(\$script)
; Parameters ....: \$script - The script to execute
; Return values .: Success - 1-based array with results
;   Failure - Not so lucky
; Author ........: Tom
; Remarks .......: Proper errorchecking is not on the ToDo list
; Related .......: _BuildScript
; ===============================================================================================================================
Func _RunScript(\$script)
Local \$path = @TempDir & "\SolveIt.au3", \$line, \$PID
FileWrite(\$path,\$script)
\$PID = Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & \$path & '"',@ScriptDir,@SW_HIDE,0x02)
While 1
If @error Then ExitLoop
Wend
FileDelete(\$path)
\$line = StringTrimRight(\$line,1)
Return StringSplit(\$line,",")
EndFunc```

It generates a custom function for the given parameters and then executes that through @AutoItExe as \$STDOUT_CHILD.

Not sure if people will approve of this method, but I was bored and this was something new for me.

Edited by Tvern

## Create an account

Register a new account