Python Logic - Centering text using periods - python

I'm taking this intro to python course online
The problem reads:
For this program, the first line of input is an integer width. Then, there are some lines of text; the line "END" indicates the end of the text. For each line of text, you need to print out a centered version of it, by adding periods .. to the left and right, so that the total length of each line of text is width. (All input lines will have length at most width.) Centering means that the number of periods added to the left and added to the right should be equal if possible; if needed we allow one more period on the left than the right. For example, for input
13
Text
in
the
middle!
END
the correct output would be
.....Text....
......in.....
.....the.....
...middle!...
the Hint given is:
For input line length of L, you should add (width-L)\\2 periods to the right side
Here is my code so far:
width = int(input())
s1 = input()
periods_remain = width - len(s1)
L = periods_remain
periods_rtside = (width-L)//2
periods_leftside = width - periods_rtside
periods_rt_str = '.' * periods_rtside
periods_left_str = '.' * periods_leftside
line1 = periods_left_str + s1 + periods_rt_str
My line1 result looks like "...........Text.." Instead of .....Text....
It can be run here
My problem seems to be the L. I'm not sure how to define L. Thanks!

You can use str.center for this:
>>> lis = ['Text', 'in', 'the', 'middle!', 'END']
>>> for item in lis:
... print item.center(13, '.')
...
.....Text....
......in.....
.....the.....
...middle!...
.....END.....
or format:
for item in lis:
print format(item,'.^13')
...
....Text.....
.....in......
.....the.....
...middle!...
.....END.....
Working version of your code:
lis = ['Text', 'in', 'the', 'middle!', 'END']
width = 13
for s1 in lis:
L = len(s1) #length of line
periods_rtside = (width - L)//2 #periods on the RHS
periods_leftside = width - periods_rtside - L #peroids on the LHS
periods_rt_str = '.' * periods_rtside
periods_left_str = '.' * periods_leftside
line1 = periods_left_str + s1 + periods_rt_str
print line1
output:
.....Text....
......in.....
.....the.....
...middle!...
.....END.....

For those still struggling with this tough question, here is my code that works in Python 3 shell, even though it still fails in http://cscircles.cemc.uwaterloo.ca/8-remix/
First_line = input("First input: ")
width = int(First_line)
while True:
s1 = input("Second input: ")
if s1 != 'END':
L = len(s1) #length of line
periods_rtside = (width - L)//2 #periods on the RHS
periods_leftside = width - periods_rtside - L #periods on the LHS
periods_rt_str = '.' * periods_rtside
periods_left_str = '.' * periods_leftside
line1 = periods_left_str + s1 + periods_rt_str
print(line1)
else:
break
To get it to work in http://cscircles.cemc.uwaterloo.ca/8-remix/ console, you need to change the first 2 lines to
width = int(input())
and
s1 to s1 = input()
and also provide your own test input by clicking on the "Enter test input" button

Just some small changes to the above code and it worked in the grader.
width = int(input())
s1 = input()
while s1 != "END":
L = len(s1)
periods_rtside = (width - L)//2
periods_leftside = width - periods_rtside - L
periods_rt_str = '.' * periods_rtside
periods_left_str = '.' * periods_leftside
line1 = periods_left_str + s1 + periods_rt_str
print(line1)
s1 = input()

Related

Divide too long text in similar chunks considering punctuation

I have a list of strings that have to be not more than X characters. Each string can contain many sentences (separated by punctuation like dots). I need to separate longer sentences than X characters with this logic:
I have to divide them into the minimum number of parts (starting from 2), in order to have all the chunks with a lower length than X as similar as possible (possibly identical), but considering the punctuation (example: if I have Hello. How are you?, I can't divide it into Hello. Ho and w are you? but in Hello. and How are you? because it's the most similar way to divide it into two equal parts, without loosing the sense of the sentences)
max = 10
strings = ["Hello. How are you? I'm fine", "other string containg dots", "another string containg dots"]
for string in string:
if len(string) > max:
#algorithm to chunck it
In this case, I will have to divide the first string Hello. How are you? I'm fine into 3 parts because with 2 parts, I'll have one of the 2 chunks longer than 10 characters (max).
Is there a smart existing solution? Or does anyone know how to do that?
An example function for chunking string (within the character minimum and maximum lengths) by punctuation (e.g. ".", ",", ";", "?"); in other words, prioritizing punctuation over character length:
import numpy as np
def chunkingStringFunction(strings, charactersDefiningChunking = [".", ",", ";", "?"], numberOfMaximumCharactersPerChunk = None, numberOfMinimumCharactersPerChunk = None, **kwargs):
if numberOfMaximumCharactersPerChunk is None:
numberOfMaximumCharactersPerChunk = 100
if numberOfMinimumCharactersPerChunk is None:
numberOfMinimumCharactersPerChunk = 2
storingChunksOfString = []
for string in strings:
chunkingStartingAtThisIndex = 0
indexingCharactersInStrings = 0
while indexingCharactersInStrings < len(string) - 1:
indexingCharactersInStrings += 1
currentChunk = string[chunkingStartingAtThisIndex:indexingCharactersInStrings + 1]
if len(currentChunk) >= numberOfMinimumCharactersPerChunk and len(currentChunk) <= numberOfMaximumCharactersPerChunk:
indexesForStops = []
for indexingCharacterDefiningChunking in range(len(charactersDefiningChunking)):
indexesForStops.append(currentChunk.find(charactersDefiningChunking[indexingCharacterDefiningChunking]) + chunkingStartingAtThisIndex)
indexesForStops = np.max(indexesForStops, axis = None)
addChunk = string[chunkingStartingAtThisIndex:indexesForStops + 1]
if len(addChunk) > 1 and addChunk != " ":
storingChunksOfString.append(addChunk)
chunkingStartingAtThisIndex = indexesForStops + 1
indexingCharactersInStrings = chunkingStartingAtThisIndex
return storingChunksOfString
Alternatively, to prioritize character length; as in, if we want to consider our (average) character length and from there, find out where our defined characters for chunking are:
import numpy as np
def chunkingStringFunction(strings, charactersDefiningChunking = [".", ",", ";", "?"], averageNumberOfCharactersPerChunk = None, **kwargs):
if averageNumberOfCharactersPerChunk is None:
averageNumberOfCharactersPerChunk = 10
storingChunksOfString = []
for string in strings:
lastIndexChunked = 0
for indexingCharactersInString in range(1, len(string), 1):
chunkStopsAtADefinedCharacter = False
if indexingCharactersInString - lastIndexChunked == averageNumberOfCharactersPerChunk:
indexingNumberOfCharactersAwayFromAverageChunk = 1
while chunkStopsAtADefinedCharacter == False:
indexingNumberOfCharactersAwayFromAverageChunk += 1
for thisCharacter in charactersDefiningChunking:
findingAChunkCharacter = string[indexingCharactersInString - indexingNumberOfCharactersAwayFromAverageChunk:indexingCharactersInString + (indexingNumberOfCharactersAwayFromAverageChunk + 1)].find(thisCharacter)
if findingAChunkCharacter > -1 and len(string[lastIndexChunked:indexingCharactersInString - indexingNumberOfCharactersAwayFromAverageChunk + findingAChunkCharacter + 1]) != 0:
storingChunksOfString.append(string[lastIndexChunked:indexingCharactersInString - indexingNumberOfCharactersAwayFromAverageChunk + findingAChunkCharacter + 1])
lastIndexChunked = indexingCharactersInString - indexingNumberOfCharactersAwayFromAverageChunk + findingAChunkCharacter + 1
chunkStopsAtADefinedCharacter = True
elif indexingCharactersInString == len(string) - 1 and lastIndexChunked != len(string) - 1 and len(string[lastIndexChunked:indexingCharactersInString + 1]) != 0:
storingChunksOfString.append(string[lastIndexChunked:indexingCharactersInString + 1])
return storingChunksOfString

Python 3.7 else statement not showing correct index?

My goal here is to print lines from text files together. Some lines, however, are not together like they should be. I resolved the first problem where the denominator was on the line after. For the else statement, they all seem to have the same value/index.
import fitz # this is pymupdf
with fitz.open("math-problems.pdf") as doc: #below converts pdf to txt
text = ""
for page in doc:
text += page.getText()
file_w = open("output.txt", "w") #save as txt file
file_w.write(text)
file_w.close()
file_r = open("output.txt", "r") #read txt file
word = 'f(x) = '
#--------------------------
list1 = file_r.readlines() # read each line and put into list
list2 = [k for k in list1 if word in k] # look for all elements with "f(x)" and put all in new list
list1_N = list1
list2_N = list2
list1 = [e[3:] for e in list1] #remove first three characters (the first three characters are always "1) " or "A) "
char = str('\n')
for char in list2:
index = list1.index(char)
def digitcheck(s):
isdigit = str.isdigit
return any(map(isdigit,s))
xx = digitcheck(list1[index])
if xx:
print(list1[index] + " / " + list1_N[index+1])
else:
print(list1[index] + list1[index+1]) # PROBLEM IS HERE, HOW COME EACH VALUE IS SAME HERE?
Output from terminal:
f(x) = x3 + x2 - 20x
/ x2 - 3x - 18
f(x) =
2 + 5x
f(x) =
2 + 5x
f(x) =
2 + 5x
f(x) =
2 + 5x
f(x) = x2 + 3x - 10
/ x2 - 5x - 14
f(x) = x2 + 2x - 8
/ x2 - 3x - 10
f(x) = x - 1
/ x2 + 8
f(x) = 3x3 - 2x - 6
/ 8x3 - 7x + 4
f(x) =
2 + 5x
f(x) = x3 - 6x2 + 4x - 1
/ x2 + 8x
Process finished with exit code 0
SOLVED
#copperfield was correct, I had repeating values so my index was repeating. I solved this using a solution by #Shonu93 in here. Essentially it locates all indices of duplicate values and puts these indices into one list elem_pos and then prints each index from list1
if empty in list1:
counter = 0
elem_pos = []
for i in list1:
if i == empty:
elem_pos.append(counter)
counter = counter + 1
xy = elem_pos
for i in xy:
print(list1[i] + list1_N[i+1])

Any simple python code suggestions to add a constant to every individual number in a .txt

so -----2-----3----5----2----3----- would become -----4-----5----7----4----5-----
if the constant was 2 and etc. for every individual line in the text file.
This would involve splitting recognising numbers in between strings and adding a constant to them e.g ---15--- becomes ---17--- not ---35---.
(basically getting a guitar tab and adding a constant to every fret number)
Thanks. Realised this started out vague and confusing so sorry about that.
lets say the file is:
-2--3--5---7--1/n-6---3--5-1---5
and im adding 2, it should become:
-4--5--7---9--3/n-8---5--7-3---7
Change the filename to something relevant and this code will work. Anything below new_string needs to be change for what you need, eg writing to a file.
def addXToAllNum(int: delta, str: line):
values = [x for x in s.split('-') if x.isdigit()]
values = [str(int(x) + delta) for x in values]
return '--'.join(values)
new_string = '' # change this section to save to new file
for line in open('tabfile.txt', 'r'):
new_string += addXToAllNum(delta, line) + '\n'
## general principle
s = '-4--5--7---9--3 -8---5--7-3---7'
addXToAllNum(2, s) #6--7--9--11--10--7--9--5--9
This takes all numbers and increments by the shift regardless of the type of separating characters.
import re
shift = 2
numStr = "---1----9---15---"
print("Input: " + numStr)
resStr = ""
m = re.search("[0-9]+", numStr)
while (m):
resStr += numStr[:m.start(0)]
resStr += str(int(m.group(0)) + shift)
numStr = numStr[m.end(0):]
m = re.search("[0-9]+", numStr)
resStr += numStr
print("Result:" + resStr)
Hi You Can use that to betwine every line in text file add -
rt = ''
f = open('a.txt','r')
app = f.readlines()
for i in app:
rt+=str(i)+'-'
print " ".join(rt.split())
import re
c = 2 # in this example, the increment constant value is 2
with open ('<your file path here>', 'r+') as file:
new_content = re.sub (r'\d+', lambda m : str (int (m.group (0)) + c), file.read ())
file.seek (0)
file.write (new_content)

Explanation of `ch[:prefix_len%len(ch)]` in python program

I am looking at this python program and almost understood its flow but I am unable to understand ch[:prefix_len%len(ch)] in the following part:
else:
prefix = ch * (prefix_len/len(ch)) + ch[:prefix_len%len(ch)]
suffix = ch * (suffix_len/len(ch)) + ch[:suffix_len%len(ch)]
Here is the context:
def banner(text, ch='=', length=78):
if text is None:
return ch * length
elif len(text) + 2 + len(ch)*2 > length:
# Not enough space for even one line char (plus space) around text.
return text
else:
remain = length - (len(text) + 2)
prefix_len = remain / 2
suffix_len = remain - prefix_len
if len(ch) == 1:
prefix = ch * prefix_len
suffix = ch * suffix_len
else:
prefix = ch * (prefix_len/len(ch)) + ch[:prefix_len%len(ch)]
suffix = ch * (suffix_len/len(ch)) + ch[:suffix_len%len(ch)]
return prefix + ' ' + text + ' ' + suffix
Could somebody please help me to understand this. Thank you.
Sure!
ch[:prefix_len % len(ch)] is accessing a slice of the ch sequence starting from the beginning (since there's no value before the : and going to one character before the index defined by prefix_len % len(ch).
This value is prefix_len (defined earlier as the length of the prefix, not surprisingly) modulus the length of ch. (Think of it as the remainder left over after integer division of prefix_len / len(ch).
I ran the function like: print(banner("Hello everyone!", "1234")) and got:
123412341234123412341234123412 Hello everyone! 1234123412341234123412341234123
so you can see it's fitting the ch value (1234 in my case) in the space it has.
They're adding the remainder.
Say prefix = 10, and ch = '#&+'
If you just multiply ch by prefix_len / len(ch), you'll get 9, but you know you need 10.
So ch[:prefix_len % len(ch)] is just indexing into ch string for the remainder.
Make sense?

How to modify Text widget in Tkinter for interlinear anotation

I was wondering if it is possible to create a textbox with tkinter that can handle interlinear input. I need to be able to have different lines "connected" to each other, and the behaviour of each line can be independent. Here is an example. It is from a linguistic annotation program. The idea is that if I have a line, say:
this is an example
x.Det be.V a.Det example.N
The spacing of the first line is automatically adjusted some line is modified to allow enough space for each word in the second line to not overlap with the words in the first line.
Is there any way to do this?
A simple way to do this would be to use a fixed width font (such as courrier) in which all characters are the same width, then format it as pure text by padding with spaces.
from Tkinter import *
sentence = [ 'this', 'is', 'an', 'example' ]
result = [ 'x.Det', 'be.V', 'a.Det', 'example.N' ]
line_start = [0, len(sentence)] # Used to split the sentence into lines no longer than line_len
line_len = 20 # Max characters in each line, including extra spaces
segment_len = 0
for i in range(len(sentence)):
s_len = len(sentence[i])
r_len = len(result[i])
# Pad words (or word groups) so the segments of sentence and result have the same width
if s_len > r_len:
result[i] += ' ' * s_len - r_len
elif s_len < r_len:
sentence[i] += ' ' * (r_len - s_len)
segment_len += max(r_len, s_len) + 1
# Check the line length
if segment_len > line_len:
segment_len = 0
line_start.insert(1, i)
root = Tk()
for i in range(len(line_start)-1):
sentence_segment = ' '.join( sentence[line_start[i]:line_start[i+1]] )
ts = Text(root, font='TkFixedFont', width = line_len, height = 1)
ts.insert(END, sentence_segment)
ts.pack()
result_segment = ' '.join( result[line_start[i]:line_start[i+1]] )
tr = Text(root, font='TkFixedFont', width = line_len, height = 1, foreground='grey')
tr.insert(END, result_segment)
tr.pack()
root.mainloop()

Categories