root/examples/sendmoremoney.pl

Revision 11293, 6.5 kB (checked in by Darren_Duncan, 3 years ago)

replaced all 'use v6;' lines with 'use v6-alpha;' in 330 files (examples/, ext/, t/, t_disabled/) ... more remain to do

  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
Line 
1use v6-alpha;
2
3my $timer;
4sub start_timer() {
5    $timer = time();
6}
7my $piggy_bank;
8
9sub show_rate($num) {
10    my $elapsed = time() - $timer;
11    if ($elapsed) {
12        say "Found all solutions in "~$elapsed~"s ("~($num/$elapsed)~" comb/s)";
13    } else {
14        say "Damn, that was fast.  Didn't even see the clock tick,";
15        say "for searching a solution space of $num!";
16    }
17    if (defined($piggy_bank)) {
18        say "There are $piggy_bank coins left in the bank.";
19    }
20}
21
22# basic test case, A + B = AC
23my $a = any(1..9);
24my $b = any(1..9);
25my $c = any(0..9);
26
27sub do_it($a,$b,$c) {
28    if ( any($a, $b, $c) == one($a, $b, $c) ) {
29        my $ac = $a * 10 + $c;
30        if ( $a + $b == $ac ) {
31            say "  A =  $a";
32            say "+ B =  $b";
33            say "--------";
34            say " AC = $ac";
35        }
36    }
37}
38
39say "Finding solutions for A + B = AC";
40start_timer();
41do_it($a,$b,$c);
42show_rate(810);
43
44# a more complicated and "classical" case :)
45sub show_me_the_money($s,$e,$n,$d,$m,$o,$r,$y) {
46
47    if (all($s,$e,$n,$d,$m,$o,$r,$y) == one($s,$e,$n,$d,$m,$o,$r,$y)) {
48
49        $piggy_bank --;
50
51        my $send = ((($s)*10+$e)*10+$n)*10+$d;
52        my $more = ((($m)*10+$o)*10+$r)*10+$e;
53        my $money = (((($m)*10+$o)*10+$n)*10+$e)*10+$y;
54
55        if ($send + $more == $money) {
56            say " send =  $send";
57            say "+more =  $more";
58            say "-------------";
59            say "money = $money";
60        }
61    }
62}
63
64my $s = any(1..9);
65my $e = any(0..9);
66my $n = any(0..9);
67my $d = any(0..9);
68my $m = any(1..9);
69my $o = any(0..9);
70my $r = any(0..9);
71my $y = any(0..9);
72
73my $c0 = any(0..1);
74my $c1 = any(0..1);
75my $c2 = any(0..1);
76my $c3 = any(0..1);
77
78sub collapse($one, $sub) { $sub.($one) };
79sub collapse($one, $two, $sub) { $sub.($one, $two) };
80sub collapse($one, $two, $three, $sub) { $sub.($one, $two, $three) };
81
82say "Finding solutions for SEND + MORE = MONEY (psuedo-optimised)";
83$piggy_bank = 1e8;
84start_timer();
85
86# this is still really ugly, but fast-ish :)
87collapse($c3, $m, -> $c3, $m {
88
89    $piggy_bank--;
90
91    # FIFTH (most significant) column of addition
92    if ($c3 == $m) {
93        say "found c3 = $c3, m = $m";
94    collapse($s, $o, $c2, -> $s, $o, $c2 {
95
96        # FOURTH column of addition
97        $piggy_bank--;
98        if ($s != $m && $s != $o && $m != $o &&
99            (( $s+$m+$c2 ) % 10 == $o ) && ( int( ( $s+$m+$c2 ) / 10 ) == $c3 ) ) {
100        say " found s = $s, o = $o, c2 = $c2";
101        collapse($e, $c1, -> $e, $c1 {
102
103            $piggy_bank--;
104            if ( $e != $s && $e != $o && $e != $m &&
105                  ( int( ( $e+$o+$c1 ) / 10 ) == $c2 ) ) {
106            say "  found e = $e, c1 = $c1";
107            collapse($d, $y, $c0, -> $d, $y, $c0 {
108
109                $piggy_bank--;
110                if ($d != $s && $d != $m && $d != $s && $d != $e && $d != $o &&
111                    $y != $s && $y != $m && $y != $s && $y != $e && $y != $o &&
112                    $d != $y &&
113                    (( $d+$e     ) % 10 == $y ) &&
114                    ( int( ( $d+$e     ) / 10 ) == $c0 )) {
115                say "   found d = $d, y = $y, c0 = $c0";
116               
117                collapse($n, $r, -> $n, $r {
118
119                    $piggy_bank--;
120                    if ($n != $s && $n != $m && $n != $s && $n != $o &&
121                        $n != $e && $n != $d && $n != $y &&
122                        $r != $s && $r != $m && $r != $s && $r != $o &&
123                        $r != $e && $r != $d && $r != $y && $r != $n &&
124                        (( $e+$o+$c1 ) % 10 == $n ) &&
125                        ( ( $n+$r+$c0 ) % 10 == $e ) &&
126                        ( int( ( $n+$r+$c0 ) / 10 ) == $c1 )) {
127
128                        say "    found n = $n, r = $r (that should be it)";
129
130                        show_me_the_money($s,$e,$n,$d,$m,$o,$r,$y);     
131
132                    }
133                });
134                }
135            });
136            }
137        });
138        }
139    });
140    }
141});
142
143show_rate(16e8);
144
145say "Finding solutions for SEND + MORE = MONEY (exhaustive)";
146
147# in fact, cheat again :-)
148# note: this would take BLEEDING AGES (days or weeks) without this
149# cheating.
150my $s = any(8..9);
151my $e = any(5..6);
152my $n = any(4..7);
153my $d = any(6..8);
154my $m = any(1..2);
155my $o = any(0,1,9);
156my $r = any(7..9);
157my $y = any(1..3);
158
159start_timer();
160show_me_the_money($s,$e,$n,$d,$m,$o,$r,$y);
161show_rate(2*2*4*3*2*3*3*3);
162
163=kwid
164
165-- Heres the equivalent SQL, as junctions have direct representation
166-- in Set Theory (see http://xrl.us/feh8)), then the below should be a
167-- very relevant way to express the problem, especially given
168-- MySQL/InnoDB (for one) already has the relevant logic to solve this
169-- problem in ~130ms on a 300MHz PII.  Although of course that is
170-- still over 39,000,000 cycles!  :-)  Oracle took longer - ~6s, but
171-- admittedly it was only running on a dual processor 1.6GHz Opteron.
172-- Pg took a similar amount of time on a 1.7GHz AthlonXP (5s), SQLite
173-- took over 30s!
174
175-- The `exhaustive' solution cranks through possibilities at about
176
177-- MySQL table setup (adjust for your DBMS as necessary)
178
179CREATE TABLE Dx ( X INTEGER(1) );
180INSERT INTO Dx (X) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
181CREATE TABLE Cx ( X INTEGER(1) );
182INSERT INTO Cx (X) VALUES (0),(1);
183
184-- actual query:
185
186SELECT
187    (S.X * 1000 + E.X * 100 + N.X * 10 + D.X) as SEND,
188    (M.X * 1000 + Oh.X * 100 + R.X * 10 + E.X) as MORE,
189    (M.X * 10000 + Oh.X * 1000 + N.X * 100 + E.X * 10 + Y.X) as MONEY
190from
191    Dx M
192    LEFT JOIN Dx S ON (M.X != S.X)
193    LEFT JOIN Dx E ON ( (M.X != E.X) AND (S.X != E.X) )
194    LEFT JOIN Dx Oh ON ( (M.X !=Oh.X) AND (S.X !=Oh.X) AND (E.X !=Oh.X) )
195    LEFT JOIN Dx N ON ( (M.X != N.X) AND (S.X != N.X) AND (E.X != N.X)
196            AND (Oh.X != N.X) )
197    LEFT JOIN Dx R ON ( (M.X != R.X) AND (S.X != R.X) AND (E.X != R.X)
198            AND (Oh.X != R.X) AND (N.X != R.X) )
199    LEFT JOIN Dx D ON ( (M.X != D.X) AND (S.X != D.X) AND (E.X != D.X)
200            AND (Oh.X != D.X) AND (N.X != D.X) AND (R.X != D.X) )
201    LEFT JOIN Dx Y ON ( (M.X != Y.X) AND (S.X != Y.X) AND (E.X != Y.X)
202            AND (Oh.X != Y.X) AND (N.X != Y.X) AND (R.X != Y.X)
203            AND (D.X != Y.X) )
204    LEFT JOIN Cx C0 ON ( C0.X = floor( (D.X + E.X) / 10 ) )
205    LEFT JOIN Cx C1 ON ( C1.X = floor( (N.X + R.X + C0.X) / 10 ) )
206    LEFT JOIN Cx C2 ON ( C2.X = floor( (E.X + Oh.X + C1.X) / 10 ) )
207    LEFT JOIN Cx C3 ON ( C3.X = floor( (S.X + M.X + C2.X) / 10 ) )
208WHERE
209    ( M.X != 0 ) AND
210    ( S.X != 0 ) AND
211    (                C3.X    ) = M.X  AND
212    MOD( S.X + M.X + C2.X, 10) = Oh.X  AND
213    MOD( E.X +Oh.X + C1.X, 10) = N.X  AND
214    MOD( N.X + R.X + C0.X, 10) = E.X   AND
215    MOD( D.X + E.X       , 10) = Y.X
216;
217
218=cut
Note: See TracBrowser for help on using the browser.