For loops over a list - python-2.7

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

Related

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.

(Python2) Combining pandas dataframe of mulilayer columns

I want to add values of dataframe of which format is same.
for exmaple
>>> my_dataframe1
class1 score
subject 1 2 3
student
0 1 2 5
1 2 3 9
2 8 7 2
3 3 4 7
4 6 7 7
>>> my_dataframe2
class2 score
subject 1 2 3
student
0 4 2 2
1 4 4 14
2 8 7 7
3 1 2 NaN
4 NaN 2 3
as you can see, the two dataframes have multi-layer columns that the main column is 'class score' and the sub columns is 'subject'.
what i want to do is that get summed dataframe which can be showed like this
score
subject 1 2 3
student
0 5 4 7
1 2 1 5
2 16 14 9
3 4 6 7
4 6 9 10
Actually, i could get this dataframe by
for i in my_dataframe1['class1 score'].index:
my_dataframe1['class1 score'].loc[i,:] = my_dataframe1['class1 score'].loc[i,:].add(my_dataframe2['class2 score'].loc[i,:], fill_value = 0)
but, when dimensions increases, it takes tremendous time to get result dataframe, and i do think it isn't good way to solve problem.
If you add values from the second dataframe, it will ignore the indexing
# you don't need `astype(int)`.
my_dataframe1.add(my_dataframe2.values, fill_value=0).astype(int)
class1 score
subject 1 2 3
student
0 5 4 7
1 6 7 23
2 16 14 9
3 4 6 7
4 6 9 10
Setup
my_dataframe1 = pd.DataFrame([
[1, 2, 5],
[2, 3, 9],
[8, 7, 2],
[3, 4, 7],
[6, 7, 7]
], pd.RangeIndex(5, name='student'), pd.MultiIndex.from_product([['class1 score'], [1, 2, 3]], names=[None, 'subject']))
my_dataframe2 = pd.DataFrame([
[4, 2, 2],
[4, 4, 14],
[8, 7, 7],
[1, 2, np.nan],
[np.nan, 2, 3]
], pd.RangeIndex(5, name='student'), pd.MultiIndex.from_product([['class2 score'], [1, 2, 3]], names=[None, 'subject']))
IIUC:
df_out = df['class1 score'].add(df2['class2 score'],fill_value=0).add_prefix('scores_')
df_out.columns = df_out.columns.str.split('_',expand=True)
df_out
Output:
scores
1 2 3
student
0 5.0 4 7.0
1 6.0 7 23.0
2 16.0 14 9.0
3 4.0 6 7.0
4 6.0 9 10.0
The way I would approach this is keep the data in the same dataframe. You could concatenate the two you have already:
big_df = pd.concat([my_dataframe1, my_dataframe2], axis=1)
Then sum over the larger dataframe, specifying level:
big_df.sum(axis=1, level='subject')

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] <--

Array elements not getting edited in a Python List

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

Avoiding IF in a simple mapping function

I'm trying to avoid an IF in the following mapping function:
X Y
1 11
2 10
3 9
4 8
5 7
6 6
7 5
8 4
9 3
10 2
11 1
12 12
It's basically Y = (12 - X), except when X = 12. In this case, Y = 12.
The Y vector is the reverse of the X vector shifted by one position. Is there a way to write this function using min and max or something like this in order to avoid a conditional?
I'm not attached to any programming language here
y = 12 - x%12;
works for all x from 1 to 12 inclusive. % is the C-style modulus operator, giving the remainder from dividing x by 12. That's zero if x is 12, and x for 1 to 11.
Ruby answer:
x = (1..12).to_a
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y = x.map{|n| 12 - n % 12}
#=> [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 12]
This can be extended to work for any length by using n.max instead of 12.