declare proc {Store Root} C H E S A B O W P L in Root=sol(c:C h:H e:E s:S a:A b:B o:O w:W p:P l:L) Root ::: 0#9 {FD.distinct Root} 10000*C + 1000*H + 100*E + 10*S + S + 1000*C + 100*A + 10*S + H + 100000*B + 10000*O + 1000*W + 100*W + 10*O + W + 10000*C + 1000*H + 100*O + 10*P + S + 100000*A + 10000*L + 1000*S + 100*O + 10*P + S + 1000000*P + 100000*A + 10000*L + 1000*E + 100*A + 10*L + E + 1000*C + 100*O + 10*O + L + 1000*B + 100*A + 10*S + S + 1000*H + 100*O + 10*P + S + 1000*A + 100*L + 10*E + S + 1000*H + 100*O + 10*E + S + 100000*A + 10000*P + 1000*P + 100*L + 10*E + S + 1000*C + 100*O + 10*W + S + 100000*C + 10000*H + 1000*E + 100*E + 10*S + E + 100000*C + 10000*H + 1000*S + 100*O + 10*A + P + 10000*S + 1000*H + 100*E + 10*E + P =: 1000000*A + 100000*L + 10000*L + 1000*W + 100*O + 10*O + L {FD.distribute ff Root} end {ExploreOne Store}
It occurs that it might improve propagation to represent the concept of "addition" in a more explicit way - to say something about the carries:
declare proc {Store Root} C H E S A B O W P L C11 C12 C21 C22 C31 C32 C41 C42 C51 C52 C61 C62 Carries in Root=sol(c:C h:H e:E s:S a:A b:B o:O w:W p:P l:L) Root ::: 0#9 Carries=lst( C11 C12 C21 C22 C31 C32 C41 C42 C51 C52 C61 C62 ) Carries ::: 0#9 {FD.distinct Root} S+H+W+S+S+E+L+S+S+S+S+S+S+E+P+P =: L+ 10*C11+ 100*C12 S+S+O+P+P+L+O+S+P+E+E+E+W+S+A+E+ C11 =: O+ 10*C21+ 100*C22 E+A+W+O+O+A+O+A+O+L+O+L+O+E+O+E+ C21 + C12 =: O+ 10*C31+ 100*C32 H+C+W+H+S+E+C+B+H+A+H+P+C+E+S+H+ C31 + C22 =: W+ 10*C41+ 100*C42 C+ O+C+L+L+ P+ H+H+S+ C41 + C32 =: L+ 10*C51+ 100*C52 B+ A+A+ A+ C+C + C51 + C42 =: L+ 10*C61+ 100*C62 P + C61 + C52 =: A {FD.distribute ff Root} end {ExploreOne Store}
Nevertheless, if we combine both approaches (and adjust the domain for the carries a bit), we get a better result than in both previous cases:
declare proc {Store Sol} local CarriesLow=[C11 C21 C31 C41 C51 C61] CarriesHigh=[C12 C22 C32 C42 C52] A B C E H L O P S W in !Sol= crypto(a:A b:B c:C e:E h:H l:L o:O p:P s:S w:W) = {FD.dom 0#9} CarriesLow ::: 0#9 CarriesHigh ::: 0#1 {FD.distinct Sol} 10000*C + 1000*H + 100*E + 10*S + S + 1000*C + 100*A + 10*S + H + 100000*B + 10000*O + 1000*W + 100*W + 10*O + W + 10000*C + 1000*H + 100*O + 10*P + S + 100000*A + 10000*L + 1000*S + 100*O + 10*P + S + 1000000*P + 100000*A + 10000*L + 1000*E + 100*A + 10*L + E + 1000*C + 100*O + 10*O + L + 1000*B + 100*A + 10*S + S + 1000*H + 100*O + 10*P + S + 1000*A + 100*L + 10*E + S + 1000*H + 100*O + 10*E + S + 100000*A + 10000*P + 1000*P + 100*L + 10*E + S + 1000*C + 100*O + 10*W + S + 100000*C + 10000*H + 1000*E + 100*E + 10*S + E + 100000*C + 10000*H + 1000*S + 100*O + 10*A + P + 10000*S + 1000*H + 100*E + 10*E + P =: 1000000*A + 100000*L + 10000*L + 1000*W + 100*O + 10*O + L S+H+W+S+S+E+L+S+S+S+S+S+S+E+P+P =: L+ 10*C11+ 100*C12 S+S+O+P+P+L+O+S+P+E+E+E+W+S+A+E+ C11 =: O+ 10*C21+ 100*C22 E+A+W+O+O+A+O+A+O+L+O+L+O+E+O+E+ C21+ C12 =: O+ 10*C31+ 100*C32 H+C+W+H+S+E+C+B+H+A+H+P+C+E+S+H+ C31+ C22 =: W+ 10*C41+ 100*C42 C+ O+C+L+L+ P+ H+H+S+ C41+ C32 =: L+ 10*C51+ 100*C52 B+ A+A+ A+ C+C + C51+ C42 =: L+ 10*C61 P + C61+ C52 =: A {FD.distribute ff [A P L B C O H S W E]} {FD.distribute naive CarriesHigh} end end {ExploreOne Store}
This solution is
1#crypto(a:3 b:6 c:4 e:2 h:5 l:7 o:8 p:1 s:0 w:9)