I am doing OCaml 99, and can't quite understand some terms in this problem.
A string representation of binary trees. (medium)
Somebody represents binary trees as strings of the following type (see example): "a(b(d,e),c(,f(g,)))".
Write an OCaml function which generates this string representation, if the tree is given as usual (as Empty or Node(x,l,r) term).
Then write a function which does this inverse; i.e. given the string
representation, construct the tree in the usual form.
Finally, combine the two predicates in a single function
tree_string which can be used in both directions.
Write the same predicate tree_string using difference lists and a
single predicate tree_dlist which does the conversion between a tree
and a difference list in both directions.
For simplicity, suppose the information in the nodes is a single letter and there are no spaces in the string.
Here are my questions:
What does predicate mean in this problem?
For the 3rd point, it asks to make a function which can be used in both directions, i.e., can accept a tree and output a string or accept a string and output a tree. Should I use functor or something like that?
I totally can't understand the 4th point. What is difference lists?
These problems were originally intended to be solved in Prolog, which explains the terminology I think.
In Prolog a predicate can represent an equality (or maybe isomorphism is a better word?) between two sorts of values, such that if you have a value of one sort it can actually calculate the value of the other sort. I.e., it works as a two-way function. It's not at all clear how to code this in OCaml. Maybe you should peek at the answers?
A difference list is a Prolog data structure. Here's a SO page that seems to explain them (I googled very quickly): Understanding difference lists (Prolog)
Related
I am supposed to write a rule in SWI Prolog, which takes a list of characters as input and then replaces each letter by a random other character with a probability of 0.01.
Example:
?- mutate([a,b,c,d,e,f,g],MutatedList).
MutatedList = [a,b,c,a,e,f,g].
Can anyone tell me how that could be implemented? I am totally clueless so far about how this could work out in Prolog.
Thanks to anyone who can help!^^
This is relatively easy. You can use maplist/3 to relate the elements of the lists in a pairwise way. (Take a look at some of my notes on maplist/3].
For each pair [InputItem,OutputItem] sampled from [InputList,OutputList], maplist/3 will call a predicate, call it choose(InputItem,OutputItem).
That predicate will relate InputItem to the same value, InputItem or to a randomly chosen character (atom of length 1), which can be generated by selecting it randomly from a list of characters. The choice on whether to perform mutation can be made using random_float/0 for example.
Of course, choose(InputItem,OutputItem) is not really a predicate (it is just called that way, both in name at runtime), as it does not behave "predicatly" at all, i.e. it will have different outcomes depending on the time of day. It's an Oracle getting information from a magic reservoir. But that's okay.
Now you are all set. Not more than 4 lines!
I'm doing the Elixir koans, and already I've worked through something like five different listy data types:
List
Char list
Word list
Tuple
Keyword list
Map
MapSet
Struct
Some of these I buy, but all of them at the same time? Does anyone actually use all of these lists for strictly separated purposes?
Short answer is: yes.
Long answer is:
Lists - are a basic data structure you use everywhere. Lists are ordered and allow duplicates. The main use case is: homogenous varied-length collections
Charlists - where Elixir uses strings (based on binaries), Erlang usually uses charlists (lists of integer codepoints). It's mainly a compatibility interface;
Word lists - I've never heard of those;
Tuples - are another basic data structure you use everywhere. The main use case is: heterogenous fixed-length collections;
Keyword lists - are very common, mainly used for options. It's a simple abstraction on top of lists and tuples (a list of two-element tuples). Allow for duplicate keys and maintain order of keys, since they are ordered pattern-matching is very impractical.
Maps - are common too. Allow for easy pattern matching on keys, but do not allow duplicate keys and are not ordered.
MapSet - sets are a basic data structure - an unordered, unique collection of elements.
Structs - are the main mechanism for polymorphism in Elixir (through protocols), allow creating more rigid structures with keyset enforced at compile-time.
With functional programming choosing the right data structure to represent your data is often half of the issue, that's why you get so many different structures, with different characteristics. Each one has it's use-cases and is useful in different ways.
#michalmuskala provided here great answer, maybe I just extend it a bit.
Lists are the workhorse in Elixir. There's a plenty of issues that you will solve with lists. Lists are not arrays, where random access is the best way to get values, instead lists in Elixir are linked data structures and you traverse them by splitting into head and tail (if you know LISP, Prolog or Erlang, you'd will just like in home).
Charlists are just lists, but narrowed to lists of integers.
Tuples - usually they contain two to four elements. There are common way to pass additional data, but still send one parameter. Common behaviours like GenServer etc. uses them as an expected reply.
Keyword lists are list of tuples and you can use them when you need to store for one key more than one value. This is syntantic sugar.
Instead of a = [{:name, "Patryk"}] you can have a = [name: "Patryk"] and access it with a[:name].
Maps are associative arrays, hashes, dicts etc. One key holds one value and keys are unique.
Set - think about mathematicians sets. Unordered collection of unique values.
Struct - as #michalmuskala wrote they are used in protocols and they are checked by the compiler. Actually they're maps defined for module.
The answers are to be read from the bottom to the top :)
#michalmuskala provided here great answer, #patnowak extended it perfectly. I am here to mostly answer to the question “Does anyone actually use all of these lists for strictly separated purposes?“
Elixir (as well as Erlang) is all about pattern matching. Having different types of lists makes it easy to narrow the pattern matching in each particular case:
List is used mostly in recursion; Erlang has no loops, instead one does recursive calls. It’s highly optimized when used properly (tail-recursion.) Usually matches as [head | tail].
charlist is used in “string” pattern matching, whatever it means. Check for “the first letter of his name is ‘A’” in Erlang would be done with pattern match against [?A | rest] = "Aleksei" |> List.Chars.to_charlist
Tuple is used in pattern matching of different instances of the more-or-less same entity. Fail/Success would be returned as tuples {:ok, result} and {:error, message} respectively and pattern matched afterwards. GenServer simplifies handling of different messages that way as well.
Map is to be pattern matched as %{name: "Aleksei"} = generic_input to immediately extract the name. Keywords are more or less the same.
etc.
I understand how an AVL tree works with integers.. but I'm having a hard time figuring out a way to insert strings into one instead. How would the strings be compared?
I've thought of just using the ASCII total value and sorting that way.. but in that situation, inserting two identical ASCII words (such as "tied" and "diet") would seem to return an error.
How do you get around this? Am I thinking about it in the wrong way, and need a different way to sort the nodes?
And no they don't need to be alphabetical or anything... just in an AVL tree so I can search for them quickly.
When working with strings, you normally use a lexical comparison -- i.e., you start with the first character of each string. If one is less than the other (e.g., with "diet" vs. "tied", "d" is less than "t") the comparison is based on that letter. If and only if the first letters are equal, you go to the second letter, and so on. The two are equal only if every character (in order) from beginning to end of the strings are equal.
Well, since an AVL tree is an ordered structure, the int string::compare(const string&) const routine should be able to give you an indication of how to order the strings.
If order of the items is actually irrelevant, you'll get better performance out of an unordered structure that can take better advantage of what you're trying to do: a hash table.
The mapping of something like a string to a fixed-size key is called a hash function, and the phenomenon where multiple keys are mapped to the same value is called a collision. Collisions are expected to happen occasionally when hashing, and a basic data structure would needs to be extended to handle it, perhaps by making each node a "bucket" (linked list, vector, array, what have you) of all the items that have colliding hash values that is then searched linearly.
Prolog has a unique way of handling things, especially since practically every operation involves recursion of one sort or another.
One of the classic examples every language has is sorting a list of integers into ascending order.
What is an optimal way (without using too many built-in predicates, which precludes a sort/2 predicate, of course) to sort a random list of integers?
Roman Barták's Prolog Programming site gives examples of different sort algorithms, ending with an optimized quicksort.
quick_sort2(List,Sorted):-q_sort(List,[],Sorted).
q_sort([],Acc,Acc).
q_sort([H|T],Acc,Sorted):-
pivoting(H,T,L1,L2),
q_sort(L1,Acc,Sorted1),q_sort(L2,[H|Sorted1],Sorted)
As far as I know the best sorting algorithms written in Prolog directly, without reference to any special built-ins use some form of merge sort.
A frequent optimization is to start merging not with lists of length 1 but with already sorted segments.
That is, to sort the list [4,5,3,6,2,7,1,2], the lists [4,5],[3,6],[2,7],[1,2] would be merged.
This can be optimized even further by assembling sorted lists not only in ascending direction, but also in the other direction. For the example above this would mean that the sorted segment is assembled as follows:
[4,5|_]
[3,4,5|_]
[3,4,5,6|_]
...
Note that in Prolog it is straight forward to extend a list both in the beginning and at the end.
Thus, we have to merge [1,2,3,4,5,6,7] and [2] only.
A current system that uses the original implementation (~1984) of Richard O'Keefe is Ciao-Prolog in
ciao-1.15/lib/sort.pl.
I've been tasked with the portion of the code that reads through two lists and finds a path between the two lists.
My problem is however with reading and returning a TRUE case if I find the required node in the first list. I've been writing my code as below.
%declare the list
circle_line([cc1,cc2,cc3,cc4,cc5,cc6,cc7,cc8,cc9,cc10,cc11,cc12,cc13,cc14,cc15,cc16]).
%the predicate that finds the station i need
check_for_station(A) :- circle_line(X),
member(A,X),
write(A),nl.
Then in the cosole I type: check_for_station(cc9).
But the answer I get is "no."
I have a feeling that I'm declaring the list wrong, because in the debugger the value of X comes out to be "H135" or something and it clearly does not loop through every element to find the one that I need.
As whythehack found, in Amzi! Prolog the classic (and nondeterministic) member/2 predicate is not a "built-in" but is provided (along with other useful list manipulation predicates like length/2) in the list library. See here for some context about the built-in versus library predicates for lists.
If check_for_station/1 is only to be called with its argument A bound (as the example suggests), then Amzi!'s built-in (and deterministic) predicate is_member/2 will do the job (and a bit more quickly).
The thinking seems to be that nondeterministic member/2 is a two-line user-definition, and providing a faster deterministic version (not permitting backtracking over members of a list) is something the user could not easily provide for themselves.