Related
I'm new to Prolog and what I'm trying to achieve is to define the tower-like type which contains lists of natural numbers. Each "floor" is supposed to have the same amount of "apartments" and I don't know how can I check it.
Assuming with "type" you mean a structure which can hold your data, I suggest using a list of lists, like this:
[[101,102,103],[201,202,203],[301,302,303]]
So now you need to check if each "floor" (sublist), has the same amount of elements. Counting the elements in a list is rather simple:
len([],0).
len([H|T],N1) :-
len(T,N),
N1 is N+1.
Which reads: an empty list [] has 0 elements. A list which can be splittet into a head element H and a rest list T has the length N1, if the length of T is N and N1 is calculated by N+1.
So what is missing? You need to go through all your sublists and get the length of the sublist. If the length of two sublists are different, then fail. If you reach the end with allways the same number, success. So the pattern would look like this:
isHotel(R):-
isHotel(R,_).
Add a placeholder for the counting, actual number of the second argument does not matter at this point.
isHotel([],_) .
If you got to a point where there are no floors left, accept for any number.
isHotel([CurrentFloor|T],N) :-
len(CurrentFloor,N),
isHotel(T,N).
If there are floors left (floorlist can be devided into the current floor CurrentFloor and all floors above T), count the rooms at this floor and go check with the left over floors T. The first time this is runs, the number N of rooms will be calculated and forwarded to every other call - therefore for the first time the calculation is just a calculation, in every other ecxecution it is a check as well. This leads to rejects if two lusts do not match in size. Please note this code does not check if the input is a list of lists of numbers.
Checked with SWISH:
?- isHotel([[101,102,103],[201,202,203],[301,302,303]]).
true.
?- isHotel([[101,102,103],[201,202,203],[301,302,3,03]]).
false.
?- isHotel([]).
true.
How does this bubble sort solution work in Prolog?
bubblesort([], []).
bubblesort([H], [H]).
bubblesort([H|D], R) :-
bubblesort(D, E),
[B|G] = E,
( (H =< B, R = [H|E])
; (H > B, bubblesort([B,H|G], R))
).
Here is an example trace: https://pastebin.com/T0DLsmAV
I understand the the line bubblesort(D,E), is responsible for sorting it down to one element, but I don't understand how this works. I understand the basics of lists in prolog, but still cannot work out how this solution operates.
The main difficulty with this code is that bad variable names were chosen and are making the logic harder to follow than it needs to be.
The first two cases are obviously base cases. The first says "the empty list is already sorted" and the second says "a singleton list is already sorted." This should make sense. The third case is where things get interesting.
Let's examine the first part.
bubblesort([H|D], R) :-
bubblesort(D, E),
All that's happened so far is we've named our result R and broken our inputs into a first element H and a tail D. From there, we have said, let's bubblesort the tail of our input and call that E. Maybe this would be a little easier to follow?
bubblesort([H|T], Result) :-
bubblesort(T, TSorted),
Next up,
[B|G] = E,
Again, bad names, but what the author is intending to do here is straightforward: take apart the result of sorting the tail so we can talk about whether the next item in the sorted tail is the right element for that position, or if it needs to switch places with the head of our input. Let's rename:
[HeadOfTSorted|RestOfTSorted] = TSorted,
Now we have a condition. Think of it in terms of prepending onto a sorted list. Say you have some element, like 3, and I hand you a sorted list. You want to determine if your 3 goes at the front or somewhere else. Well, suppose I gave you a sorted list that looked like [5,7,19,23,...]. You'd know that your 3 is right where it needs to be, and you'd hand back [3,5,7,19,23,...]. That's exactly the first case of the condition:
( (H =< HeadOfTSorted, Result = [H|TSorted])
Now consider another case, where I hand you a list that starts with [1,2,...]. You know you can't just put the three at the start and give me back [3,1,2,...]. But you don't really know where the 3 goes; it just doesn't go at the start. So what you have to do is resort the rest of the list with the 3 at the start, after the 1: [1 | resorted([3,2,...])]. That's effectively the other branch of the condition:
; (H > HeadOfTSorted, bubblesort([HeadOfTSorted,H|RestOfTSorted], R))
).
Hope this helps!
note: the key to recursive problem solving is exactly not to think about the minutiae of our code's operations. Imagine you already have the solution, then just use it to solve a smaller subproblem, thus arriving at the full problem's solution.
Your code, with more suggestive variable names so I could follow it, reads:
bubblesort([], []). % empty list is already sorted
bubblesort([H], [H]). % singleton list is already sorted
bubblesort([H|T], S) :- % `[H|T]` sorted is `S`, *if*
bubblesort(T, [M|R]), % `T` sorted is `[M|R]`, *and*
( % *either*,
H =< M, % in case `H` is not greater than `M`,
S = [H,M|R] % `S` is `[H,M|R]`,
; % *or*
H > M, % in case `H` is greater than `M`,
bubblesort([M,H|R], S) % `S` is `[M,H|R]` sorted by the same algorithm
).
(H is for "head", T is for "tail", S is "sorted", R "rest" and M is "minimum" -- see below for that).
We prove its correctness by structural induction. The induction hypothesis (IH) is that this definition is correct for shorter lists. We need to prove it is then also correct for a longer list. Indeed T is one-element shorter than [H|T]. Thus IH says [M|R] is sorted. This means M is the minimum element in T. It also means T is non-empty (sorting doesn't change the number of elements), so the clauses are indeed mutually-exclusive.
If H is not larger than the minimum element in T, [H,M|R] is obviously sorted.
Otherwise, we sort [M,H|R]. M is the minimum element and thus guaranteed to be the first in the result. What's actually sorted is [H|R], which is one element shorter, thus by IH sorting it works. QED.
If the last step sounds fishy to you, consider replacing the second alternative with the equivalent
; H > M, % in case `H` is greater then `M`,
bubblesort([H|R], S1), % `S1` is `[H|R]` sorted by the same algorithm
S = [M|S1]
).
where the applicability of the induction step is even clearer.
I'm not so sure it's a bubble sort though.
update: Indeed, measuring the empirical orders of growth, its number of inferences grows as ~ n3 (or slower), but true bubble sort clocked at ~ n2.1 (close enough to the theoretical ~ n2), where n is the list's length:
tbs([], []). % 'true' bubble sort
tbs([H],[H]).
tbs(L,S):- bubble(L,B),
( L==B -> S=L ; tbs(B,S) ).
bubble([],[]).
bubble([A],[A]).
bubble([A,B|C],R):-
( A =< B -> bubble([B|C],X), R=[A|X]
; bubble([A|C],X), R=[B|X] ).
I just can't understand how this algorithm works. All the explanations I've seen say that if you have a set such as {A, B, C} and you want all the permutations, start with each letter distinctly, then find the permutations of the rest of the letters. So for example {A} + permutationsOf({B,C}).
But all the explanations seem to gloss over how you find the permutations of the rest. An example being this one.
Could someone try to explain this algorithm a little more clearly to me?
To understand recursion you need to understand recursion..
(c) Programmer's wisdom
Your question is about that fact, that "permutations of the rest" is that recursive part. Recursion always consist of two parts: trivial case and recursion case. Trivial case points to a case when there's no continue for recursion and something should be returned.
In your sample, trivial part would be {A} - there's only one permutation of this set - itself. Recursion part will be union of current element and this "rest part" - i.e. if you have more than one element, then your result will be union of permutation between this element and "rest part". In terms of permutation: the rest part is current set without selected element. I.e. for set {A,B,C} on first recursion step that will be {A} and "rest part": {B,C}, then {B} and "rest part": {A,C} - and, finally, {C} with "rest part": {A,B}
So your recursion will last till the moment when "the rest part" will be single element - and then it will end.
That is the whole point of recursive implementation. You define the solution recursively assuming you already have the solution for the simpler problem. With a little tought you will come to the conclusion that you can do the very same consideration for the simpler case making it even more simple. Going on until you reach a case that is simple enough to solve. This simple enough case is known as bottom for the recursion.
Also please note that you have to iterate over all letters not just A being the first element. Thus you get all permutations as:
{{A} + permutationsOf({B,C})} +{{B} + permutationsOf({A,C})} + {{C} + permutationsOf({A,B})}
Take a minute and try to write down all the permutations of a set of four letters say {A, B, C, D}. You will find that the algorithm you use is close to the recursion above.
The answer to your question is in the halting-criterion (in this case !inputString.length).
http://jsfiddle.net/mzPpa/
function permutate(inputString, outputString) {
if (!inputString.length) console.log(outputString);
else for (var i = 0; i < inputString.length; ++i) {
permutate(inputString.substring(0, i) +
inputString.substring(i + 1),
outputString + inputString[i]);
}
}
var inputString = "abcd";
var outputString = "";
permutate(inputString, outputString);
So, let's analyze the example {A, B, C}.
First, you want to take single element out of it, and get the rest. So you would need to write some function that would return a list of pairs:
pairs = [ (A, {B, C})
(B, {A, C})
(C, {A, B}) ]
for each of these pairs, you get a separate list of permutations that can be made out of it, like that:
for pair in pairs do
head <- pair.fst // e.g. for the first pair it will be A
tails <- perms(pair.snd) // e.g. tails will be a list of permutations computed from {B, C}
You need to attach the head to each tail from tails to get a complete permutation. So the complete loop will be:
permutations <- []
for pair in pairs do
head <- pair.fst // e.g. for the first pair it will be A
tails <- perms(pair.snd) // e.g. tails will be a list of permutations computed from {B, C}
for tail in tails do
permutations.add(head :: tail); // here we create a complete permutation
head :: tail means that we attach one element head to the beginning of the list tail.
Well now, how to implement perms function used in the fragment tails <- perm(pair.snd). We just did! That's what recursion is all about. :)
We still need a base case, so:
perms({X}) = [ {X} ] // return a list of one possible permutation
And the function for all other cases looks like that:
perms({X...}) =
permutations <- []
pairs <- createPairs({X...})
for pair in pairs do
head <- pair.fst // e.g. for the first pair it will be A
tails <- perms(pair.snd) // e.g. tails will be a list of permutations computed from {B, C}
for tail in tails do
permutations.add( head :: tail ); // here we create a complete permutation
return permutations
I am trying to solve the maximum sub array problem with a brute force approach i.e generating all the possible subarrays combinations. I got something that works but it's not satisfying at all because it produces way too many duplicated subarrays.
Does anyone knows a smart way to generate all the subarrays (in [[]] form) with a minimal number of duplicated elements ?
By the way, I'm new to Haskell. Here's my current solution:
import qualified Data.List as L
maximumSubList::[Integer]->[Integer]
maximumSubList x = head $ L.sortBy (\a b -> compare (sum b) (sum a)) $ L.nub $ slice x
where
-- slice will return all the "sub lists"
slice [] = []
slice x = (slice $ tail x) ++ (sliceLeft x) ++ (sliceRight x)
-- Create sub lists by removing "left" part
-- ex [1,2,3] -> [[1,2,3],[2,3],[3]]
sliceRight [] = []
sliceRight x = x : (sliceRight $ tail x)
-- Create sub lists by removing "right" part
-- ex [1,2,3] -> [[1,2,3],[1,2],[1]]
sliceLeft [] = []
sliceLeft x = x : (sliceLeft $ init x)
There are many useful functions for operating on lists in the standard Data.List module.
import Data.List
slice :: [a] -> [[a]]
slice = filter (not . null) . concatMap tails . inits
dave4420's answer is how to do what you want to do using smart, concise Haskell. I'm no Haskell expert, but I occasionally play around with it and find solving a problem like this to be an interesting distraction, and enjoy figuring out exactly why it works. Hopefully the following explanation will be helpful :)
The key property of dave4420's answer (which your answer doesn't have) is that the pair (startPos, endPos) is unique for each subarray it generates. Now, observe that two subarrays are distinct if either their startPos or endPos is different. Applying inits to the original array returns a list of subarrays that each have unique startPos, and the same endPos (equal to the number of elements in the array). Applying tails to each of these subarrays in turn produces another list of subarrays -- one list of subarrays is output per input subarray. Notice that tails does not disturb the distinctness between input subarrays because the subarrays output by invoking tails on a single input subarray all retain the same startPos: that is, if you have two subarrays with distinct startPoses, and put both of them through tails, each of the subarrays produced from the first input subarray will be distinct from each of the subarrays produced from the second one.
Additionally, each of the subarrays produced by the invocation of tails on a single subarray are distinct because, although they all share the same startPos, they all have distinct endPoses. Therefore all subarrays produced by (concatMap tails) . inits are distinct. It only remains to note that no subarray is missed out: for any subarray starting at position i and ending at position j, that subarray must appear as the j-i+1th list produced by applying tails to the i+1th list produced by inits. So in conclusion, every possible subarray appears exactly once!
What is the standard way of inserting an element to a specific position in a list in OCaml. Only recursion is allowed. No assignment operation is permitted.
My goal is to compress a graph in ocaml by removing vertexes with in_degree=out_degree=1. For this reason I need to remove the adjacent edges to make a single edge. Now the edges are in a list [(6,7);(1,2);(2,3);(5,4)]. So I need to remove those edges from the list and add a single edge.
so the above list will now look like [(6,7);(1,3);(5,4)]. Here we see (1,2);(2,3) is removed and (1,3) is inserted in the second position. I have devised an algorithm for this. But to do this I need to know how can I remove the edges (1,2);(2,3) from position 2,3 and insert (1,3) in position 2 without any explicit variable and in a recursive manner.
OCaml list is immutable so there's no such thing like removing and inserting elements in list operations.
What you can do is creating a new list by reusing certain part of the old list. For example, to create a list (1, 3)::xs' from (1, 2)::(2, 3)::xs' you actually reuse xs' and make the new list using cons constructor.
And pattern matching is very handy to use:
let rec transform xs =
match xs with
| [] | [_] -> xs
| (x, y1)::(y2, z)::xs' when y1 = y2 -> (x, z)::transform xs'
| (x, y1)::(y2, z)::xs' -> (x, y1)::transform ((y2, z)::xs')
You can do something like that :
let rec compress l = match l with
[] -> []
| x :: [] -> [x]
| x1 :: x2 :: xs ->
if snd x1 = fst x2 then
(fst x1, snd x2) :: compress xs
else x1 :: compress (x2 :: xs)
You are using the wrong datastructure to store your edges and your question doesnt indicate that you can't choose a different datastructure. As other posters already said: lists are immutable so repeated deletion of elements deep within them is a relatively costly (O(n)) operation.
I also dont understand why you have to reinsert the new edge at position 2. A graph is defined by G=(V,E) where V and E are sets of vertices and edges. The order of them therefor doesnt matter. This definition of graphs also already tells you a better datastructure for your edges: sets.
In ocaml, sets are represented by balanced binary trees so the average complexity of insertion and deletion of members is O(log n). So you see that for deletion of members this complexity is definitely better than the one of lists (O(n)) on the other hand it is more costly to add members to a set than it is to prepend elements to a list using the cons operation.
An alternative datastructure would be a hashtable where insertion and deletion can be done in O(1) time. Let the keys in the hashtable be your edges and since you dont use the values, just use a constant like unit or 0.