Raku code

```raku sub create-table(:@headers, :@columns, Bool :$markdown = False --> Nil) { unless @headers.elems == @columns.elems { $*ERR.spurt: "Table is out of shape: Number of headers must be equal to number of columns.\n"; $*ERR.flush; return; } unless [==] @columnsĀ».elems { $*ERR.spurt: "Table is out of shape: All columns must have the same length.\n"; $*ERR.flush; return; } my constant $ADDITIONAL-SPACING = 2; my constant $COLUMN-SEPARATOR = '| '; my constant $LEFT-BOUNDARY = '| '; my constant $JOIN-SEPARATOR = '+'; my constant $MARKDOWN-BOUNDARY = '|:'; # # HEADING # my Str:D $row-separator = ''; my @headers-to-max-col-values = []; for @headers.kv -> $idx, $header { my Int:D $max-col-value = @columns[$idx].max(:by(&chars)).chars; @headers-to-max-col-values.push($header => $max-col-value) for 0..^@columns[$idx].elems; my Str:D $heading-row = ~ ($idx == 0 ?? $LEFT-BOUNDARY !! '') ~ $header ~ (' ' x ($max-col-value + $ADDITIONAL-SPACING + ($idx == 0 ?? 1 !! 0))) ~ $COLUMN-SEPARATOR ; $*OUT.spurt: $heading-row; if $markdown { $row-separator ~= ~ ($idx == 0 ?? $MARKDOWN-BOUNDARY !! '') ~ '-' x ($header.chars + $max-col-value + $ADDITIONAL-SPACING + ($idx == 0 ?? $LEFT-BOUNDARY.chars !! 0) - 1) ~ $MARKDOWN-BOUNDARY ~ ($idx != @headers.end ?? '-' !! ''); $row-separator .= chop(1) if $idx == @headers.end; } else { $row-separator ~= ~ ($idx == 0 ?? $JOIN-SEPARATOR !! '') ~ '-' x ($header.chars + $max-col-value + $ADDITIONAL-SPACING + ($idx == 0 ?? $LEFT-BOUNDARY.chars !! 0)) ~ $JOIN-SEPARATOR ~ ($idx != @headers.end ?? '-' !! ''); } if $idx eq @headers.end { $*OUT.spurt: "\n$row-separator\n"; } } # # ROWS # my Int:D $aligned-data-offset = @columns.min(:by(&elems)).elems; my Int:D $row-count = @headers.elems; my Int:D $next-idx = 0; my Int:D $newrow-indicator = 0; my Int:D $iterations = 0; my Str:D @values = @columns.map(*.Slip); my $m = @values.elems div @columns.head.elems; for 0 ..^ @values.elems -> $n { my $first-row = $n %% $m; my $pair = @headers-to-max-col-values[$next-idx]; my Int:D $chars = $pair.value + $pair.key.chars + $ADDITIONAL-SPACING + ($first-row ?? 1 !! 0); my Str:D $row-part = sprintf("%-{$chars}s", @values[$next-idx]) ~ $COLUMN-SEPARATOR; if $next-idx >= @values.elems - $aligned-data-offset { $next-idx = $iterations + 1; $iterations += 1; } else { $next-idx += $aligned-data-offset } if $newrow-indicator >= $row-count { $*OUT.flush; $*OUT.spurt: "\n$LEFT-BOUNDARY"; $newrow-indicator = 0; } else { $*OUT.spurt: $LEFT-BOUNDARY if $n == 0; } $*OUT.spurt: $row-part; $newrow-indicator += 1; } $*OUT.spurt: ("\n$row-separator" unless $markdown) ~ "\n"; $*OUT.flush; } ```
### Usage ```raku create-table headers => ["Process Name", "Arrival Time", "Service Time", "Turnaround Time"], columns => [ ["P1", "P2", "P3", "P4", "P5"], ["1", "3", "6", "2", "3"], ["3", "1", "8", "1", "4"], ["3", "1", "8", "1", "4"], ], :markdown, ; ``` ### Output ``` | Process Name | Arrival Time | Service Time | Turnaround Time | |:-----------------|:---------------|:---------------|:------------------| | P1 | 1 | 3 | 3 | | P2 | 3 | 1 | 1 | | P3 | 6 | 8 | 8 | | P4 | 2 | 1 | 1 | | P5 | 3 | 4 | 4 | ```