Search code examples
algorithm

Display grouped words in a table with equal height columns


I want to sort an array of words alphabetically and output them grouped in a table with X columns. All columns should be the same length, except for the rightmost column, which serves as a balancer. The rightmost column may be shorter, but not longer.

I am still in the concept phase before I program this and the letter headings in between are causing me problems. For visual reasons, these must not be at the very beginning and end of a column. If I want to calculate the maximum height of all columns, I don't yet know where these letters will be. They are deleted at the beginning of the columns because the column heading already exists. And they must not be at the end either, as in the example with 'S'. In this case, I would have to increase the total height of the columns by 1 and rebuild the table, but then it can happen that a bold letter is at the end of other columns and in the worst case I end up in an endless loop.

Can this be solved at all?

A-De Do-G H-K L-Oc Or-R
Ant Dog Hat Lamp Orange
Apple E I Lion P
B Egg Ice M Penguin
Ball Elephant Island Monkey Piano
Bridge F J Mountain Q
C Fish Jack N Question
Car Flower Juice Nest R
Cat G K Nose Rabbit
D Garden Kite O Rose
Desk Goat King Ocean S (ERROR)
words = [
    "Ant",
    "Apple",
    "Ball",
    "Bridge",
    "Car",
    "Cat",
    "Desk",
    "Dog",
    "Egg",
    "Elephant",
    "Fish",
    "Flower",
    "Garden",
    "Goat",
    "Hat",
    "Ice",
    "Island",
    "Jack",
    "Juice",
    "Kite",
    "King",
    "Lamp",
    "Lion",
    "Monkey",
    "Mountain",
    "Nest",
    "Nose",
    "Ocean",
    "Orange",
    "Penguin",
    "Piano",
    "Question",
    "Rabbit",
    "Rose",
    "Snake",
    "Sun",
    "Tiger",
    "Tree",
    "Umbrella",
    "Van",
    "Victory",
    "Water",
    "Whale",
    "Xylophone",
    "Yellow",
    "Yard"
    "Zoo",
];

Solution

  • The below is obvious recursive search:

    d=['a',2,'b',2,'c',2,'d',2,'e',2,'f',2,'g',2,'h',1,'i',2,
       'j',2,'k',2,'l',2,'m',2,'n',2,'o',2,'p',2,'q',1,'r',2,'s',2]
    x=5
    
    l=[]
    i=[]
    for k in range(0,len(d),2):
        l.append(d[k])
        i.append(d[k+1])
    import math
    rw=math.ceil((len(l)+sum(i)-x)/x)
    
    while True:
        n=0
        for w in i:
            n+=w+1
            pos=(n-1)%rw+1
            if pos==rw:
                break
            if pos==1:
                n-=1
        else:
            break
        
        rw+=1
    print(rw)
    

    Explanation:

    • d is data, x is your x column, data is structured in a way like starting alphabet, followed by number of it (there are two words starting with a)
    • the data is split into l(start letters) l has no use but you can use it for printing output,i(no of words)
    • rw=math.ceil((len(l)+sum(i))/x) defines the minimum row case, where minimum there should be rows to satisfy all words+all headers-x(all headers of word list may become heading, so all bolds are at heading), rw doesn't include the heading row, so rw+1 of the outut will be actual rows.
    • in recursive loop with increasing rw, you use for loop to determine y position(pos) of every header and if it was and end of table, break the loop(go to next rows(rw) number)
    • if the pos of header was at start of table, it will be merged into heading(like header of h,l is in heading in your table) this causes a reduction in n(number of element tracker)
    • break in else of for means that if for loop is finished without breaking,then the rw is fitting all condition and thus we can exit the while loop and finally print the required rows I have provided way for you to find the minimum rows that will satisfy your condition, you can use this rw value to print the table, which is not a part of algorithm question.
      Note:
      output as a excel table
      the top ones are heading(a,i) the output of my code is 22, which means the above table, you can see right side to columns are empty, but for the case:
      d=['a',2,'b',2,'c',2,'d',2,'e',2,'f',2,'g',2,'h',1,'i',2, 'j',2,'k',2,'l',2,'m',2,'n',2,'o',2,'p',2,'q',1,'r',2,'s',2] (s has two elements) this is the only min possible row, satisfying rest conditions.

    I used word heading for top 5 bold ones, header for the bolds inside table.