Advertisement
Guest User

Untitled

a guest
Feb 28th, 2022
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Prolog 10.11 KB | None | 0 0
  1. % mathler solver tool by S.Devulder
  2.  
  3. :- use_module(lists).
  4.  
  5. /*
  6. :- dynamic m_/3.
  7. member2(X, Y) :-
  8.     (   m_(X, Y, 1) ->
  9.         true
  10.     ;   m_(X, Y, 0) ->
  11.         fail
  12.     ;   (   member(X, Y) ->
  13.             Z=1
  14.         ;   Z=0
  15.         ),
  16.         assertz(m_(X,Y,Z)),
  17.         Z==1
  18.     ).
  19. */
  20. %:- use_module(tabling), table member2/2.
  21. member2(X,Y) :- member(X,Y).
  22. %member2(X,Y) :- append(_, [X|_] ,Y).
  23.  
  24. %:- dynamic digit_/1.
  25. %digit(X) :-  digit_(X),!;member(X, "0123456789"),assert(digit_(X)).
  26. %digit(X) :- memberchk(X,"0123456789").
  27. digit(0'0). digit(0'1). digit(0'2). digit(0'3). digit(0'4).
  28. digit(0'5). digit(0'6). digit(0'7). digit(0'8). digit(0'9).
  29.  
  30. % parses a number
  31. num(Num, [Digit|L], Res, M) :- digit(Digit), !, num(Num*10+Digit-48, L, Res, M).
  32. num(Num, L, Res/1, L) :- Res is Num.
  33.  
  34. % convert list of ascii codes into tokens
  35. tokenize(0'+,+). tokenize(0'-,-). tokenize(0'*,*). tokenize(0'/,/).
  36. tokenize(0'(,'('). tokenize(0'),')').
  37. tokenize(0'0,0). tokenize(0'1,1). tokenize(0'2,2). tokenize(0'3,3). tokenize(0'4,4).
  38. tokenize(0'5,5). tokenize(0'6,6). tokenize(0'7,7). tokenize(0'8,8). tokenize(0'9,9).
  39.  
  40. tokenize([],[]).
  41. tokenize([Ascii|L], [Symbol|M]) :-
  42.     tokenize(Ascii, Symbol),
  43.     tokenize(L, M).
  44. tokenize([0'0,Digit|_],_) :-  digit(Digit),!,fail. % reject leading digit.
  45. tokenize([Digit|L], [Num|M]) :-
  46.    digit(Digit),
  47.    num(Digit-48, L, Num, R),
  48.    tokenize(R, M).
  49.  
  50. %testcase
  51. %main :- tokenize("(1-2)*345+0",X), write(X),nl,fail.
  52.  
  53. % symbol kind
  54. operator(+). operator(-). operator(*). operator(/).
  55. bra('('). ket(')').
  56.  
  57. % calculate a simple opeation
  58. rational(_/_).
  59. calc(U, V, P/Q) :- % normalize
  60.    X is U,
  61.    (   X=0 ->
  62.        P=0,
  63.        Q=1
  64.    ;   Y is V,
  65.        Z is gcd(X,Y),
  66.        P is X div Z,
  67.        Q is Y div Z
  68.    ).
  69. calc(A/B, +, C/D, R) :- calc(A*D+B*C, B*D, R).
  70. calc(A/B, -, C/D, R) :- calc(A*D-B*C, B*D, R).
  71. calc(A/B, *, C/D, R) :- calc(A*C, B*D, R).
  72. calc(_, /, 0/_, _) :- !, fail. % can’t divide by 0
  73. calc(A/B, /, C/D, R) :- calc(A*D, B*C, R).
  74.  
  75. :- dynamic c_/4.
  76. calc2(X,Op,Y,R) :-
  77. %    calc(X,Op,Y,R).
  78.    c_(X,Op,Y,R),!;calc(X,Op,Y,R), asserta(c(X,Op,Y,R)).
  79.  
  80. % operator precedence
  81. precedence(+,1). precedence(-,1). precedence(*,2). precedence(/,2).
  82.  
  83. % Shunting-yard algorithm
  84. eval_op(X, L, [A,B|Nums], [Y|Ops], Res) :-
  85.    precedence(X, Px),
  86.    precedence(Y, Py),
  87.    Px =< Py, !,
  88.    calc2(B, Y, A, C),
  89.    eval(L, [C|Nums], [X|Ops], Res).
  90. eval_op(X, L, Nums, Ops, Res) :-
  91.    eval(L, Nums, [X|Ops], Res).
  92.  
  93. eval_ket(L, Nums, [X|Ops], Res) :-
  94.    bra(X), !,
  95.    eval(L, Nums, Ops, Res).
  96. eval_ket(L, [X,Y|Nums], [Op|Ops], Res) :-
  97.    calc2(Y, Op, X, Z),
  98.    eval_ket(L, [Z|Nums], Ops, Res).
  99.  
  100. eval([Tk|L], Nums, Ops, Res) :-
  101.    (   rational(Tk) ->
  102.        eval(L, [Tk|Nums], Ops, Res)
  103.    ;   operator(Tk) ->
  104.        eval_op(Tk, L, Nums, Ops, Res)
  105.    ;   bra(Tk) ->
  106.        eval(L, Nums, [Tk|Ops], Res)
  107.    ;   ket(Tk) ->
  108.        eval_ket(L, Nums, Ops, Res)
  109.    ).
  110. eval([], [X,Y|Nums], [Op|Ops], Res) :-
  111.    calc(Y, Op, X, Z),
  112.    eval([], [Z|Nums], Ops, Res).
  113. eval([],[N],[],N).
  114.  
  115. % eval(-String, +Value)
  116. eval(Str, Val) :- tokenize(Str, TokenList), eval(TokenList, [], [], Val).
  117.  
  118. % print a string
  119. puts([0'\\,0'n| L]) :- nl, puts(L).
  120. puts([X|L]) :- put_code(X),puts(L).
  121. puts([]).
  122.  
  123. %testcase
  124. %main :- member(L,["1+2*3","(1+2)","1","1+2","1+2-3","(1+2)*3","1+(2*3)"]),puts(L),nl,eval(L,R),write(=),write(R),nl,fail.
  125.  
  126. % possible next character
  127. :- dynamic(after_/3).
  128. after(X, Y) :-
  129.    (   after_(X, Y, Z), !
  130.    ;   (   memberchk(X, "0123456789") ->
  131.            memberchk(Y, "0123456789+-*/)"),
  132.            Z=1
  133.        ;   memberchk(X, "+-*/(") ->
  134.            memberchk(Y, "0123456789("),
  135.            Z=1
  136.        ;   memberchk(X, ")") ->
  137.            memberchk(Y, "+-*/)"),
  138.            Z=1
  139.        ;   Z=0
  140.        ),
  141.        assert(after_(X,Y,Z))
  142.    ), !,
  143.    Z=1.
  144.  
  145. % utility to select either a l8st with or without distinct elements
  146. filter(+distinct,Ascii,L,_) :- member(Ascii,L), !,fail.
  147. filter(+distinct,Ascii,L,[Ascii|L]) :- !.
  148. filter(+distinct,_,_,done).
  149.  
  150. filter(-distinct, Ascii, L, done) :- member(Ascii, L), !.
  151. filter(-distinct, _, done, done) :- !.
  152. filter(-distinct, Ascii, L, [Ascii|L]).
  153.  
  154. filter(all, _, _, _).
  155.  
  156. % at most MaxOps operator
  157. op_count(Ascii, NumOps, MaxOps, NumOp2) :-
  158.    (   memberchk(Ascii, "+-*/") ->
  159.        NumOp2 is NumOps+1,
  160.        NumOp2 =< MaxOps
  161.    ;   NumOp2 =  NumOps
  162.    ).
  163.  
  164. % choose(+Possible_symbols, +Previous_symbol, +Distinct_filter, -Result)
  165. choose([Alphabet], Prev, filter(Mode,In),  _, _, [Ascii]) :-
  166.    member2(Ascii, Alphabet),
  167. %    memberchk(Ascii, "0123456789)"),
  168.    (Ascii=0');digit(Ascii)),
  169.     after(Prev, Ascii),
  170.     filter(Mode, Ascii, In, done).
  171. choose([Alphabet|Choices], Prev, filter(Mode,In), NumOps, MaxOps, [Ascii|M]) :-
  172.     member2(Ascii, Alphabet),
  173.     after(Prev, Ascii),
  174.     op_count(Ascii, NumOps, MaxOps, NumOp2),
  175.     filter(Mode, Ascii, In, Out),
  176.     choose(Choices, Ascii, filter(Mode,Out), NumOp2, MaxOps, M).
  177.  
  178. % choose(+List_of_choices, -String_respecting_the_list_of_choices)
  179. choose2(Choices, MaxOps, String) :-
  180.     choose(Choices, 0'(, filter(all,[]), 0, MaxOps, String).    
  181.  
  182. % mandatory(+ListOfString,-ResultString)
  183. % builds a string containing all distinct chars from a list of string
  184. mandatory(Misplaced, Mandatory) :- append(Misplaced, T), sort(T, Mandatory).
  185.  
  186. % build_choice(+FoundSymbols,+AllPossibleSymbols,+MisplacedSymbols,-Result)
  187. % build a list of choices accounting for the ones already known, the list of
  188. % all possible symbols, and the mizplaced ohes.
  189. get_choice(Symbol, _, [Symbol]) :- memberchk(Symbol, "0123456789+-*/()"), !.
  190. get_choice(_, Alphabet, Alphabet).
  191.  
  192. build_choices([Symbol|L], Alphabet, [Misplaced|M], [Choice|C]) :-
  193.    get_choice(Symbol, Alphabet, Choice_),
  194.    subtract(Choice_, Misplaced, Choice),
  195.    build_choices(L, Alphabet, M, C).
  196. build_choices([], _, [], []).
  197.  
  198. % find a string compatible with the current constraints
  199. find(TargetNum, Found, Alphabet, Misplaced, MaxOps, String) :-
  200.    mandatory(Misplaced, Mandatory), % all misplaced symbols must be used (eg. mandatory)
  201.    build_choices(Found, Alphabet, Misplaced, Choices), % find all possible symbols for each cell
  202.    choose(Choices, MaxOps, String), % build a string from the possilities
  203.    subset(Mandatory, String), %  check that it uses all of the mandatory symbols
  204.    eval(String, Val), % evaluate the string
  205.    calc(TargetNum/1, -, Val, 0/_). % the value must match the goal number.
  206.  
  207. %main  :- find(12,"0123456789+-*/()", ["","","",""],S), puts(S), nl, fail.
  208.  
  209. %012.4.6.89+-*/()
  210. %....4.6.89+.*/..
  211.  
  212.  
  213. %main(Str) :- find(132, "../.*.+.", "0124689+-*/()", ["9","64","*","","/","8","","46"],Str),puts(Str), nl.
  214. %main(Str) :- find(132, "../.*.+.", "0124689+-*/()", ["","4","*","","/","","","6"],Str),puts(Str), nl.
  215. %main(Str) :- find(41, "........","5790-*/()",["","2","","","","-","8",""],Str),puts(Str),nl.
  216. %main(Str) :- find(41, "...-../.","257890-*/()",["","2","9","","2","-8","8",""],Str),puts(Str),nl.
  217.  
  218. %main(S) :- find(5,".....","1234567890+-*/",["","","","",""],S),puts(S),nl.
  219. %main(S) :- find(5,".....","1245690+*/",["","","","6",""],S),puts(S),nl.
  220.  
  221. %main(S):- find(26,"......","1234567890+-*/",["","","","","",""],S),puts(S),nl.
  222. %main(S):- find(26,"......","245680+-*/",["","2","","-","",""],S),puts(S),nl.
  223. %main(S):- find(26,"2..8..","24580-*/",["","24","","-","-",""],S),puts(S),nl.
  224.  
  225. %main(S):- find(69,".....","1234567890+-*/",["","","","",""],1,S),puts(S),nl.
  226. %main(S):- find(69,"....7","13467890-*/",["1","","","",""],1,S),puts(S),nl.
  227.  
  228. %main(S):- find(108,"......","1234567890+-*/",["","","","","",""],2,S),puts(S),nl.
  229. %main(S):- find(108,"1.5-.7","14567890+-*/",["","","","","",""],2,S),puts(S),nl.
  230.  
  231. %main(S) :- find(7,"........","1234567890+-*/()",["","","","","","","",""],3,S),puts(S),nl.
  232. %main(S) :- find(7,"1.3.....","12345689-/()",["","2","","4","","","",""],3,S),puts(S),nl.
  233.  
  234. %main(S):- find(28,"......","1234567890+-*/",["","","","","",""],2,S),puts(S),nl.
  235. %main(S):- find(28,".2....","246780+*/",["","","","","",""],2,S),puts(S),nl
  236. %main(S):- find(28,"42/...","24680*/",["","","","","",""],2,S),puts(S),nl.
  237.  
  238. %main(S) :- find(15,"........","1234567890+-*/()",["","","","","","","",""],3,S),puts(S),nl.
  239. %main(S) :- find(15,"........","2467890+-()",["","2","9","","","","4",""],3,S),puts(S),nl.
  240.  
  241. %main(S):- find(2,"../2.","24890+-*/",["2","4","","",""],1,S),puts(S),nl.
  242.  
  243. :- use_module(date).
  244. %main :- now(T1), findall(Str,main(Str),Set), now(T2), Time is T2-T1, length(Set,Size), write([size = Size, time = Time]), nl.
  245.  
  246. cmp_le(_=A, _=B) :- A  =<  B.
  247.  
  248. pivoting(_,[],[],[]).
  249. pivoting(H,[X|T],[X|L],G):-cmp_le(X,H),!,pivoting(H,T,L,G).
  250. pivoting(H,[X|T],L,[X|G]):-pivoting(H,T,L,G).
  251.  
  252. qsort(List,Sorted):-q_sort(List,[],Sorted).
  253. q_sort([],Acc,Acc).
  254. q_sort([H|T], Acc, Sorted) :-
  255.    pivoting(H, T, L1, L2),
  256.    q_sort(L1, Acc, Sorted1),
  257.    q_sort(L2, [H|Sorted1], Sorted).
  258.  
  259. :- dynamic count/2.
  260. start_stat :- retractall(count/2), forall(member(S, "0123456789+-*/()N"), assert(count(S,0))).
  261. inc_stat(S) :- retract(count(S,N)),N1 is N+1,assert(count(S,N1)).
  262. str_stat([X|L]) :- inc_stat(X), str_stat(L).
  263. str_stat([]).
  264. print_stat :-
  265.    findall(S=N, count(S,N), L),
  266.    qsort(L, Ls),
  267.    forall(member((S=N),Ls), (put_code(S),write(=),write(N),nl)),
  268.    nl.
  269.  
  270. rep(0,_,[]):-!.
  271. rep(N,X,[X|L]):-N1 is N-1, rep(N1, X, L).
  272.  
  273.  
  274. find2(Found, Alphabet, Misplaced, MaxOps, String) :-
  275.    mandatory(Misplaced, Mandatory), % all misplaced symbols must be used (eg. mandatory)
  276.    build_choices(Found, Alphabet, Misplaced, Choices), % find all possible symbols for each cell
  277.    choose2(Choices, MaxOps, String), % build a string from the possilities
  278.    subset(Mandatory, String), %  check that it uses all of the mandatory symbols
  279.    eval(String, Val/1),
  280.    between(10,99,Val),
  281.    str_stat(String),
  282.    str_stat("N"),
  283.    count(78, C),
  284.    write(C),
  285.    write('   '),
  286.    puts(String),
  287.    write(=),
  288.    write(Val),
  289.    nl.
  290.  
  291. main2(Size, MaxOp) :-
  292.    rep(Size, 0'., Found),
  293.     rep(Size, [], Misplaced),
  294.     find2(Found, "0123456789+-*/()", Misplaced, MaxOp, _).
  295.    
  296. main :- start_stat,forall(main2(6,2),true),nl,print_stat.
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement