Dictionary Keys-Repeat (List<int>) in Python# - python-2.7

This is an assignment; I have worked over it and somewhere get stuck;
This is the input from text file:
min: 1,2,3,5,6
max: 1,2,3,5,6
avg: 1,2,3,5,6
p90: 1,2,3,4,5,6,7,8,9,10
sum: 1,2,3,5,6
min: 1,5,6,14,24
max: 2,3,9
p70: 1,2,3
This is the required output to the text file:
The min of [1, 2, 3, 5, 6] is 1
The max of [1, 2, 3, 5, 6] is 6
The avg of [1, 2, 3, 5, 6] is 3.4
The 90th percentile of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] is 9
The sum of [1, 2, 3, 5, 6] is 17
The min of [1, 5, 6, 14, 24] is 1
The max of [2, 3, 9] is 9
The 70th percentile of [1, 2, 3] is 2
This is my work-out to the text file:
The min of [1, 5, 6, 14, 24] is 1
The max of [2, 3, 9] is 9
The avg of [1, 2, 3, 5, 6] is 3.4
The p90 of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] is 9.0
The sum of [1, 2, 3, 5, 6] is 17
The p70 of [1, 2, 3] is 2.1
Logics
I wrote a function to read from a file and insert the keys:values into dictionary;
Below is the dictionary
OrderedDict([('min', [1, 5, 6, 14, 24]), ('max', [2, 3, 9]), ('avg', [1, 2, 3, 5, 6]), ('p90', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), ('sum', [1, 2, 3, 5, 6]), ('p70', [1, 2, 3])])
From here I compute the required and write the results to the file
My question; how can I make the keys min and max duplicate in the dictionary as you can see the have been overwritten

The problem is, that the keys in a dictionary are unique. That means, a dictionary can only have one entry with the key 'min'. That's why your first entry with the key 'min' gets overwritten by the second.
To solve this I would recommend to change the structure type from Dictionary to something else (like a nested List).
list = []
list.append(['min', [1, 2, 3, 5, 6]])
you will get a list of rows, each containing the function (like 'min') and the number array.
More about Lists

Related

Sort an integer array by converting an element to its sum of numbers

The question I am given is
We are given an array.
In one operation we can replace any element of the array with any two elements that sum to that element.
For example: array = {4, 11, 7}. In one operation you can replace array[1] with 5 and 6 which sums to 11. So the array becomes array = {4, 5, 6, 7}
Return the minimum number of steps in which the whole array can be sorted in non-decreasing order. Along with array in sorted order.
For example: array = {3,9,3}
I think the answer will be 9 will be converted to 3,3,3
But I cannot think of a general formula of doing it.
My thoughts on the solution are
Suppose we want to convert number 6 and 9
We use if and else
IF
we see that we divide a number by 2 and take ceiling but it is greater than the number on it's right side(last example in the question) then we keep subtracting that number(3) until we get integer 0.
That is 9 = 3(number on right of 9 in array in last example) - 3 - 3
ELSE
simply do ceiling(num / 2) to get first number and then num - ceil(num / 2) to ger second. 7 will be 4 and 3.
Please can someone think of a general formula for doing it?
Edy's way (as I interpret it) in Python:
def solve(xs):
limit = 10**100
out = []
for x in reversed(xs):
parts = (x - 1) // limit + 1
limit, extra = divmod(x, parts)
out += extra * [limit+1] + (parts - extra) * [limit]
print(len(out) - len(xs), out[::-1])
solve([4, 11, 7])
solve([3, 9, 3])
solve([9, 4, 15, 15, 28, 23, 13])
Output showing steps and result array for the three test cases (Try it online!):
1 [4, 5, 6, 7]
2 [3, 3, 3, 3, 3]
8 [3, 3, 3, 4, 5, 5, 5, 7, 8, 9, 9, 10, 11, 12, 13]
An output illustrating the progress:
[4, 11, 7] = (input)
[4, 11, [7]]
[4, [5, 6], [7]]
[[4], [5, 6], [7]]
[3, 9, 3] = (input)
[3, 9, [3]]
[3, [3, 3, 3], [3]]
[[3], [3, 3, 3], [3]]
[9, 4, 15, 15, 28, 23, 13] = (input)
[9, 4, 15, 15, 28, 23, [13]]
[9, 4, 15, 15, 28, [11, 12], [13]]
[9, 4, 15, 15, [9, 9, 10], [11, 12], [13]]
[9, 4, 15, [7, 8], [9, 9, 10], [11, 12], [13]]
[9, 4, [5, 5, 5], [7, 8], [9, 9, 10], [11, 12], [13]]
[9, [4], [5, 5, 5], [7, 8], [9, 9, 10], [11, 12], [13]]
[[3, 3, 3], [4], [5, 5, 5], [7, 8], [9, 9, 10], [11, 12], [13]]
Code for that (Try it online!):
def solve(xs):
print(xs, '= (input)')
limit = 10**100
for i, x in enumerate(reversed(xs)):
parts = (x - 1) // limit + 1
limit, extra = divmod(x, parts)
xs[~i] = (parts - extra) * [limit] + extra * [limit+1]
print(xs)
print()
You would want to scan from the right to the left. For convenient explanation, let's mark the right-most element x_0, and the left-most x_{n-1} (n can increase as you split a number into two).
If x_{i} > x_{i-1}, you would want to divide x_{i} into ((x_{i} - 1) / x_{i-1}) + 1 parts, where / is integer division, as evenly as possible.
So for example:
If x_{i} = 15, x_{i-1] = 5, divide x_{i} into (15-1)/5 + 1 = 3 parts: (5, 5, 5).
If x_{i} = 19, x_{i-1] = 5, divide x_{i} into (19-1)/5 + 1 = 4 parts: (4, 5, 5, 5).
(To divide a number equally into a non-decreasing sequence would require a bit of calculation, which shouldn't be too difficult.)
Once you know the sequence, it would be straightforward to repeatedly split a number into 2 to produce that sequence.

How to put in variable as list

I'm trying to make a program that for a sublist of numbers, uses index as a variable and selects each number from the list of lists
so if my numbest = [[1, 2, 3, 4, 5], [2, 4, 6, 8, 10], [3, 5, 7, 9, 11]]
I want to be able to call the function like this
column_sum(2, [[1, 2, 3, 4, 5], [2, 4, 6, 8, 10], [3, 5, 7, 9, 11]]) will add the numbers at index 2 in each sublist (3, 6, and 7) and will return the number 16."
I can't for the life of me figure out how to print
for i in numlist:
print numbest[index]
Looks like Python, so imma say that all you need to do is have a variable that is a running total, add up all the numbers that are the values at the index you specify, and then return that value.
Alexander is also right and if his way is easier for you, you can find resources https://www.w3schools.com/python/ref_func_sum.asp and https://www.w3schools.com/python/python_lists_comprehension.asp

Writting in sub-ndarray of a ndarray in the most pythonian way. Python 2

I have a ndarray like this one:
number_of_rows = 3
number_of_columns = 3
a = np.arange(number_of_rows*number_of_columns).reshape(number_of_rows,number_of_columns)
a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
But I want something like this:
array([[0, 100, 101],
[3, 102, 103],
[6, 7, 8]])
To do that I want to avoid to do it one by one, I rather prefer to do it in arrays or matrices, because later I want to extend the code.
Nothe I have change a submatrix of the initial matrix (in mathematical terms, in terms of this example ndarray). In the example the columns considered are [1,2] and the rows [0,1].
columns_to_keep = [1,2]
rows_to_keep = [0,1]
My first try was to do:
a[rows_to_keep,:][:,columns_to_keep] = np.asarray([[100,101],[102,103]])
However this doesn't modify the initial a, I am not having any error, so a=
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
So I have implemented a piece of code that goes do the job:
b = [[100, 101],[102, 103]]
for i in range(len(rows_to_keep)):
a[i,columns_to_keep] = b[i]
Al thought the previous lines do the job I am wondering how to do it slicing and in a faster fashion. Also in a way that with:
columns_to_keep = [0,2]
rows_to_keep = [0,2]
the desired output is
array([[100, 1, 101],
[3, 4, 5],
[102, 7, 103]]).
Many thanks!
Indexing with lists like [1,2] is called advanced indexing. By itself it produces a copy, not a view. You have to use one indexing expression, not two to assign or change values. That is a[[1,2],:] is a copy, a[[1,2],:][:,[1,2]] += 100 modifies that copy, not the original a.
In [68]: arr = np.arange(12).reshape(3,4)
Indexing with slices; this is basic indexing:
In [69]: arr[1:,2:]
Out[69]:
array([[ 6, 7],
[10, 11]])
In [70]: arr[1:,2:] += 100
In [71]: arr
Out[71]:
array([[ 0, 1, 2, 3],
[ 4, 5, 106, 107],
[ 8, 9, 110, 111]])
Doing the same indexing with lists requires arrays that 'broadcast' against each other. ix_ is a handy way of generating these:
In [73]: arr[np.ix_([1,2],[2,3])]
Out[73]:
array([[106, 107],
[110, 111]])
In [74]: arr[np.ix_([1,2],[2,3])] -= 100
In [75]: arr
Out[75]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Here's what ix_ produces - a tuple of arrays, one is (2,1) in shape, the other (1,2). Together they index a (2,2) block:
In [76]: np.ix_([1,2],[2,3])
Out[76]:
(array([[1],
[2]]), array([[2, 3]]))
For the continuous rows and columns case, you can use basic slicing like this:
In [634]: a
Out[634]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [635]: b = np.asarray([[100, 101],[102, 103]])
In [636]: a[:rows_to_keep[1]+1, columns_to_keep[0]:] = b
In [637]: a
Out[637]:
array([[ 0, 100, 101],
[ 3, 102, 103],
[ 6, 7, 8]])

When changing data inside a list using a for loop, how do you append the list to a dictionary each time the loop iterates?

Basically, wanted to iterate over a list of numerical data to change it's contents, where the numerical at the start of the list is moved to the last, and then the data is shifted to the left. Whilst I have achieved this, as the printed contents of the loop gives the desired results, when trying to append the contents of said loop to said dictionary, it only does this for the final iteration. Here's my code:
minor=[1,2,3,4,5,6]
MNP = {'scale degree' : []
}
def patterns(scale):
for i in scale:
print (scale)
scale.insert(len(scale),scale[0])
del(scale[0])
MNP['scale degree'].append(scale)
using the function patterns, this is the output:
>>> patterns(minor)
the list, minor, is at the top of the page by the way.
output:
[1, 2, 3, 4, 5, 6]
[2, 3, 4, 5, 6, 1]
[3, 4, 5, 6, 1, 2]
[4, 5, 6, 1, 2, 3]
[5, 6, 1, 2, 3, 4]
[6, 1, 2, 3, 4, 5]
Yet when I try to print the contents of the list, scale degree, in the MNP dict, the result is:
MNP['scale degree']
[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]]
I am very perplexed by this result, it's as if the output changes depending on the operation called upon it?
Thank you for any help in advance. It's also worth noting that I've been stuck with this for a good amount of time, so if there's any resources out there that may help me understand similar occurrences i certainly wouldn't pass that up.
The reason this happens is because what you store in MNP['scale degree'] is only a reference to scale. So when you change scale, so do the entries in MNP['scale degree']. What you need to do to avoid this is copying scale each time you append it (i.e. creating a new list instead of adding a reference). You can do this with the copy module:
import copy
minor=[1,2,3,4,5,6]
MNP = {'scale degree' : []
}
def patterns(scale):
for i in scale:
print (scale)
scale.insert(len(scale),scale[0])
del(scale[0])
MNP['scale degree'].append(copy.copy(scale))
patterns(minor)
print(MNP['scale degree'])

Trying to simulate python combinations in C++ with next_permutation

I need to port a snippet written in Python to C++
but that snippet is using combinations from itertools in python.
The line that I'm really interested to porting over to C++ is this one:
for k in combinations(range(n-i),2*i):
range(n-i) in Python will generate a list from 0 to (n-i) - 1
Let n = 16, i = 5
print range(n-i)
outputs:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
and python combinations will generate all possible combinations in that list.
e.g.
print list(combinations(range(n-i),2*i))
outputs:
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
(0, 1, 2, 3, 4, 5, 6, 7, 8, 10),
(0, 1, 2, 3, 4, 5, 6, 7, 9, 10),
(0, 1, 2, 3, 4, 5, 6, 8, 9, 10),
(0, 1, 2, 3, 4, 5, 7, 8, 9, 10),
(0, 1, 2, 3, 4, 6, 7, 8, 9, 10),
(0, 1, 2, 3, 5, 6, 7, 8, 9, 10),
(0, 1, 2, 4, 5, 6, 7, 8, 9, 10),
(0, 1, 3, 4, 5, 6, 7, 8, 9, 10),
(0, 2, 3, 4, 5, 6, 7, 8, 9, 10),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)]
I want to generate similar output using std::vector and next_permutation from C++ but I'm still getting erroneous results. This is my current approach:
for(int j = 0; j < n-i; j++) {
temp_vector.push_back(j);
}
That snippet is equivalent to range(n-i) in Python.
But the following snippet:
do {
myvector.push_back(temp_vector);
} while(next_permutation(temp_vector.begin(),temp_vector.begin()+2*i));
cout<<myvector.size()<<endl;
Is not equivalent to combinations(range(n-i),2*i)) in Python, and I've tried many variations and still haven't been able to come up with the results I'm expecting.
For example:
Let n = 16
i = 5
Python
>>> print len(list(combinations(range(n-i),2*i)))
11
C++
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> temp_vector;
vector< vector<int> > myvector;
int n = 16, i = 5;
for(int j = 0; j < n - i; j++) {
temp_vector.push_back(j);
}
do {
myvector.push_back(temp_vector);
} while(next_permutation(temp_vector.begin(), temp_vector.begin()+2*i));
cout<<myvector.size()<<endl;
return 0;
}
g++ combinations.cpp
./a.out
3628800
Any guidance will be greatly appreciated! Thanks a lot!
combinations and permutations are not the same thing.
A combination is an unordered list of a subset of the items from another set. A permutation is a unique order of the items in the list.
You're generating all combinations of 10 things from a list of 11 things, so you'll get 11 results, each one missing a different one of the original 11 items.
Generating every permutation will generate every unique order of the original 11 items. Since the items in this case are all unique that means the result would be 11! lists where each contains all 11 items. You're only generating permutations from the first 10 items however, so you're getting 10! lists, none of which contain the 11th item.
You need to find an algorithm for generating combinations instead of permutations.
There's no built-in algorithm for combinations. std::next_permutation can be used as part of an algorithm to generate combinations: See Generating combinations in c++.
Here's an old draft proposal for algorithms for combinations, including code.