Task: Align columns






PHP: <?php
$j2justtype = array('L' => STR_PAD_RIGHT,
                    'R' => STR_PAD_LEFT,
                    'C' => STR_PAD_BOTH);
 

function aligner($str, $justification = 'L') {
  global $j2justtype;
  assert(array_key_exists($justification, $j2justtype));
  $justtype = $j2justtype[$justification];

  $fieldsbyrow = array();
  foreach (explode("\n", $str) as $line)
    $fieldsbyrow[] = explode('$', $line);
  $maxfields = max(array_map('count', $fieldsbyrow));

  foreach (range(0, $maxfields - 1) as $col) {
    $maxwidth = 0;
    foreach ($fieldsbyrow as $fields)
      $maxwidth = max($maxwidth, strlen(array_key_exists($col, $fields) ? $fields[$col] : 0));
    foreach ($fieldsbyrow as &$fields)
      $fields[$col] = str_pad(array_key_exists($col, $fields) ? $fields[$col] : "", $maxwidth, ' ', $justtype);
    unset($fields); // see http://bugs.php.net/29992
  }
  $result = '';
  foreach ($fieldsbyrow as $fields)
    $result .= implode(' ', $fields) . "\n";
  return $result;
}

$textinfile = 'Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$\'dollar\'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.';
 
foreach (array('L', 'R', 'C') as $j)
  echo aligner($textinfile, $j);

?>





Fortran:       SUBROUTINE RAKE(IN,M,X,WAY)	
Collates column widths so that each column is wide enough for its widest member.
       INTEGER IN		
       INTEGER M		
       CHARACTER*1 X		
       INTEGER WAY		
       INTEGER W(M + 1)		
       INTEGER C(0:M + 1)	
       CHARACTER*(M) ACARD	
       CHARACTER*(28 + 4*M) FORMAT	
       INTEGER I		
       INTEGER L,LF		
       INTEGER NF,MF		
       CHARACTER*6 WAYNESS(-1:+1)	
       PARAMETER (WAYNESS = (/"Left","Centre","Right"/))	
       INTEGER LINPR	
       COMMON LINPR	
        W = 0		
        MF = 0		
        C(0) = 0	
        WRITE (LINPR,*)	
        WRITE (LINPR,*) "Align ",WAYNESS(MIN(MAX(WAY,-1),+1))	

Chase through the file assessing the lengths of each field.
   10   READ (IN,11,END = 20) L,ACARD(1:L)	
   11   FORMAT (Q,A)				
        CALL LIZZIEBORDEN	
        W(1:NF) = MAX(W(1:NF),C(1:NF) - C(0:NF - 1) - 1)	
        MF = MAX(MF,NF)		
        GO TO 10		

Concoct a FORMAT based on the maximum size of each field. Plus one.
   20   REWIND(IN)		
        WRITE (FORMAT,21) W(1:MF) + 1	
   21   FORMAT ("(",<MF>("A",I0,","))	
        LF = INDEX(FORMAT,", ")		
        IF (LF.LE.0) STOP "Format trouble
        FORMAT(LF:LF) = ")"			
        WRITE (LINPR,*) "Format",FORMAT(1:LF)	

Chug afresh, this time knowing the maximum length of each field.
   30   READ (IN,11,END = 40) L,ACARD(1:L)	
        CALL LIZZIEBORDEN		
        SELECT CASE(WAY)	
         CASE(-1)		
          WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1)//	
     1     REPEAT(" ",W(I) - C(I) + C(I - 1) + 1),I = 1,NF)	
         CASE( 0)		
          WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1)//	
     1     REPEAT(" ",(W(I) - C(I) + C(I - 1) + 1)/2),I = 1,NF)	
         CASE(+1)		
          WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1),I = 1,NF)	
         CASE DEFAULT		
         WRITE (LINPR,*) "Huh? WAY=",WAY	
         STOP "Unanticipated value for WAY
        END SELECT		
        GO TO 30		
Closedown
   40   REWIND(IN)		
       CONTAINS	
        SUBROUTINE LIZZIEBORDEN	
          NF = 0		
          DO I = 1,L		
            IF (ICHAR(ACARD(I:I)).EQ.ICHAR(X)) THEN	
              NF = NF + 1		
              C(NF) = I		
            END IF		
          END DO		
          NF = NF + 1		
          C(NF) = L + 1		
        END SUBROUTINE LIZZIEBORDEN	
      END SUBROUTINE RAKE	

      INTEGER L,M,N	
      INTEGER LINPR,IN	
      COMMON LINPR	
      LINPR = 6		
      IN = 10		
      OPEN (IN,FILE="Rake.txt",STATUS="OLD",ACTION="READ")	
      N = 0		
      M = 0		

    1 READ (IN,2,END = 10) L	
    2 FORMAT (Q)	
      N = N + 1		
      M = MAX(M,L)	
      GO TO 1		

   10 REWIND (IN)	
      WRITE (LINPR,*) N,"Recs, longest rec. length is ",M
      CALL RAKE(IN,M,"$",-1)	
      CALL RAKE(IN,M,"$", 0)	
      CALL RAKE(IN,M,"$",+1)	
      END