prolog - Evaluate a number in (a few) natural language -
assume list, each element can be:
a) number 1,2,...9
b) number 10, 100, 10000, ... (numbers of form 10^(2^n) n>=0).
it need (as simple possible) rule evaluates list 1 integer number. examples of evaluation are:
[1] => 1 [2] => 2 [10 1] => 11 [2 10 1] => 21 [2 100 1 10 4] => 214 [2 10 1 100 4] => 2104 [2 10 1 100 10000] => 21000000
in other words, numbers 10, 100, ... equivalent of tenths, hundreds, million, ... in english , rule evaluate usual in english , other languages: 10, 100 "multiplies" values before them, numbers after them added.
(i know definition not exact one, finding definition part of problem. not hesitate requests more examples if necessary).
note than, in same way in natural language, number 0 not necessary. even, initial languages, not present in grammar.
addendum
the major difficulty in problem expression [2 10000 3 10] can not taken (2*10000+3)*10, 2*10000+3*10. example [2 10 1 10000 3 10] (2*10+1)*10000+3*10.
proof of not homework: interest on numbering (and, in general, in natural language) that, in context, more error-safe binary. example, in context of supermarket prices, "two thousands blah" keeps meaning, while 1001blah totally undefined.
with ingenuity, start covering patterns...
test :- forall(member(l=r, [ [1] = 1, [2] = 2, [10, 1] = 11, [2, 10, 1] = 21, [2, 100, 1, 10, 4] = 214, [2, 10, 1, 100, 4] = 2104, [2, 10, 1, 100, 10000] = 21000000 ]), test(l, r)). test(l, r) :- pattern(l, e), r =:= e -> writeln(ok(l,r)) ; writeln(ko(l,r)). pattern([a], a) :- dig(a). pattern([a, b], a+b) :- ten(a), dig(b). pattern([a, b, c], a*b+c) :- mul_ten(a, b), dig(c). pattern([a, b, c, d, e], a*b + c*d + e) :- mul_ten(a,b), mul_ten(c,d), b > d, dig(e). pattern([a, b, c, d, e], ((a*b+c)*d)+e) :- mul_ten(a,b), ten(d), dig(e). % doubt... pattern([a, b, c, d, e], (a*b+c)*d*e) :- mul_ten(a,b), ten(d), ten(e). % doubt... dig(d) :- between(1,9,d). ten(t) :- between(0,10,e), t =:= 10^(2^e). % 10 -> inappropriate (too zeroes ?) mul_ten(m,t) :- between(1,9,m), ten(t). % 9 -> inappropriate ?
plain pattern matching. running:
?- test. ok([1],1) ok([2],2) ok([10,1],11) ok([2,10,1],21) ok([2,100,1,10,4],214) ok([2,10,1,100,4],2104) ok([2,10,1,100,10000],21000000) true.
i think there little space recursion, afaik idioms cover used cases, without 'smart' evaluation... anyway, cannot find way in (that is, never use) pattern
[2 10 1 100 4] => 2104
edit now, dcg , clp(fd) :
:- use_module(library(clpfd)). test :- forall(member(l=r, [ [1] = 1, [2] = 2, [10, 1] = 11, [2, 10, 1] = 21, [2, 100, 1, 10, 4] = 214, [2, 10, 1, 100, 4] = 2104, [2, 10, 1, 100, 10000] = 21000000 ]), test(l, r)). test(l, r) :- phrase(pattern(e), l), r #= e -> writeln(ok(l,r)) ; writeln(ko(l,r)). pattern(a) --> dig(a). pattern(a+b) --> ten(a), dig(b). pattern(a*b+c) --> mul_ten(a, b), dig(c). pattern(a*b+c*d) --> mul_ten(a, b), mul_ten(c, d). pattern(a*b + c*d + e) --> mul_ten(a,b), mul_ten(c,d), dig(e). pattern(((a*b+c)*d)+e) --> mul_ten(a,b), [c], ten(d), dig(e). % doubt... pattern((a*b+c)*d*e) --> mul_ten(a,b), [c], ten(d), ten(e). % doubt... dig(d) --> [d], {d #>= 1, d #=< 9}. ten(t) --> [t], {t #>= 1, t #= (10^(2^e)), e #> 0, e #=< 10}. mul_ten(m,t) --> dig(m), ten(t).
edit op/3 directive, also...
:- op(100,fx, dig). :- op(100,fx, ten). :- op(100,xfx, mul). pattern(a) --> dig a. pattern(a+b) --> ten a, dig b. pattern(a*b+c) --> mul b, dig(c). pattern(a*b+c*d) --> mul b, c mul d. pattern(a*b+c*d+e) --> mul b, c mul d, dig e. pattern(((a*b+c)*d)+e) --> mul b, [c], ten d, dig e. % doubt... pattern((a*b+c)*d*e) --> mul b, [c], ten d, ten e. % doubt... dig d --> [d], {d #>= 1, d #=< 9}. ten t --> [t], {t #>= 1, t #= (10^(2^e)), e #> 0, e #=< 10}. m mul t --> dig m, ten t.
Comments
Post a Comment