Related
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.
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]])
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
possible_list = []
bigger_list = []
new_list= [0, 25, 2, 1, 14, 1, 14, 1, 4, 6, 6, 7, 0, 10, 11]
for i in range(0,len(new_list)):
# if the next index is not greater than the length of the list
if (i + 1) < (len(new_list)):
#if the current value is less than the next value
if new_list[i] <= new_list[i+1]:
# add the current value to this sublist
possible_list.append(new_list[i])
# if the current value is greater than the next, close the list and append it to the lager list
bigger_list.append(possible_list)
print bigger_list
How do I find the longest consistent increment in the list called new_list?
I expect the result to be
[[0,2], [2], [1,14], [1,14], [1,4,6,6,7], [0,10,11]]
I can find the remaining solution from there myself.
One problem (but not the only one) with your code is that you are always adding the elements to the same possible_list, thus the lists in bigger_list are in fact all the same list!
Instead, I suggest using [-1] to access the last element of the list of subsequences (i.e. the one to append to) and [-1][-1] to access the last element of that subsequence (for comparing the current element to).
new_list= [0, 25, 2, 1, 14, 1, 14, 1, 4, 6, 6, 7, 0, 10, 11]
subseq = [[]]
for e in new_list:
if not subseq[-1] or subseq[-1][-1] <= e:
subseq[-1].append(e)
else:
subseq.append([e])
This way, subseq ends up the way you want it, and you can use max to get the longest one.
>>> subseq
[[0, 25], [2], [1, 14], [1, 14], [1, 4, 6, 6, 7], [0, 10, 11]]
>>> max(subseq, key=len)
[1, 4, 6, 6, 7]
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'])