Adding an element to a list and then reverse it - list

I'm learning Haskell, and attempting to understand lists.
From researching, to add an element to a list, you would normally do:
let numbers = [4,8,15,16,23,42]
numbers ++ [56]
but to quote this answer:
If you need to do this, there is usually a better way to structure
your algorithm. For example, you can build your list in reverse order
(adding elements at the beginning) and only call reverse at the end.
Code:
let numbers = [23,43,56]
let newNumbers = 69:numbers
reverse newNumbers
Output:
[56,43,23,69]
Question:
Is the code I've written correct according to the quoted answer?
I want to understand the terminology a little better, can I say I'm adding elements to the head of the list? From my understanding, every new element would be the first element, and the value returned when I write head newNumbers.

You need to distinguish between the linked list data structure and whatever list-like data type you are implementing with the linked list. You can do exactly two things to modify a linked list: prepend a new head to the list, and remove the current head (if the linked list isn't empty).
The use case the quote talks about is common for a queue data type: you can add to one end and remove from the other end. You can implement this using two linked lists, by adding new elements to one list and removing elements from the other. The implementation of the queue takes care of reversing as necessary to ensure that you never remove an item before every other item inserted previously is removed.
data Queue a = Queue [a] [a]
-- Put new elements on the incoming list.
addToQueue :: a -> Queue a -> Queue a
addToQueue x (Queue incoming outgoing) = Queue (x:incoming) outgoing
-- Take elements from the outgoing list, whose elements are stored
-- in the reverse order that they were added to the incoming list
-- previously.
removeFromQueue :: Queue a -> (a, Queue a)
removeFromQueue (Queue [] []) = error "Cannot remove from empty queue"
removeFromQueue (Queue incoming (x:xs)) = (x, Queue incoming xs)
removeFromQueue (Queue incoming []) = removeFromQueue (Queue [] (reverse incoming))
(We're not concerned with good ways to deal with removing from an empty queue here; just call it an error and leave it at that.)
Adding to the incoming list and removing from the outgoing list is easy. The tricky part is how and when we transfer items from the incoming list to the outgoing list. We only do so when the outgoing list is empty, and when it is, we transfer the entire incoming list at once, reversing it in the process. In other words, we're building up the incoming list in reverse,
but only ever reverse it when necessary, not after each and every single item is added.
Amortized analysis can be used to show that although reverse could be slow, it is balanced by the number of fast operations that precede and can follow it.

Related

Returning a first element from an improper list in Erlang

So I've been trying to implement this function in my module and so far I got this:
EXAMPLE 1.
[2,[3,[4,[5,[6,[7,[8,[]]]]]]]]
I am trying to figure out how I can make it look like a proper list, ie:
EXAMPLE 2.
[2,3,4,5,6,7,8].
I know I have to play with Heads and Tails but I am miserably failing at understanding it.
Any help would be appreciated.
Thanks!
Actually in the example 1 you show proper list. List that just consists of 2 elements - number and another list.
Improper list is different thing - for instance [1|2].
You can turn example 1 into example 2 by lists:flatten.
1> M = [2,[3,[4,[5,[6,[7,[8,[]]]]]]]].
[2,[3,[4,[5,[6,[7,[8,[]]]]]]]]
2> lists:flatten(M).
[2,3,4,5,6,7,8]
The root of the problem is how you have built your list. What you have here:
[2,[3,[4,[5,[6,[7,[8,[]]]]]]]]
is not one list but nested lists each of two elements. When you do [Element,List] this does NOT prepend Element to List but builds a new list with Element as the first element and List as the second element. Note that each list is a proper list but you have not built one list but nested lists.
To prepend Element to List you use the syntax [Element | List]. So:
[2|[3|[4|[5|[6|[7|[8|[]]]]]]]]
which builds the list [1,2,3,4,5,6,7,8].
So [Element | List] and [Element,List] are two very different things, the first prepends an element to the beginning of a list while the second builds a new list of two elements. There is no direct way of appending an element to a list without rebuilding the list.
Not as obvious as it looks at first, but this is a manual way of doing what lists:flatten/1 does (in this particular case, its more interesting otherwise):
proper(L) -> proper([], L).
proper(A, [H|[T]]) -> proper([H|A], T);
proper(A, []) -> lists:reverse(A).

Display the middle data item from a LLL with ONLY one traversal

I just have a question about a singly linked list in C++ programming. I am trying to display the middle data item of a singly linked list of integer values with ONLY one traversal. Any hints will be very helpful !
I was able to solve this problem with more than one traversal, but I MUST only traverse the linked list once in order to display the middle data item.
Thanks !
Since there is no restriction on memory, Copy all the elements of the list into an array. Finally go to the middle of the array and get the data.

prolog - tail recursion issue

I am new to prolog and I am trying to create a predicate and am having some trouble.
I have a list of cities that are connected via train. They are connected via my links/2 clause.
links(toronto, ajax).
links(toronto, markham).
links(toronto, brampton).
links(brampton, markham).
links(markham, ajax).
links(brampton, mississauga).
links(mississauga, toronto).
links(mississuaga, oakville).
links(oakville, st.catharines).
links(oakville, hamilton).
links(hamilton, st.catharines).
I am writing a predicate called addnewcities which will take a list of cities and then return a new list containing the original list, plus all the cities that are directly connected to each of the cities in the original list.
Here is a (rough looking) visual representation of the links.
If my input list was [toronto] I want my output to be (order doesnt matter) [ajax,markham,brampton,mississauga,toronto].
If input was [oakville,hamilton] I want the output to be [mississauga,st.catharines,oakville,hamilton].
Here is my predicate so far.
addnewcities([],_).
addnewcities([CitiesH|Tail],Ans):- directer(CitiesH,Ans2), merger(Ans2,[CitiesH],Ans), addnewcities(Tail,Ans).
directer/2 takes a city and saves a list containing all the directly connected cities in the second arg.
merger/3 just merges two lists making sure there are no duplicates in the final list.
When my input is a list with one element ie [toronto] it works!
But when I have a list with multiple elements [toronto,ajax] it says "false" every time.
I'm pretty sure my issue is that when it recurses for the second time, merge is what says its false. I just don't know how to get around this so that my list can keep being updated instead of being checked if true or false.
Any help is appreciated!
this query uses library support to solve the problem:
addcities(Cs, L) :-
setof(D, C^(member(C,Cs), (C=D;link(C,D);link(D,C))), L).
This should work for what you want:
addcities(A,B):-
addcitiesaux(A,[],B).
addcitiesaux([],X,X).
addcitiesaux([X|Xs],L,R):-
link(X,A),
\+ member(A,L),
!,
addcitiesaux([X|Xs],[A|L],R).
addcitiesaux([X|Xs],L,R):-
link(A,X),
\+ member(A,L),
!,
addcitiesaux([X|Xs],[A|L],R).
addcitiesaux([X|Xs],L,R):-
addcitiesaux(Xs,[X|L],R).

Binary tree Breadth-first search

I'm using OCaml. I have type:
type 'a bt = Empty | Node of 'a * 'a bt * 'a bt;;
Also I have example BST:
let tree = Node(1,Node(2,Node(4,Empty,Empty),Empty),Node(3,Node(5,Empty,Node(6,Empty,Empty)),Empty));
I need to write function: breadthBT : 'a bt -> 'a list which will be Breadth-first search traversal. For above example tree it should returns [1; 2; 3; 4; 5; 6]
How to write that function? I can write only following function which uses DST :
let rec breadthBT tree =
if tree=Empty then []
else let Node(w,l,r)=tree in (w::breadthBT l)#breadthBT r;;
Above function returns (for example tree) [1; 2; 4; 3; 5; 6]. But I can't write function which uses BFS. Could you help me?
It is not a compilable solution. Just a tip.
You should iterate from top level root node to deep level nodes. Let our function receives accumulator for the answer and list of nodes (your 'a bt values) as second parameter. You can map this list by getting first element of triple and than you receive next part of answer. Also you need to evaluate next level of tree. For every node there are at most two descendants. You can map your list and apply _a_function_to receive list of descendants. It will be next level of your tree. And than --- recursion.
A will not specify this _a_function_. Try to study what is concatMap in google.
Happy hacking!
Imagine you stick your nose to the tree. Is it possible to traverse the tree in the breadth-first manner without bookmarking positions in your notepad? No, because the order can make you jump from one branch to another unrelated branch. So you need a notepad with "remaining positions to visit". You pick the next remaining position from the notepad and jump to it blindly. Since you erase visited positions from the notepad, you are at a node you have not visited yet. And since you cannot get up the tree without visiting intermediate nodes, you haven't visited the two nodes now above you. But you resist the instinct to climb the branches directly -- heck, this is breadth first order. You do not want to forget about these two unvisited nodes, so you want to put them into the notebook. Where do you put them, in front of the notebook or on its back? On the back of course, otherwise you would pick one of them immediately and that's what we want to avoid. Et voila: your notepad is a FIFO queue of nodes, which you keep (i.e. pass) around as an accumulator, but also consume to pick a subtree to visit.

Advice on how to synchronize bewteen 2 actors- one add/remove from list and other clean list

I need advice in design and c++ implementation (I am a java guy, new to c++).
I have list of processes.
One thread add/remove process to the list and second thread once in 10ms runs and collects all processes (and removes them from the list) that have timed out. Each process has a creation timestamp when it was added to the list. If 3 sec have passed and the process is still in the list (not removed by the first thread) it is removed from the list by the cleaner process.
This has to be with low overhead.
So I have processListContainer with 3 methods:
add, remove , clean
need to sync between the add/removeById and the clean.
This can be done by clever thinking such as creating a new list when cleaning, and handle multiple lists.
The list size is around 100K and thousands added in sec
You can organize your list of processes into a list of sublists. Each sublist is a collection of processes that would expire within the same 5ms interval. This would allow your cleaner thread to clear out an entire sublist when it is deciding to remove stale processes, instead of iterating through individual processes.
The list initially contains an empty sublist.
The clean operation is a loop with the exit condition being either the head sublist is empty or the head sublist is not expirable. If the head sublist has expired, it cleans out the list. If the list has more than 1 sublist, it removes the resulting empty sublist. The loop repeats.
So, add would check to see if the process belongs to the last sublist. If so, it adds itself to that sublist. If not, it creates a new sublist, and adds itself to it, and adds the sublist to the list.
The remove element removes the provided element from the sublist. If the sublist becomes empty, and there is more than one sublist in the list, it removes the empty sublist.
In this scheme, add should not need to lock, since it only manipulates the tail, or an unexpirable sublist. clean and remove both need locks since they may both manipulate the head of the list.
You only need to keep one list, and protect it with a mutex. Also I'd avoid a 'cleaner' process, and have processes remove themselves from the list when they complete.