Splitting string every 80 spaces - python

I have a string of 6400 numbers which I want to put into an 80x80 string format, for example
string1 = '1 2 3 4 5 6 7 8 9'
What I'm trying to do is this:
string2 = '''1 2 3
4 5 6
7 8 9'''
*the numbers are different lengths too
I have tried using split() but I don't know how to 'count' the amount of spaces and put it into one large string

You can split on space and iterate through it making chunks of given size:
string1 = '1 2 3 4 5 6 7 8 9'
size = 3
splits = string1.split()
print('\n'.join(' '.join(splits[j] for j in range(i, i+size)) for i in range(0, len(splits), size)))
# 1 2 3
# 4 5 6
# 7 8 9

Variable-length numbers? Just use regex.
import re
string1 = '1 22 333 4444 55555 666666 77777777 888888888 9999999999'
string2 = '\n'.join(re.findall('((?:\S+ ){2}\S+)', string1))
The (?:) makes a group you can repeat but doesn't capture it in the match, which makes the direct join possible. Without it, you'd get tuples.
A re.sub would also work.
string2 = re.sub('((\S+ ){2}\S+) ', lambda m: m.group()+'\n', string1)
You would use a {79} instead of the {2} of course, which repeats the '\S+ ' pattern (one or more non-whitespace characters followed by a space) so you don't have to write it out.

You could do this by slicing the string by a set chunk size
# Print a new line every 6 characters
# Change this as needed
chunk_size = 6
# The string to split
s = '1 2 3 4 5 6 7 8 9'
# Iterate over a range of numbers 0 to the length of the string
# with a step size of `chunk_size`
# With `chunk_size` as 6, the range will look like
# [0, 6, 12]
for i in range(0, len(s), chunk_size):
# Slice the string from the current index
# to the current index plus the chunk size
# ie: [0:6], [6:12], [12:18]
print(s[i:i+chunk_size])
print()
# To do this with list comprehension
s2 = "\n".join(s[i:i+chunk_size] for i in range(0, len(s), chunk_size))
print(s2)
# Ouptut:
# 1 2 3
# 4 5 6
# 7 8 9
Or if you have variable length numbers, do as Austin said, and apply the same concept on a split version of the string
chunk_size = 3
s = '10 20 30 4 5 6 7 8 9'.split()
for i in range(0, len(s), chunk_size):
print(" ".join(s[i:i+chunk_size]))
print()
s2 = "\n".join(" ".join(s[i:i+chunk_size]) for i in range(0, len(s), chunk_size))
print(s2)
# Output:
# 10 20 30
# 4 5 6
# 7 8 9

Related

how to print out a range with the single digit right justified

For example, if I had a range of 10, it would print:
9
8
7
and so on. Then when I have double digits, so with a range of 11, it prints out:
10
9
8
But, I want it to print out with the 9 under the 0 instead. Any way to do this?
You could use str.rjust:
for i in reversed(range(1, 11)):
print(str(i).rjust(2))
Output:
10
9
8
7
6
5
4
3
2
1
In Python 3:
for i in range(11)[::-1]:
print(f"{i:>2}")
If you want three-digit numbers, change the 2 to a 3.
You can just add a space at the beginning of the number.
I just calculate the amount of digits and pad the lower number with spaces
max = 1337
max_len = len(str(max))
for i in reversed(range(max)):
str_len = len(str(i))
if max_len > str_len:
difference = max_len - str_len #calculate amount of needed spaces
print(" " * difference + str(i)) #pad string with spaces
else:
print(i)

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.

Subtraction of one string values from another string values

I got two strings, called string1 and string2. Both consists of 6 different numbers.
What i would like to do in Python is to substract the values in string1 from the values in string2. How do I do this? I Guess this involves a for loop, since I only want to substract the first value in string1 from the first value in string2. And substract the second value from string1 from the second value in string2 etc.
So if string 1 got the numbers
2 5 8 9 6 3
and string 2 got the numbers
2 3 5 9 3 2
I want to take "string1" minus "string2" to get
0 2 3 0 3 1
Any suggestions?
You can achieve this with split(), zip(), and join():
" ".join([str(int(a) - int(b)) for a, b in zip(s1.split(), s2.split())])
Building on #pault answer, you can have the following variation (removed the calls to split(), added a conditional):
"".join([str(int(a) - int(b)) if a != ' ' else ' ' for a, b in zip(s1, s2)])
which is simply fancier way of doing:
" ".join([str(int(a) - int(b)) for a, b in zip(s1.replace(' ', ''), s2.replace(' ', ''))])
The latter might be more readable.
You can use regular expressions:
import re
s1 = '2 5 8 9 6 3'
s2 = '2 3 5 9 3 2'
new_string = ' '.join(str(a-b) for a, b in zip(map(int, re.findall('\d+', s1)), map(int, re.findall('\d+', s2))))
Output:
'0 2 3 0 3 1'
s1 = '2 5 8 9 6 3'
s2 = '2 3 5 9 3 2'
l1 = [int(x) for x in s1.split()]
l2 = [int(x) for x in s2.split()]
r1 = [v1 - v2 for v1, v2 in zip(l1, l2)]
.split() splits your string into a list based on where whitespace occurs (although you could provide it an argument to tell it to split on something else).
[int(x) for x in s1.split()] is a list comprehension. It's a one-line loop that does stuff for each value in a list (the split string). We need to convert the values in the split string into ints.
zip(l1, l2) takes the values in two lists and pairs them up. You'd need the lists to have the same number of elements for this to work (we do). From here, we use another list comprehension to pull out pairs of values and then take the difference.
edit (ty danihp): if you need the results to be a string, you can join the values in the list with ' '.join([str(x) for x in r1]) (this uses a space to separate elements in the list).
Step for step:
s1 = '2 5 8 9 6 3'
s2 = '2 3 5 9 3 2'
s3 = [int(x) for x in s1.split()] # split and convert to int
s4 = [int(x) for x in s2.split()] # split and convert to int
s5 = [] # result
for idx in range(0,len(s3)): # length are equal so this is ok
s5.append(s3[idx]-s4[idx]) # put into result
rv = " ".join([str(x) for x in s5]) # join result to string
print(s1)
print(s2)
print(s3)
print(s4)
print(s5)
print(rv)
Output:
2 5 8 9 6 3
2 3 5 9 3 2
[2, 5, 8, 9, 6, 3]
[2, 3, 5, 9, 3, 2]
[0, 2, 3, 0, 3, 1]
0 2 3 0 3 1
Since python is typed, you cannot subtact the strings: you have to convert each string to a list of integers and then subtract each one of the elements.
You can do this with only one loop:
s1 = '2 5 8 9 6 3'
s2 = '2 3 5 9 3 2'
list_diff = [int(x2) - int(x1) for x1, x2 in zip(s1.split(), s2.split())]
# or if you want the result as a string:
list_diff = [str(int(x1) - int(x2)) for x1, x2 in zip(s1.split(), s2.split())]
result = " ".join(list_diff)

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

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.

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

Categories

Resources