Trouble with Lists (python) - list

I tried the pop() method with the index of the sandwich in the first loop, but it gave me the same problem. Only every second element gets printed.

You're modifying the sandwich_orders list while iterating over it, which is messes up your iteration. Since there aren't any conditions there anyway, I'd finish the iteration and then just assign an empty list to it: sandwich_orders = [], or clear it: sandwich_orders.clear().
Or better yet, since you aren't using this list after the loop is done, just leave it be.

Related

Correct way to add an element to the end of a list?

I was reading on this Haskell page about adding an element to the end of a List.
Using the example, I tried it out for my self. Given the following List I wanted to add the number 56 at the end of it.
Example:
let numbers = [4,8,15,16,23,42]
numbers ++ [56]
I was thrown off by this comment:
Adding an item to the end of a list is a fine exercise, but usually
you shouldn't do it in real Haskell programs. It's expensive, and
indicates you are building your list in the wrong order. There is
usually a better approach.
Researching, I realize that what I'm actually doing is creating a List with 56 as the only element and I'm combining it with the numbers list. Is that correct?
Is using ++ the correct way to add an element to the end of a List?
++ [x] is the correct way to add an element to the end of a list, but what the comment is saying is that you shouldn't add elements to the end of a list.
Due to the way lists are defined, adding an element at the end always requires making a copy of the list. That is,
xs ++ ys
needs to copy all of xs but can reuse ys unchanged.
If xs is just one element (i.e. we're adding to the beginning of a list), that's no problem: Copying one element takes practically no time at all.
But if xs is longer, we need to spend more time in ++.
And if we're doing this repeatedly (i.e. we're building up a big list by continually adding elements to the end), then we need to spend a lot of time making redundant copies. (Building an n-element list in this way is an O(n2) operation.)
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.
It's the correct way in that all ways of doing it must reduce to at least that much work. The problem is wanting to append to the end of a list at all. That's not an operation that's possible to do efficiently with immutable linked lists.
The better approach is figuring out how to solve your specific problem without doing that. There are a lot of potential approaches. Picking the right one depends on the details of what you're doing. Maybe you can get away with just using laziness correctly. Maybe you are best off generating the list backwards and then reversing it once at the end. Maybe you're best off using a different data structure. It all depends on your specific use case.

How to find the node at the beginning of cycle in linked list? [duplicate]

This question already has answers here:
Finding loop in a singly linked-list
(13 answers)
Closed 4 years ago.
From Cracking the Coding Interview, there is an exercise that says:
Given a circular linked list, implement an algorithm that returns the node at the beginning of the loop.
Definition of circular linked list: A (corrupt) linked list in which a node's next pointer points to an earlier node, so as to make a loop in the linked list.
The algorithmic answer is basically using a slow and fast runner to iterate through the linked list to see if it loops. If the slow and fast runner collide, it loops, so then you find the node at the beginning of the loop. (If they don't collide, then the fast runner will eventually reach the end of the linked list, meaning there is no cycle.)
But the book's answer for finding where the node at the beginning of the loop is relies on the ASSUMPTION that the linked list has a "non-looped" part of size k. Once the slow and fast runners collide, you move the slow runner to the head of the linked list. You iterate both at the same speed until they collide. Where they collide is the node at the beginning of the loop.
My question is, is it possible to find where the node at the beginning of the loop is WITHOUT assuming the linked list has a "non-looped" part of size k? Or do I have to assume that there is a "non-looped" part of size k?
I have 2 answers for this question,
One:
If you have loop inside the list in size k, if you move one of the pointer k steps from the head and another pointer from the head and move them together, finnally when one of them do a full loop, and the another one just start the loop, and then this the reason they both meet at the begining of the loop. all you need is count the nodes on the loop.
Second:
I intreduce my solution by example:
assume we got this list:
find a common pointer using the faster and slower runner method.
let's assume that they meet in node number 7.
after you do it remmber the next pointer of node 7 (as the end of the list).
and for now we can reduction to another problem for solve this problem and that is finding first common element in two linked lists that the end of them is pointer of "node 8", and the head of one of them is the head of the list (node 0) and for the other list head is "node 8".
it's look like this:
you can solve it by the following steps:
1) Get count of the nodes in the first list, let count be c1.
2) Get count of the nodes in the second list, let count be c2.
3) Get the difference of counts d = abs(c1 – c2)
4) Now traverse the bigger list from the first node till d nodes so that from here onwards both the lists have equal no of nodes.
5) Then we can traverse both the lists in parallel till we come across a common node. (Note that getting a common node is done by comparing the address of the nodes).
Unless the book specifically assumes the existence of a positive such k, k can also be zero.
Here's an informal argument for the case k=0:
Assume that the entire list is a loop.
If the fast runner is twice as fast as the slow runner, they will collide when the slow runner has completed one loop, and the fast runner has completed two.
If you then start the slow runner from the beginning again, the two will collide immediately on the first node.
I'm not familiar with that book, but I don't think you read it right. Probably k is the size of the loop, and the algorithm works like this:
Detect a loop using either Floyd's or Brent's algorithm. (both are described here: https://en.wikipedia.org/wiki/Cycle_detection)
Let k be the a multiple of the size of the loop, so that once you're in the loop, you'll get back to the same node if you make k steps. You can measure this after you find the cycle, or you can just count the difference in steps between the "fast pointer" and the "slow pointer" while looking for the cycle.
Put 2 pointers at the head of the list (call them fast and slow again), and advance the "fast" pointer k times.
While the fast and slow pointers point at different nodes, advance them in lock step, so that the fast pointer is always k steps ahead.
The algorithm will stop as soon as the slow pointer gets into the loop -- the first node that can be reached again by advancing through the list.

How to apply rules to a list, before the head of the list?

I have a set of rules with this form:
regla(o,o,o,o).
And the way the statement (this is homework) is written, I have a list as input, and I have to apply this rules 2 elements before the list starts (this is possible because it is said that there are infinite symbols before and after the list starts, all being the same).
Now, the problem I have is that I cannot come up with a way to operate to the whole list.
That is, my idea was to make an operation to the head of the list, then recursively to the body of the list, and finally, another operation to the tail of the list.
something like this (it does not work yet, unfortunately):
:- ensure_loaded('automaton.pl').
listsplit([H1,H2,H3|T], H1,H2,H3, T).
%regla(o,o,H1,Output).**This would be the operation to the head of the list**
%append(Output,Accumulator).%we manually add the first and last elements of the list
%cells(InList,OutList). Caso Base:
%cells( [ ], _).%perhaps cells( [ ], []). would be less dangerous
cells(Input, Result):-cellsAUX(Input, Accumulator, Result).%base case removed because examples use it in the equivalent to the cellsAUX call
cellsAUX([], Result, Result).
cellsAUX(Input, Accumulator, Result):-**This would be the operations to the body of the list, calling itself recursively, and adding the results of each iteration to an Accumulator**
listsplit(Input,Head1Arg1,Head2Arg1,Head3Arg1,T),
regla(Head1Arg1,Head2Arg1,Head3Arg1,Output),
cellsAUX([Head2Arg1,Head3Arg1|T] , [Output|Accumulator], Result).
Is there some approach to make this without so many sub cases? I just can't shake this feeling I am making it more difficult than it is needed.
For reference, the input would be something like oxoxo, and as I said, it is assumed everything before and after are o's.
Thanks in advance, and sorry for the poorly formed question, I do not have enough vocabulary to "call" this problem the right way.

How to design a loop whose stop condition is the emptiness of a container

I'm sorry for the tricky title, here is the example
graph main_graph = //initialize graph
graph sub_graph = //pick a subset of edges from the main_graph
while ( ! sub_graph.size() == 0) {
select_edge(); //here I pick an edge basing on some heuristics
reduce_graph(); //here I remove some edges from the main_graph
sub_graph = //pick a subset of edges from the main_graph
}
So the point is that I have to write the very same code to define the sub_graph before entering the loop (because it could be already empty) and right before entering a new iteration.
This would not be that bad, if it wasn't that I actually have three nested loops with the same problem, and the code to inizialize the sub_graph is a bunch of lines of code, so my code would look a lot replicated.
Any suggestion on how to better design this loop(s)? I have no restrictions (can use for, do-while...)
Even if this is pseudo-code, since is more a 'design' question, I'm coding in C++!
To avoid repeating lots of code, put the code in a function:
graph calc_subgraph(...) {...}
Then use it to initialize and recalculate your values:
for (graph subgraph = calc_subgraph(...); subgraph.size() != 0; subgraph = calc_subgraph(...))
If the code to initialize sub_Graph is a lot of lines, then write a function that returns an initialized graph, or a function that initializes sub_graph via a passed reference/pointer. Then just call the function inside the loop. That will thin the amount of code that you have to write and read. Loops that involve using the same code twice show up from time to time.
Writing loops that output comma separated lists is a good example of this, since you want the commas to stay on the inside of the list items. So you can either do the first item before the loop, or remove a comma after the loop.
In these kind of cases, calling the initializing code before the loop, and then again at the end of each loop iteration may be faster then putting a conditional test in the loop to skip parts of it every time.

How do I merge two linked lists in C++?

I asked a question last night on how to sort() a double linked list in C++.
I managed to get it to work, but now I'd like to merge two lists, but I can't
get it to work. I don't have much code, I'm sorry. Everything I tried
absolutely made no sense. I'd just like if someone could give me some hints on
where to start, or on how to do this, with the information I'm going to
provide.
This is what I had in the beginning:
void next() { if (curr != tail) curr = curr->next; }
I believe I only need these.
I looked at some exemples online, but it doesn't make any sense to me. It
seems so different than what I have right now. Apparently it should be A LOT
easier than doing a sort function, which I had barely any trouble doing.
Any explanation/hints would be greatly appreciated! And I'm sorry once again
for the lack of code, I just don't know where to start.
You can actually do this in multiple ways
Take the two sorted lists, and literally merge them so that you end up with a sorted list
Take the two sorted lists, and create a third new list that contains elements from both the lists in sorted order
Merge the two sorted/unsorted lists, and then sort the resulting list
It looks like you're trying to do no. 3 here.
In which case, you can just
Start from head of the current list, and go to next until you reach the last element
Set curr->next = other_list.head
Call sort on the current list
This would however destruct the original list. I think it's better to copy them to a third list.
for_each(auto x in list2name)
{
list1name.push_back(x);
}
or if you're using C++ 11
for(auto x : list2name)
{
list1name.push_back(x);
}
If you have used the std::list as a linked list you can always use the existing merge() function http://www.cplusplus.com/reference/stl/list/
If this is something you have implemented yourself just get the tail of one of the lists and use something like this:
tail = list_1.get_tail();
tail.set_next(list_2.get_head())
Basically getting the last entry in list 1 and then setting the next elemt to be the first element of list 2.
I'm still a bit confused what you're after, but this is the most basic way I can think of.
Then again, I might be completely off.
Good luck