Sum of two list numbers in a table - python

I have, for example, two lists of numbers:
List_numbers_1 = [3, 54, -30]
List_numbers_2 = [65, 8, 800]
I want to create a function that runs the following table of sums:
3 + 65 = 68
54 + 8 = 62
-30 + 800 = 770
The table is lined up, and that is my goal. In order to creat that function I have create other 3 functions that maybe will help me:
'''it returns the width of a number '''
def max_width(List_numbers_1):
string_List_numbers_1 = map(str, List_numbers_1)
width_List_numbers_1 = map(len, string_List_numbers_1)
return max(width_List_numbers_1)
Output: 3
'''it returns the padd for a number'''
def left_padded(number, width):
return str(number).rjust(width)
left_padded(54, 5)
' 54'
left_padded(-56, 5)
' -56'
'''It returns a padd for all the numbers of the list'''
def all_left_padded(List_numbers_1, width):
return list(map(lambda number: left_padded(number, width), List_numbers_1))
all_left_padded(List_numbers_1, 5)
[' 3', ' 54', ' -30']
I think the above functions can be useful for my last function. Nevertheless, I will really appreciate any other idea. If it is possible I would prefer a function that use the return statement but with print() will be ok.
I fact I think this function has to contain return and print as well.
THANK YOU

Without numpy, you can zip the lists together and add them up:
[sum(i) for i in zip(lst1,lst2)]
It is easier to use a list comprehension rather than map
For formatting the numbers it is natural to use str.format().
As you don't know the widths of the numbers in advance, you first create
a format string, and the easiest way to do that is to use format
# maxlen returns the length of the longest element
def maxlen(l):
return max([len(str(i)) for i in l])
# sumtable returns a formatted multiline string containing the sums
# written in a human readable form.
def sumtable(l1,l2):
#sums contains the answers, and table is the full table numbers in
#the calculations as a list of tuples
sums = [sum(i) for i in zip(l1,l2)]
table = list(zip(l1,l2,sums))
width1 = maxlen(l1)
width2 = maxlen(l2)
widthsum = maxlen(sums)
# formatstring has a form like "{:3d} + {:5d} = {:5d}\n"
formatstring = "{{:{}d}} + {{:{}d}} = {{:{}d}}\n".format(width1,width2,widthsum)
# unpack the values from the table into the format string and return.
return (formatstring.format(*table[0])
+ formatstring.format(*table[1])
+ formatstring.format(*table[2]))
print(sumtable([3,54,-30],[65,8,800]))
# 3 + 65 = 68
# 54 + 8 = 62
# -30 + 800 = 770

If you can use a 3rd party library, this is trivial with numpy:
import numpy as np
lst1 = [3, 54, -30]
lst2 = [65, 8, 800]
res = np.sum([lst1, lst2], axis=0)
# array([ 68, 62, 770])

`in order to display the table of sums'''
>def table(L1, L2):
Sum = list(map(lambda x, y: x + y, L1, L2))
widthL1 = max_width(L1)
widthL2 = max_width(L2)
widthSum = max_width(Sum)
first_column = all_left_padded(L1, widthL1)
second_column = all_left_padded(L2, widthL2)
third_column = all_left_padded(Sum, widthsum)
triplets = zip(first_column, second_column, third_column)
return list(map(lambda triplet: str_sum(triplet), triplets))
# for displaying the table
>def printable(L1, L2):
t = table(L1, L2)
for row in t:
print(row)
😀
# the str_sum function was:
def str_sum(Tuple):
return '{ } + { } = { }'.format(Tuple)
> str_sum((2,3,5))
'2 + 3 = 5'

# I was thinking: why instead summing two Lists, I will sum n lists?
# I would create two functions
>L1 = [1, 2]
>L2 = [2, 3]
> L3 = [4, 5]
> Group = (L1, L2, L3)
> Sum = [sum(l) for l in zip(*Group)]
>Sum
[7, 10]
# and for creating a Tuple with n elements because if the table has n Lists the Tuple must have n elements
> def str_sum(Tuple):
n = len (Tuple)
f = ((n -2)*'{ } + ' + '{ } = { }')
return f.format(*Tuple)
>str_sum((1, 2, 3, 8, 7, 21))
('1 + 2 + 3 + 8 + 7 = 21')

Related

Knapsack with SPECIFIC AMOUNT of items from different groups

So this is a variation of the Knapsack Problem I came with the other day.
It is like a 0-1 Knapsack Problem where there are multiple groups and each item belongs to only one group. The goal is to maximize the profits subject to the constraints. In this case, a fixed number of items from each group have to be chosen for each group.
It is similar to the Multiple Choice Knapsack Problem, but in that case you only pick 1 of item of each group, in this one you want to pick x amount of items of each group
So, each item has: value, weight and group
Each group has an item count (Ex: if group A (or 0) has 2, the final solution needs to have 2 items of group A, no more no less)
And and you also have a maximum capacity (not related to the groups)
This translates into:
values[i] = The value of the ith element
weights[i] = The weigth of the ith element
groups[i] = The group of the ith element
C = Capacity
n = Amount of elements
m = Amount of groups
count[j] = Amount of items of group j
I'm attempting a Recursive solution first and then I will try a Dynamic approach.
Any solution would be appreciated (preferably Python, but anything will do :) ).
Usefull links I found:
Theorical solution of a similar problem
First approach to the Multiple Choice Knapsack Problem
Multiple Choice Knapsack Problem solved in Python
Knapsack with count constraint
Full code also in: https://github.com/pabloroldan98/knapsack-football-formations
Explanation after the code.
This code is for an example where you have a Fantasy League with a playersDB where each player has price (weight), points (value) and position (group); there is a list of possible_formations (group variations); and a budget (W) you can't go over.
Full code:
main.py:
from group_knapsack import best_full_teams
playersDB = [
Player(name="Keylor Navas", price=16, points=7.5, position="GK"),
Player(name="Laporte", price=23, points=7.2, position="DEF"),
Player(name="Modric", price=22, points=7.3, position="MID"),
Player(name="Messi", price=51, points=8.2, position="ATT"),
...
]
possible_formations = [
[3, 4, 3],
[3, 5, 2],
[4, 3, 3],
[4, 4, 2],
[4, 5, 1],
[5, 3, 2],
[5, 4, 1],
]
budget = 300
best_full_teams(playersDB, possible_formations, budget)
group_knapsack.py:
import itertools
from MCKP import knapsack_multichoice_onepick
def best_full_teams(players_list, formations, budget):
formation_score_players = []
for formation in formations:
players_points, players_prices, players_comb_indexes = players_preproc(
players_list, formation)
score, comb_result_indexes = knapsack_multichoice_onepick(
players_prices, players_points, budget)
result_indexes = []
for comb_index in comb_result_indexes:
for winning_i in players_comb_indexes[comb_index[0]][comb_index[1]]:
result_indexes.append(winning_i)
result_players = []
for res_index in result_indexes:
result_players.append(players_list[res_index])
formation_score_players.append((formation, score, result_players))
print("With formation " + str(formation) + ": " + str(score))
for best_player in result_players:
print(best_player)
print()
print()
formation_score_players_by_score = sorted(formation_score_players,
key=lambda tup: tup[1],
reverse=True)
for final_formation_score in formation_score_players_by_score:
print((final_formation_score[0], final_formation_score[1]))
return formation_score_players
def players_preproc(players_list, formation):
max_gk = 1
max_def = formation[0]
max_mid = formation[1]
max_att = formation[2]
gk_values, gk_weights, gk_indexes = generate_group(players_list, "GK")
gk_comb_values, gk_comb_weights, gk_comb_indexes = group_preproc(gk_values,
gk_weights,
gk_indexes,
max_gk)
def_values, def_weights, def_indexes = generate_group(players_list, "DEF")
def_comb_values, def_comb_weights, def_comb_indexes = group_preproc(
def_values, def_weights, def_indexes, max_def)
mid_values, mid_weights, mid_indexes = generate_group(players_list, "MID")
mid_comb_values, mid_comb_weights, mid_comb_indexes = group_preproc(
mid_values, mid_weights, mid_indexes, max_mid)
att_values, att_weights, att_indexes = generate_group(players_list, "ATT")
att_comb_values, att_comb_weights, att_comb_indexes = group_preproc(
att_values, att_weights, att_indexes, max_att)
result_comb_values = [gk_comb_values, def_comb_values, mid_comb_values,
att_comb_values]
result_comb_weights = [gk_comb_weights, def_comb_weights, mid_comb_weights,
att_comb_weights]
result_comb_indexes = [gk_comb_indexes, def_comb_indexes, mid_comb_indexes,
att_comb_indexes]
return result_comb_values, result_comb_weights, result_comb_indexes
def generate_group(full_list, group):
group_values = []
group_weights = []
group_indexes = []
for i, item in enumerate(full_list):
if item.position == group:
group_values.append(item.points)
group_weights.append(item.price)
group_indexes.append(i)
return group_values, group_weights, group_indexes
def group_preproc(group_values, group_weights, initial_indexes, r):
comb_values = list(itertools.combinations(group_values, r))
comb_weights = list(itertools.combinations(group_weights, r))
comb_indexes = list(itertools.combinations(initial_indexes, r))
group_comb_values = []
for value_combinations in comb_values:
values_added = sum(list(value_combinations))
group_comb_values.append(values_added)
group_comb_weights = []
for weight_combinations in comb_weights:
weights_added = sum(list(weight_combinations))
group_comb_weights.append(weights_added)
return group_comb_values, group_comb_weights, comb_indexes
MCKP.py:
import copy
def knapsack_multichoice_onepick(weights, values, max_weight):
if len(weights) == 0:
return 0
last_array = [-1 for _ in range(max_weight + 1)]
last_path = [[] for _ in range(max_weight + 1)]
for i in range(len(weights[0])):
if weights[0][i] < max_weight:
if last_array[weights[0][i]] < values[0][i]:
last_array[weights[0][i]] = values[0][i]
last_path[weights[0][i]] = [(0, i)]
for i in range(1, len(weights)):
current_array = [-1 for _ in range(max_weight + 1)]
current_path = [[] for _ in range(max_weight + 1)]
for j in range(len(weights[i])):
for k in range(weights[i][j], max_weight + 1):
if last_array[k - weights[i][j]] > 0:
if current_array[k] < last_array[k - weights[i][j]] + \
values[i][j]:
current_array[k] = last_array[k - weights[i][j]] + \
values[i][j]
current_path[k] = copy.deepcopy(
last_path[k - weights[i][j]])
current_path[k].append((i, j))
last_array = current_array
last_path = current_path
solution, index_path = get_onepick_solution(last_array, last_path)
return solution, index_path
def get_onepick_solution(scores, paths):
scores_paths = list(zip(scores, paths))
scores_paths_by_score = sorted(scores_paths, key=lambda tup: tup[0],
reverse=True)
return scores_paths_by_score[0][0], scores_paths_by_score[0][1]
player.py:
class Player:
def __init__(
self,
name: str,
price: float,
points: float,
position: str
):
self.name = name
self.price = price
self.points = points
self.position = position
def __str__(self):
return f"({self.name}, {self.price}, {self.points}, {self.position})"
#property
def position(self):
return self._position
#position.setter
def position(self, pos):
if pos not in ["GK", "DEF", "MID", "ATT"]:
raise ValueError("Sorry, that's not a valid position")
self._position = pos
def get_group(self):
if self.position == "GK":
group = 0
elif self.position == "DEF":
group = 1
elif self.position == "MID":
group = 2
else:
group = 3
return group
Explanation:
Okay,so I managed to find a solution translating what was here: Solving the Multiple Choice Knapsack Problem from C++ to Python. My solution also gives the path that got you to that solution. It uses Dynamic Programming and it's very fast.
The input data, instead of having groups[i], has the weights and the values as a list of lists, where every list inside represent the values of each group:
weights[i] = [weights_group_0, weights_group_1, ...]
values[i] = [values_group_0, values_group_1, ...]
Where:
weights_group_i[j] = The weigth of the jth element of the ith group
values_group_i[j] = The value of the jth element of the ith group
Those would be the inputs of knapsack_multichoice_onepick. Here is an example:
# Example
values = [[6, 10], [12, 2], [2, 3]]
weights = [[1, 2], [6, 2], [3, 2]]
W = 7
print(knapsack_multichoice_onepick(weights, values, W)) # (15, [(0, 1), (1, 1), (2, 1)])
After that I followed #user3386109 's suggestion and did the combinations with the indexes. The group preprocesing methods are players_preproc, generate_group and group_preproc.
Again, this code is for an example where you have a Fantasy League with a playersDB where each player has price (weight), points (value) and position (group); there is a list of possible_formations (group variations); and a budget (W) you can't go over.
The best_full_teams method prints everything and uses all the previous ones.

How to create the smallest possible number remaining zeros?

I was given a task to create the smallest number from two numbers remaining zeros.
But I cannot solve the task because of my code is not remaining all zeros appropriate. If the input is
245
36
the output is 23456 and that's correct. But with input:
40
305
it outputs: [0,0,3,4,5]. But should be 30045.
Here's my code:
f1 = [int(x) for x in input()]
f2 = [int(y) for y in input()]
f = f1+f2
for each in range(len(f)):
for eacc in range(each+1, len(f)):
if f[each] > f[eacc]:
f[each], f[eacc] = f[eacc], f[each]
for zero in range(len(f)):
if f[zero] == 0 and f[0] > 0:
f.remove(0)
f.insert(zero+1, 0)
break
print(f)
n1 = 40
n2 = 305
# sort lexicograhically
ns = sorted(str(n1) + str(n2))
# move the first non-zero element to the start
i = ns.count('0')
if 0 < i < len(ns):
ns[0:0] = ns.pop(i)
Remove all the zeros. Get all the permutations and find the min. Then add zero from index 1
from itertools import permutations
a=list('40')+list('305')
a=list(map(int,a))
num_of_zero=a.count(0) # get the count of zeros
for i in range(num_of_zero):
a.pop(a.index(0))
new_list=list(min(list(permutations(a)))) # get all the permutations
for i in range(num_of_zero):
new_list.insert(1,0) # insert zeros at index 1 shifting all element to the right
print(''.join(map(str,new_list)))#30045
Without permutations sorted will also work
a=list('40')+list('305')
a=list(map(int,a))
num_of_zero=a.count(0)
for i in range(num_of_zero):
a.pop(a.index(0))
new_list=sorted(a)
for i in range(num_of_zero):
new_list.insert(1,0)
print(''.join(map(str,new_list)))#30045
Using numpy
import numpy as np
a=list('40')+list('305')
a=list(map(int,a))
num_of_zero=a.count(0)
new_list=sorted(a) # sorted will return [0,0,3,4,5]
I = np.nonzero(new_list) #return non_zero_array
if(len(I[0])>0):
first_non_zero_value=new_list.pop(I[0][0]) #get index of first element
new_list.insert(0,first_non_zero_value)
print(''.join(map(str,new_list)))#30045
Here you could use itertools.permutations. First I would use map to change the ints to lists. Next I would concatenate them and have one list of 5 ints. Then using permutations we could generate all possible numbers that could be made from these 5 ints. From our new list we could now take the min using *list comprehension to filter out any item that begins with 0 using if i[0]. Since it is a tuple we have to convert the elements to str then we can join them into an int and print
from itertools import permutations
a = 40
b = 305
a = [*map(int, str(a))]
b = [*map(int, str(b))]
c = a + b
combo = list(permutations(c, len(c)))
res = min([i for i in combo if i[0]])
res = [str(i) for i in res]
print(''.join(res))
# 30045
If a = 0, b = 0 is a potential input, a try/except block would be neccessary
try:
res = min([i for i in combo if i[0]])
res = [str(i) for i in res]
print(int(''.join(res)))
except ValueError:
res = 0
print(res)

Python: Multiplying numbers in a list of tuples and totalling it

I'm trying to create a code where the first two numbers of a tuple are multiplied, and then totaled with other tuples. Here's my very wonky code:
numbers = [(68.9, 2, 24.8),
(12.4, 28, 21.12),
(38.0, 15, 90.86),
(23.1, 45, 15.3),
(45.12, 90, 12.66)]
def function(numbers):
first_decimal = [element[1] for element in numbers]
integer = [element[2] for element in numbers]
string_1 = ''.join(str(x) for x in first_decimal)
string_2 = ''.join(str(x) for x in integer)
# It says 'TypeError: float() argument must be a string or a number',
# but doesn't this convert it to a string??
tot = 1
for element in first_decimal:
tot = float(first_decimal) * int(integer)
return tot
function(numbers)
Forgot about the output. So basically what is needed is the total of:
total_add = 68.9 + 2, 12.4 + 28, 23.1 + 45, 45.12 + 90
i.e. the first two numbers of every tuple in the list. Apologies.
If you literally want to add up the product of the first two elements in each tuple, then you can use the sum() function with a generator:
>>> sum(t[0] * t[1] for t in numbers)
6155.299999999999
which we can check is correct through the following
>>> 68.9 * 2 + 12.4 * 28 + 38.0 * 15 + 23.1 * 45 + 45.12 * 90
6155.299999999999
My preference is to use a vectorised approach via numpy:
import numpy as np
numbers = [(68.9, 2, 24.8),
(12.4, 28, 21.12),
(38.0, 15, 90.86),
(23.1, 45, 15.3),
(45.12, 90, 12.66)]
a = np.array(numbers)
res = np.dot(a[:, 0], a[:, 1])
# 6155.3
First off, element[1] will give you the second entry of the tuple, indexing for a tuple or list always starts at 0. Apart from that, you're giving yourself a hard time with your function by converting variables back and forth. Not sure what you are trying to do with this part anyway:
string_1 = ''.join(str(x) for x in first_decimal)
string_2 = ''.join(str(x) for x in integer)
It seems pretty unecessary. Now to give you a solution that is similar to your approach. Basically, we enumerate through every tuple of the list, multiply the first two entries and add them to the total amound:
numbers = [(68.9, 2, 24.8),
(12.4, 28, 21.12),
(38.0, 15, 90.86),
(23.1, 45, 15.3),
(45.12, 90, 12.66)]
def function(numbers_list):
total_add = 0
# Because numbers is a list of tuples, you can just
# use `len()` to find the number of tuples
for tuple in range(len(numbers_list)):
total_add += numbers_list[tuple][0] * numbers_list[tuple][1]
return total_add
function(numbers)
or simply:
def function(numbers_list):
total_add = 0
for tuple in numbers_list:
total_add += tuple[0] * tuple[1]
return total_add
which can be further shortened to Joe Iddons answer:
total_add = sum(t[0] * t[1] for t in numbers)

How to cycle through the index of an array?

line 14 is where my main problem is.i need to cycle through each item in the array and use it's index to determine whether or not it is a multiple of four so i can create proper spacing for binary numbers.
def decimalToBinary(hu):
bits = []
h = []
while hu > 0:
kla = hu%2
bits.append(kla)
hu = int(hu/2)
for i in reversed(bits):
h.append(i)
if len(h) <= 4:
print (''.join(map(str,h)))
else:
for j in range(len(h)):
h.index(1) = h.index(1)+1
if h.index % 4 != 0:
print (''.join(map(str,h)))
elif h.index % 4 == 0:
print (' '.join(map(str,h)))
decimalToBinary( 23 )
If what you're looking for is the index of the list from range(len(h)) in the for loop, then you can change that line to for idx,j in enumerate(range(len(h))): where idx is the index of the range.
This line h.index(1) = h.index(1)+1 is incorrect. Modified your function, so at least it executes and generates an output, but whether it is correct, i dont know. Anyway, hope it helps:
def decimalToBinary(hu):
bits = []
h = []
while hu > 0:
kla = hu%2
bits.append(kla)
hu = int(hu/2)
for i in reversed(bits):
h.append(i)
if len(h) <= 4:
print (''.join(map(str,h)))
else:
for j in range(len(h)):
h_index = h.index(1)+1 # use h_index variable instead of h.index(1)
if h_index % 4 != 0:
print (''.join(map(str,h)))
elif h_index % 4 == 0:
print (' '.join(map(str,h)))
decimalToBinary( 23 )
# get binary version to check your result against.
print(bin(23))
This results:
#outout from decimalToBinary
10111
10111
10111
10111
10111
#output from bin(23)
0b10111
You're trying to join the bits to string and separate them every 4 bits. You could modify your code with Marcin's correction (by replacing the syntax error line and do some other improvements), but I suggest doing it more "Pythonically".
Here's my version:
def decimalToBinary(hu):
bits = []
while hu > 0:
kla = hu%2
bits.append(kla)
hu = int(hu/2)
h = [''.join(map(str, bits[i:i+4])) for i in range(0,len(bits),4)]
bu = ' '.join(h)
print bu[::-1]
Explanation for the h assignment line:
range(0,len(bits),4): a list from 0 to length of bits with step = 4, eg. [0, 4, 8, ...]
[bits[i:i+4] for i in [0, 4, 8]: a list of lists whose element is every four elements from bits
eg. [ [1,0,1,0], [0,1,0,1] ...]
[''.join(map(str, bits[i:i+4])) for i in range(0,len(bits),4)]: convert the inner list to string
bu[::-1]: reverse the string
If you are learning Python, it's good to do your way. As #roippi pointed out,
for index, value in enumerate(h):
will give you access to both index and value of member of h in each loop.
To group 4 digits, I would do like this:
def decimalToBinary(num):
binary = str(bin(num))[2:][::-1]
index = 0
spaced = ''
while index + 4 < len(binary):
spaced += binary[index:index+4]+' '
index += 4
else:
spaced += binary[index:]
return spaced[::-1]
print decimalToBinary(23)
The result is:
1 0111

max() function, getting the max tuple

SO i wand to use max() in order to check 3 tuple in the form of (int, str, str),
i want to get the max value of cell 1 out of the 3, but i want to add different ints.
exmpale:
tup_1 = 5, 'adasd', 'dadas'
tup_2 = 4, 'adasda', 'dadad'
tup_3 = 3, 'adasds', 'asdasda'
gap = -2
score = 2
max(tup_1[0] + score, tup_2[0] + gap, tup_3[0] + gap)
i want to get back the tuple with the max value of the first cell, again i wan the tuple not the int, any ideas?
tup_1 = 5, 'adasd', 'dadas'
tup_2 = 4, 'adasda', 'dadad'
tup_3 = 3, 'adasds', 'asdasda'
gap = -2
score = 2
print(max((tup_1[0] + score, tup_1),
(tup_2[0] + gap, tup_2),
(tup_3[0] + gap, tup_3))[1])

Categories