2

I know the function print() can align text to right or to left, but can I align to both sides?

Example: This text:

Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore 
et dolore magna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco laboris nisi ut 
aliquip ex ea commodo consequat. Duis aute irure  
dolor in reprehenderit.

Should be look like this:

Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed  do  eiusmod tempor incididunt ut labore 
et dolore magna  aliqua. Ut enim  ad minim veniam, 
quis nostrud  exercitation ullamco laboris nisi ut 
aliquip ex ea  commodo consequat. Duis  aute irure  
dolor in reprehenderit.
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
zvi
  • 3,677
  • 2
  • 30
  • 48
  • did you try center format `^` – Joe Ferndz Nov 20 '20 at 07:49
  • @JoeFerndz I tried but that's not what I want. Can you share your code? – zvi Nov 20 '20 at 07:53
  • 1
    @wasifHasan - the second output replaces some spaces by double spaces to align the right hand side of the text to the same column - not the same. Also not the same as using centered. – Patrick Artner Nov 20 '20 at 07:54
  • 1
    Interestingly there is no full text justification format in python. However a few folks have tried this out and posted it on the internet. Here's one i found. https://www.malikbrowne.com/blog/text-justification-coding-question – Joe Ferndz Nov 20 '20 at 08:02
  • and one on stack exchange https://codereview.stackexchange.com/questions/95505/text-justification – Joe Ferndz Nov 20 '20 at 08:03
  • @JoeFerndz Ah, I was writing the Python code for this locally. Looks like you found the resource :) – Serial Lazer Nov 20 '20 at 08:09
  • I can't recognize the use case: mono-spaced font in combination with distributed blank padding is not in any way impressive. There are reasons, why DTP programs have tons of options for fine-adjustement in respect to given font. – guidot Nov 20 '20 at 08:12
  • @guidot I can take it one step forward: check if there is too many spaces - and split the word to 2 lines. That's will be look find (IMHO). – zvi Nov 20 '20 at 08:20

2 Answers2

2

There is no way to do that I know of that's build in. You can however try to solve it yourself:

One possible (not that great looking) algorithm:

  • split text into lines
  • find longest line
  • for all other lines:
    • find first space, and add another space
    • if still not long enough, move to next not yet elongated space

This could look like so:

def justify_text(text):
    # split text into lines and find longest
    lines = [line.strip() for line in text.split("\n")]
    ll = len(max(lines, key=len))

    # iterate lines
    for i, l in enumerate(lines):
        # remember last elongates space
        pos_space = 0
        # do for all lines but the last one
        while len(l) < ll and (i != len(lines)-1):
            # print(l) # uncomment to see stages of refining
            pos_space = l.find(" ", pos_space)
            if pos_space == -1:
                # start over from beginning
                pos_space = l.find(" ", 0)
                if pos_space == -1:
                    # no space inside the line, can't do anything about it
                    # we break to avoid endless loop
                    break
            # splice in a space and increase next search position
            l = l[:pos_space] + " " + l[pos_space:]
            pos_space += 2
        # store changed line
        lines[i] = l

    return '\n'.join(lines)

t = """Lorem ipsum dolor sit amet, consectetur adipiscing more text
elit, sed do eiusmod tempor incididunt ut labore 
et dolore magna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco laboris nisi ut 
aliquip ex ea commodo consequat. Duis aute irure  
dolor in reprehenderit."""

print(justify_text(t))

and produces:

Lorem ipsum dolor sit amet, consectetur adipiscing more text
elit,    sed    do   eiusmod  tempor  incididunt  ut  labore
et    dolore    magna  aliqua.  Ut  enim  ad  minim  veniam,
quis    nostrud    exercitation   ullamco  laboris  nisi  ut
aliquip    ex    ea   commodo  consequat.  Duis  aute  irure
dolor in reprehenderit.

To get closer to what your text looks like you would have to find the space to elongate from alternatingly searching from both sides of the line.


If you do not start from a already line-split text you can do a pre-step (although using the linked algo from codereview is more efficient in that case):

t = """Lorem ipsum dolor sit amet, consectetur adipiscing more text elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit."""

def prep_text(text, no_longer_then=50):
    words = text.split(" ")
    result = [[]]
    for w in words:
        if sum(len(part) for part in result[-1]) + len(w) > no_longer_then:
            result.append([w])
        else:
            result[-1].append(w)
    print(result)
    return '\n'.join(' '.join(inner) for inner in result)

prepped = prep_text(t)    
print(prepped)

Outputs:

#        1         2         3         4         5
# 345678901234567890123456789012345678901234567890
Lorem ipsum dolor sit amet, consectetur adipiscing
more text elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit.
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thanks, but on my question the text is long text, not separate to lines, so it's a little harder. But your solution is good start point... – zvi Nov 20 '20 at 08:23
  • 1
    @zvi see edit for how to split up yout test first hand - but if you do not start with multiple lines already it might be beneficial to change the algo and avoid the prep-step. – Patrick Artner Nov 20 '20 at 08:39
1

I wrote my own version here (also has a padding with "-" when many spaces in line): https://github.com/zvibazak/both_sides_align

Usage:

both_sides_align(txt, size, max_spaces=5)

txt - text to be aligned

size - size of the output

max_spaces - max space to add to a line (above this number - a "-" will be added and split the word to next line)

Example:

Using this code

from both_sides_align import both_sides_align
both_sides_align(txt,60,3)

Will give this text:

Nulla luctus bibendum nulla nec efficitur. Quisque id aliq-
uam enim. Etiam non lectus  id risus  rhoncus  condimentum.
Nam ultrices ex quis risus iaculis  ullamcorper. Vivamus id
venenatis mi, et suscipit ipsum.```
zvi
  • 3,677
  • 2
  • 30
  • 48