SEND + MORE = MONEY

From Rosetta Code
Revision as of 09:25, 13 February 2023 by Horst (talk | contribs) (→‎{{header|Free Pascal}}: 41 Words)
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;
uses
  sysutils;// TDatetime
const
  nmax = 9;
  maxLen = 5;
  maxIDx = 41;
type
 tFreeDgt = array[0..nmax+1] of Int32;
 tSymbWord = String[maxLen];
 tDgtWord =  record
               DW_DgtsIdx: array[1..maxLen] of UInt8;
               DW_maxIdx: Uint8;
             end;
const
//  cSumWords : array[0..maxIDx] of tSymbWord =('SEND','MORE','MONEY');

//MANYOTHERS=M2A7N6Y4O1T9H5E0R8S3
//{
  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 : tFreeDgt;
  SymbInUse : array[0..10] of char;
  DgtToSymb : array[0..10] of UInt8;
  Words :array[0..maxIDx] of tSymbWord;
  DgtWords : array[0..maxIDx] of tDgtWord;
  SymbInUseCount,gblCount : Uint32;
  fullStop: boolean;
  ch : char;

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;
  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;
    while j < maxLen do
    begin
      inc(j);
      Words[i] := Low(SymbToIdx)+Words[i];
    end;
    RevString(Words[i]);
  end;


  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;

  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
    write(SymbInUse[i]);
  writeln(SymbInUseCount-1:4,' symbols');
end;

procedure OneSol(idx:int32);
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(DigitSample[symbolIdx]);
  end;
  writeln(cSumWords[idx]:maxLen+2);
end;

function AddWords(const DS:tFreeDgt):boolean;
var
  col,row,
  sum,carrySum,carry : NativeUInt;
begin
  // No zero as first symbol
  For row := maxIdx downto 0 do
    with DgtWords[row] do
      if DS[DW_DgtsIdx[DW_maxidx]] = 0 then
        EXIT(false);

  carry := 0;
  carrySum := 0;
  For col := 1 to maxLen do
  Begin
    sum := carrysum MOD 10;
    carrysum := carrysum  DIV 10;
    carry :=0;
    For row := maxIdx-1 downto 0 do
    Begin
      sum := sum+DS[DgtWords[row].DW_DgtsIdx[col]];
      if sum > 9 then
      begin
        carry := sum DIV 10;
        sum := sum - 10 * carry;
        inc(CarrySum,Carry);
      end;
    end;
    //digit of sum
    if sum <> DS[DgtWords[maxIDx].DW_DgtsIdx[col]] then
      EXIT(false);
  end;
  if carrysum <>0 then
    EXIT(false);
  For row := 0 to High(DgtWords)do
    OneSol(row);
  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 : 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;
  writeln;
  WriteLn(gblCount,' checks ',FormatDateTime(' NN:SS.ZZZ',T1-t0),' secs');
end.
@TIO.RUN:
8 symbols
 9567   SEND
 1085   MORE
10652  MONEY

2704147 checks  00:00.090 secs
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

496179 checks  00:00.061 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