33
\$\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, 2020 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, 2020 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, 2020 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, 2020 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\$ Dec 4, 2020 at 13:23

16 Answers 16

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\$ Dec 4, 2020 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, 2020 at 9:19
  • \$\begingroup\$ @ovs Thanks! :) \$\endgroup\$ Dec 4, 2020 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, 2020 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\$ Dec 4, 2020 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, 2020 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, 2020 at 11:28
  • \$\begingroup\$ @Dingus - I was trying newline in %[], didn't knew it works inside "" too! \$\endgroup\$
    – vrintle
    Dec 4, 2020 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\$ Dec 4, 2020 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, 2020 at 13:17
  • \$\begingroup\$ Oh yeah, that's even easier then: len(l[0]) and saves me 8 bytes in my answer, thanks! \$\endgroup\$ Dec 4, 2020 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, 2020 at 10:35
  • \$\begingroup\$ @vrintle Thanks, I always seem to overlook something... \$\endgroup\$
    – Neil
    Dec 4, 2020 at 10:43
  • \$\begingroup\$ Japt should not be beating Charcoal in a challenge like this; try harder! :p \$\endgroup\$
    – Shaggy
    Dec 4, 2020 at 23:58
  • \$\begingroup\$ @Shaggy Yeah, I just spotted a trivial 4-byte saving without even trying... \$\endgroup\$
    – Neil
    Dec 5, 2020 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\$
0
\$\begingroup\$

Pip, 36 bytes

P'-M@P*gWRsX3LXW*4N JgPsX#a+2WR'|WRs

Takes lines of input as command-line arguments; or, with the -r flag, as lines of stdin. Lines must be padded with spaces to the same length. Try it online!

Explanation

Let's break this into two halves: the data + tabletop, and the legs.

P'-M@P*gWRsX3
       g       List of input lines
        WR     Wrap each line in
          sX3  Three spaces
     P*        Print each line
    @          Take the first one
 '-M           List containing one hyphen for each character in that line
P              Print (concatenated together by default)

LXW*4N JgPsX#a+2WR'|WRs
       Jg                Join the lines of input into one string
     N                   Count occurrences in that string of
 XW                      Regex matching [a-zA-Z0-9]
   *4                    repeated 4 times
L                        Loop that many times:
             a            First line of input
            #             Length
              +2          Plus 2
          sX              String of that many spaces
                WR'|      Wrap in pipe characters
                    WRs   Wrap in spaces
         P                Print
\$\endgroup\$
0
\$\begingroup\$

Vyxal ao, 34 bytes

ƛ3Ip…L;G:3+\-*,‹‛ƛ↓□⁋ẎL$I‛ |p‛|
+*

Try it Online! Probably not optimal, but beats Jelly :P

a flag is for multiline input; o forces implicit output even though there are print statements in the code.

ƛ3Ip…L;G:3+\-*,‹‛ƛ↓□⁋ẎL$I‛ |p‛|
+*                                # Full program

ƛ     ;                     # For each line in input (`a` flag):
 3Ip                        #   Prepend 3 spaces
    …                       #   Print ^
     L                      #   and return its length

G:                          # Take the maximum length from ^ and duplicate
  3+                        # Add 3 to one copy
    \-*,                    # Print that many `-`s
        ‹                   # Decrement the other maximum length copy for later

            □⁋              # From inputs...
              ẎL            # ...find the number of
         ‛ƛ↓                # ...`data`s (dictionary-compressed)
                $           # Swap number of "data"s for (maximum length - 1)
                 I          # Push that many spaces
                  ‛ |p      # Prepend " |" to ^
                      ‛|\n+ # Append "|\n" to ^ (\n is an actual newline)
 *                          # Repeat as many times as the number of datas to make the legs
                            # `o` flag - implicitly output the legs of the table
\$\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.