I'm currently stuck with the following problem :
I have a database of n elements and I want to do a recursive search so that I will get all the possible matches .
So , lets say , I get k matches for the first pattern . For every k matches I found I re-search the database with the next pattern and get the new association lists ....and so on . This is my problem , I cannot make a function that will give me all the results .
I really cannot get myself to think of a "plan" to attack this problem . I always wonder how to save my curent assoc-list and , at the same time , remove it when I get to the end.
Summary of my idea: If I have a database=db and need to match n patterns . I start with pattern 0 , get k assoc-list and I want to move forward to match pattern 1 , having in mind I have k assoc-lists from the previous,. I finish pattern 1 and get M assoc-list , for every m assoc-list I go forward ... In the end I either get a assoc-list of size n(number of patterns) or get false.
I really only want some ideas so I can get past this "brick wall". Please judge,stab,kill my idea , anything. Thank you.
I am not certain whether you wish to narrow or broaden your search based on subsequent searches. Here is pseudocode that broadens:
recursive_search (list_of_patterns)
if is_empty(list_of_patterns)
return empty_list
pattern = pop_first(list_of_patterns)
return query(pattern) + recursive_search(list_of_patterns)
EDIT to keep your pattern with the query as an alist... my scheme-foo is weak, but here goes:
(define query_alist (lambda x)(x . query-exec(x)))
(define r_query (lambda pattern__list)
(cond
((null pattern_list) ())
(else ((query_alist (first pattern_list) (r_query (rest pattern_list)))
)
)
Related
As a part of a Tic Tac Toe playing bot, I need a function that evaluates combinations of tiles to points. The code would look something like this:
(case combination
("EEEEE" 0)
("EEEEP" 1)
("EEEPE" 1)
("EEEPP" 2)
("EEPEE" 1)
("EEPEP" 2)
("EEPPE" 2)
("EEPPP" 3)
("EPEEE" 1)
("EPEEP" 2)
("EPEPE" 2)
("EPEPP" 3)
("EPPEE" 2)
("EPPEP" 3)
("EPPPE" 3)
("EPPPP" 4)
("PEEEE" 1)
("PEEEP" 2)
("PEEPE" 2)
("PEEPP" 3)
("PEPEE" 2)
("PEPEP" 3)
("PEPPE" 3)
("PEPPP" 4)
("PPEEE" 2)
("PPEEP" 3)
("PPEPE" 3)
("PPEPP" 4)
("PPPEE" 3)
("PPPEP" 4)
("PPPPE" 4)
("PPPPP" 5))
(This is not the place to discuss the value of such an approach, for it is used for reasons unrelated to the question)
The problem is that case uses a predicate that doesn't return true for identical strings that aren't the same object (hard to find if it's eq or eql). How can you change that?
EDIT: I solved the original problem by converting the string into a corresponding binary number, which can be compared using eql or used as an index in a list.
Use alexandria:switch from the alexandria library, available from quicklisp.
(switch (combination :test #'string=)
("FOO" …)
…)
Your code just calculates (count #\P combination).
Usually I would convert the string in a number and compute with it. Using LOGCOUNT to get the on bits or something. Even if I were using a large CASE-like switch, I would convert the string once to a number, instead of doing a multitude of string comparisons.
You could write a macro:
(defmacro string-case (key &rest forms)
(let ((k (gensym "KEY")))
`(let ((,k ,key))
(cond
,#(loop for (str . body) in forms
collect `((string= ,k ,str) ,#body))))))
And then use it like case. Note that this macro will check each substring one at a time (up to 32 branches in your case), which is less efficient than eg looking at the first character and deciding what to do, then looking at the next character and so on (5-10 branches in your case), which is less efficient than doing what you actually intend (eg counting #\P) (this can be done with 5-6 easily predicted branches, or maybe 10 depending on implementation). Of these options, the second generated the most code, then the first, then the third.
Another approach would be to convert combination to a symbol. The resulting code will look like this:
(case (intern combination)
(EEEEE 0)
(EEEEP 1)
(EEEPE 1)
...)
But you need to keep in mind that intern operates at runtime in the context of current package (*package*), which means that if this is part of a function that is called outside of the package where it's defined, it will not work. There are 2 ways to work around this (basically, two variations of one): either intern in the package ((intern combination <your-package>)) or intern as keyword. In the later case, the whole form will look like this:
(case (intern combination :keyword)
(:EEEEE 0)
(:EEEEP 1)
(:EEEPE 1)
...)
Also worth noting may be performance considerations. They shouldn't be a problem as, although interning is a rather heavy operation, initially, when it's called repeatedly on an already interned symbol it's, basically, just a dictionary lookup.
Another solution may be to define the rules as a list, and search through the list for the matching string.
(defun match-combination (combination)
(let ((rules '(("EEEEE" 0)
("EEEEP" 1)
("EEEPE" 1)
...)))
(cadr (find combination rules :key #'car :test #'string=))))
I'm learning Scheme for the first time, and for practice I'm trying to write a program that returns a list of a specified length with all values equal to 1. I'm using the MIT/GNU Edwin editor on Windows 10. Here's the code I typed:
(define (listlength n)
(if (= n 1)
(list 1)
(append (list 1) (listlength (- n 1)))))
(listlength 5)
I would hope for C-x C-e to return (1 1 1 1 1), but instead I get an unbound variable error:
;Unbound variable: listlength
;To continue, call RESTART with an option number:
; (RESTART 3) => Specify a value to use instead of listlength.
; (RESTART 2) => Define listlength to a given value.
; (RESTART 1) => Return to read-eval-print level 1.
;Start debugger? (y or n):
The only reason I can think of is that it doesn't like me calling listlength in the definition of listlength, but that's supposed to be part of what makes Scheme Scheme, so??? i'm at a loss?? Thanks for any help you can give me!
You should check if you use C-x C-e at the end of the function. C-x C-e will evaluate the expression at the left of the cursor. Or you can use M-z ,which will evaluate the whole expression not matter where is the cursor.
I am also a beginner of Scheme, and I hope the answer can help you!
So I am trying to draw the decision of tree of 2 Prolog problems, one that uses the accumulator and other that doesn't. Here are my problems and the solutions I did, respectively:
length([H|T],N) :- length(T,N1), N is N1+1.
length([ ],0).
Goal: ?: length([1,2,3],N)
Second one with accumulator:
length_acc(L,N) :- len_acc(L,0,N).
len_acc([H|T], A, N) :- A1 is A+1, len_acc(T, A1, N).
len_acc([], A, A).
Goal: ?-length_acc([1,2], N).
Are the decision trees correctly drawn? Or have I made a mistake? Whats the correct way to draw these kind of recursive decision tree?
Thanks.
The tree you are referring to is usually called a search-tree aka SLD-tree, not to be confused with a proof-tree.
Both the problems you have outlined are the most simple cases of search-trees:
there is only one solution
the query does not fail
each step in the search can only match a single clause (empty list vs non-empty list)
These three characteristics imply that there will only be a single branch in the SLD tree.
You'll get the following search-trees:
Note that for it to be a correct search-tree, at most one goal is resolved in each step, which makes search-trees very large... therefore it's common that people make simplified trees where multiple goals can be resolved in each step, which arguably are not true search-trees but illustrates the search in a more succint way.
Edges in the tree are labeled with substitutions that are applied to the variables as part of the unification algorithm.
Search-trees correspond closely to traces, and you can usually do a straight translation from a trace of your program to a search tree.
I advise you to study search-trees for queries that have multiple answers and branches that can fail, which gives more interesting trees with multiple branches. An example from The Art of Prolog by Sterling, Shapiro:
Program:
father(abraham, isaac). male(isaac)
father(haran, lot). male(lot).
father(haran, milcah). female(milcah).
father(haran, yiscah). female(yiscah).
son(X,Y):- father(Y,X), male(X).
daughter(X,Y):- father(Y,X), female(X).
Query:
?: son(S, haran)
Search-tree:
A nice way to understand something is to re-implement it yourself.
It's especially nice to implement Prolog when you already have Prolog to implement it with. :)
program( patriarchs, P ) :-
P = [ % [son(S, haran)] , % Resolvent
[father(abraham, isaac)] % Clauses...
, [father(haran, lot)] % [Head, Body...]
, [father(haran, milcah)]
, [father(haran, yiscah)]
, [male(isaac)]
, [male(lot)]
, [female(milcah)]
, [female(yiscah)]
, [son(X,Y), father(Y,X), male(X)]
, [daughter(X,Y), father(Y,X), female(X)]
].
solve( Program ):-
Program = [[] | _]. % empty resolvent -- success
solve( [[Goal | Res] | Clauses] ) :-
member( Rule, Clauses),
copy_term( Rule, [Head | Body]), % rename vars
Goal = Head, % unify head
append( Body, Res, Res2 ), % replace goal
solve( [Res2 | Clauses] ).
query( What, Query ):- % Query is a list of Goals to Solve
program( What, Program),
solve( [ Query | Program ] ).
Testing,
23 ?- query( patriarchs, [son(S, haran)] ).
S = lot ;
false.
Now the above solve/1 can be augmented to record the record of successful instantiations of Goal making the unifications Goal = Head possible.
Basically what I am trying to do with this is alter the reader so that it will accept vector notation like i+j+k. The goal of this is to convert things that look like vectors into strings while not affecting anything else. For instance, if someone typed in abc it would still throw an error message, but if someone typed in i+j+k would return "i+j+k".
This is what I have so far:
#lang racket/base
(require syntax/strip-context)
(provide (except-out (all-from-out racket/base)
#%top)
(rename-out (#%my-top #%top)))
(require (for-syntax racket/base))
(define-syntax (#%my-top stx)
(syntax-case stx ()
[(_ . quat)
#' (test (#%datum . quat))]
[(_ . other)
(syntax/loc stx
(#%datum . other))]))
(define (quat? testExp)
(regexp-match-exact? #rx"([+-]?([0-9]+[i-k]?|[0-9]*[i-k])([+-]([0-9]+[i-k]?|[0-9]*[i-k]))*)" testExp))
(define (test x)
(cond ((quat? (symbol->string x)) (symbol->string x))
(else (strip-context x))))
This code does work in converting vector notation into strings. i+j+k successfully becomes "i+j+k". But the problem is that it converts EVERYTHING into syntax first, and I cannot get it back to whatever it originally was. For example, abc will become 'abc and it wont throw an error like it normally should. I have no idea how to get around this. I originally thought all I needed was a simple change to that else statement on the final line, but I cannot get anything to work. I am beginning to think I need to try a completely new approach. Any help would be greatly appreciated.
Also, it should be noted that you have to have this code in one file, I called mine parse.rkt, and perform your tests in a separate file that only has
#lang racket
(require "parse.rkt")
I'm working on a p2p app that uses hash trees.
I am writing the hash tree construction functions (publ/4 and publ_top/4) but I can't see how to fix publ_top/4.
I try to build a tree with publ/1:
nivd:publ("file.txt").
prints hashes...
** exception error: no match of right hand side value [67324168]
in function nivd:publ_top/4
in call from nivd:publ/1
The code in question is here:
http://github.com/AndreasBWagner/nivoa/blob/886c624c116c33cc821b15d371d1090d3658f961/nivd.erl
Where do you think the problem is?
Thank You,
Andreas
Looking at your code I can see one issue that would generate that particular exception error
publ_top(_,[],Accumulated,Level) ->
%% Go through the accumulated list of hashes from the prior level
publ_top(string:len(Accumulated),Accumulated,[],Level+1);
publ_top(FullLevelLen,RestofLevel,Accumulated,Level) ->
case FullLevelLen =:= 1 of
false -> [F,S|T]=RestofLevel,
io:format("~w---~w~n",[F,S]),
publ_top(FullLevelLen,T,lists:append(Accumulated,[erlang:phash2(string:concat([F],[S]))]),Level);
true -> done
end.
In the first function declaration you match against the empty list. In the second declaration you match against a list of length (at least) 2 ([F,S|T]). What happens when FullLevelLen is different from 1 and RestOfLevel is a list of length 1? (Hint: You'll get the above error).
The error would be easier to spot if you would pattern match on the function arguments, perhaps something like:
publ_top(_,[],Accumulated,Level) ->
%% Go through the accumulated list of hashes from the prior level
publ_top(string:len(Accumulated),Accumulated,[],Level+1);
publ_top(1, _, _, _) ->
done;
publ_top(_, [F,S|T], Accumulated, Level) ->
io:format("~w---~w~n",[F,S]),
publ_top(FullLevelLen,T,lists:append(Accumulated,[erlang:phash2(string:concat([F],[S]))]),Level);
%% Missing case:
% publ_top(_, [H], Accumulated, Level) ->
% ...