Advertisement
Guest User

Untitled

a guest
Feb 25th, 2022
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Prolog 6.98 KB | None | 0 0
  1. :- dynamic digit_/1.
  2. %digit(X) :-  digit_(X),!;member(X, "0123456789"),assert(digit_(X)).
  3. digit(X) :- member(X,"0123456789").
  4.  
  5. % parses a number
  6. num(Num, [Digit|L], Res, M) :-
  7.     digit(Digit), !,
  8.     num(Num*10+Digit-48, L, Res, M).
  9. num(Num, L, Res/1, L) :- Res is Num.
  10.  
  11. % convert list of ascii codes into tokens
  12. tokenize(0'+,+). tokenize(0'-,-). tokenize(0'*,*). tokenize(0'/,/).
  13. tokenize(0'(,'('). tokenize(0'),')').
  14. tokenize([],[]).
  15. tokenize([Ascii|L], [Symbol|M]) :-
  16.     tokenize(Ascii, Symbol),
  17.     tokenize(L, M).
  18. tokenize([0'0,Digit|_],_) :-  digit(Digit),!,fail. % reject leading digit.
  19. tokenize([Digit|L], [Num|M]) :-
  20.    digit(Digit),
  21.    num(Digit-48, L, Num, R),
  22.    tokenize(R, M).
  23.  
  24. %testcase
  25. %main :- tokenize("(1-2)*345+0",X), write(X),nl,fail.
  26.  
  27. % symbol kind
  28. operator(+). operator(-). operator(*). operator(/).
  29. bra('('). ket(')').
  30.  
  31. % calculate a simple opeation
  32. rational(_/_).
  33. calc(U, V, P/Q) :- % normalize
  34.    X is U,
  35.    (   X=0 ->
  36.        P=0,
  37.        Q=1
  38.    ;   Y is V,
  39.        Z is gcd(X,Y),
  40.        P is X div Z,
  41.        Q is Y div Z
  42.    ).
  43. calc(A/B, +, C/D, R) :- calc(A*D+B*C, B*D, R).
  44. calc(A/B, -, C/D, R) :- calc(A*D-B*C, B*D, R).
  45. calc(A/B, *, C/D, R) :- calc(A*C, B*D, R).
  46. calc(_, /, 0/_, _) :- !, fail. % canโ€™t divide by 0
  47. calc(A/B, /, C/D, R) :- calc(A*D, B*C, R).
  48.  
  49. % operator precedence
  50. precedence(+,1). precedence(-,1). precedence(*,2). precedence(/,2).
  51.  
  52. % Shunting-yard algorithm
  53. eval_op(X, L, [A,B|Nums], [Y|Ops], Res) :-
  54.    precedence(X, Px),
  55.    precedence(Y, Py),
  56.    Px =< Py, !,
  57.    calc(B, Y, A, C),
  58.    eval(L, [C|Nums], [X|Ops], Res).
  59. eval_op(X, L, Nums, Ops, Res) :-
  60.    eval(L, Nums, [X|Ops], Res).
  61.  
  62. eval_ket(L, Nums, [X|Ops], Res) :-
  63.    bra(X), !,
  64.    eval(L, Nums, Ops, Res).
  65. eval_ket(L, [X,Y|Nums], [Op|Ops], Res) :-
  66.    calc(Y, Op, X, Z),
  67.    eval_ket(L, [Z|Nums], Ops, Res).
  68.  
  69. eval([Tk|L], Nums, Ops, Res) :-
  70.    (   rational(Tk) ->
  71.        eval(L, [Tk|Nums], Ops, Res)
  72.    ;   operator(Tk) ->
  73.        eval_op(Tk, L, Nums, Ops, Res)
  74.    ;   bra(Tk) ->
  75.        eval(L, Nums, [Tk|Ops], Res)
  76.    ;   ket(Tk) ->
  77.        eval_ket(L, Nums, Ops, Res)
  78.    ).
  79. eval([], [X,Y|Nums], [Op|Ops], Res) :-
  80.    calc(Y, Op, X, Z),
  81.    eval([], [Z|Nums], Ops, Res).
  82. eval([],[N],[],N).
  83.  
  84. % eval(-String, +Value)
  85. eval(Str, Val) :-
  86.    tokenize(Str, TokenList),
  87.    eval(TokenList, [], [], Val).
  88.  
  89. % print a string
  90. puts([X|L]) :- put_code(X),puts(L).
  91. puts([]).
  92.  
  93. %testcase
  94. %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.
  95.  
  96. % possible next character
  97. :- dynamic(after_/2).
  98. after(X, Y) :-
  99.    (   after_(X, Y), !
  100.    ;   (   member(X, "0123456789") ->
  101.            member(Y, "0123456789+-*/)")
  102.        ;   member(X, "+-*/(") ->
  103.            member(Y, "0123456789(")
  104.        ;   member(X, ")") ->
  105.            member(Y, "+-*/)")
  106.        ),
  107.        assert(after_(X,Y))
  108.    ).
  109.  
  110. % utility to select either a l8st with or without distinct elements
  111. filter(+distinct,Ascii,L,_) :- member(Ascii,L), !,fail.
  112. filter(+distinct,Ascii,L,[Ascii|L]) :- !.
  113. filter(+distinct,_,_,done).
  114.  
  115. filter(-distinct, Ascii, L, done) :- member(Ascii, L), !.
  116. filter(-distinct, _, done, done) :- !.
  117. filter(-distinct, Ascii, L, [Ascii|L]).
  118.  
  119. % choose(+Possible_symbols, +Previous_symbol, +Distinct_filter, -Result)
  120. choose([Alphabet], Prev, filter(Mode,In), [Ascii]) :-
  121.    member(Ascii, Alphabet),
  122.    member(Ascii, "0123456789)"),
  123.    after(Prev, Ascii),
  124.    filter(Mode, Ascii, In, done).
  125. choose([Alphabet|Choices], Prev, filter(Mode,In), [Ascii|M]) :-
  126.    member(Ascii, Alphabet),
  127.    after(Prev, Ascii),
  128.    filter(Mode, Ascii, In, Out),
  129.    choose(Choices, Ascii, filter(Mode,Out), M).
  130.  
  131. % choose(+List_of_choices, -String_respecting_the_list_of_choices)
  132. choose(Choices, String) :-
  133.    choose(Choices, 0'(, filter(+distinct,[]), String) ; % distinct ekelents first
  134.     choose(Choices, 0'(, filter(-distinct,[]), String).
  135.  
  136. % for debuugging
  137. found(String, Val, Target) :-
  138.    puts(String),
  139.    write(=),
  140.    E is Val-Target,
  141.    write(Target+E),
  142.    nl.
  143.  
  144. % all_ member(+String1, +Srring2) check that all chars of String1 appear in String2
  145. all_member([X|L], String) :- member(X, String), all_member(L, String).
  146. all_member("",_).
  147.  
  148. % mandatory(+ListOfString,+Auxlist,-ResultString)
  149. % builds a string containing all distinct chars from a list of string
  150. mandatory([X|M],InSet,OutSet) :-
  151.    mandatory2(X,InSet,TempSet),
  152.    mandatory(M,TempSet,OutSet).
  153. mandatory([],Set,Set).
  154. mandatory2([X|L], InSet, OutSet) :-
  155.    (   member(X, InSet) ->
  156.        mandatory2(L, InSet, OutSet)
  157.    ;   mandatory2(L, [X|InSet], OutSet)
  158.    ).
  159. mandatory2([],Set,Set).
  160.  
  161. % set difference
  162. diff([X|L], Set, Diff) :-
  163.    (   member(X, Set) ->
  164.        diff(L, Set, Diff)
  165.    ;   Diff=[X|Diff2],
  166.        diff(L, Set, Diff2)
  167.    ).
  168. diff([],_,[]).
  169.  
  170. % build_choice(+FoundSymbols,+AllPossibleSymbols,+MisplacedSymbols,-Result)
  171. % build a list of choices accounting for the ones already known, the list of
  172. % all possible symbols, and the mizplaced ohes.
  173. get_choice(Symbol, _, [Symbol]) :- member(Symbol, "0123456789+-*/()"), !.
  174. get_choice(_, Alphabet, Alphabet).
  175. build_choices([Symbol|L], Alphabet, [Misplaced|M], [Choice|C]) :-
  176.    get_choice(Symbol, Alphabet, Choice_),
  177.    diff(Choice_, Misplaced, Choice),
  178.    build_choices(L, Alphabet, M, C).
  179. build_choices([], _, [], []).
  180.  
  181. % find a string compatible with the current constraints
  182. find(GoalNumber, Found, Alphabet, Misplaced, String) :-
  183.    mandatory(Misplaced, [], Mandatory), % all misplaced symbols must be used (eg. mandatory)
  184.    build_choices(Found, Alphabet, Misplaced, Choices), % find all possible symbols for each cell
  185.    choose(Choices, String), % build a string from the possilities
  186.    all_member(Mandatory, String), %  check that it uses all of the mandatory symbols
  187.    eval(String, Val), % evaluate the string
  188.    calc(GoalNumber/1, -, Val, 0/_). % the value must match the goal number.
  189.  
  190. %main  :- find(12,"0123456789+-*/()", ["","","",""],S), puts(S), nl, fail.
  191.  
  192. %012.4.6.89+-*/()
  193. %....4.6.89+.*/..
  194.  
  195.  
  196. %main(Str) :- find(132, "../.*.+.", "0124689+-*/()", ["9","64","*","","/","8","","46"],Str),puts(Str), nl.
  197. %main(Str) :- find(132, "../.*.+.", "0124689+-*/()", ["","4","*","","/","","","6"],Str),puts(Str), nl.
  198. %main(Str) :- find(41, "........","5790-*/()",["","2","","","","-","8",""],Str),puts(Str),nl.
  199. %main(Str) :- find(41, "...-../.","257890-*/()",["","2","9","","2","-8","8",""],Str),puts(Str),nl.
  200.  
  201. %main(S) :- find(5,".....","1234567890+-*/",["","","","",""],S),puts(S),nl.
  202. %main(S) :- find(5,".....","1245690+*/",["","","","6",""],S),puts(S),nl.
  203.  
  204. %main(S):- find(26,"......","1234567890+-*/",["","","","","",""],S),puts(S),nl.
  205. %main(S):- find(26,"......","245680+-*/",["","2","","-","",""],S),puts(S),nl.
  206. main(S):- find(26,"2..8..","24580-*/",["","24","","-","-",""],S),puts(S),nl.
  207.  
  208. :- use_module(date).
  209. main :- now(T1), findall(Str,main(Str),Set), now(T2), Time is T2-T1, length(Set,Size), write([size = Size, time = Time]), nl.
  210.  
  211.  
  212.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement