Python: function to group number by tens place - python

Takes a list of numbers and groups the numbers by their tens place, giving every tens place it's own sublist.
ex:
$ group_by_10s([1, 10, 15, 20])
[[1], [10, 15], [20]]
$ group_by_10s([8, 12, 3, 17, 19, 24, 35, 50])
[[3, 8], [12, 17, 19], [24], [35], [], [50]]
my approach:
limiting = 10
ex_limiting = 0
result = []
for num in lst:
row = []
for num in lst:
if num >= ex_limiting and num <= limiting:
row.append(num)
lst.remove(num)
result.append(row)
ex_limiting = limiting
limiting += 10
But it returns [[1], [10, 20]].
What's wrong with my approach and how can I fix it?

You may already have a correct answer, but here's an alternative solution:
def group_by_10s(mylist):
result = []
decade = -1
for i in sorted(mylist):
while i // 10 != decade:
result.append([])
decade += 1
result[-1].append(i)
return result
group_by_10s([8, 12, 3, 17, 19, 24, 35, 50])
#[[3, 8], [12, 17, 19], [24], [35], [], [50]]
It uses only plain Python, no extra modules.

You can use a list comprehension:
def group_by_10s(_d):
d = sorted(_d)
return [[c for c in d if c//10 == i] for i in range(min(_d)//10, (max(_d)//10)+1)]
print(group_by_10s([1, 10, 15, 20]))
print(group_by_10s([8, 12, 3, 17, 19, 24, 35, 50]))
print(group_by_10s(list(range(20))))
Output:
[[1], [10, 15], [20]]
[[3, 8], [12, 17, 19], [24], [35], [], [50]]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]

Credit to advice for not iterating list during loop.
I got this answer at the end, for anyone who wants the answer.
Thanks for support!
def group_by_10s(numbers):
external_loop = int(max(numbers)/10)
limiting = 10
ex_limiting = 0
result = []
for external_loop_count in range(external_loop+1):
row = []
for num in numbers:
if num >= ex_limiting and num < limiting:
row.append(num)
row.sort()
result.append(row)
ex_limiting = limiting
limiting += 10
return(result)

How about this one?
numbers = [8, 12, 3, 17, 19, 24, 35, 50]
def group_by_10s(numbers):
arr = []
for i in range((max(numbers) / 10) + 1):
arr.append([])
numbers.sort()
for number in numbers:
if number < 10:
arr[0].append(number)
else:
index = number / 10
arr[index].append(number)
return arr
print group_by_10s(numbers)
# [[3, 8], [12, 17, 19], [24], [35], [], [50]]

Do not modify the list while you are iterating over it, as when you remove items from it, some items get skipped over. Also change the bounds so that you will only append to row if num < limiting. I would add in a check to make sure the list has elements before adding it to result:
for num in lst:
row = []
for num in lst:
if num >= ex_limiting and num < limiting:
row.append(num)
if len(row) > 0 :
result.append(row)
ex_limiting = limiting
limiting += 10
This will yield:
[[1], [10, 15], [20]]

Related

Python array logic

I am trying to create a list of lists with the input of m and n, where m is the number of lists within the main list and n is the number of elements within each given list. The grid should contain the integers from start to start + rows * cols - 1 and be ascending. But, every odd numbered row should be descending instead.
The code I've written is returning the expected results, but my automated tester is saying it's incorrect. Maybe my logic is messed up somewhere?
inputs:
start = 1, m = 3, n = 5
expected:
[[1,2,3,4,5],[10,9,8,7,6],[11,12,13,14,15]]
result = []
mylist = []
start = 1
for x in range(0, rows):
for x in range(0, cols):
result.append(start)
start += 1
for y in range(0, rows):
if y%2 != 0:
mylist.append(result[cols - 1::-1])
del result[cols - 1::-1]
else:
mylist.append(result[0:cols])
del result[0:cols]
return mylist
One possible solution, using itertools.count:
from itertools import count
def build(m, n, start=1):
lst, c = [], count(start)
for i in range(m):
lst.append([next(c) for j in range(n)][::-1] if i % 2 else [next(c) for j in range(n)])
return lst
print(build(3, 5, 1))
Prints:
[[1, 2, 3, 4, 5], [10, 9, 8, 7, 6], [11, 12, 13, 14, 15]]
print(build(3, 0, 1))
Prints:
[[], [], []]
just generate the list of numbers you need which will be n * m, in your case that would generate 0 to 14 in the python range function. However as we want to start at ` then we need to add the start offset too the range end.
Now we can generate all the numbers we need we just need to think about how to create them.
well we can add numbers to the list until the list reaches the size of n, then we need to start a new list, However if the list we just finished is an even numbered row then we need to reverse that list.
def build_lists(m, n, start=1):
data =[[]]
for i in range(start, n * m + start):
if len(data[-1]) < n:
data[-1].append(i)
else:
if len(data) % 2 == 0:
data[-1] = data[-1][::-1]
data.append([i])
if len(data) % 2 == 0:
data[-1] = data[-1][::-1]
return data
print(build_lists(3, 5))
print(build_lists(6, 3))
print(build_lists(6, 2, 100))
OUTPUT
[[1, 2, 3, 4, 5], [10, 9, 8, 7, 6], [11, 12, 13, 14, 15]]
[[1, 2, 3], [6, 5, 4], [7, 8, 9], [12, 11, 10], [13, 14, 15], [18, 17, 16]]
[[100, 101], [103, 102], [104, 105], [107, 106], [108, 109], [111, 110]]

Can my code be more simple?

An n-by-n square matrix (table of numbers) is a magic matrix if the sum of its row and the sum of each column are identical. For example, the 4-by-4 matrix below is a magic matrix. The sum of every row and the sum of every column are exactly the same value 34.
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
Write a function that takes a 4-by-4 matrix as an argument and then determine if the matrix is magic or not. The
#matrix should be stored as a two-dimensional list. Test your function with a magic matrix and a none magic matrix.
def magic(matrix = []):
magic_matrix = False
if len(matrix) != 4:
print('Enter a 4 * 4 matrix')
return magic_matrix
row1Sum = sum(matrix[0])
rowSum_ok = True
for row in range(1, 4):
if sum(matrix[row]) != row1Sum:
rowSum_ok = False
break
colSum_ok = True
for col in range(4):
s_col = 0
for row in range(4):
s_col += matrix[row][col]
if s_col != row1Sum:
colSum_ok = False
break
if rowSum_ok and colSum_ok:
magic_matrix = True
return magic_matrix
def mainMagic():
m1 = [[9, 6, 3, 16],
[4, 15, 10, 5],
[14, 1, 8, 11],
[7, 12, 13, 2]]
print('\nThe matrix:')
for i in range(4):
for j in m1[i]:
print(str(j).rjust(3), end =' ')
print()
if magic(m1):
print('is a magic matrix.')
else:
print('is not a magic matrix.')
m2 = [[6, 22, 44, 18],
[1, 11, 10, 13],
[3, 17, 6, 12],
[9, 14, 2, 1]]
print('\nThe matrix:')
for i in range(4):
for j in m2[i]:
print(repr(j).rjust(3), end = ' ')
print()
if magic(m2):
print('is a magic matrix.')
else:
print('is not a magic matrix.')
mainMagic()
With a couple of set comprehensions and a zip() that is fairly straight forward to cleanup like:
Code:
def is_magic(matrix):
sum_rows = {sum(row) for row in matrix}
sum_cols = {sum(col) for col in zip(*matrix)}
return len(sum_cols) == 1 and sum_cols == sum_rows
Test Code:
m1 = [[9, 6, 3, 16],
[4, 15, 10, 5],
[14, 1, 8, 11],
[7, 12, 13, 2]]
m2 = [[6, 22, 44, 18],
[1, 11, 10, 13],
[3, 17, 6, 12],
[9, 14, 2, 1]]
print(is_magic(m1))
print(is_magic(m2))
Results:
True
False

Aggregation in array element - python

I have a OP : {'2017-05-06': [3, 7, 8],'2017-05-07': [3, 9, 10],'2017-05-08': [4]}
from the OP I just want another OP :
{'2017-05-06': [15, 11, 10],'2017-05-07': [19, 13, 12],'2017-05-08': [4]}
which means:
Ncleand is 2017-05-06
element total is 18 so '2017-05-06': [3 -18, 7-18, 8-18] = '2017-05-06': [15, 11, 10]
likewise all elements data.
So final output is {'2017-05-06': [15, 11, 10],'2017-05-07': [19, 13, 12],'2017-05-08': [4]}
How to do this?
Note : I am using python 3.6.2 and pandas 0.22.0
code so far :
import pandas as pd
dfs = pd.read_excel('ff2.xlsx', sheet_name=None)
dfs1 = {i:x.groupby(pd.to_datetime(x['date']).dt.strftime('%Y-%m-%d'))['duration'].sum() for i, x in dfs.items()}
d = pd.concat(dfs1).groupby(level=1).apply(list).to_dict()
actuald = pd.concat(dfs1).div(80).astype(int)
sum1 = actuald.groupby(level=1).transform('sum')
m = actuald.groupby(level=1).transform('size') > 1
cleand = sum1.sub(actuald).where(m, actuald).groupby(level=1).apply(list).to_dict()
print (cleand)
From the cleand I want to do this?
In a compact (but somehow inefficient) way:
>>> op = {'2017-05-06': [3, 7, 8],'2017-05-07': [3, 9, 10],'2017-05-08': [4]}
>>> { x:[sum(y)-i for i in y] if len(y)>1 else y for x,y in op.items() }
#output:
{'2017-05-06': [15, 11, 10], '2017-05-07': [19, 13, 12], '2017-05-08': [4]}
def get_list_manipulation(list_):
subtraction = list_
if len(list_) != 1:
total = sum(list_)
subtraction = [total-val for val in list_]
return subtraction
for key, values in data.items():
data[key] = get_list_manipulation(values)
>>>{'2017-05-06': [15, 11, 10], '2017-05-07': [19, 13, 12], '2017-05-08': [4]}

Python FloorOfX Using Binary Search

How do I write the code by using binary search:
def floorofx(L, x):
pass
Like define low, high, middle for each of element. As,
Input: L = [11, 12, 13, 14, 15, 20, 27, 28], x = 17
Output: 15
15 is the largest element in L smaller than 17.
Input: L = [11, 12, 13, 14, 15, 16, 19], x = 20
Output: 19
19 is the largest element in L smaller than 20.
Input: L = [1, 2, 8, 10, 10, 12, 19], x = 0
Output: -1
Since floor doesn't exist, output is -1.
Can someone help me with it?
You can simply use the bisect module and decrement the obtained index.
from bisect import bisect_right
def floorofx(L, x):
idx = bisect_right(L,x)
return L[idx-1] if idx > 0 else -1
This generates the following results (for your given sample input):
>>> floorofx(L = [11, 12, 13, 14, 15, 20, 27, 28], x = 17)
15
>>> floorofx(L = [11, 12, 13, 14, 15, 16, 19], x = 20)
19
>>> floorofx(L = [1, 2, 8, 10, 10, 12, 19], x = 0)
-1
Mind that L must be sorted, and that in case -1 is an element of L, you cannot make the distinction between "not found" and -1 as a result. Since we use binary search, the algorithm runs in O(log n).

How to print an interval in sorted list

I want to know how to print numbers which are in sorted list. The interval will be given. For example:
list = [5, 10, 14, 18, 20, 30, 55]
and our interval input is between 11 and 29. So the program must print 14, 18,20.
You can simmply do as follows:
a_list = [5, 10, 14, 18, 20, 30, 55]
print([v for v in a_list if 11 <= v <= 29])
# Prints [14, 18, 20]
number_list = [5, 10, 14, 18, 20, 30, 55]
interval_list = [11,29]
result_list = []
for number in number_list:
if number in range(interval_list[0], interval_list[1]):
result_list.append(number)
print result_list

Categories