21
\$\begingroup\$

Task: convert a HTML page into a mountain!

When HTML pages are indented, they can look like:

<div>
    <div>
        <div>
        </div>
        <div>
            <div>
            </div>
        </div>
    </div>
</div>

But to be honest, a mountain is more representative of this structure.

So we can rewrite it as:

     /\
  /\/  \
 /      \
/        \

The outermost slashes on the left and right correspond to the outer div - each pair of HTML tags should be represented as / for the starting tag and \ for the ending tag - inside all tags are "higher", with the same structure.

Input:

  • There will be no <!DOCTYPE>
  • There will be no self-closing tags e.g. <img /> or <br />
  • There may be attributes or content inside the tags
  • There may be spaces or tabs - your program should ignore these
  • There will be no spaces between < or </ and the tag name
  • All input will be valid HTML

Output - a mountain representing the tags as above.

More testcases:

Input:

<div id="123"> HI </div><a><span></span></a>

Output:

   /\
/\/  \

Input:

<body id="<"></body>

Output:

/\
\$\endgroup\$
14
  • 18
    \$\begingroup\$ A word of caution for golfers... \$\endgroup\$
    – Luis Mendo
    Jan 9, 2018 at 0:07
  • \$\begingroup\$ Will there ever be </ div>? or can we assume the slash is always adjacent to the div \$\endgroup\$
    – Riker
    Jan 9, 2018 at 0:16
  • \$\begingroup\$ hmmm, I'll be nice - you can assume no spaces after < or </ (until the tag name) - however there may still be spaces for attributes e.g. <div id="aDiv"> \$\endgroup\$
    – Solver
    Jan 9, 2018 at 0:18
  • 5
    \$\begingroup\$ Perhaps this could use a few more test cases? \$\endgroup\$
    – Birjolaxew
    Jan 9, 2018 at 18:05
  • 1
    \$\begingroup\$ This really needs more test cases, and an exact description (in BNF, say) of what the input will look like. I don’t know what "Valid HTML" means exactly, and how many edge cases I should support. (First one that comes to mind: space between the tag name and > such as <a >b</a >.) \$\endgroup\$
    – Lynn
    Jan 13, 2018 at 17:13

5 Answers 5

14
\$\begingroup\$

HTML + CSS + JavaScript, 39 + 141 + 20 = 200 bytes

Outputs visually to the webpage. To allow this to work with special elements like <body>, all letters in the input are replaced.

p.innerHTML=prompt().replace(/\w/g,'a')
#p,#p *{display:flex;padding:0 0 1rem;align-items:flex-end;font-size:0}#p :before,#p :after{content:'/';font-size:1rem}#p :after{content:'\\'
<pre id=p>


HTML + CSS + JavaScript, 10 + 103 + 20 = 133 bytes

Solution that works if there is no content within tags.

p.innerHTML=prompt()
#p,#p *{display:flex;padding:0 0 1em;align-items:flex-end}#p :before{content:'/'}#p :after{content:'\\'
<pre id=p>

\$\endgroup\$
5
  • 2
    \$\begingroup\$ This is really clever! \$\endgroup\$ Jan 9, 2018 at 23:00
  • 1
    \$\begingroup\$ I've never seen golfed CSS before :) \$\endgroup\$
    – Solver
    Jan 11, 2018 at 8:03
  • \$\begingroup\$ This fails both of the test cases. \$\endgroup\$
    – Giuseppe
    Jan 12, 2018 at 14:12
  • \$\begingroup\$ @Giuseppe I think you may be able to fix it with display = none on all elements and using an iframe instead of a <pre> \$\endgroup\$
    – Solver
    Jan 12, 2018 at 18:11
  • \$\begingroup\$ @Giuseppe Fixed. \$\endgroup\$
    – darrylyeo
    Jan 13, 2018 at 16:35
6
\$\begingroup\$

Javascript + JQuery, 275 246 bytes

Saved 29 bytes thanks to Rick Hitchcock

j=(a,b,c,i)=>{s=(c=' '.repeat(b))+'/\n';for(i=0;V=a.children[i];i++){s=s+j(V,b+1)}return s+c+'\\\n';};f=s=>{s=j($(s)[0],0).split`
`;w=Math.max.apply(0,s.map(a=>a.length));o='';for(i=w-1;i>=0;i--){for(c=0;C=s[c];c++){o+=C[i]||' '}o+='\n'}alert(o)}

A pretty Naïve solution to the problem. Parses the HTML with JQuery's $(string), then recursively builds a sideways mountain with the format:

/
 /
  children...
 \
\

Then rotates the resulting string counterclockwise, and alerts the result.

    j=(a,b,c,i)=>{s=(c=' '.repeat(b))+'/\n';for(i=0;V=a.children[i];i++){s=s+j(V,b+1)}return s+c+'\\\n';};f=s=>{s=j($(s)[0],0).split`
`;w=Math.max.apply(0,s.map(a=>a.length));o='';for(i=w-1;i>=0;i--){for(c=0;C=s[c];c++){o+=C[i]||' '}o+='\n'}return o}

update=_=>outp.textContent=f(inp.value)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id=inp oninput=update()></textarea>
<pre id=outp></pre>

\$\endgroup\$
4
  • \$\begingroup\$ Are you sure it's naïve and not naïve? (I can stop this joke if you want) \$\endgroup\$ Jan 9, 2018 at 2:32
  • \$\begingroup\$ 269 bytes by changing to: j=(a,b,c,i)=>{s=(c=' '.repeat(b))+'/\n';for(i ... \$\endgroup\$ Jan 9, 2018 at 20:41
  • \$\begingroup\$ Change to for(c=0;c<s.length;c++) to for(c=0;s[c];c++) \$\endgroup\$ Jan 9, 2018 at 20:47
  • \$\begingroup\$ Similarly, change for(i=0;i<a.children.length;i++) to for(i=0;a.children[i];i++) \$\endgroup\$ Jan 9, 2018 at 20:50
3
\$\begingroup\$

HTML + JavaScript (ES6), 8 + 192 = 200 bytes

JS

s=>[...(E.innerHTML=s,y=0,o=[],m=n=>1+[...n.children].map(m).join``+0)(E.firstChild)].map((c,x,a)=>{(o[y+=+c]||(o[y]=[...a].fill` `))[x]=`\\/`[c],y+=~-c})&&o.reverse().map(l=>l.join``).join`
`

HTML

<a id=E>

f=

s=>[...(E.innerHTML=s,y=0,o=[],m=n=>1+[...n.children].map(m).join``+0)(E.firstChild)].map((c,x,a)=>{(o[y+=+c]||(o[y]=[...a].fill` `))[x]=`\\/`[c],y+=~-c})&&o.reverse().map(l=>l.join``).join`
`

console.log(f(`<div>
    <div>
        <div>
        </div>
        <div>
        </div>
        <div>
            <div>
            </div>
        </div>
    </div>
</div>`))
<a id=E>

Less golfed

s=>{
    E.innerHTML=s,
    y=0,
    o=[],
    m=n=>1+[...n.children].map(m).join``+0,
    [...m(E.firstChild)].map((c,x,a)=>{
        y+=+c
        if(!o[y]) o[y]=[...a].fill` `
        o[y][x]=`\\/`[c]
        y+=~-c
    })
    return o.reverse().map(l=>l.join``).join`\n`
}
\$\endgroup\$
3
  • \$\begingroup\$ Shouldn't the byte count include the id=E HTML element since you are relying on it for the code to work? \$\endgroup\$
    – Birjolaxew
    Jan 10, 2018 at 1:55
  • \$\begingroup\$ @Birjolaxew Whoops! I missed that somehow. \$\endgroup\$
    – darrylyeo
    Jan 10, 2018 at 3:51
  • 1
    \$\begingroup\$ HTML has built-in HTML parser... creative solution. \$\endgroup\$
    – DELETE_ME
    Jan 10, 2018 at 13:19
1
\$\begingroup\$

05AB1E, 38 26 23 bytes

¶¡εDð¢4÷s'/å_„\/sèú}ζR»

Try it online!


I am still golfing this. It assumes that in HTML you will always use 4 spaces for indentation, and does not work on "non-pretty" HTML. Not sure how to handle the "content" part, if this is invalid please edit the question to show an example with a node that has content.

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

Charcoal, 28 bytes

≔¹ηF⮌θ«≡ι"≦¬η<Fη¿⁼ζ/←¶\↙/≔ιζ

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

≔¹η

The h variable is used to keep track of whether we are inside quotes.

F⮌θ«

Loop over the string in reverse order.

≡ι

Switch on the currenc character.

"≦¬η

If it's a " then toggle the quote flag.

<Fη

If it's a < and we're not inside quotes, then...

¿⁼ζ/

If the next character (previous in the loop because we're looping in reverse) is a /, then...

←¶\

Move up and draw a \ leftwards, else...

↙/

Draw a / and move down and left.

≔ιζ

Remember the character for the next loop iteration.

\$\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.