ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Justify algorithm

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Justify algorithm

    Hello guys, has anyone done a justify algorithm before?

    Here is my problem. I have a string that is very long, and i have limited space on the paper to print it, so i have 4 smaller strings to make it fit nicely.

    The problem is that words can be cut when just copying the substrings over, so i have several options:

    -Do nothing and leave it ugly
    -Search for the last space on the small string and make the word that was going to be cut to appear on the next line
    -Pad the small string with spaces and remove the word that would be cut so it looks aligned (justify)

    If you have other proposals please do so

  • #2
    Re: Justify algorithm

    strangely enough I have a very similar requirement on some warehouse labels - I'll await a sexy piece of code with bated breath...

    If it comes as a sub-procedure then I will buy the (virtual) beers...
    predictably positive, permanently punctilious, purposely proactive, potentially priceless, primarily professional : projex

    Comment


    • #3
      Re: Justify algorithm

      I would go for option2

      "Search for the last space on the small string and make the word that was going to be cut to appear on the next line"

      Comment


      • #4
        Re: Justify algorithm

        I have plant pot labels in which I have to print the scientific names, and I use option two.

        You also may want to have some sort of fallback to the ugly if you cant find a blank space after working back a certain number of letters. For instance, if you have 4 lines of 80 characters each, you may not want to go back more than 20 characters or so without just filling in all 80 without breaking, as not to have a line with more than 20 unprinted characters.

        I use a more advanced option with my plant labels. I only have 3 lines and 40 characters each to print the scientific name of a plant, in which in the case of a complex hybrid, can be really long. What I do is to perform one pass by breaking on blank spaces, and attempting to get the entire name to fit within those three lines. If I cant do this without having part of the name chopped off, I then do it again but make line 2 ugly with no break, but keep the break at line 1. If I still cant get the entire name to fit, I print all lines ugly and what fits is what fits.
        Michael Catalani
        IS Director, eCommerce & Web Development
        Acceptance Insurance Corporation
        www.AcceptanceInsurance.com
        www.ProvatoSys.com

        Comment


        • #5
          Re: Justify algorithm

          well!!

          May i see your string which want to break or u want to manipulate
          Young people knows how to run fast but old people knows the way..

          Comment


          • #6
            Re: Justify algorithm

            For the one that asked about the sample string:

            Code:
            INCENDIO, RAYO, EXPLOSION, HUMO, AGENTES DE EXTINCIÓN, CAÍDA DE ÁRBOLES Y ANTENAS, HURACÁN, VENTARRÓN O TEMPESTAD, IMPACTO DE VEHÍCULOS DE TERCEROS, HUMO POR MAL FUNCIONAMIENTO DE EQUIPOS
            I have 4 strings sized 60 chars on my printer file. If i do a regular copy for each 60 chars, then the report looks like this:

            PHP Code:
            INCENDIORAYOEXPLOSIONHUMOAGENTES DE EXTINCIÓNCAÍDA
             DE ÁRBOLES Y ANTENAS
            HURACÁNVENTARRÓN O TEMPESTADIMPAC
            TO DE VEHÍCULOS DE TERCEROS
            HUMO POR MAL FUNCIONAMIENTO DE 
            EQUIPOS 
            So the justify algorithm should do this:

            PHP Code:
            INCENDIORAYOEXPLOSIONHUMOAGENTES DE EXTINCIÓNCAÍDA
            DE  ÁRBOLES  Y   ANTENAS
            ,  HURACÁN,  VENTARRÓN O  TEMPESTAD
            IMPACTO   DE   VEHÍCULOS   DE   TERCEROS,   HUMO   POR   MAL
            FUNCIONAMIENTO DE EQUIPOS 

            Comment


            • #7
              Re: Justify algorithm

              Originally posted by MichaelCatalani View Post
              I have plant pot labels in which I have to print the scientific names, and I use option two.

              You also may want to have some sort of fallback to the ugly if you cant find a blank space after working back a certain number of letters. For instance, if you have 4 lines of 80 characters each, you may not want to go back more than 20 characters or so without just filling in all 80 without breaking, as not to have a line with more than 20 unprinted characters.

              I use a more advanced option with my plant labels. I only have 3 lines and 40 characters each to print the scientific name of a plant, in which in the case of a complex hybrid, can be really long. What I do is to perform one pass by breaking on blank spaces, and attempting to get the entire name to fit within those three lines. If I cant do this without having part of the name chopped off, I then do it again but make line 2 ugly with no break, but keep the break at line 1. If I still cant get the entire name to fit, I print all lines ugly and what fits is what fits.
              Did someone say "pot plant"?!?
              "Time passes, but sometimes it beats the <crap> out of you as it goes."

              Comment


              • #8
                Re: Justify algorithm

                Ok, i finally did the algorithm myself. It is completely unoptimized, assumes a string sized 256 as a parameter and the result string to be sized 60, and doesn't look to fill all lines. I leave all that as an exercise left to the reader

                Basically it copies words to a new string until the word cannot fit in the string, and then pushes the words with an additional space into a result string

                PHP Code:
                           restantes=60;
                           
                pos=1// posicion inicial
                           
                dow %scan(' ':cadena:pos)>0;
                             
                posblanco=%scan(' ':cadena:pos);
                             
                palabra=%subst(cadena:pos:posblanco-pos);
                             if %
                len(%trim(palabra))<restantes;
                               if 
                pos=1;
                                 
                cadenaw=%trim(palabra);
                               else;
                                 
                cadenaw=%trim(cadenaw)+' '+%trim(palabra);
                               endif;
                             else;
                               
                //no me queda espacio, salirme del ciclo
                               
                leave;
                             endif;
                             
                //actualizar posicion de la cadena
                             
                pos=posblanco+1;
                             
                restantes=60-pos+1;
                           
                enddo;
                           
                //ya tengo la cadena sin truncar la ultima palabra, debo darle restantes espacios
                           //en blanco
                           
                restantes+=1;
                           
                pos=1;
                           
                dow restantes>0;
                             
                posblanco=%scan(' ':cadenaw:pos);
                             
                palabra=%subst(cadenaw:pos:posblanco-pos);
                             if 
                pos=1;
                               
                cadenafin=%trim(palabra);
                             else;
                               
                cadenafin=%trim(cadenafin)+'  '+%trim(palabra);
                               
                restantes-=1;
                             endif;
                             
                //actualizar posicion de la cadena
                             
                pos=posblanco+1;
                           
                enddo;
                           
                //termine de empujar la cadena, copiar el resto intacto
                           
                cadenafin=%trim(cadenafin)+' '+%subst(cadenaw:pos:60-pos);
                           return 
                cadenafin

                Comment


                • #9
                  Re: Justify algorithm

                  New version, less buggy but sadly a lot more static. Way unoptimized, and if there are more spaces to "push" in the new string than words, it starts over again to push an additional space, but doesn't work too well. In my tests it works well enough to use it, will leave one space or two sometimes.

                  Assumes:
                  -256 sized string
                  -4 strings sized 60 to partition the big string



                  PHP Code:
                             dow i<=4;
                               
                  restantes=60;
                               
                  cadena=%subst(pc1_descob:poslinea:256-poslinea);
                               
                  primeravez=*on;
                               
                  pos=1;
                               
                  acomode=*off;
                               
                  cadenafin=*blanks;
                               
                  dow %scan(' ':cadena:pos)>0;
                                 
                  posblanco=%scan(' ':cadena:pos);
                                 
                  palabra=%subst(cadena:pos:posblanco-pos);
                                 if %
                  len(%trim(palabra))<=restantes;
                                   if 
                  primeravez=*on;
                                     
                  cadenaw=%trim(palabra);
                                     
                  primeravez=*off;
                                   else;
                                     
                  cadenaw=%trim(cadenaw)+' '+%trim(palabra);
                                   endif;
                                 else;
                                   
                  //no me queda espacio, salirme del ciclo
                                   
                  leave;
                                 endif;
                                 
                  //actualizar posicion de la cadena
                                 
                  pos=posblanco+1;
                                 
                  restantes=60-pos+1;
                               
                  enddo;
                               
                  //ya tengo la cadena sin truncar la ultima palabra, debo darle restantes espacios
                               //en blanco
                               
                  poslinea+=pos-1//ya habia incrementado pos en la ultima iteracion
                               
                  restantes+=1//al incrementar restantes arriba ya habia tomado en cuenta un espacio
                               //adicional, como no lo voy a tener tengo un restante mas
                               
                  pos=1;
                               
                  dow restantes>0;
                                 
                  acomode=*on;
                                 
                  posblanco=%scan(' ':cadenaw:pos);
                                 
                  palabra=%subst(cadenaw:pos:posblanco-pos);
                                 if 
                  pos=1;
                                   
                  cadenafin=%trim(palabra);
                                 else;
                                   if 
                  pasada=1;
                                     
                  cadenafin=%trim(cadenafin)+'  '+%trim(palabra);
                                   else;
                                     
                  cadenafin=%trim(cadenafin)+'   '+%trim(palabra);
                                   endif;
                                   
                  restantes-=1;
                                   
                  //mas espacios que palabras, volver a comenzar
                                   
                  if %len(%trim(palabra))=0;
                                     
                  pos=1;
                                     
                  pasada=2;
                                     
                  posblanco=0;
                                     
                  cadenafin=*blanks;
                                   endif;
                                 endif;
                                 
                  //actualizar posicion de la cadena
                                 
                  pos=posblanco+1;
                               
                  enddo;
                               
                  //termine de empujar la cadena, copiar el resto intacto
                               
                  if acomode=*on//si tuve que ingresarle espacios
                                 
                  if pasada=1;
                                   
                  cadenafin=%trim(cadenafin)+' '+%subst(cadenaw:pos:60-pos);
                                 else;
                                   
                  cadenafin=%trim(cadenafin)+'  '+%subst(cadenaw:pos:60-pos);
                                 endif;
                               else; 
                  //no tuve que ingresar espacios, copiar intacta
                                 
                  cadenafin=cadenaw;
                               endif;
                               if 
                  i=1;
                                 
                  descob1=cadenafin;
                               elseif 
                  i=2;
                                 
                  descob2=cadenafin;
                               elseif 
                  i=3;
                                 
                  descob3=cadenafin;
                               elseif 
                  i=4;
                                 
                  descob4=cadenafin;
                               endif;
                               
                  i+=1;
                             
                  enddo

                  Comment


                  • #10
                    Re: Justify algorithm

                    . let x = piece length (in your case = 60)
                    . Check for the x+1 position.
                    . if blank, you don't need to force a line break. Just align the x+2 element to x+ 1 and so on for that line.
                    . if not blank, move backwards from x and look for a space.
                    . if no space, let things be as they are.
                    . if space at y, break line; new line starts at y + 1.
                    . check for space at y + x + 1.
                    . loop through the above.
                    â??No bird soars too high if he soars with his own wingsâ?? â?? William Blake

                    Comment


                    • #11
                      Re: Justify algorithm

                      You may want to give the below a try. I dug it out of my playpin from when I was getting a handle for the language. It's by no means perfect, and you'll likely have to move the "chunk handling" part of the code into the dow loop to handle your smaller long names, (as well as adjust the size appropriately to fit your needs), but maybe it'll help you on your way to turning your problem into a workable module. I'd fix it myself, but, alas, it's time to leave the office for the day!

                      PHP Code:
                            *---------------------------------------------------------------*
                            * 
                      V A R I A B L E S                                             *
                            *---------------------------------------------------------------*
                           
                      D myString        S            240A   Inz(*blanks)
                           
                      D myStringArray   S             52A   dim(99)
                           
                      D currentSnippet  S            240A   inz(*blanks)
                           
                      D charPosition    S              5p 0 Inz(*ZEROS)
                           
                      D currentLength   S              3  0 inz(*zeros)
                           
                      D snippetLength   S              3  0 inz(*zeros)
                           
                      D nextToken       S              3  0 inz(*zeros)
                           
                      D i#              S              3  0 inz(1)
                            
                      *---------------------------------------------------------------*
                            * 
                      K E Y L I S T                                                 *
                            *---------------------------------------------------------------*
                            *---------------------------------------------------------------*
                            * 
                      M A I N                                                       *
                            *---------------------------------------------------------------*
                            /
                      free
                              myString 
                      =
                                 
                      'This is a test to see how much of this blob will be ' +
                                 
                      'wrapped around to the next line.  This will hopefully align ' +
                                 
                      'and justify each new line as it is encountered';
                             
                      //   myString =
                             //     'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                             //      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                             //      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

                               
                      charPosition 1;
                               
                      charPosition = %SCAN(' ':%trim(myString):charPosition);
                               
                      dow (charPosition 0);
                                  
                      currentLength =
                                     %
                      len(%trim(myStringArray(i#)));

                                  
                      currentSnippet = %subst(myString:1:charPosition);

                                  
                      snippetLength = %len(%trim(currentSnippet));

                                  if (
                      currentLength 52) AND
                                     (
                      currentLength snippetLength 52);
                                     
                      myStringArray(i#) =  %trim(myStringArray(i#)) + ' ' +
                                                          
                      %trim(currentSnippet);
                                  else;

                                     
                      i# += 1;
                                     
                      myStringArray(i#) =  %trim(myStringArray(i#)) +
                                                          
                      %trim(currentSnippet);
                                  endif;

                                  
                      myString = %trim(%subst(myString:charPosition));
                                  
                      charPosition = %SCAN(' ':%trim(myString));
                               
                      enddo;

                               
                      // handle the last chunk of data that may be hanging out if there are no
                               // found spaces
                               
                      if (%len(%trim(myString)) > 52);
                                  
                      dou %len(%trim(myString)) < 52;
                                     
                      myStringArray(i#) = %subst(myString:1:52);
                                     
                      myString = %subst(myString:52);
                                     
                      i# += 1;
                                  
                      enddo;
                                  
                      myStringArray(i#) = %trim(myString);
                               
                      else;
                                  
                      i# += 1;
                                  
                      myStringArray(i#) = %trim(myString);

                               
                      endif;

                               for 
                      i# = 1 by 1 to 4;
                                 
                      dsply myStringArray(i#);
                               
                      endfor;

                              *
                      INLR = *ON;
                            /
                      end-free 
                      I'll take a gander at it tomorrow to see if I can fit it into your specific requirements. Best of luck

                      Comment


                      • #12
                        Re: Justify algorithm

                        Here is a text wrap example posted by RPG genius Scott Klement a few years ago, is it of any use?

                        Pete

                        Code:
                             FQSYSPRT   O    F   80        PRINTER
                        
                             D dbfield         s           1500A
                             D line            s             80A
                        
                             D max             s             10I 0
                             D linemax         s             10I 0
                             D start           s             10I 0
                             D end             s             10I 0
                             D len             s             10I 0
                        
                              /free
                                dbfield = 'Four score and seven years ago our fathers brought '
                                        + 'forth on this continent, a new nation, conceived in '
                                        + 'Liberty, and dedicated to the proposition that all '
                                        + 'men are created equal. Now we are engaged in a great '
                                        + 'civil war, testing whether that nation, or any nation '
                                        + 'so conceived and so dedicated, can long endure. We are '
                                        + 'met on a great battlefield of that war. We have come to '
                                        + 'dedicate a portion of that field, as a final resting '
                                        + 'place for those who here gave their lives for that that '
                                        + 'nation might live. It is altogether fitting and proper '
                                        + 'that we should do this. But, in a larger sense, we can '
                                        + 'not dedicate -- we can not consecrate -- we can not '
                                        + 'hallow -- this ground. The brave men, living and dead, '
                                        + 'who struggled here, have consecrated it, far above our '
                                        + 'poor power to add or detract. The world will little '
                                        + 'note, nor long remember what we say here, but it can '
                                        + 'never forget what they did here. It is for us the '
                                        + 'living, rather, to be dedicated here to the unfinished '
                                        + 'work which they who fought here have thus far so nobly '
                                        + 'advanced. It is rather for us to be here dedicated to '
                                        + 'the great task remaining before us -- that from these '
                                        + 'honored dead we take increased devotion to that cause '
                                        + 'for which they gave the last full measure of devotion '
                                        + '-- that we here highly resolve that these dead shall '
                                        + 'not have died in vain -- that this nation, under God, '
                                        + 'shall have a new birth of freedom -- and that government '
                                        + 'of the people, by the people, for the people, shall '
                                        + 'not perish from the earth.';
                        
                        
                                max = %len(%trimr(dbfield));
                                start = 1;
                        
                                dow ( start <= max );
                        
                                     linemax = start + %size(line);
                        
                                     if (linemax > max);
                                        linemax = max;
                                     endif;
                        
                                     end = linemax;
                        
                                     dow (end < max and %subst(dbfield:end:1) <> ' ');
                                       end = end - 1;
                                       if (end <= start);
                                          end = linemax;
                                          leave;
                                       endif;
                                     enddo;
                        
                                     len = (end - start) + 1;
                                     line = %subst(dbfield:start:len);
                                     except printme;
                        
                                     start = start + len;
                                enddo;
                        
                                *inlr = *on;
                        
                              /end-free
                        
                             OQSYSPRT   E            PrintMe
                             O                       Line
                        Last edited by Pete; August 26, 2009, 06:44 AM.

                        Comment


                        • #13
                          Re: Justify algorithm

                          Originally posted by Pete View Post
                          Here is a text wrap example posted by RPG genius Scott Klement a few years ago, is it of any use?
                          There is an error in the way this code displays: If you see the code that says:
                          Code:
                          dow (end<>' ');
                          It should actually read.

                          Code:
                          dow ( end < max and %subst( dbfield : end : 1 ) <> ' ' );

                          This code snippet is displaying incorrectly because there were no spaces between the field names and the "<" symbol, and for some reason that screws up the way the code is displayed on the post. The code itself was correct, its just being truncated when displayed in the post. Whats really weird is that if you quote the reply, it displays correctly in your new response box until you post it ,and then its screwed up again and truncated.


                          Scott's code will split lines up based upon having an indefinite number of output lines. It would have to be modified in order to print using a finite number of lines, and whether you need maximum characters printed or not.

                          Also, I highly suggest not using field names like start, end, or len in your programs. *start, *end, len and %len are all reserved words in RPG. Using field names like StartPosition, EndPosition, and FieldLength separates the field names from reserved RPG names, and makes the fields more self-documenting.
                          Michael Catalani
                          IS Director, eCommerce & Web Development
                          Acceptance Insurance Corporation
                          www.AcceptanceInsurance.com
                          www.ProvatoSys.com

                          Comment


                          • #14
                            Re: Justify algorithm

                            Good catch, thanks Michael! My apologies for not proofing the post....it looked good on the preview, and I didn't look close at the actual post.

                            Pete

                            Comment

                            Working...
                            X