Finding the same numbers in an input and summing the paired numbers - python

I want to find number pairs in an input, then sum up those pairs, but leave out unpaired numbers. By that I mean
8 8 8 = 16
8 8 8 8 8 = 32
so numbers with a pair of two will get counted but a number that doesn't have a pair won't get counted. Sorry if I worded this weird I don't know how to explain it, but the example will help.
For example:
8 3 4 4 5 9 9 5 2
Would output:
36
4+4+5+5+9+9 = 36
In Python.

Use collections.Counter
>>> import collections
>>> s = "8 3 4 4 5 9 9 5 2"
>>> l = s.split()
>>> sum([int(item)*count for item, count in collections.Counter(l).items() if count > 1])
36
or
>>> s = "8 3 4 4 5 9 9 5 2"
>>> l = s.split()
>>> sum([int(item)*count for item, count in collections.Counter(l).items() if count%2 == 0])
36

As a correction of the answer #avinash-raj gave:
import collections
s = "8 3 4 4 5 9 9 5 2"
l = s.split()
print(sum([int(item) * 2 * (count // 2) for item, count in collections.Counter(l).items()]))
As explanation:
we vacuum up all the numbers in to a Counter, which will tell us the number of times a key has been seen
the expression (count // 2) is integer division, and gives us the number of complete pairs. Thus if we've seen a key 9 times, (count // 2) -> 9 / 2 -> 4.

Related

Trouble in swapping and assignment min and max elements

IMPORTANT UPD AT THE END!
The existing code works not for all cases.
def myfunc(x):
a = [int(i) for i in x.split()]
a[a.index(min(a))], a[a.index(max(a))] = a[a.index(max(a))], a[a.index(min(a))]
a = [str(i) for i in a]
return ' '.join(a)
myfunc()
It works for 3 4 5 2 1 and don't work for 1 5 4 3 2.
Why?
!!!UPD: I made some changes and it looks very strange.
I used two different lines separately (with commented one of them). The program gives different results in some cases. BUT THE MOST INTERESTING, when I used two of them, uncommented - the program don't return the income string?
# a[a.index(min(a))], a[a.index(max(a))] = a[a.index(max(a))], a[a.index(min(a))]
a[a.index(max(a))], a[a.index(min(a))] = a[a.index(min(a))], a[a.index(max(a))]
Cases which I use:
#print(myfunc("5 1 4 3 2"))
#print(myfunc("1 5 4 3 2"))
#print(myfunc("3 4 5 2 1"))
#print(myfunc("-30000 30000"))
#print(myfunc("2147483647 -2147483648"))
#print(myfunc("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 17 16 15 14"))
#print(myfunc("1 2 3 4 5 6 7 8 9 10"))
#print(myfunc("1 9 8 7 6 5 4 3 2 10"))
UPD+=1 Guys I changed code to:
minind = a.index(min(a))
maxind = a.index(max(a))
a[minind], a[maxind] = a[maxind], a[minind]
Now it works for all case. But question about previous cases are still open
Please help. I spend about 2 hours in tries to find some explanation of this...
Please help
The reason it doesn't work is because the assignments are being executed sequentially. When you write:
a[a.index(min(a))], a[a.index(max(a))] = a[a.index(max(a))], a[a.index(min(a))]
it's essentially equivalent to:
tempmax, tempmin = a[a.index(max(a))], a[a.index(min(a))]
a[a.index(min(a))] = tempmax
a[a.index(max(a))] = tempmin
But notice that after doing the tempmax assignment, a.index(max(a)) can change. index() returns the earliest index, so if the minimum element was before the maximum element, this will now return the original minimum element's location (because it now contains the maximum element), and assigns tempmin back to it.
Your code assumes that the indexes to be assigned are computed before any of the assignments are done, but that's not how it actually works.
Your code doesn't work if the minimum is located before the maximum.
For example:
s = "1 5 4 3 2" # this doesn't work
myfunc(s)
>>> '1 5 4 3 2'
s = "5 1 4 3 2" # this works
myfunc(s)
>>> '1 5 4 3 2'
But, as you noticed, if you define indices before swapping, everything works fine.
def myfunc(x):
a = [int(i) for i in x.split()]
mn = a.index(min(a))
mx = a.index(max(a))
a[mn], a[mx] = a[mx], a[mn]
a = [str(i) for i in a]
return ' '.join(a)
s = "1 5 4 3 2"
myfunc(s)
>>> '5 1 4 3 2'
I'm waiting for some illuminati mind to have an answer for this.

Print a number table in a simple format

I am stuck trying to print out a table in Python which would look like this (first number stands for amount of numbers, second for amount of columns):
>>> print_table(13,4)
0 1 2 3
4 5 6 7
8 9 10 11
12 13
Does anyone know a way to achieve this?
This is slightly more difficult than it sounds initially.
def numbers(n, r):
print('\n'.join(' '.join(map(str, range(r*i, min(r*(i + 1), n + 1)))) for i in range(n//r + 1)))
numbers(13, 4)
#>>> 0 1 2 3
4 5 6 7
8 9 10 11
12 13
def numbers(a,b):
i=0;
c=0;
while i<=a:
print(i,end="") #prevents printing a new line
c+=1
if c>=b:
print("\n") #prints a new line when the number of columns is reached and then reset the current column number
c=0;
I think it should work
def num2(n=10, r=3):
print('\n'.join(' '.join(tuple(map(str, range(n+1)))[i:i+r]) for i in range(0, n+1, r)))
<<<
0 1 2
3 4 5
6 7 8
9 10

Check a variable is a multiple of 10

I need my program to check an in putted variable (e_gtin) and then calculate the GTIN from it (times the 1,3,5 and 7th number by three then add the 7 numbers up and divide by the nearest 10 times table) So far, it times the numbers and adds them up but I don't know where to go from there in terms of making it a multiple of ten
In Addition i eventually used this code
calculator = int(e_gtin[0])*3+int(e_gtin[1])+\
int(e_gtin[2])*3+int(e_gtin[3])+\
int(e_gtin[4])*3+int(e_gtin[5])+\
int(e_gtin[6])*3
rounding = round(calculator+4)
The plus 4 is so the variable will always round up rather than rounding down (The GTIN calculation specifies this)
e_gtin being an inputted 7 digit GTIN code.
Thanks go to --->
https://stackoverflow.com/users/906693/roadrunner66
You are presumably asking about calculating the check-digit on a GTIN8 number. An explanation is given here http://www.gs1.org/how-calculate-check-digit-manually
e = input("Enter a 7 digit number - ")
# note: an integer number can not be accessed like a string or list,
# make it a string first
e=str(e)
sum= int(e[0])*3+int(e[1])+\
int(e[2])*3+int(e[3])+\
int(e[4])*3+int(e[5])+\
int(e[6])*3
checkdigit = 9 - (sum-1) % 10
print sum,checkdigit
To understand the working of a the modulo operator, just play with it, make yourself a table etc.
import numpy as np
sums=np.array([50,51,52,53,54,55,56,57,58,59,60,61])
print sums
print sums % 10
print 10 - sums % 10 # all results right except for 10s which should be zeros
print 10 - (sums-1) % 10 -1
output:
[50 51 52 53 54 55 56 57 58 59 60 61]
[0 1 2 3 4 5 6 7 8 9 0 1]
[10 9 8 7 6 5 4 3 2 1 10 9]
[0 9 8 7 6 5 4 3 2 1 0 9]

Number Pyramid Nested for Loop

I'm wondering if you could help me out. I'm trying to write a nested for loop in Python 3 that displays a number pyramid that looks like;
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
Can anybody help me out? It would be much appreciated!
This is what I have so far:
col = 1
for i in range(-1, 18, col*2):
for j in range(1, 0, 1):
print(" ", end = "")
for j in range(i, 0, -2):
print(j, end = " ")
print()
So, I can only get half of the pyramid to display.
I guess the main problems I'm having is:
How do i get the output to display an increasing and then decreasing value (ie. 1, 2, 4, 2, 1)?
An alternate way using list comprehensions.
Always break the problem down into digestable chunks. Each line is a mirror of itself, so lets just deal with first making out set of numbers we need.
This generates a list of strings that hold all powers of two which is what this is generating
lines = []
for i in range(1,9):
lines.append([str(2**j) for j in range(i)])
But if we just print this list, a) its going to only have half, and b) its going to mush the numbers together. We need to buffer the numbers with spaces. Fortunately, the last row will have the largest digits for any column, so:
Firstly, how long does each line need to end up being (we need this later) and also, what is the longest number in each column. We can use len as we cast the numbers to strings above.
b = len(lines[-1])
buffers = [len(x) for x in lines[-1]]
Now I have everything I need to print the strings (we stopped using numbers above):
So, for each line, find out how long it is, and expand the array it to the length of the longest line by filling the left of the array with empty strings (for this we're still pretending we're only printing the left half of the triangle):
for line in lines:
l = len(line)
line = [" "]*(b-len(line)) + line
With each line now buffered, we'll make a new array that we will print from. By zip()ing together the line and the buffer, we can easily right justify (String.rjust()) numberic strings, expanded out to the length required.
out = []
for x,y in zip(line,buffers):
out.append(x.rjust(y))
Remmeber until now, we've still just been working with the left half of the pyramid. So we take the output array, reverse it (array[::-1]) and then take every element but the first (array[1:]) and join it all together with a string and print it out.
print(" ".join(out+out[::-1][1:]))
Voila! The completed code:
lines = []
for i in range(1,9):
lines.append([str(2**j) for j in range(i)])
b = len(lines[-1])
buffers = [len(x) for x in lines[-1]]
for line in lines:
l = len(line)
line = [" "]*(b-len(line)) + line
out = []
for x,y in zip(line,buffers):
out.append(x.rjust(y))
print(" ".join(out+out[::-1][1:]))
Output:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
height = 8
maxHeight = height - 1
for i in range(height):
k, Max = 1, i * 2 + 1
print(maxHeight * " ", end="")
maxHeight -= 1
for j in range(Max):
print("%5d" % k, end="")
if (j < (Max // 2)):
k *= 2
else:
k //= 2
print()
Output:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
This could be the other 9 line solution.
Generate power of two's numbers as series
Find the offset need to add in each rows
Print the empty space for the each row before printing the palindromic list.
Ie. (offset * (n - i)) times " "(empty space)
Build palindromic series by slice operation ie. temp + temp[::-1][1:]
Print the palindromic series and offset spaces relative to the length of the number you are printing.
Code:
n = 8
numbers = [2**x for x in range(n)] # Generate interseted series.
offset = len(str(numbers[-1:])) -1 # Find the max offset for the tree.
for i in range(1, n+1): # Iterate n times. 1 to n+1 helps eazy slicing.
temp = numbers[:i] # Slice series to get first row numbers.
print(' ' * (offset * (n - i)), end=" ") # Prefix spaces, multiples of offset.
for num in temp + temp[::-1][1:]: # Generate palindromic series for the row.
print(num, end=" " * (offset - len(str(num)))) # Adjust offset for the number.
print('')
output:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1

Grouping list of integers in a range into chunks

Given a set or a list (assume its ordered)
myset = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
I want to find out how many numbers appear in a range.
say my range is 10. Then given the list above, I have two sets of 10.
I want the function to return [10,10]
if my range was 15. Then I should get [15,5]
The range will change. Here is what I came up with
myRange = 10
start = 1
current = start
next = current + myRange
count = 0
setTotal = []
for i in myset:
if i >= current and i < next :
count = count + 1
print str(i)+" in "+str(len(setTotal)+1)
else:
current = current + myRange
next = myRange + current
if next >= myset[-1]:
next = myset[-1]
setTotal.append(count)
count = 0
print setTotal
Output
1 in 1
2 in 1
3 in 1
4 in 1
5 in 1
6 in 1
7 in 1
8 in 1
9 in 1
10 in 1
12 in 2
13 in 2
14 in 2
15 in 2
16 in 2
17 in 2
18 in 2
19 in 2
[10, 8]
notice 11 and 20 where skipped. I also played around with the condition and got wired results.
EDIT: Range defines a range that every value in the range should be counted into one chuck.
think of a range as from current value to currentvalue+range as one chunk.
EDIT:
Wanted output:
1 in 1
2 in 1
3 in 1
4 in 1
5 in 1
6 in 1
7 in 1
8 in 1
9 in 1
10 in 1
11 in 2
12 in 2
13 in 2
14 in 2
15 in 2
16 in 2
17 in 2
18 in 2
19 in 2
[10, 10]
With the right key function, thegroupbymethod in the itertoolsmodule makes doing this fairly simple:
from itertools import groupby
def ranger(values, range_size):
def keyfunc(n):
key = n/(range_size+1) + 1
print '{} in {}'.format(n, key)
return key
return [len(list(g)) for k, g in groupby(values, key=keyfunc)]
myset = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
print ranger(myset, 10)
print ranger(myset, 15)
You want to use simple division and the remainder; the divmod() function gives you both:
def chunks(lst, size):
count, remainder = divmod(len(lst), size)
return [size] * count + ([remainder] if remainder else [])
To create your desired output, then use the output of chunks():
lst = range(1, 21)
size = 10
start = 0
for count, chunk in enumerate(chunks(lst, size), 1):
for i in lst[start:start + chunk]:
print '{} in {}'.format(i, count)
start += chunk
count is the number of the current chunk (starting at 1; python uses 0-based indexing normally).
This prints:
1 in 1
2 in 1
3 in 1
4 in 1
5 in 1
6 in 1
7 in 1
8 in 1
9 in 1
10 in 1
11 in 2
12 in 2
13 in 2
14 in 2
15 in 2
16 in 2
17 in 2
18 in 2
19 in 2
20 in 2
If you don't care about what numbers are in a given chunk, you can calculate the size easily:
def chunk_sizes(lst, size):
complete = len(lst) // size # Number of `size`-sized chunks
partial = len(lst) % size # Last chunk
if partial: # Sometimes the last chunk is empty
return [size] * complete + [partial]
else:
return [size] * complete

Categories

Resources