# File lib/columnize.rb, line 113
  def columnize(*args)

    list, opts = parse_columnize_options(args)

    # Some degenerate cases
    return '' if not list.is_a?(Array)
    return  "<empty>\n" if list.empty?
    l = list.map{|li| li.to_s}
    return "%s%s%s\n" % [opts[:array_prefix], l[0], 
                         opts[:array_suffix]] if 1 == l.size

    nrows = ncols = 0  # Make nrows, ncols have more global scope
    colwidths = []     # Same for colwidths
    if opts[:displaywidth] - opts[:lineprefix].length < 4
      opts[:displaywidth] = opts[:lineprefix].length + 4
    else
      opts[:displaywidth] -= opts[:lineprefix].length
    end
    if opts[:arrange_vertical]
      array_index = lambda {|num_rows, row, col| num_rows*col + row }
      # Try every row count from 1 upwards
      1.upto(l.size-1) do |_nrows|
        nrows = _nrows
        ncols = (l.size + nrows-1) / nrows
        colwidths = []
        totwidth = -opts[:colsep].length

        0.upto(ncols-1) do |col|
          # get max column width for this column
          colwidth = 0
          0.upto(nrows-1) do |_row|
            row = _row
            i = array_index.call(nrows, row, col)
            break if i >= l.size
            colwidth = [colwidth, cell_size(l[i], opts[:term_adjust])].max
          end
          colwidths.push(colwidth)
          totwidth += colwidth + opts[:colsep].length
          if totwidth > opts[:displaywidth]
            ncols = col
            break
          end
        end
        break if totwidth <= opts[:displaywidth]
      end
      ncols = 1 if ncols < 1
      nrows = l.size if ncols == 1
      # The smallest number of rows computed and the max widths for
      # each column has been obtained.  Now we just have to format
      # each of the rows.
      s = ''
      0.upto(nrows-1) do |_row| 
        row = _row
        texts = []
        0.upto(ncols-1) do |col|
          i = array_index.call(nrows, row, col)
          if i >= l.size
            x = ''
          else
            x = l[i]
          end
          texts.push(x)
        end
        texts.pop while !texts.empty? and texts[-1] == ''
        if texts.size > 0
          0.upto(texts.size-1) do |col|
            unless ncols == 1 && opts[:ljust]
              if opts[:ljust]
                texts[col] = texts[col].ljust(colwidths[col])
              else
                texts[col] = texts[col].rjust(colwidths[col])
              end
            end
          end
          s += "%s%s\n" % [opts[:lineprefix], texts.join(opts[:colsep])]
        end
      end
      return s
    else
      array_index = lambda {|num_rows, row, col| ncols*(row-1) + col }
      # Assign to make enlarge scope of loop variables.
      totwidth = i = rounded_size = 0  
      # Try every column count from size downwards.
      l.size.downto(1) do |_ncols|
        ncols = _ncols
        # Try every row count from 1 upwards
        min_rows = (l.size+ncols-1) / ncols
        min_rows.upto(l.size) do |_nrows|
          nrows = _nrows
          rounded_size = nrows * ncols
          colwidths = []
          totwidth = -opts[:colsep].length
          colwidth = row = 0
          0.upto(ncols-1) do |col|
            # get max column width for this column
            1.upto(nrows) do |_row|
              row = _row
              i = array_index.call(nrows, row, col)
              break if i >= l.size
              colwidth = [colwidth, cell_size(l[i], opts[:term_adjust])].max
            end
            colwidths.push(colwidth)
            totwidth += colwidth + opts[:colsep].length
            break if totwidth > opts[:displaywidth];
          end
          if totwidth <= opts[:displaywidth]
            # Found the right nrows and ncols
            nrows  = row
            break
          elsif totwidth >= opts[:displaywidth]
            # Need to reduce ncols
            break
          end
        end
        break if totwidth <= opts[:displaywidth] and i >= rounded_size-1
      end
      ncols = 1 if ncols < 1
      nrows = l.size if ncols == 1
      # The smallest number of rows computed and the max widths for
      # each column has been obtained.  Now we just have to format
      # each of the rows.
      s = ''
      prefix = if opts[:array_prefix].empty?
                 opts[:lineprefix] 
               else 
                 opts[:array_prefix]
               end
      1.upto(nrows) do |row| 
        texts = []
        0.upto(ncols-1) do |col|
          i = array_index.call(nrows, row, col)
          if i >= l.size
            break
          else
            x = l[i]
          end
          texts.push(x)
        end
        0.upto(texts.size-1) do |col|
          unless ncols == 1 && opts[:ljust]
            if opts[:ljust]
              texts[col] = texts[col].ljust(colwidths[col]) if ncols != 1
            else
              texts[col] = texts[col].rjust(colwidths[col])
            end
          end
        end
        s += "%s%s\n" % [prefix, texts.join(opts[:colsep])]
        prefix = opts[:lineprefix]
      end
      s += opts[:array_suffix]
      return s
    end
  end