Array elements not getting edited in a Python List - python-2.7

sticks = int(raw_input());
stickList= map(int,raw_input().split()) ;
stickList = sorted(stickList);
for i in xrange(0,len(stickList)):
stickList[i] = stickList[i]-stickList[0];
print stickList;
Given Input is :
6
5 4 4 2 2 8
Why the output is this: [0, 2, 4, 4, 5, 8]
instead of [0,0,2,2,3,6]

That is because you are changing the value in source stickList in for loop.
After first iteration in loop stickList[0] will become 0 for remaining iterations.
As ShadowRanger mentioned reversed list will do,
stickList = map(int, "5 4 4 2 2 8".split())
stickList.sort()
for i in reversed(xrange(len(stickList))):
stickList[i] -= stickList[0]
print stickList

Related

How to construct a tree given its depth and postorder traversal, then print its preorder traversal

I need to construct a tree given its depth and postorder traversal, and then I need to generate the corresponding preorder traversal. Example:
Depth: 2 1 3 3 3 2 2 1 1 0
Postorder: 5 2 8 9 10 6 7 3 4 1
Preorder(output): 1 2 5 3 6 8 9 10 7 4
I've defined two arrays that contain the postorder sequence and depth. After that, I couldn't come up with an algorithm to solve it.
Here's my code:
int postorder[1000];
int depth[1000];
string postorder_nums;
getline(cin, postorder_nums);
istringstream token1(postorder_nums);
string tokenString1;
int idx1 = 0;
while (token1 >> tokenString1) {
postorder[idx1] = stoi(tokenString1);
idx1++;
}
string depth_nums;
getline(cin, depth_nums);
istringstream token2(depth_nums);
string tokenString2;
int idx2 = 0;
while (token2 >> tokenString2) {
depth[idx2] = stoi(tokenString2);
idx2++;
}
Tree tree(1);
You can do this actually without constructing a tree.
First note that if you reverse the postorder sequence, you get a kind of preorder sequence, but with the children visited in opposite order. So we'll use this fact and iterate over the given arrays from back to front, and we will also store values in the output from back to front. This way at least the order of siblings will come out right.
The first value we get from the input will thus always be the root value. Obviously we cannot store this value at the end of the output array, as it really should come first. But we will put this value on a stack until all other values have been processed. The same will happen for any value that is followed by a "deeper" value (again: we are processing the input in reversed order). But as soon as we find a value that is not deeper, we flush a part of the stack into the output array (also filling it up from back to front).
When all values have been processed, we just need to flush the remaining values from the stack into the output array.
Now, we can optimise our space usage here: as we fill the output array from the back, we have free space at its front to use as the stack space for this algorithm. This has as nice consequence that when we arrive at the end we don't need to flush the stack anymore, because it is already there in the output, with every value where it should be.
Here is the code for this algorithm where I did not include the input collection, which apparently you already have working:
// Input example
int depth[] = {2, 1, 3, 3, 3, 2, 2, 1, 1, 0};
int postorder[] = {5, 2, 8, 9, 10, 6, 7, 3, 4, 1};
// Number of values in the input
int n = sizeof(depth)/sizeof(int);
int preorder[n]; // This will contain the ouput
int j = n; // index where last value was stored in preorder
int stackSize = 0; // how many entries are used as stack in preorder
for (int i = n - 1; i >= 0; i--) {
while (depth[i] < stackSize) {
preorder[--j] = preorder[--stackSize]; // flush it
}
preorder[stackSize++] = postorder[i]; // stack it
}
// Output the result:
for (int i = 0; i < n; i++) {
std::cout << preorder[i] << " ";
}
std::cout << "\n";
This algorithm has an auxiliary space complexity of O(1) -- so not counting the memory needed for the input and the output -- and has a time complexity of O(n).
I won't give you the code, but some hints how to solve the problem.
First, for postorder graph processing you first visit the children, then print (process) the value of the node. So, the tree or subtree parent is the last thing that is processed in its (sub)tree. I replace 10 with 0 for better indentation:
2 1 3 3 3 2 2 1 1 0
--------------------
5 2 8 9 0 6 7 3 4 1
As explained above, node of depth 0, or the root, is the last one. Let's lower all other nodes 1 level down:
2 1 3 3 3 2 2 1 1 0
-------------------
1
5 2 8 9 0 6 7 3 4
Now identify all nodes of depth 1, and lower all that is not of depth 0 or 1:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 8 9 0 6 7
As you can see, (5,2) is in a subtree, (8,9,10,6,7,3) in another subtree, (4) is a single-node subtree. In other words, all that is to the left of 2 is its subtree, all to the right of 2 and to the left of 3 is in the subtree of 3, all between 3 and 4 is in the subtree of 4 (here: empty).
Now lets deal with depth 3 in a similar way:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 6 7
8 9 0
2 is the parent for 2;
6 is the parent for 8, 8, 10;
3 is ahe parent for 6,7;
or very explicitly:
2 1 3 3 3 2 2 1 1 0
-------------------
1
/ / /
2 3 4
/ / /
5 6 7
/ / /
8 9 0
This is how you can construct a tree from the data you have.
EDIT
Clearly, this problem can be solved easily by recursion. In each step you find the lowest depth, print the node, and call the same function recursively for each of its subtrees as its argument, where the subtree is defined by looking for current_depth + 1. If the depth is passed as another argument, it can save the necessity of computing the lowest depth.

C++ Sort vector by index

I need to sort a std::vector by index. Let me explain it with an example:
Imagine I have a std::vector of 12 positions (but can be 18 for example) filled with some values (it doesn't have to be sorted):
Vector Index: 0 1 2 3 4 5 6 7 8 9 10 11
Vector Values: 3 0 2 3 2 0 1 2 2 4 5 3
I want to sort it every 3 index. This means: the first 3 [0-2] stay, then I need to have [6-8] and then the others. So it will end up like this (new index 3 has the value of previous idx 6):
Vector Index: 0 1 2 3 4 5 6 7 8 9 10 11
Vector Values: 3 0 2 1 2 2 3 2 0 4 5 3
I'm trying to make it in one line using std::sort + lambda but I can't get it. Also discovered the std::partition() function and tried to use it but the result was really bad hehe
Found also this similar question which orders by odd and even index but can't figure out how to make it in my case or even if it is possible: Sort vector by even and odd index
Thank you so much!
Note 0: No, my vector is not always sorted. It was just an example. I've changed the values
Note 1: I know it sound strange... think it like hte vecotr positions are like: yes yes yes no no no yes yes yes no no no yes yes yes... so the 'yes' positions will go in the same order but before the 'no' positions
Note 2: If there isn't a way with lambda then I thought making it with a loop and auxiliar vars but it's more ugly I think.
Note 3: Another example:
Vector Index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Vector Values: 3 0 2 3 2 0 1 2 2 4 5 3 2 3 0 0 2 1
Sorted Values: 3 0 2 1 2 2 2 3 0 3 2 0 4 5 3 0 2 1
The final Vector Values is sorted (in term of old index): 0 1 2 6 7 8 12 13 14 3 4 5 9 10 11 15 16 17
You can imagine those index in 2 colums, so I want first the Left ones and then the Right one:
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
You don't want std::sort, you want std::rotate.
std::vector<int> v = {20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31};
auto b = std::next(std::begin(v), 3); // skip first three elements
auto const re = std::end(v); // keep track of the actual end
auto e = std::next(b, 6); // the end of our current block
while(e < re) {
auto mid = std::next(b, 3);
std::rotate(b, mid, e);
b = e;
std::advance(e, 6);
}
// print the results
std::copy(std::begin(v), std::end(v), std::ostream_iterator<int>(std::cout, " "));
This code assumes you always do two groups of 3 for each rotation, but you could obviously work with whichever arbitrary ranges you wanted.
The output looks like what you'd want:
20 21 22 26 27 28 23 24 25 29 30 31
Update: #Blastfurnace pointed out that std::swap_ranges would work as well. The rotate call can be replaced with the following line:
std::swap_ranges(b, mid, mid); // passing mid twice on purpose
With the range-v3 library, you can write this quite conveniently, and it's very readable. Assuming your original vector is called input:
namespace rs = ranges;
namespace rv = ranges::views;
// input [3, 0, 2, 3, 2, 0, 1, 2, 2, 4, 5, 3, 2, 3, 0, 0, 2, 1]
auto by_3s = input | rv::chunk(3); // [[3, 0, 2], [3, 2, 0], [1, 2, 2], [4, 5, 3], [2, 3, 0], [0, 2, 1]]
auto result = rv::concat(by_3s | rv::stride(2), // [[3, 0, 2], [1, 2, 2], [2, 3, 0]]
by_3s | rv::drop(1) | rv::stride(2)) // [[3, 2, 0], [4, 5, 3], [0, 2, 1]]
| rv::join
| rs::to<std::vector<int>>; // [3, 0, 2, 1, 2, 2, 2, 3, 0, 3, 2, 0, 4, 5, 3, 0, 2, 1]
Here's a demo.

Longest sub-sequence the elements of which make up a set of increasing integers

Find the length of the longest continuous sub-sequence of an array the elements of which make up a set of continuous increasing integers.
The input file consists of the number n(the number of elements in the array) followed by n integers.
example input - 10 1 6 4 5 2 3 8 10 7 7
example output - 6(1 6 4 5 2 3 since they make the set 1 2 3 4 5 6).
I was able to write an algorithm that satisfies 0<n<5000 but in order to get 100 points the algorithm had to work for 0<=n<=50000.
How about something like this? Arrange the array elements in descending order, each coupled with its index-range as a local maximum (for example, A[0] = 10 would be the maximum for array indexes, [0, 10], while A[3] = 4 would be the local maximum for array indexes, [3,3]. Now traverse this list and find the longest, continuously descending sequence where the index-ranges are all contained in the starting range.
10 1 6 4 5 2 3 8 10 7 7
=> 10, [ 0,10]
8, [ 1, 7]
7, [ 9,10]
6, [ 1, 6] <--
5, [ 3, 6] | ranges
4, [ 3, 3] | all
3, [ 5, 6] | contained
2, [ 5, 5] | in [1,6]
1, [ 1, 1] <--

For loops over a list

I want to apply two 'for' loops (slightly different from each other) on list. First 'for' loop will be from the minimum value to the left side and second from the minimum value to the right side. Following is the list:
a = [3,4,6,7,8,4,3,1,6,7,8,9,4]
# to get min index
b = a.index(min(a))
c=a[0:b+1]
d=a[b:len(a)]
for i in reversed(c):
print i
and
for i in d:
print i
So for example, first 'for' loop will run from the index value 8 to 1 and second 'for' loop will run from 8 to 13. I am not sure how to run loops in opposite directions starting from the minimum value. Any suggestions would be helpful.
>>> a = [3,4,6,7,8,4,3,1,6,7,8,9,4]
>>> b = a.index(min(a))
>>> b
7
A loop that runs from the index 7 to 0. (not 8 to 1):
>>> for i in range(b, -1, -1):
... print i, a[i]
...
7 1
6 3
5 4
4 8
3 7
2 6
1 4
0 3
A loop that run from 8 to 12:
>>> for i in range(b+1, len(a)):
... print i, a[i]
...
8 6
9 7
10 8
11 9
12 4
>>> a[b:None:-1]
[1, 3, 4, 8, 7, 6, 4, 3]
>>> a[b+1:]
[6, 7, 8, 9, 4]
UPDATE
Followings are more Pythonic methods of getting the index of the minimum value:
>>> min(xrange(len(a)), key=a.__getitem__)
7
>>> min(enumerate(a), key=lambda L: L[1])[0]
7
>>> import operator
>>> min(enumerate(a), key=operator.itemgetter(1))[0]
7

Calculate order statistics from a matrix in SAS

I have a matrix in SAS/IML:
x = {7 6 3 3 8,
2 3 5 2 5,
2 6 4 3 8,
7 4 8 1 3,
8 8 6 8 7,
3 2 6 1 5 };
I want to create a new matrix that contains the highest k values of each column in x. For example, if k=3, I want the result matrix to contain:
8 8 8 8 8
7 6 6 3 8
7 6 6 3 7
because, for instance, the largest 3 numbers in the first column of x are 8, 7, and 7.
I've unsuccessfully tried to figure out how to do this using the rank function.
Your code looks fine. Here's a minor revision:
do c=1 to ncol(x);
r = rank(x[,c]);
y = x[loc(r>=nrow(x)-k+1), c];
call sort(y);
tops[,c] = y;
end;
As to avoiding the loop to make it faster, it's not necessary. Even with 10,000 columns, this code runs in a fraction of a second. Try running the following timing code:
x = j(500, 10000);
call randgen(x,"normal");
k = 3;
t0=time();
tops = j(k,ncol(x),0);
do c=1 to ncol(x);
r = rank(x[,c]);
y = x[loc(r>=nrow(x)-k+1), c];
call sort(y);
tops[,c] = y;
end;
t=time()-t0;
print t;
Here's a partial answer I've come up with:
k = 3;
tops = j(k,ncol(x),0);
do c=1 to ncol(x);
r = rank(x[,c]);
h=loc(r>=nrow(x)-k+1);
tops[,c] = x[,c][h];
end;
This approach uses a loop, which I'd like to avoid, so please post improvements if possible!