 <p>We <strong>can do</strong> better by translating number-theoretic properties into the language of constraints!</p> <blockquote> <p>All terms are of the form 87...12 = 4*21...78 or 98...01 = 9*10...89.</p> </blockquote> <p>We implement <code>a031877_ndigitsNEWER_/3</code> based on <code>a031877_ndigitsNEW_/3</code> and directly add above property as two finite-domain constraints:</p> <pre> a031877_ndigitsNEWER_(Z_big,N_digits,[K|D_big]) :- <b>K in {4}\/{9}</b>, % (new) length(D_big,N_digits), <b>D_big ins (0..2)\/(7..9)</b>, % (new) reverse(D_small,D_big), digits_number(D_big,Z_big), digits_number(D_small,Z_small), Z_big #= Z_small * K. </pre> <p>Let's re-run the benchmarks we used before!</p> <pre><code>?- time((a031877_ndigitsNEWER_(Z,5,Zs),labeling([ff],Zs),false)). % 73,011 inferences, 0.006 CPU in 0.006 seconds (100% CPU, 11602554 Lips) false. ?- time((a031877_ndigitsNEWER_(Z,6,Zs),labeling([ff],Zs),false)). % 179,424 inferences, 0.028 CPU in 0.028 seconds (100% CPU, 6399871 Lips) false. ?- time((a031877_ndigitsNEWER_(Z,7,Zs),labeling([ff],Zs),false)). % 348,525 inferences, 0.037 CPU in 0.037 seconds (100% CPU, 9490920 Lips) false. </code></pre> <p>Summary: For the three queries, we consistently observed a significant reduction of search required. Just consider how much the inference counts shrank: 1.45M -> 73k, 5M -> 179k, 15.1M -> 348k.</p> <p>Can we do even better (while preserving declarativity of the code)? I don't know, I guess so...</p>