12
\$\begingroup\$

Input a strict subset of HTML <table> string representation as defined below. Output parsed table, while any cells who span multiple rows or columns, record its value on the top left cell, and fill other cells as empty strings.

Supported HTML Syntax

Table: '<table>' '\n' Row Row* '</table>'
Row: '<tr>' Cell* '</tr>' '\n'
Cell: '<td' (' colspan="' ColSpan '"')? (' rowspan="' RowSpan '"')? '>' Content '</td>'
Colspan: Integer
RowSpan: Integer
Content: /[a-z]+/
Integer: /[2-9]|[1-9][0-9]+/

Notes:

  • Text in quotes 'text' will be provided as-is.
  • Text in slashes /text/ is regular expression
  • ? means optional, zero or one
  • * means any number of repeat, may be zero
  • You may assume the table is well-formed, and is rectangle
  • You may assume the table is non-empty (has at least one cell).

Explain:

  • A valid xml whose root element is <table>;
  • Only children of <table> are <tr>; (no <tbody> or other tags)
  • Always have a line break after <table> or </tr>, no other unnecessary whitespace characters;
  • Only children of <tr> are <td>;
  • <td> may contain colspan and rowspan attribute, no other attributes may provided, and colspan must come before rowspan if both of them are provided;
  • table cell only contains lower case latin letters, at least 1 character
  • rowspan and colspan would be integers greater than 1

If you cannot read / parse the syntax define, don't worry. Just checkout the testcases which are well explained.

Rules

  • Input is a string with HTML (XHTML) syntax define above. It is flexible to choose how to input (via stdin, via file, or some other ways...). However, as this question is tagged as , you are not allowed to input pre-parsed HTML / XML document.
  • Output can be in any reasonable format who represent the 2d string array. If you choose to output a single string (or display on screen, write to file), you may use any delimiter you want. But the delimiter should not be letters, the cell separator and the line separator should be different. You may also output as csv, tsv; or other reasonable table format such as xlsx; or even HTML table (without any colspan or rowspan). If you try to render it on screen, your output should be able to distinguish a table with some rows or columns that only contains empty strings from tables that such rows or columns are absent.
  • Your implementation may have some restriction on the size of table, but it should at least support any table who have 100 columns, 100 rows and 100 letters per each cell.
  • This is as usual. And standard loopholes applied here.

Testcases

Testcase 1: The simple example without colspan, rowspan

Input

<table>
<tr><td>a</td><td>b</td><td>c</td></tr>
<tr><td>x</td><td>y</td><td>z</td></tr>
</table>

Output

[["a", "b", "c"]
 ["x", "y", "z"]]

Explain

    1   2   3
  +---+---+---+
1 | a | b | c |
  +---+---+---+
2 | x | y | z |
  +---+---+---+

Testcase 2: An example with colspan

Input:

<table>
<tr><td colspan="2">a</td><td>c</td></tr>
<tr><td>x</td><td colspan="2">y</td></tr>
</table>

Output:

[["a", "",  "c"],
 ["x", "y", "" ]]

Explain:

    1   2   3
  +---+---+---+
1 | a     | c |
  +---+---+---+
2 | x | y     |
  +---+---+---+

Testcase 3: An example with rowspan

Input:

<table>
<tr><td rowspan="2">a</td><td>b</td><td rowspan="2">c</td></tr>
<tr><td>y</td></tr>
</table>

Output:

[["a", "b", "c"],
 ["",  "y", "" ]]

Explain:

    1   2   3
  +---+---+---+
1 | a | b | c |
  +   +---+   +
2 |   | y |   |
  +---+---+---+

Testcase 4: An example with both colspan and rowspan

Input:

<table>
<tr><td colspan="2" rowspan="2">a</td><td>c</td></tr>
<tr><td>z</td></tr>
</table>

Output:

[["a", "",  "c"],
 ["",  "",  "z"]]
    1   2   3
  +---+---+---+
1 | a     | c |
  +       +---+
2 |       | z |
  +---+---+---+

Testcase 5: Single cell edge case

Input:

<table>
<tr><td colspan="2" rowspan="2">text</td></tr>
</table>

Output:

[["text", ""],
 ["",     ""]]

Explain

    1   2
  +---+---+
1 | text  |
  +       +
2 |       |
  +---+---+

Testcase 6: A complex example

Input:

<table>
<tr><td rowspan="2">a</td><td rowspan="2">b</td><td rowspan="2">c</td><td rowspan="3">d</td></tr>
<tr></tr>
<tr><td colspan="2">e</td><td rowspan="2">g</td></tr>
<tr><td>i</td><td>j</td><td rowspan="2">l</td></tr>
<tr><td colspan="3">m</td></tr>
<tr><td>long</td><td colspan="3" rowspan="2">text</td></tr>
<tr><td>here</td></tr>
</table>

Output:

[["a", "b", "c", "d"],
 ["",  "",  "",  "" ],
 ["e", "",  "g", "" ],
 ["i", "j", "",  "l"],
 ["m", "",  "",  "" ],
 ["long", "text", "", ""],
 ["here", "",     "", ""]]

Explain:

      1    2   3   4
  +------+---+---+---+
1 | a    | b | c | d |
  +      +   +   +   +
2 |      |   |   |   |
  +------+---+---+   +
3 | e        | g |   |
  +------+---+   +---+
4 | i    | j |   | l |
  +------+---+---+   +
5 | m            |   |
  +------+---+---+---+
6 | long | text      |
  +------+           +
7 | here |           |
  +------+---+---+---+
\$\endgroup\$
2
  • \$\begingroup\$ "If you try to render it on screen" does that imply we can render on screen instead of outputting a 2d string array? \$\endgroup\$
    – corvus_192
    Commented May 7 at 20:01
  • \$\begingroup\$ you may "represent" the 2d array flexible. while, render it on screen is one option here. \$\endgroup\$
    – tsh
    Commented May 8 at 6:07

3 Answers 3

5
\$\begingroup\$

JavaScript (Node.js), 175 bytes

x=>x.replace(/<t.(?: c.*?(\d+)")?(?: .*?(\d+)")?>(\w*)/g,(t,c=t<'<te'||!--y,r=1,v)=>{for(i=0;c;++i)if(!(X[~y]?.[i]+1))for(j=1,--c;+r+--j;u[i]=v,v='')u=X[~y-j]||=[]},X=y=[])&&X

Attempt This Online!

\$\endgroup\$
3
  • \$\begingroup\$ 178 bytes \$\endgroup\$
    – Arnauld
    Commented May 6 at 15:07
  • \$\begingroup\$ @Arnauld All are support of ||= or something else? \$\endgroup\$
    – l4m2
    Commented May 6 at 16:42
  • \$\begingroup\$ and ?. support. \$\endgroup\$
    – l4m2
    Commented May 6 at 16:47
3
\$\begingroup\$

Charcoal, 144 bytes

SθSθ≔⁰ηW›Lθ⁸«≔⁰ζF∧›Lθ⁹⪪✂θ⁷±χ¹</td><td«≔E⊞O⪪κwspan=ω∨Σλ¹ε≔✂κ⊕⌕κ>Lκ¹κ≔⁺η§ε¹δF⁻δLυ⊞υ⟦⟧F✂υηδ¹«W∧‹ζLλ¬⁼§λζ⁰≦⊕ζF⁻⁺ζ§ε⁰Lλ⊞λ⁰F§ε⁰«§≔λ⁺ζμκ≔ωκ»»»≦⊕ηSθ»⭆¹υ

Try it online! Link is to verbose version of code. Explanation:

Sθ

Skip over the initial <table>.

Sθ

Read the first line of the table body.

≔⁰η

Start at (0-indexed) row 0.

W›Lθ⁸«

Repeat until </table> is reached.

≔⁰ζ

Start at column 0.

F∧›Lθ⁹⪪✂θ⁷±χ¹</td><td«

Loop over the cells of the table, excluding the leading <td and trailing </td>.

≔E⊞O⪪κwspan=ω∨Σλ¹ε

Extract the rowspan and colspan. (This depends on the text not containing digits.)

≔✂κ⊕⌕κ>Lκ¹κ

Extract the text.

≔⁺η§ε¹δ

Get the height necessary to include this rowspan.

F⁻δLυ⊞υ⟦⟧

Extend the table to that height if necessary.

F✂υηδ¹«

Loop over each row in the rowspan.

W∧‹ζLλ¬⁼§λζ⁰≦⊕ζ

Increase the column until it's not a used cell. (This only makes a difference on the first row, in which case the column advances past the previous cell and any cells from rowspans in previous rows.)

F⁻⁺ζ§ε⁰Lλ⊞λ⁰

Extend the row to the width necessary to include the colspan.

F§ε⁰«

Loop for every colspan.

§≔λ⁺ζμκ

Set the cell to the current text.

≔ωκ

Clear the current text.

»»»≦⊕η

Advance to the text row.

Sθ

Read the next line of the table.

»⭆¹υ

Pretty-print the final table, as the default output would confuse empty cells with the double-spacing between rows.

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

sh + pandoc, 19 bytes

pandoc -fhtml -tgfm

Convert from html to github-flavoured markdown (gfm). Input from stdin, output to stdout.

Example output:

|      |      |     |     |
|------|------|-----|-----|
| a    | b    | c   | d   |
|      |      |     |     |
| e    |      | g   |     |
| i    | j    |     | l   |
| m    |      |     |     |
| long | text |     |     |
| here |      |     |     |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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