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\$
  • 18
    \$\begingroup\$ A word of caution for golfers... \$\endgroup\$ – Luis Mendo Jan 9 '18 at 0:07
  • \$\begingroup\$ Will there ever be </ div>? or can we assume the slash is always adjacent to the div \$\endgroup\$ – Rɪᴋᴇʀ Jan 9 '18 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 '18 at 0:18
  • 5
    \$\begingroup\$ Perhaps this could use a few more test cases? \$\endgroup\$ – Birjolaxew Jan 9 '18 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 '18 at 17:13
13
\$\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\$
  • 2
    \$\begingroup\$ This is really clever! \$\endgroup\$ – Rick Hitchcock Jan 9 '18 at 23:00
  • 1
    \$\begingroup\$ I've never seen golfed CSS before :) \$\endgroup\$ – Solver Jan 11 '18 at 8:03
  • \$\begingroup\$ This fails both of the test cases. \$\endgroup\$ – Giuseppe Jan 12 '18 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 '18 at 18:11
  • \$\begingroup\$ @Giuseppe Fixed. \$\endgroup\$ – darrylyeo Jan 13 '18 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\$
  • \$\begingroup\$ Are you sure it's naïve and not naïve? (I can stop this joke if you want) \$\endgroup\$ – Esolanging Fruit Jan 9 '18 at 2:32
  • \$\begingroup\$ 269 bytes by changing to: j=(a,b,c,i)=>{s=(c=' '.repeat(b))+'/\n';for(i ... \$\endgroup\$ – Rick Hitchcock Jan 9 '18 at 20:41
  • \$\begingroup\$ Change to for(c=0;c<s.length;c++) to for(c=0;s[c];c++) \$\endgroup\$ – Rick Hitchcock Jan 9 '18 at 20:47
  • \$\begingroup\$ Similarly, change for(i=0;i<a.children.length;i++) to for(i=0;a.children[i];i++) \$\endgroup\$ – Rick Hitchcock Jan 9 '18 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\$
  • \$\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 '18 at 1:55
  • \$\begingroup\$ @Birjolaxew Whoops! I missed that somehow. \$\endgroup\$ – darrylyeo Jan 10 '18 at 3:51
  • 1
    \$\begingroup\$ HTML has built-in HTML parser... creative solution. \$\endgroup\$ – user202729 Jan 10 '18 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.