SEND + MORE = MONEY: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Free Pascal}}: no more unneeded carry calc)
Line 288: Line 288:
<syntaxhighlight lang="pascal">
<syntaxhighlight lang="pascal">
program SymbolToDigit;
program SymbolToDigit;
{$IFDEF FPC}{$MODE DELPHI}{$Optimization ON,All}{$ENDIF}
{$IFDEF Windows}{$APPTYPE CONSOLE}{$ENDIF}
uses
uses
sysutils;// TDatetime
sysutils;// TDatetime
const
const
nmax = 9;
nmax = 9;
maxLen = 5;
maxLen = 7;

maxIDx = 41;
type
type
tFreeDgt = array[0..nmax+1] of Int32;
tFreeDgt = array[0..nmax+1] of Int32;
tSymbWord = String[maxLen];
tSymbWord = String[maxLen];
tDgtWord = record
tDgtWord = record
DW_DgtsIdx: array[1..maxLen] of UInt8;
DW_DgtsIdx: array[1..maxLen] of UInt8;
DW_maxIdx: Uint8;
DW_maxIdx: Uint8;
end;
end;
tDgtFront = record
DW_DgtsIdx: array[1..nmax+1] of UInt8;
DW_maxIdx: Uint8;
end;
tInUse = set of 0..nmax+1;
const
const
{
// cSumWords : array[0..maxIDx] of tSymbWord =('SEND','MORE','MONEY');
maxIDx = 2;
cSumWords : array[0..maxIDx] of tSymbWord =('SEND','MORE','MONEY');
}
{
maxIDx = 4;
cSumWords : array[0..maxIDx] of tSymbWord =('ABRA','CADABRA','ABRA','CADABRA','HOUDINI');
}


//MANYOTHERS=M2A7N6Y4O1T9H5E0R8S3
//MANYOTHERS=M2A7N6Y4O1T9H5E0R8S3
maxIDx = 41;
//{
cSumWords : array[0..maxIDx] of tSymbWord =(
cSumWords : array[0..maxIDx] of tSymbWord =(
'SO','MANY','MORE','MEN','SEEM','TO','SAY','THAT',
'SO','MANY','MORE','MEN','SEEM','TO','SAY','THAT',
Line 313: Line 329:
'MOON','AS','HE','HAS','AT','THE','OTHER','TEN',
'MOON','AS','HE','HAS','AT','THE','OTHER','TEN',
'TESTS');
'TESTS');

//}
var
var
{$ALIGN 32}
{$ALIGN 32}
DigitSample : tFreeDgt;
DigitSample,
DigitSampleSolution : tFreeDgt;
SymbInUse : array[0..10] of char;
SymbInUse : array[0..10] of char;
DgtToSymb : array[0..10] of UInt8;
Words :array[0..maxIDx] of tSymbWord;
Words :array[0..maxIDx] of tSymbWord;
DgtWords : array[0..maxIDx] of tDgtWord;
DgtWords : array[0..maxIDx] of tDgtWord;
DgtFrontWords :tDgtFront;
SymbInUseCount,gblCount : Uint32;
SymbInUseCount,gblCount : Uint32;
fullStop: boolean;
fullStop: boolean;
ch : char;
ch : char;

procedure OneSol(idx:int32;const DS:tFreeDgt);
var
i,symbolIdx : Int32;
begin
For i := maxlen downto 1 do
begin
symbolIdx := DgtWords[idx].DW_DgtsIdx[i];
if symbolIdx = 0 then
write(' ')
else
write(DS[symbolIdx]);
end;
writeln(cSumWords[idx]:maxLen+2);
end;


procedure RevString(var s:tSymbWord);
procedure RevString(var s:tSymbWord);
Line 342: Line 374:
//CHR(ORD('A')-1) = '@' is placeholder for no Symbol
//CHR(ORD('A')-1) = '@' is placeholder for no Symbol
SymbToIdx : array['@'..'Z'] of byte;
SymbToIdx : array['@'..'Z'] of byte;
FrontSymbols :tInUse;
i,j : Int32;
i,j : Int32;
Begin
Begin
Line 354: Line 387:
//position of highest symbol
//position of highest symbol
DgtWords[i].DW_maxIdx := j;
DgtWords[i].DW_maxIdx := j;
while j < maxLen do
// extend by '@' aka zero
begin
inc(j);
Words[i] := Low(SymbToIdx)+Words[i];
end;
RevString(Words[i]);
RevString(Words[i]);
setlength(Words[i],maxlen);
For j := j+1 to maxLen do
Words[i][j] := Low(SymbToIdx);
end;
end;
// find all symbols


for j := 1 to High(tSymbWord) do
for j := 1 to High(tSymbWord) do
Begin
Begin
For i := 0 to maxIDx do
For i := 0 to maxIdx do
begin
begin
ch := Words[i][j];
ch := Words[i][j];
Line 376: Line 407:
end;
end;
end;
end;
dec(SymbInUseCount);

For i := 0 to maxIDx do
begin
for j := 1 to maxlen do
DgtWords[i].DW_DgtsIdx[j]:= SymbToIdx[Words[i][j]];
end;
For i := 1 to SymbInUseCount do
For i := 1 to SymbInUseCount do
write(SymbInUse[i]);
write(SymbInUse[i]);
writeln(SymbInUseCount-1:4,' symbols');
writeln(SymbInUseCount:4,' symbols');
end;


//get index for every symbol in word
procedure OneSol(idx:int32);
For i := 0 to maxIdx do
var
with DgtWords[i] do
i,symbolIdx : Int32;
for j := 1 to High(tSymbWord) do
begin
DW_DgtsIdx[j]:= SymbToIdx[Words[i][j]];
For i := maxlen downto 1 do
begin
//find all first symbols
symbolIdx := DgtWords[idx].DW_DgtsIdx[i];
FrontSymbols := [];
if symbolIdx = 0 then
write(' ')
For i := 0 to maxIDx do
with DgtWords[i] do
else
write(DigitSample[symbolIdx]);
include(FrontSymbols,DW_DgtsIdx[DW_maxIdx]);

end;
j := 1;
writeln(cSumWords[idx]:maxLen+2);
For i := 0 to nmax+1 do
if i in FrontSymbols then
Begin
DgtFrontWords.DW_DgtsIdx[j] := i;
inc(j);
end;
DgtFrontWords.DW_maxIdx := j-1;
end;
end;


Line 405: Line 437:
var
var
col,row,
col,row,
sum,carrySum,carry : NativeUInt;
sum,carry : NativeUInt;
begin
begin
// No zero as first symbol
// check for zero in first symbols of words
with DgtFrontWords do
For row := maxIdx downto 0 do
with DgtWords[row] do
For col := DW_maxIdx downto 1 do
begin
if DS[DW_DgtsIdx[DW_maxidx]] = 0 then
if DS[DW_DgtsIdx[col]] = 0 then
EXIT(false);
EXIT(false);
end;

carry := 0;
carry := 0;
carrySum := 0;
For col := 1 to maxLen do
For col := 1 to maxLen do
Begin
Begin
sum := carrysum MOD 10;
sum := carry;
carrysum := carrysum DIV 10;
carry := 0;
carry :=0;
// add one column
For row := maxIdx-1 downto 0 do
For row := maxIdx-1 downto 0 do
Begin
sum := sum+DS[DgtWords[row].DW_DgtsIdx[col]];
sum := sum+DS[DgtWords[row].DW_DgtsIdx[col]];
if sum > 9 then
begin
if sum > 9 then
begin
carry := sum DIV 10;
sum := sum - 10 * carry;
carry := sum DIV 10;
inc(CarrySum,Carry);
sum := sum - 10 * carry;
end;
end;
end;
//digit of sum
//digit of sum
if sum <> DS[DgtWords[maxIDx].DW_DgtsIdx[col]] then
if sum <> DS[DgtWords[maxIDx].DW_DgtsIdx[col]] then
EXIT(false);
EXIT(false);
end;
end;
if carrysum <>0 then
If Carry = 0 then
DigitSampleSolution := DS;
EXIT(false);
For row := 0 to High(DgtWords)do
OneSol(row);
EXIT(true);
EXIT(true);
end;
end;
Line 445: Line 474:
i,Col : nativeInt;
i,Col : nativeInt;
begin
begin
if fullStop then
if fullStop then EXIT;
EXIT;
IF row <= 10 then
IF row <= 10 then
begin
begin
Line 468: Line 496:
end
end
end;
end;

var
var
T1,T0: TDateTime;
T1,T0: TDateTime;
i : Uint32;
i,j : Uint32;


begin
begin
Line 483: Line 512:
NextPermute(1,DigitSample);
NextPermute(1,DigitSample);
t1:= time;
t1:= time;
IF maxIDx < 10 then
For i := 0 to High(DgtWords)do
OneSol(i,DigitSampleSolution);
writeln;
For i := 1 to SymbInUseCount do
begin
j := DigitSampleSolution[i];
write(SymbInUse[i],'=',j,' ');
end;
writeln;
writeln;
WriteLn(gblCount,' checks ',FormatDateTime(' NN:SS.ZZZ',T1-t0),' secs');
WriteLn(gblCount,' checks ',FormatDateTime(' NN:SS.ZZZ',T1-t0),' secs');
end.</syntaxhighlight>
end.
</syntaxhighlight>
{{out|@TIO.RUN}}
{{out|@TIO.RUN}}
<pre>
<pre>
8 symbols
DEYNROSM 8 symbols
9567 SEND
9567 SEND
1085 MORE
1085 MORE
10652 MONEY
10652 MONEY


D=7 E=5 Y=2 N=6 R=8 O=0 S=9 M=1
2704147 checks 00:00.090 secs
2704147 checks 00:00.043 secs
OYENMTSRAH
//shorthened 'SO','MANY','MORE','MEN','SEEM','TO','SAY',
10 symbols
OYENMTSRAH 10 symbols
31 SO
2764 MANY
2180 MORE
206 MEN
3002 SEEM
91 TO
374 SAY
9579 THAT
9504 THEY
274 MAY
3116 SOON
984 TRY
91 TO
3974 STAY
79 AT
5120 HOME
31 SO
73 AS
91 TO
300 SEE
18 OR
5078 HEAR
950 THE
3720 SAME
160 ONE
276 MAN
984 TRY
91 TO
2009 MEET
950 THE
9072 TEAM
16 ON
950 THE
2116 MOON
73 AS
50 HE
573 HAS
79 AT
950 THE
19508 OTHER
906 TEN
90393 TESTS


O=1 Y=4 E=0 N=6 M=2 T=9 S=3 R=8 A=7 H=5
496179 checks 00:00.061 secs
496179 checks 00:00.013 secs</pre>
</pre>


=={{header|Phix}}==
=={{header|Phix}}==

Revision as of 14:22, 13 February 2023

SEND + MORE = MONEY is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Write a program in your language to solve SEND + MORE = MONEY: A Great Puzzle.

ALGOL 68

Translation of: Julia

This task can be solved without using seven nested loops but then again, it can be solved with them - so why not?.
Uses the observations of the Julia sample (unsuprisingly as this is a translation of the Julia sample).

BEGIN # solve the SEND+MORE=MONEY puzzle - translation of the Julia sample #
  INT m = 1;
  OP C = ( INT n )CHAR: REPR ( ABS "0" + n ); # convert integer to a digit #
  FOR s FROM 8 TO 9 DO
    FOR e FROM 0 TO 9 DO
      IF e /= m AND e/= s THEN
        FOR n FROM 0 TO 9 DO
          IF n /= m AND n /= s AND n /= e THEN
            FOR d FROM 0 TO 9 DO
              IF d /= m AND d /= s AND d /= e AND d /= n THEN
                FOR o FROM 0 TO 9 DO
                  IF o /= m AND o /= s AND o /= e AND o /= n AND o /= d THEN
                    FOR r FROM 0 TO 9 DO
                      IF r /= m AND r /= s AND r /= e AND r /= n AND r /= d AND r /= o THEN
                        FOR y FROM 0 TO 9 DO
                          IF y /= m AND y /= s AND y /= e AND y /= n AND y /= d AND y /= o AND y /= r THEN
                            IF ( 1000 * ( s + m ) ) + ( 100 * ( e + o ) ) + ( 10 * ( n + r ) ) + ( d + e )
                             = ( 10 000 * m ) + ( 1000 * o ) + ( 100 * n ) + ( 10 * e ) + y
                            THEN
                              print( ( C s, C e, C n, C d, " + ", C m, C o, C r, C e, " = ", C m, C o, C n, C e, C y
                                     )
                                   )
                            FI
                          FI
                        OD
                      FI
                    OD
                  FI
                OD
              FI
            OD
          FI
        OD
      FI
    OD
  OD
END
Output:
9567 + 1085 = 10652

BASIC

Rosetta Code problem: https://rosettacode.org/wiki/SEND_%2B_MORE_%3D_MONEY

by Jjuanhdez, 02/2023

BASIC256

Translation of: FreeBASIC
Works with: Run BASIC
Works with: Just BASIC
Works with: Liberty BASIC
m = 1
for s = 8 to 9
  for e = 0 to 9
    if e <> m and e <> s then
      for n = 0 to 9
        if n <> m and n <> s and n <> e then
          for d = 0 to 9
            if d <> m and d <> s and d <> e and d <> n then
              for o = 0 to 9
                if o <> m and o <> s and o <> e and o <> n and o <> d then
                  for r = 0 to 9
                    if r <> m and r <> s and r <> e and r <> n and r <> d and r <> o then
                      for y = 0 to 9
                        if y <> m and y <> s and y <> e and y <> n and y <> d and y <> o then
                          if ((1000*(s+m)) + (100*(e+o)) + (10*(n+r)) + (d+e)) = ((10000* m) + (1000*o) + (100*n) + (10*e) + y) then
                            print s;e;n;d; " + "; m;o;r;e; " = "; m;o;n;e;y
                          end if
                        end if
                      next y
                    end if
                  next r
                end if
              next o
            end if
          next d
        end if
      next n
    end if
  next e
next s
Output:
Same as FreeBASIC entry.

Yabasic

Translation of: FreeBASIC
m = 1
for s = 8 to 9
  for e = 0 to 9
    if e <> m and e <> s then
      for n = 0 to 9
        if n <> m and n <> s and n <> e then
          for d = 0 to 9
            if d <> m and d <> s and d <> e and d <> n then
              for o = 0 to 9
                if o <> m and o <> s and o <> e and o <> n and o <> d then
                  for r = 0 to 9
                    if r <> m and r <> s and r <> e and r <> n and r <> d and r <> o then
                      for y = 0 to 9
                        if y <> m and y <> s and y <> e and y <> n and y <> d and y <> o then
                          if ((1000*(s+m)) + (100*(e+o)) + (10*(n+r)) + (d+e)) = ((10000* m) + (1000*o) + (100*n) + (10*e) + y)  ? str$(s), str$(e), str$(n), str$(d), " + ", str$(m), str$(o), str$(r), str$(e), " = ", str$(m), str$(o), str$(n), str$(e), str$(y)
                        fi
                      next y
                    fi
                  next r
                fi
              next o
            fi
          next d
        fi
      next n
    fi
  next e
next s
end
Output:
Same as FreeBASIC entry.

FreeBASIC

Translation of: Julia
Dim As Byte m = 1, s, e, n, d, o, r, y
For s = 8 To 9
    For e = 0 To 9
        If e <> m And e <> s Then
            For n = 0 To 9
                If n <> m And n <> s And n <> e Then
                    For d = 0 To 9
                        If d <> m And d <> s And d <> e And d <> n Then
                            For o = 0 To 9
                                If o <> m And o <> s And o <> e And o <> n And o <> d Then
                                    For r = 0 To 9
                                        If r <> m And r <> s And r <> e And r <> n And r <> d And r <> o Then
                                            For y = 0 To 9
                                                If y <> m And y <> s And y <> e And y <> n And y <> d And y <> o Then
                                                    If ((1000*(s+m)) + (100*(e+o)) + (10*(n+r)) + (d+e)) = _
                                                       ((10000* m) + (1000*o) + (100*n) + (10*e) + y) Then
                                                        Print s & e & n & d & " + " & _
                                                        m & o & r & e & " = " &  m & o & n & e & y
                                                    End If
                                                End If
                                            Next y
                                        End If
                                    Next r
                                End If
                            Next o
                        End If
                    Next d
                End If
            Next n
        End If
    Next e
Next s

Sleep
Output:
9567 + 1085 = 10652

Go

Translation of: Wren
package main

import (
    "fmt"
    "time"
)

func contains(a []int, v int) bool {
    for i := 0; i < len(a); i++ {
        if a[i] == v {
            return true
        }
    }
    return false
}

func main() {
    start := time.Now()
    var sends [][4]int
    var ors [][2]int
    m := 1
    digits := []int{0, 2, 3, 4, 5, 6, 7, 8, 9}
    for s := 8; s <= 9; s++ {
        for _, e := range digits {
            if e == s {
                continue
            }
            for _, n := range digits {
                if n == s || n == e {
                    continue
                }
                for _, d := range digits {
                    if d == s || d == e || d == n {
                        continue
                    }
                    sends = append(sends, [4]int{s, e, n, d})
                }
            }
        }
    }
    for _, o := range digits {
        for _, r := range digits {
            if r != o {
                ors = append(ors, [2]int{o, r})
            }
        }
    }
    fmt.Println("Solution(s):")
    for _, send := range sends {
        SEND := 1000*send[0] + 100*send[1] + 10*send[2] + send[3]
        for _, or := range ors {
            send2 := send[:]
            or2 := or[:]
            if contains(send2, or[0]) || contains(send2, or[1]) {
                continue
            }
            MORE := 1000*m + 100*or[0] + 10*or[1] + send[1]
            for _, y := range digits {
                if contains(send2, y) || contains(or2, y) {
                    continue
                }
                MONEY := 10000*m + 1000*or[0] + 100*send[2] + 10*send[1] + y
                if SEND+MORE == MONEY {
                    fmt.Printf("%d + %d = %d\n", SEND, MORE, MONEY)
                }
            }
        }
    }
    fmt.Printf("\nTook %s.\n", time.Since(start))
}
Output:
Solution(s):
9567 + 1085 = 10652

Took 1.149804ms.

Julia

A hoary old task, solved with pencil before electricity was a thing.

Since the M in Money is the result of carry in base 10 of two single digits it is a 1 (we exclude 0 here though that would work, but then MONEY would be spelled ONEY).

In addition, the S plus 1 then needs to result in a carry, so S is 8 or 9, depending on whether there is a carry into that column. Pencil and paper can continue, but from here the computer is likely quicker.

let
    m = 1
    for s in 8:9
        for e in 0:9
            e in [m, s] && continue
            for n in 0:9
                n in [m, s, e] && continue
                for d in 0:9
                    d in [m, s, e, n] && continue
                    for o in 0:9
                        o in [m, s, e, n, d] && continue
                        for r in 0:9
                            r in [m, s, e, n, d, o] && continue
                            for y in 0:9
                                y in [m, s, e, n, d, o] && continue
                                if 1000s + 100e + 10n + d + 1000m + 100o + 10r + e ==
                                   10000m + 1000o + 100n + 10e + y
                                    println("$s$e$n$d + $m$o$r$e == $m$o$n$e$y")
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
Output:

9567 + 1085 == 10652

Pascal

Free Pascal

simple brute force. Permutation stolen by nQueens.

program SymbolToDigit;
{$IFDEF FPC}{$MODE DELPHI}{$Optimization ON,All}{$ENDIF}
{$IFDEF Windows}{$APPTYPE CONSOLE}{$ENDIF}
uses
  sysutils;// TDatetime
const
  nmax = 9;
  maxLen = 7;

type
 tFreeDgt = array[0..nmax+1] of Int32;
 tSymbWord = String[maxLen];
  
 tDgtWord =  record
               DW_DgtsIdx: array[1..maxLen] of UInt8;
               DW_maxIdx: Uint8;
             end;
             
 tDgtFront  =  record
                 DW_DgtsIdx: array[1..nmax+1] of UInt8;
                 DW_maxIdx: Uint8;
               end;             
  tInUse = set of 0..nmax+1;           
const
{
  maxIDx = 2;
  cSumWords : array[0..maxIDx] of tSymbWord =('SEND','MORE','MONEY');
}  
{
  maxIDx = 4;  
  cSumWords : array[0..maxIDx]  of tSymbWord =('ABRA','CADABRA','ABRA','CADABRA','HOUDINI');
}

//MANYOTHERS=M2A7N6Y4O1T9H5E0R8S3
  maxIDx = 41;
  cSumWords : array[0..maxIDx] of tSymbWord =(
    'SO','MANY','MORE','MEN','SEEM','TO','SAY','THAT',
    'THEY','MAY','SOON','TRY','TO','STAY','AT','HOME',
    'SO','AS','TO','SEE','OR','HEAR','THE','SAME','ONE',
    'MAN','TRY','TO','MEET','THE','TEAM','ON','THE',
    'MOON','AS','HE','HAS','AT','THE','OTHER','TEN',
    'TESTS');

var
{$ALIGN 32}
  DigitSample,
  DigitSampleSolution : tFreeDgt;
  SymbInUse : array[0..10] of char;
  Words :array[0..maxIDx] of tSymbWord;
  DgtWords : array[0..maxIDx] of tDgtWord;
  DgtFrontWords :tDgtFront;
  SymbInUseCount,gblCount : Uint32;
  fullStop: boolean;
  ch : char;

procedure OneSol(idx:int32;const DS:tFreeDgt);
var
  i,symbolIdx : Int32;
begin
  For i := maxlen downto 1 do
  begin
    symbolIdx :=  DgtWords[idx].DW_DgtsIdx[i];
    if symbolIdx = 0 then
      write(' ')
    else
      write(DS[symbolIdx]);
  end;
  writeln(cSumWords[idx]:maxLen+2);
end;

procedure RevString(var s:tSymbWord);
var
  i,j: NativeInt;
begin
  i := 1;
  j := Length(s);
  while j>i do
  begin
    ch:= s[i];s[i]:= s[j];s[j] := ch;
    inc(i);dec(j);
  end;
end;

procedure GetSymbols;
var
  //CHR(ORD('A')-1) = '@' is placeholder for no Symbol
  SymbToIdx : array['@'..'Z'] of byte;
  FrontSymbols :tInUse;
  i,j : Int32;
Begin
  fillchar(SymbToIdx,SizeOf(SymbToIdx),#255);
  SymbToIdx['@'] := 0;
  SymbInUseCount := 1;//['@'] is always zero

  For i := 0 to maxIDx do
  begin
    Words[i] := cSumWords[i];
    j := length(Words[i]);
    //position of highest symbol
    DgtWords[i].DW_maxIdx := j;
    // extend by '@' aka zero
    RevString(Words[i]);
    setlength(Words[i],maxlen);
    For j := j+1 to maxLen do
      Words[i][j] := Low(SymbToIdx);
  end;
  // find all symbols
  for j := 1 to High(tSymbWord) do
  Begin
    For i := 0 to maxIdx do
    begin
      ch := Words[i][j];
      if SymbToIdx[ch] = 255 then
      begin
        SymbToIdx[ch] := SymbInUseCount;
        SymbInUse[SymbInUseCount] := ch;
        inc(SymbInUseCount);
      end;
    end;
  end;
  dec(SymbInUseCount);
  For i := 1 to SymbInUseCount do
    write(SymbInUse[i]);
  writeln(SymbInUseCount:4,' symbols');

  //get index for every symbol in word
  For i := 0 to maxIdx do
    with DgtWords[i] do
      for j := 1 to High(tSymbWord) do
        DW_DgtsIdx[j]:= SymbToIdx[Words[i][j]];
        
  //find all first symbols
  FrontSymbols := [];
  For i := 0 to maxIDx do
    with DgtWords[i] do
      include(FrontSymbols,DW_DgtsIdx[DW_maxIdx]);

  j := 1;  
  For i := 0 to nmax+1 do
    if i in FrontSymbols then
    Begin
      DgtFrontWords.DW_DgtsIdx[j] := i;
      inc(j);
    end;   
  DgtFrontWords.DW_maxIdx := j-1;
end;

function AddWords(const DS:tFreeDgt):boolean;
var
  col,row,
  sum,carry : NativeUInt;
begin
  // check for zero in first symbols of words
  with DgtFrontWords do
    For col := DW_maxIdx downto 1 do
    begin
      if DS[DW_DgtsIdx[col]] = 0 then 
        EXIT(false);
    end;
    
  carry := 0;
  For col := 1 to maxLen do
  Begin
    sum := carry;
    carry := 0;
    // add one column
    For row := maxIdx-1 downto 0 do
      sum := sum+DS[DgtWords[row].DW_DgtsIdx[col]];
      
    if sum > 9 then
    begin
      carry := sum DIV 10;
      sum := sum - 10 * carry;
    end;  
    //digit of sum
    if sum <> DS[DgtWords[maxIDx].DW_DgtsIdx[col]] then
      EXIT(false);
  end;
  If Carry = 0 then
    DigitSampleSolution := DS; 
  EXIT(true);
end;

procedure NextPermute(Row:nativeInt;var DS:tFreeDgt);
var
  i,Col : nativeInt;
begin
  if fullStop then   EXIT;
  IF row <= 10 then
  begin
    NextPermute(Row+1,DS);
    For i := row+1 to 10 do
    begin
      //swap
      Col := DS[i];
      DS[i] := DS[Row];
      DS[Row] := Col;
        NextPermute(Row+1,DS);
      //Undo swap
      DS[Row] := DS[i];
      DS[i] := Col;
    end
  end
else
  begin
    fullStop :=  AddWords(DS);
    inc(gblCount);
  end
end;

var
  T1,T0: TDateTime;
  i,j : Uint32;

begin
  DigitSample[0] := 0;
  For i := 0 to nmax do
    DigitSample[i+1] := i;
  GetSymbols;

  t0 := time;
  gblCount := 0;
  fullStop := false;
  NextPermute(1,DigitSample);
  t1:= time;
  IF maxIDx < 10 then
    For i := 0 to High(DgtWords)do 
      OneSol(i,DigitSampleSolution);
  writeln;
  For i := 1 to SymbInUseCount do
  begin  
     j := DigitSampleSolution[i];
     write(SymbInUse[i],'=',j,' ');
  end;   
  writeln;
  WriteLn(gblCount,' checks ',FormatDateTime(' NN:SS.ZZZ',T1-t0),' secs');
end.
@TIO.RUN:
DEYNROSM   8 symbols
   9567     SEND
   1085     MORE
  10652    MONEY

D=7 E=5 Y=2 N=6 R=8 O=0 S=9 M=1 
2704147 checks  00:00.043 secs
//shorthened    'SO','MANY','MORE','MEN','SEEM','TO','SAY',
OYENMTSRAH  10 symbols

O=1 Y=4 E=0 N=6 M=2 T=9 S=3 R=8 A=7 H=5 
496179 checks  00:00.013 secs

Phix

Mighta gota bit carried away here...

with javascript_semantics
sequence answer
procedure solve(sequence sums,solve_order,firsts,correct_to, integer l,avail,done=0)
    done += 1
    integer d = solve_order[done]
    for ad=firsts[done] to 9 do
        integer m = power(2,ad)
        if and_bits(avail,m) then
            answer[d] = ad
            integer ct = correct_to[done]
            if ct then
                integer carry = 0, bOK = true
                for i=1 to ct do
                    carry += sum(extract(answer,sums[i][1]))
                    if remainder(carry,10)!=answer[sums[i][2]] then
                        bOK = false
                        exit
                    end if
                    carry = floor(carry/10)
                end for
                if bOK then
                    if ct=length(sums) then
                        if carry=0 then
                            ?answer
                        end if
                    else
                        solve(sums,solve_order,firsts,correct_to,l,avail-m,done)
                    end if
                end if
            else
                solve(sums,solve_order,firsts,correct_to,l,avail-m,done)
            end if
            answer[d] = -1
        end if
    end for
end procedure

procedure cryptarithm(string s)
    integer eq = find('=',s)
    sequence ans = trim(s[eq+1..$]),
           words = apply(split(s[1..eq-1],'+'),trim),
             res = join(unique(join(words,"")&ans,"STABLE"),"")
    integer l = length(res)
    for i,w in words do
        words[i] = apply(true,find,{w,{res}})
    end for
    ans = apply(true,find,{ans,{res}})
    sequence sums = {},
      solve_order = {}
    for i=1 to length(ans) do
        sequence set = {}
        for w in words do
            if length(w)>=i then
                integer wi = w[-i]
                set &= wi
                if not find(wi,solve_order) then
                    solve_order &= wi
                end if
            end if
        end for
        integer ai = ans[-i]
        if not find(ai,solve_order) then
            solve_order &= ai
        end if
        sums = append(sums,{set,ai})
    end for
    assert(length(solve_order)=l)
    sequence firsts = repeat(0,l),
         correct_to = repeat(0,l)
    for f in unique(join(apply(true,extract,{words,{{1}}}),{})&ans[1]) do
        firsts[find(f,solve_order)] = 1
    end for
    integer mm = 0
    for i,fs in apply(sums,flatten) do
        integer m = max(apply(true,find,{fs,{solve_order}}))
        mm = max(m,mm)
        correct_to[mm] = i
    end for
    assert(correct_to[$]=length(sums))
    answer = repeat(-1,l)
    printf(1,"%s - %s is ",{s,res})
    solve(sums,solve_order,firsts,correct_to,l,0b1_111_111_111)
end procedure

constant tests = {
`SEND+MORE=MONEY`,
`TO+GO=OUT`,
`SEND + A + TAD + MORE = MONEY`,
`ABRA + CADABRA + ABRA + CADABRA = HOUDINI`,
`I + GUESS + THE + TRUTH = HURTS`,
`THATS + THE + THEORY = ANYWAY`,
-- tad slow, 5.8s vs 0.2s for all above:
`SO+MANY+MORE+MEN+SEEM+TO+SAY+THAT+
 THEY+MAY+SOON+TRY+TO+STAY+AT+HOME+
 SO+AS+TO+SEE+OR+HEAR+THE+SAME+ONE+
 MAN+TRY+TO+MEET+THE+TEAM+ON+THE+
 MOON+AS+HE+HAS+AT+THE+OTHER+TEN
 =TESTS`}
papply(tests,cryptarithm)
Output:
SEND+MORE=MONEY - SENDMORY is {9,5,6,7,1,0,8,2}
TO+GO=OUT - TOGU is {2,1,8,0}
SEND + A + TAD + MORE = MONEY - SENDATMORY is {9,2,8,3,7,4,1,0,6,5}
ABRA + CADABRA + ABRA + CADABRA = HOUDINI - ABRCDHOUIN is {7,4,5,1,9,3,6,0,8,2}
I + GUESS + THE + TRUTH = HURTS - IGUESTHR is {5,2,6,8,1,4,7,9}
THATS + THE + THEORY = ANYWAY - THASEORYNW is {8,6,9,7,3,2,4,1,5,0}
SO+MANY+MORE+MEN+SEEM+TO+SAY+THAT+
 THEY+MAY+SOON+TRY+TO+STAY+AT+HOME+
 SO+AS+TO+SEE+OR+HEAR+THE+SAME+ONE+
 MAN+TRY+TO+MEET+THE+TEAM+ON+THE+
 MOON+AS+HE+HAS+AT+THE+OTHER+TEN
 =TESTS - SOMANYRETH is {3,1,2,7,6,4,8,0,9,5}

Translation of Raku

Quite a bit slower than the above

enum S, E, N, D, M, O, R, Y

function check(sequence p)
    if p[M]!=0 and
       sum(sq_mul(extract(p,{S,E,N,D}),{1000,100,10,1}))+
       sum(sq_mul(extract(p,{M,O,R,E}),{1000,100,10,1}))=
     sum(sq_mul(extract(p,{M,O,N,E,Y}),{10000,1000,100,10,1})) then
        printf(1,"   %d%d%d%d\n",extract(p,{S,E,N,D}))
        printf(1," + %d%d%d%d\n",extract(p,{M,O,R,E}))
        printf(1,"= %d%d%d%d%d\n",extract(p,{M,O,N,E,Y}))
        return false
    end if
    return true -- continue
end function

{} = permutes(tagset(9,0),check,8)
Output:
   9567
 + 1085
= 10652

Raku

Idiomatic

enum <D E M N O R S Y>;

sub find_solution ( ) {
    for ('0'..'9').combinations(8) -> @c {
        .return with @c.permutations.first: -> @p {
            @p[M] !== 0 and

            @p[  S,E,N,D].join
          + @p[  M,O,R,E].join
         == @p[M,O,N,E,Y].join
        }
    }
}

my @s = find_solution();
say "    {@s[  S,E,N,D].join}";
say " +  {@s[  M,O,R,E].join}";
say "== { @s[M,O,N,E,Y].join}";
Output:
    9567
 +  1085
== 10652

Fast

Alternately, a version written in 2015 by Carl Mäsak. Not very concise but quite speedy. Applying the observation that M must be 1 and S must be either 8 or 9 gets the runtime under a tenth of a second.

my int $s = 7;
while ++$s <= 9 {
    next if $s == 0;

    my int $e = -1;
    while ++$e <= 9 {
        next if $e == $s;

        my int $n = -1;
        while ++$n <= 9 {
            next if $n == $s;
            next if $n == $e;

            my int $d = -1;
            while ++$d <= 9 {
                next if $d == $s;
                next if $d == $e;
                next if $d == $n;

                my int $send = $s*1000 + $e*100 + $n*10 + $d;

                my int $m = 1;

                my int $o = -1;
                while ++$o <= 9 {
                    next if $o == $s;
                    next if $o == $e;
                    next if $o == $n;
                    next if $o == $d;
                    next if $o == $m;

                    my int $r = -1;
                    while ++$r <= 9 {
                        next if $r == $s;
                        next if $r == $e;
                        next if $r == $n;
                        next if $r == $d;
                        next if $r == $m;
                        next if $r == $o;

                        my int $more = $m*1000 + $o*100 + $r*10 + $e;

                        my int $y = -1;
                        while ++$y <= 9 {
                            next if $y == $s;
                            next if $y == $e;
                            next if $y == $n;
                            next if $y == $d;
                            next if $y == $m;
                            next if $y == $o;
                            next if $y == $r;

                            my int $money =
                                $m*10000 + $o*1000 + $n*100 + $e*10 + $y;
                            next unless $send + $more == $money;
                            say 'SEND + MORE == MONEY';
                            say "$send + $more == $money";
                        }
                    }
                }
            }
        }
    }
}
printf "%.3f elapsed seconds", now - INIT now;
Output:
SEND + MORE == MONEY
9567 + 1085 == 10652
0.080 elapsed seconds

Ring

// Bert Mariani  2023-02-09 | A Monte Carlo method to solve the encryted message | SEND + MORE = MONEY

t1 = clock()          // 
See "Start Clock: "+ t1 +nl
counter    = 1
aSendory   = [["s","-"],["e","-"],["n","-"],["d","-"],["o","-"],["r","-"],["y","-"]]
aRandom    = List(10)                       // 0-9

for j = 1 to 100000000
	aRandom = GenRandomUniq()            // 5 2 0 8 7 1 6 4 3 9 	
	for i = 1 to 7
	    if aRandom[1] != 1               // m = 1
	       aSendory[i][2] = aRandom[1]
	       del(aRandom,1)                // Shorten list, remove value entry picked
	    else
	       del(aRandom,1)
	       i--
	    ok
	next
        if (TrySolution(aSendory)) break  else  counter++   ok  // True=1 = Solution Found      
next
See "End   Clock.: "+ (clock() - t1) +nl
See "Count cycles: "+ counter +nl

Func GenRandomUniq()
throwLimit = 10                      // 0-9, Ring does 1-10
aList = 1:throwLimit
aOut  = []
while len(aOut) != throwLimit
    nSize = len(aList)	
    if nSize > 0
        nIndex = random(nSize)       // Random pointer into list
        if nIndex = 0  nIndex=1 ok   // Ignore 0, Ring Index at 1-10		
        aOut + (aList[nIndex] -1)    // -1 fix value 0-9, Ring +1 Extract list entry content
        del(aList,nIndex)            // Shorten list, remove value entry picked
    else
        aOut + aList[1]
        aList = []
    ok
end
return aOut

Func TrySolution(aTry)
     s1 = ( aTry[1][2]) * 1000      // send   
     e1 = ( aTry[2][2]) *  100         
     n1 = ( aTry[3][2]) *   10        
     d1 = ( aTry[4][2]) *    1        
     nbr1 = s1 + e1 + n1 + d1
     m1 = 1             * 1000      // more
     o1 = ( aTry[5][2]) *  100
     r1 = ( aTry[6][2]) *   10
     e1 = ( aTry[2][2]) *    1 
     nbr2 = m1 + o1 + r1 + e1
     m1 = 1             * 10000     // money
     o1 = ( aTry[5][2]) *  1000
     n1 = ( aTry[3][2]) *   100
     e1 = ( aTry[2][2]) *    10
     y1 = ( aTry[7][2]) *     1
     nbr3 = m1 + o1 +n1 + e1 + y1
     nbr4 = nbr1 + nbr2
     if (nbr3 = nbr4)
        See "Solved: SEND: "+ nbr1 +" MORE: "+ nbr2 +" MONEY: "+ nbr3 +" Check "+ nbr4 +nl
        return (nbr3 = nbr4 )      // True
     ok  
return False
Output:
// Output
// Start Clock: 32
// Solved: SEND: 9567 MORE: 1085 MONEY: 10652 Check 10652
// End   Clock.: 3792
// Count cycles: 28316

Ring

t1 = clock() // start
see "works..." + nl + nl
aListSend = []
aListMore = []

for s = 0 to 9
    for e1 = 0 to 9
        for n = 0 to 9
            for d = 0 to 9
                bool = s!=e1 and s!=n and s!=d and e1!=n and e1!=d and n!=d
                if bool
                   sendmore = s*1000+e1*100+n*10+d
                   add(aListSend,sendmore)
                   add(aListMore,sendmore)
                ok
            next
        next
    next
next

for ind1 = len(aListSend) to 1 step -1 
    for ind2 = 1 to len(aListMore)
        strSend = string(aListSend[ind1])
        strMore = string(aListMore[ind2])
        m = substr(strMore,1,1)
        o = substr(strMore,2,1)
        r = substr(strMore,3,1)
        e2 = substr(strMore,4,1)
        bool1 = substr(strSend,m)
        bool2 = substr(strSend,o)
        bool3 = substr(strSend,r)
        if substr(strSend,2,1) = substr(strMore,4,1)
            bool4 = 0
        else
            bool4 = 1
        ok
        boolSendMore = bool1 + bool2 + bool3 + bool4
        if boolSendMore < 1
           if substr(strSend,2,1) = substr(strMore,4,1)
              for y = 0 to 9
                  strMoney1 = substr(strMore,1,1) + substr(strMore,2,1) + substr(strSend,3,1)
                  strMoney2 = substr(strMore,4,1) + string(y)
                  strMoney = strMoney1 + strMoney2
                  numMoney = number(strMoney)
                  numSend = number(strSend)
                  numMore = number(strMore)
                  y1 = substr(strMoney,5,1)
                  ySend = substr(strSend,y1)
                  yMore = substr(strMore,y1)
                  yCheck = ySend + yMore
                  r = substr(strMore,3,1)
                  rCheck = substr(strSend,r)
                  if (numSend + numMore = numMoney) and yCheck < 1 and rCheck < 1
                      see "SEND = "+strSend+" MORE = "+strMore+" MONEY = "+strMoney+nl+nl              
                      exit 3
                  ok
             next
           ok
        ok
    next
next
see "Time: "+ clock() - t1 // end
see "done..." + nl
Output:
works...
SEND = 9567 MORE = 1085 MONEY = 10652
done...
Time: 31.9 s

Wren

Clearly M = 1 and S must be 8 or 9. Brute force can be used to solve for the other letters.

var start = System.clock
var sends = []
var ors = []
var m = 1
var digits = (0..9).toList
digits.remove(m)
for (s in 8..9) {
    for (e in digits) {
        if (e == s) continue
        for (n in digits) {
            if (n == s || n == e) continue
            for (d in digits) {
                if (d == s || d == e || d == n) continue
                sends.add([s, e, n, d])
            }
        }
    }
}
for (o in digits) {
    for (r in digits) {
        if (r == o) continue
        ors.add([o, r])
    }
}
System.print("Solution(s):")
for (send in sends) {
    var SEND = 1000 * send[0] + 100 * send[1] + 10 * send[2] + send[3]
    for (or in ors) {
        if (send.contains(or[0]) || send.contains(or[1])) continue
        var MORE = 1000 * m + 100 * or[0] + 10 * or[1] + send[1]
        for (y in digits) {
            if (send.contains(y) || or.contains(y)) continue
            var MONEY = 10000 * m + 1000 * or[0] + 100 * send[2] + 10 * send[1] + y
            if (SEND + MORE == MONEY) {
                System.print("%(SEND) + %(MORE) = %(MONEY)")
            }
        }
    }
}
System.print("\nTook %(System.clock - start) seconds.")
Output:
Solution(s):
9567 + 1085 = 10652

Took 0.051735 seconds.

XPL0

include xpllib; \for Print
def M = 1;
int S, E, N, D, O, R, Y;
begin \ Solve the SEND+MORE=MONEY puzzle - Translation of the Algol 68 sample
  for S:= 8 to 9 do
    for E:= 0 to 9 do
      if E # M and E # S then
        for N:= 0 to 9 do
          if N # M and N # S and N # E then
            for D:= 0 to 9 do
              if D # M and D # S and D # E and D # N then
                for O:= 0 to 9 do
                  if O # M and O # S and O # E and O # N and O # D then
                    for R:= 0 to 9 do
                      if R # M and R # S and R # E and R # N and R # D and R # O then
                        for Y:= 0 to 9 do
                          if Y # M and Y # S and Y # E and Y # N and Y # D and Y # O and Y # R then
                            if 1000*(S+M) + 100*(E+O) + 10*(N+R) + D + E = 10_000*M + 1000*O + 100*N + 10*E + Y then
                              Print("%d%d%d%d + %d%d%d%d = %d%d%d%d%d\n", S, E, N, D, M, O, R, E, M, O, N, E, Y);
end
Output:
9567 + 1085 = 10652