30
\$\begingroup\$

We're getting markdown tables! I assume this is what they look like:

     data
   data data  data
---------------------
 |                 |
 |                 |
 |                 |
 |                 |

Your task is to make a program or function to generate one of these tables. You'll be given input (string, list of lines, list of characters, etc.) containing data, which looks like this:

datadata

         data
  data           data
data data  data

The data consists of spaces and non-overlapping datas. The data will not necessarily form neat stacks (it can float in midair). There is guaranteed to be data on the top and bottom lines, as well as some touching the left side. You can choose if the data is right padded with spaces or not.

The table will always be six characters wider than the data, padded three spaces on the left. The table top is directly below the bottom row of data, and is made up of a line of -s.

As for the legs, everyone knows taller tables can support more weight, so they'll need to be one unit tall for every data in the input. They will be made up of |s, one space in from the sides.

This is , so shortest answer in bytes per language wins!

Test cases

Input:

data

Output:

   data
----------
 |      |

Input:

data data data
 data data data

Output:

   data data data
    data data data
---------------------
 |                 |
 |                 |
 |                 |
 |                 |
 |                 |
 |                 |

Input:

data

data

Output:

   data
   
   data
----------
 |      |
 |      |
\$\endgroup\$
10
  • 2
    \$\begingroup\$ May input contains extra spaces? For example " data ", "data \n data". \$\endgroup\$ – tsh Dec 4 '20 at 6:36
  • 2
    \$\begingroup\$ To be clear: we're outputting the input unchanged with the table as defined underneath it? \$\endgroup\$ – Shaggy Dec 4 '20 at 9:29
  • 1
    \$\begingroup\$ Some doubts: 1) Can we return just the "table string" from function and print the data-string using footer code? 2) @Shaggy - I think input must have to change as output has 3 spaces left-padding on every row! \$\endgroup\$ – vrintle Dec 4 '20 at 9:51
  • 1
    \$\begingroup\$ Don't know about linking to testcase, I wrote and posted my answer before following the link and didn't fully understand the challenge until I saw the extra testcases. For clarity it's best to make them a part of the post. \$\endgroup\$ – Noodle9 Dec 4 '20 at 11:45
  • 1
    \$\begingroup\$ @tsh The data is guaranteed to be touching the left side, the the first example wouldn't occur. You can choose how the right padding works, so you don't have to handle the second example you gave. \$\endgroup\$ – Redwolf Programs Dec 4 '20 at 13:23

14 Answers 14

10
\$\begingroup\$

Perl 5 -lpF, 88 74 66 bytes

Because we're allowed to require the input to be padded on the right side, @DomHastings was able to shave 8 bytes off my method while eliminating the need for List::Util.

END{printf'-'x(@F+6)."
 |%@{[@F+3]}s"x$q,("|")x$q}s//   /;$q+=y;d;

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1. You can save 8 bytes if you have right-padded input and use -F too! Try it online! \$\endgroup\$ – Dom Hastings Dec 4 '20 at 13:36
6
\$\begingroup\$

05AB1E, 31 30 28 bytes

¬g6+©'-תð®×'|1®Í‚ǝIJ'd¢и«.c

-1 byte thanks to @ovs.

Input as a list of lines, right-padded with spaces to an equal length.

Try it online or verify all test cases.

Explanation:

¬                  # Get the first line of the (implicit) input-list (without popping)
 g                 # Pop and push its length
  6+               # Add 6
    ©              # Store this value in variable `®` (without popping)
     '-×          '# Pop and create a string of that many "-"
        ª          # Append it to the list of lines
ð®×                # Create a string consisting of `®` amount of spaces
     1             # Push 1
      ®Í           # Push value `®` and decrease it by 2
        ‚          # Pair them together: [1,®-2]
   '|    ǝ        '# Insert a "|" at those (0-based) indices in the spaces-string
          IJ       # Push the input-list, and join it to a single string
            'd¢   '# Count the amount of "d"s in it
               и   # Repeat the legs-string that many times as list
                «  # And merge the two lists together
.c                 # And finally centralize this list, which adds leading spaces where
                   # necessary, and implicitly joins the list by newlines
                   # (after which the result is output implicitly)
\$\endgroup\$
4
  • \$\begingroup\$ 30 bytes with manual printing. \$\endgroup\$ – ovs Dec 4 '20 at 9:19
  • \$\begingroup\$ @ovs Thanks! :) \$\endgroup\$ – Kevin Cruijssen Dec 4 '20 at 10:19
  • \$\begingroup\$ Could you save anything by right padding the input with spaces so you'd just have to get the length of one line instead of the max length of all lines? \$\endgroup\$ – Shaggy Dec 4 '20 at 11:18
  • \$\begingroup\$ @Shaggy Thanks indirectly. 05AB1E doesn't really have any convenient builtins for right-padding unfortunately, except maybe the box builtin .B (split string by newlines, and pad trailing spaces so all strings are the same length). Not really useful directly with my current approach, but in combination with the .c (centralize) builtin, it does save a byte in the end. AND, because taking the input already right-padded is allowed in the rules, an additional byte can be saved by just dropping the .B. \$\endgroup\$ – Kevin Cruijssen Dec 4 '20 at 11:58
5
\$\begingroup\$

APL (Dyalog Unicode), 60 57 56 55 41 bytes

{3⌽↑(↓'-'⍪⍨' '∘,⍣6⊢⍵),↓(+/∊'d'⍷⍵)6⍴' | '}

Try it online!

Input as a character matrix.

-1 byte from ovs.

-14 bytes, following xash's answer.

Explanation(old)

{↑('   '∘,¨↓⍵),(⊂a/'-'),(+/∊'d'⍷⍵)/⊂2⌽'|  |'↑⍨a←6+⊃⌽⍴⍵}
                                      '|  |'                 a set of table legs
                                            ↑⍨               pad to length
                                              a←6+⊃⌽⍴⍵       6 + row size
                                       a←                    store in var a
                                    ⊂2⌽                      rotate 2 steps and wrap
                         (        )/                         replicate that by:
                             'd'⍷⍵                           boolean matrix of occurrences of 'data'   
                          +/∊                                sum all the occurrences
                        ,                                    concatenate with
               (⊂a/'-')                                      '-' repeated a times
  ('   '∘,¨↓⍵),                                              and the input padded with 3 spaces on the left
 ↑                                                           convert to matrix(join with newlines)
\$\endgroup\$
0
4
\$\begingroup\$

Japt, 30 28 27 bytes

Hmm ... thought this would work out much shorter.

Takes input as an array of lines, right-padded with spaces and outputs an array of lines.

cU¬èd ô@S+i|i|úUÎÊ+3ÃvÈç-
û

Try it or run all test cases

cU¬èd ô@S+i|i|úUÎÊ+3ÃvÈç-\nû     :Implicit input of array U
c                                :Concatenate
 U¬                              :  Join U
   èd                            :  Count the "d"s
      ô                          :  Range [0,count]
       @                         :  Map
        S                        :    Space
         +                       :    Append
          i                      :      A space prepended with
           |i                    :        A "|" prepended with
             |ú                  :          A "|" right padded with spaces to length
               UÎÊ+3             :          Length of first element of U plus 3
                    Ã            :End map
                     v           :Modify first element
                      È          :By passing it through the following function
                       ç-        :  Fill with "-"
                         \n      :Reassign to U (saves a byte over having to close all the nested methods)
                           û     :Centre pad each element with spaces to the length of the longest
\$\endgroup\$
4
\$\begingroup\$

J, 41 bytes

0 3|.(' | '$~6,~1#.'d'=,),~'-',~' '&,.^:6

Try it online!

How it works

  • ' '&,.^:6 prepend a space to each row 6 times.
  • '-',~ append a new row filled with -.
  • 1#.'d'=, count the ds in the input.
  • ' | '$~6,~ shape | into dimensions count 6, so count rows of | |
  • ,~ append the leg rows to the tables, filling possible empty space on the right with .
  • 0 3|. shift every row 3 characters to the left.

Or in pictures:

data

      data

      data
----------

      data
----------
 |  |

    data   
-----------
 |       |
\$\endgroup\$
4
\$\begingroup\$

Ruby 2.7, 112 98 77 74 bytes

Saved 6 bytes using String#count method, thanks to Razetime!
Saved 3 bytes using literal newline, thanks to Dingus!

->m{m.map{" "*3+_1}<<?-*(6+c=m[0].size)+"
 | #{" "*c} |"*(m*"").count(?d)}

Try it online!

  • TIO uses an older version of Ruby, while in Ruby 2.7, we've numbered parameters, i.e., _1, which saves 2 bytes.
\$\endgroup\$
3
  • 1
    \$\begingroup\$ -6, just counting d \$\endgroup\$ – Razetime Dec 4 '20 at 9:22
  • 1
    \$\begingroup\$ -3 bytes with a literal newline, two literal spaces, and some rearrangement to avoid shouty map!. (I also simplified the footer a bit.) \$\endgroup\$ – Dingus Dec 4 '20 at 11:28
  • \$\begingroup\$ @Dingus - I was trying newline in %[], didn't knew it works inside "" too! \$\endgroup\$ – vrintle Dec 4 '20 at 13:36
3
\$\begingroup\$

Python 3.8, 113 107 95 bytes

Saved 6 a whopping 18 bytes thanks to Dom Hastings!!!

lambda l:['   '+a for a in l]+[(r:=6+len(l[0]))*'-']+''.join(l).count('d')*[' |'+(r-4)*' '+'|']

Try it online!

Inputs a list of right-space-padded strings and returns a list of strings.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ +1 You can use len(a) instead of a.rfind('a') for -6 too! Try it online! \$\endgroup\$ – Dom Hastings Dec 4 '20 at 13:11
  • \$\begingroup\$ @DomHastings That's great and just realised I can require right padding for additional saves - thanks! :D \$\endgroup\$ – Noodle9 Dec 4 '20 at 13:17
  • \$\begingroup\$ Oh yeah, that's even easier then: len(l[0]) and saves me 8 bytes in my answer, thanks! \$\endgroup\$ – Dom Hastings Dec 4 '20 at 13:28
3
\$\begingroup\$

Jelly, 36 bytes

Ỵ⁶x3¤;ṄƊ€ẈṀ+©3”-xṄṛċ”d®e®’,2¤¥þị⁾| Y

Try it online!

Takes input as a single string.

This is disgustingly hacked together, but Jelly's never been particularly good at strings.

How it works

Ỵ⁶x3¤;ṄƊ€ẈṀ+©3”-xṄṛċ”d®e®’,2¤¥þị⁾| Y - Main link. Takes s on the left
Ỵ                                    - Split into a list of lines
       Ɗ€                            - Over each line l:
    ¤                                -   Group together as a nilad:
 ⁶                                   -     " "
  x3                                 -     [" ", " ", " "]
     ;                               -   Prepend to l
      Ṅ                              -   Print
         Ẉ                           - Get the lengths of each line
          Ṁ                          - Take the maximum
           + 3                       - Add 3
            ©                        - Save it to the register, r
              ”-                     - "-"
                x                    - Repeat that many times
                 Ṅ                   - Print
                  ṛ                  - Discard everything and use s
                   ċ”d               - Count occurrences of "d", d
                      ®              - Yield the register, r
                             ¥þ      - Create an d×r grid and to each cell (i, j):
                            ¤        -   Group into a nilad:
                        ®            -     r
                         ’           -     r-1
                           2         -     2
                          ,          -     [r-1, 2]
                       e             -   Is i in [r-1, 2]?
                               ị⁾|   - Index each cell into "| "
                                   Y - Join by newlines
\$\endgroup\$
3
\$\begingroup\$

Charcoal, 29 25 bytes

WS⊞υι↑№ΣυdM←³Lθ←Fυ↑‖OOLθυ

Try it online! Link is to verbose version of code. Takes newline-terminated rectangular input. Explanation:

WS⊞υι

Input the data.

↑№ΣυdM←³

Print the left leg and the --- at the top of the left leg.

Lθ

Print the middle part of the table.

←Fυ↑

Move the cursor to the top right of the data. The following reflection will then move it to the top left. (Moving here avoids confusion between the use of the arrows as movement and as modifiers for reflection or printing direction.)

‖OOLθ

Reflect to complete the right of the table.

υ

Print the data.

\$\endgroup\$
4
  • \$\begingroup\$ Hm.. you'd also misinterpreted the question statement (like me :P). Actually, it says to print n amount of legs, where n is number of times "data" appears in that multiline string/matrix. \$\endgroup\$ – vrintle Dec 4 '20 at 10:35
  • \$\begingroup\$ @vrintle Thanks, I always seem to overlook something... \$\endgroup\$ – Neil Dec 4 '20 at 10:43
  • \$\begingroup\$ Japt should not be beating Charcoal in a challenge like this; try harder! :p \$\endgroup\$ – Shaggy Dec 4 '20 at 23:58
  • \$\begingroup\$ @Shaggy Yeah, I just spotted a trivial 4-byte saving without even trying... \$\endgroup\$ – Neil Dec 5 '20 at 0:12
3
\$\begingroup\$

C (gcc), 204 194 187 181 174 bytes

174-byte solution thanks to @ceilingcat.

z,s,i;main(c,v)char**v;{for(;++z<c;)printf("   %s\n",v[z]);for(;c--;)for(s=0;z=v[c][s++];)i+=z=='d';for(;z++<strlen(v[1])+6;putchar(45));for(;i--;)printf("\n |%*c",z-4,'|');}

Try it online!

Takes each line of input as a right-padded command line argument.

\$\endgroup\$
0
2
\$\begingroup\$

Retina, 53 bytes

\`.+
   $&   
L$`d
$%=
T`p`-
*\0G`
T`-` 
%,T1,,-2` `|

Try it online! Takes rectangular input. Explanation:

\`.+
   $&   

Pad the input by 3 spaces on each side and print the result.

L$`d
$%=

Repeat each line by the count of its ds.

T`p`-

Change all the characters to -s.

*\0G`

Print the first line.

T`-` 

Change all the characters to spaces.

%,T1,,-2` `|

Change the (0-indexed) second and second last characters to |s and implicitly print the resulting legs.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6),  105  103 bytes

Expects a single string with right-padded lines.

s=>s[R='replace'](/^|t/g,c=>o+=`
`+(p=c?' | ':'---')+q[R](/./g,p[0])+p,o=s[R](/.+/g,s=>'   '+(q=s)))&&o

Try it online!

Commented

s =>                     // s = input string
s[R = 'replace'](        // replace in s:
  /^|t/g,                //   match the beginning of the string
                         //   and each 't' (of 'data')
  c =>                   //   for each matching character c:
    o +=                 //     append to o:
      `\n` + (           //       a line-feed
        p =              //       followed by p defined as:
          c ?            //         if c is not empty:
            ' | '        //           ' | '
          :              //         else:
            '---'        //           '---'
      )                  //
      + q[R](/./g,       //       followed by each character in q ...
                   p[0]) //       ... replaced with the 1st character of p
      + p,               //       followed by p
  o =                    //   initialize the output string o:
    s[R](                //     replace in s:
      /.+/g, s =>        //       each line s
        '   '            //       with 3 leading spaces
        + (q = s)        //       followed by s, which is copied in q
    )                    //     end of replace()
) && o                   // end of replace(); return o
\$\endgroup\$
1
\$\begingroup\$

Jelly, 38 bytes

Ỵ⁶x3¤;Ɱ©ẈṀ+3µ⁶ẋ”|2,-¦Wẋ³ċ”d¤;@”-xWƊ®;Y

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Perl 5 + -pl055F, 53 bytes

A different approach to @Xcali's answer. Requires lines to be padded with spaces.

$;+=y/d//;say"   $_"}{$\=$\x(6+($#x=@F))."
 | @x |"x$

Try it online!

Explanation

Firstly, -l055 sets $\ to '-', -p implicitly wraps wraps the code in while(<STDIN>){...;print;} and -F splits each line of input into chars in @F.

In the code, due to the implicit code added by -p, for each line of text increment $; with the number of d in the code then say the line with three leading spaces. The }{ breaks out of the implicit while and $\ is then set to $\ repeated 6+@F (whilst also setting $#x to @F's scalar value) times concatenated with a string consisting of: a leading newline, space, pipe (|), space, @x interpolated, space, pipe, which itself it repeated $; times.

@F, when used in a scalar context like this, returns the number of elements in @F - which is the number of chars in the line, since each line is space-padded this works fine. $#x is a 'magic' variable which contains the last index of @x and means that @x now contains @F+1 empty values. When an array is interpolated into a double-quoted string, its values are printed out with a space between each, so an empty array with @F+1 elements interpolated, results in a string consisting of @F spaces. This code ends with just $ because of the -p-added code which contains ; saving another byte.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.