Print Any Older Version of the Queue [closed] - algorithm

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I came across this question and thought of asking what is the best possible way to achieve this.
Given a FIFO queue. you can assume that queue contains integers. Every time an insertion or deletion happens, a new version of the queue is created. At any time, you have to print(whole content of the queue) any older version of the queue with minimal time and space complexity.

This is assuming you meant a FIFO queue and not some other kind of queue, like a priority queue.
Store it in an array and keep two pointer variables, one to its head and another to its tail.
For example:
insert 3 2 5 9 - version 1
q = [3 2 5 9]
^ ^
delete, delete - version 2
q = [3 2 5 9]
^ ^
insert 6 3 4 - version 3
q = [3 2 5 9 6 3 4]
^ ^
To print a version, you just need to store two values for each version: where the pointers were. Printing is then linear in the size of the queue at that version.
The vector can grow big, but you have to store every element there ever was in it if you want to be able to print any version.
You can also use a linked list to avoid array resizing if you consider that a problem. Just make sure not to remove a node from memory when deleting.

Your problem is to make the queue a partially persistent data structure.
Partially persistent means that you can query any version, but you only can make updates in the most recent version.
A couple years ago I've given a speech about making any pointer data structure persistent. It was based on "Making data structures persistent" by Driscoll, Sarnak, Sleator and Tarjan.
Clearly, any queue can be implemented as a linked data structure. If you want the simplest practical version, you may be interested in method called "The Fat Node Method" which is described on page 91 in the above PDF.
The idea is to store in every node several pointers to the next elements corresponding to different versions of the queue. Each pointer has assigned a version number called timestamp.
For every insert or delete operation, you update pointers only in nodes touched by the update operation.
For lookup operation in the i-th version of the queue, you simply follow the pointers with the largest timestamp not exceeding i. You can find the pointer to follow using the binary search.
In the given PDF there is also a more complex, but also even more efficient method called "The Node-Copying Method".

There are many possible solutions. Here is one with all operations guaranteed O(log(n)) and normal operations an amortized O(log(log(n)).
Keep an operation counter. Store the items in a skip list (see http://en.wikipedia.org/wiki/Skip_list for a definition of that) based on the order of the insertion operation. When an element is removed, fill in the id of the removal operation. For efficiency of access, keep a pair of pointers to the current head and current tail.
To insert an element, add it to the current tail. To return an element, return it to the current head. To return a past state, search the skip list for the then head, then start walking the list until you read the then tail.
The log(n) operations here are finding the past head, and (very occasionally) inserting a new head that happens to be a high node in the skip list.

Now lets us assume that in a FIFO queue, the head pointer is at the beginning of the array, and then the tail pointer is at the end of the current insertion. Then by storing the current tail position pointer value in a variable which is used as the head pointer position during future insertion and tail position again takes the end of that insertion. This way just by using a single variable and with only insertion taking place, previous versions can be printed from the beginning of the array to the tail pointer.
insert 3 2 1 4
a=[3 2 1 4] --version 1
^ ^
b e
p = e;
insert 5 7 8
a=[3 2 1 4 5 7 8] --version 2
^ ^
b e
here version 1 = position 0 to position p = [3 2 1 4]
p = e;
delete 3
a=[2 1 4 5 7 8] --version 3
^ ^
b e
here version 2 = position 0 to position p =[2 1 4 7 8]
where
b = beginning
e = end
Hence by using a single variable to hold previous version tail position and assuming the beginning position to be always 0 , previous versions can be easily printed.

Related

two algorithms, same results on my machine, different results on tests [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am new in code, so, it would be cool,if somebody would helo me.
Task:
You have target-numer and a lot of other numbers. You need to find the numbers that you add up to get a sum equal to the target-number. If you found this numbers, you type "1" in out-put file, otherwise type "0". All numbers are in diapason 0 < N < 999 999 999
input-file format:
5
1 8 9 2 4 1 5 3....
I wrote 2 different algorithms, both work correctly. But I have tests,(no code sources, they are on the website, where I found task) and first algorithm passes all test accept of speed-test, but second can't pass even 1st test, have error "wrong answer".
I want to test my fastest version.
This algorithm does:
Open the file with numbers.
Convert all strings with numbers to numbers. Write all the numbers in a slice.
Write the target from the array to a separate variable. Target = the first element of the slice due to the input format.
Create a new slice. Rewrite it with all the numbers that < = target.
Sort the slice in ascending order (built-in sorting from golang)
Find the sum:
6.1 take the current slice element and subtract it from the target. The resulting number = the second term.
6.2 using the binary array dissection Method, we search for this number in the slice. (method from golanfg package)
6.3 If found, write 1 to the output file and exit the program.
6.4 Otherwise go to a new iteration of the loop and return to point 6.1
6.5 If the cycle has ended and we haven't left the program, we assume that there are no 2 numbers forming the sum for the target. print 0 to the output file.
Could you help me to find, where is mistake?
Here is the link for the file on my git:
https://github.com/0xBECEDA/ozon-tasks/blob/master/task-f/SO1.go
This file will create test-file with numbers:
https://github.com/0xBECEDA/ozon-tasks/blob/master/task-f/make-test-file.go
This is test-file:
https://github.com/0xBECEDA/ozon-tasks/blob/master/task-f/input.txt
first your problem, you read input from file to only 100 byte slice, but your input data can consume more place All numbers are in diapason 0 < N < 999 999 999 ,so i think you don`t read all the data from file

Drawing consisting of two linked lists with pointers and values

I just started taking an algorithms course, however, due to some family issues, I did not have a chance to participate in the first two lectures. Now I'm in a bit of a pickle, because I don't understand much of what is going on.
Above is a picture of a task that I need to solve. From what i understand, L0 is a list containing all values of S and L1 is a list containing all values of S and a pointer to the corresponding value in L0. However, what I do not understand is when they start bringing in delta and drawings. If anyone could clarify the meaning of delta and the parameter delta = 3, I might have a chance of solving it.
Any help is appreciated.
Here, 'delta' is just a parameter. You can call it 'd' if you prefer.
L0 contains all elements of S (as a linked list).
L1 contains every 'delta'th element of S as a linked list, with a pointer to the corresponding value in L0.
So the answer to 2.1 is something like:
L0: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
^ ^ ^
| | |
L1: 1 -----------> 4 -----------> 7
That is, L1 contains the 0th, 3rd, and 6th (i=0, delta, 2*delta, where delta=3) element of S.

Understanding queue arithmetic in data structures

When an element is inserted in a queue, REAR = REAR + 1. When an element is deleted from the queue, FRONT = FRONT + 1 when queues are implemented using arrays.
Now, initially, both FRONT = REAR = -1 indicating the queue is empty. When the first element is added, FRONT = REAR = 0 (assuming array from 0 to n-1).
Now, if we assume a condition where FRONT = 0 and REAR = n-1 implying the queue is full. When a few elements are removed the FRONT pointer changes. Let us say FRONT = 5 and REAR = 10. Hence, array locations 0 to 4 are free.
When I wish to add an element now, I add at the location 0 and FRONT points to it. But the locations 1, 2, 3 and 4 are free.
But, when the next time I try to insert an element, the compiler will throw an error saying the queue is full. Since FRONT = 0 and REAR = n-1. How do I insert at the remaining locations and also understand this queuing arithmetic better?
I would also like to understand how FRONT = REAR + 1 acts as a condition for checking if the queue is full?
You want to think circularly here in terms of relative, circular ranges instead of absolute, linear ones. So you don't want to get too hung up on the absolute indices/addresses of FRONT and REAR. They're relative to each other, and you can use modulo arithmetic to start getting back to the beginning of the array like Pac-Man when he goes off the side of the screen. It can be useful when you're drawing these things out to literally draw your array as a circle on your whiteboard.
When I wish to add an element now, I add at the location 0 and FRONT points to it. But the locations 1, 2, 3 and 4 are free.
I think here you got it backwards a bit. According to your logic, insertions advance the REAR, not FRONT. In such a case, REAR would be at 0, and FRONT would still be at 5. If you push again, REAR=1 and you'd overwrite the first index, and FRONT would still be 5.
If N=3 and FRONT=2 and REAR=2, we have one element in the queue after pushing and popping a lot. When you push (enqueue), we set: REAR=(REAR+1)%N making FRONT=2, REAR=0 giving us two elements. If we push again, FRONT=2, REAR=1 giving us 3 elements, and the queue is full.
Visually:
R
[..x]
F
R
[x.x]
F
R
[xxx]
F
... and now we're full. A queue is full if the next circular index from the REAR is the FRONT. In the case where FRONT=2, REAR=1, we can see that (REAR+1)%N == FRONT, so it's full.
If we popped (dequeued) at this point at this point, we would set FRONT=(FRONT+1)%N and it would look like this:
R
[xx.]
F
I would also like to understand how FRONT = REAR + 1 acts as a condition for checking if the queue is full?
This doesn't suffice when you use this kind of circular indexing. We need a slight augmentation: the queue is full when FRONT == (REAR+1)%N. We need that modulo arithmetic to handle those "wrap around to the other side" cases.

Parallel for loop for addition of local matrices in OpenMP

I have n local copies of matrices,say 'local', in n threads. I want to update a global shared matrix 's' with its elements being sum of corresponding elements of all local matrices.
For eg. s[0][0] = local_1[0][0] + local_2[0][0]+...+local_n[0][0].
I wrote the following loop to achieve it -
#pragma omp parallel for
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
s[i][j]=s[i][j]+local[i][j];
}
This doesn't seem to work. Could someone kindly point out where am I going wrong?
Updated with example -
Suppose there are 3 threads, with following local matrices -
thread 1
local = 1 2
3 4
thread 2
local = 5 6
7 8
thread 3
local = 1 0
0 1
shared matrix would then be
s = 7 8
10 13
Throughout this answer I'm assuming that you have correctly created a private version of local on each thread as your question and example, but not your code snippet, indicate.
As you've written the code the variable i is private, that is each thread has it's own copy. Since it's the iteration variable for the outermost loop each thread will get it's own set of values to work on. Supposing that you have 3 threads and 3 rows then thread 0 will get i value 0, thread 1 will get 1, and so on. Obviously (or not) with more rows to iterate over each thread would get more i values to work on. In all cases each thread will get a disjoint subset of the set of all values that i takes.
However, if thread 0 gets only i==0 to work on the computation
s[i][j]=s[i][j]+local[i][j];
will only ever work on the 0-th row of local on thread 0. With the example I'm using i, on thread 0, never equals 1 so the values in the 1-th row of local on thread 0 never gets added to row 1 of s.
Between them the 3 threads will update the 3 rows of s but each will only add its own row of its own version of local.
As for how to do what you want to do, have a look at this question and the accepted answer. You are attempting an array reduction which, for reasons explained here, is not directly supported in C or C++.
This should be a comment to the last paragraph of the answer, if I was permitted to do so.
The first method in the referenced question is parallelizing the array filling but not the array reduction. According to the specs (v4 p122):
The critical construct restricts execution of the associated structured block to a
single thread at a time.
Each thread reduces its own part of the array, but only one after the other, in essence the code is run serially. The only reason for the summing loop to be inside the parallel region is that the arrays are local to each thread which makes sense only when filling them benefits from the parallelism.

Stack question: pop out in a pattern

At run time I want to input two types of datatype, double and string.
One of the condition is that String should pop in the order I input, and double will pop as the usual stack behaviour, LIFO. Another condition is that the stack is limited to max size 10
E.g. one runtime example
Input Hello 1 World 2 blah blah 3 4 5
Output Hello 5 World 4 blah blah 3 2 1
My first question is how many ways is there to solve this problem?
I have solved this problem using 3 stacks, one which stores double, one which store strings, and one which is used to reverse the string order.
I need to save the pattern so the program know which order the doubles comes, thus I save the pattern to the string stack. Since the stack is limited to size 10, I will need to save the pattern in another way.
So this is how my string stack will look like after the push
Hello*
World*
blah
blah***
So when at the first read I need to make specific read in that Stack position and just extract Hello out of it. Asterisk * is left for later use when I tell the program next pop is an double.
My second question is that I wonder if there is some other more elegant solution to this problem. Since my solution will involve some string manipulation to solve this problem. And as for now I'm not actually using the pop function in the string case as it is supposed to be used. I made the solution in C++ btw.
What you're doing is fine, except that if you must use a stack, then you aren't allowed to access random locations in a stack -- you can only push/pop -- and also it's not so nice to modify the input strings and store asterisks in them.
You can solve this using only push/pop operations with 5 stacks (technically, only 4 will be used at any one time, but since they are of different types, you need to declare all 5 in your program):
stack 1: push doubles in input order
stack 2: push strings in input order
stack 3: push data types (double or string) in input order
stack 4: reverse the order of strings in stack 2
stack 5: reverse the order of data types in stack 3
Now pop one data type at a time from stack 5, if it is a double, pop from stack 1, otherwise pop from stack 5, and print the popped value.
Edit: #jleedev makes a good point that there isn't a general solution when the stack size is limited. What I've described above assumes that you're allowed to use multiple stacks and each stack can hold as many items as present in the input.
I'll ignore the stack size constraint since I think it's meaning is unclear. In addition, if you can use multiple stacks all limited to size 10, then you can simulate larger stacks by using multiple actual stacks.
So, this can be done with 2 stacks using only push/pop.
push everything onto stack A.
pop everything from A onto B.
if B.empty return
if B.top is a double goto 7
output B.top and pop it off of B
goto 3
pop all of B onto A
while A.top is not a double pop A onto B
output A.top and pop it off of A
goto 2.

Resources