After winning the SO raffle, you could have been on top the world, and you were! The raffle had been going on for a year, now, and you were one of a hundred programmers who were selected to enter into the SO stronghold. And finally, the wait is over. Today is the day you go to--[obfuscated text proceeds].

Whoops. Sorry, not supposed to tell.

Anyhow, you finally have arrived to meet a stoic-faced man in a black suit with the tiny SO emblem on it. He frowns at you. "The others are already inside," he said, noting that you had been identified at the gate. "Quickly."

You rush inside, a tad scared. What on earth had gone on? What was wrong at SO? Inside, you observe the other 99 programmers are staring intently at their screens, typing. You take the remaining seat, and are greeted with the following message:

Hello, programmer! It seems that we have encountered a problem; SO has been penetrated, by whom we don't know. (Personally, I suspect it was a Pyth or CJam programmer, but hey.) However, all that has been harmed is the Markdown editor. Well, actually, that's quite a lot, but that's where you come in.
I want you to create a program (or function, we're not picky) that will interpret a markdown file and convert it to our new "SO Beautifier-Arity-Decomposer" (a.k.a. "SOBAD") format. You must do this in the shortest amount of bytes--we are running on lowdown until we resolve this hacking issue. Thanks for your time, and best of luck!

The Maker of Stack Overflow

Objective Given a valid markdown file as input to your submission, perform and output the following transformations on the input:

(When I use the + symbol, I mean the RegExp "one or more instances of previous character" operator, not a literal plus sign.)

  • Transform all Level 1 headers (# ... or ...\n=+) to { ... }, with ... becoming ALL CAPS.
  • Transform all Level 2 headers (## ... or ...\n-+) to {{ ... }}, with every word capitalized
  • Transform all Level 3 headers (### ...) to small caps; that is, all letters (case insensitive) are mapped to ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ in a respective fashion.
  • Transform all bold instances (**...**) to ..., with ... becoming ALL CAPS.
  • Transform all italic instances (_..._) to . . ., where a space has been inserted between each pair of characters.
  • Transform all code instances (`...`) to < ... >.
  • Transform all strikethrough instances (---...---) to -.-.-.-, where a - has been inserted between each pair of characters.
  • Transform all numbered list instances (N. {a}\nN. {b} ... where N matches the regex [0-9]+) to (1. {a}\n 2. {b}...)
  • Transform all unordered list instances (* ...\n* ......) to (o ...\n o ......)

More details

  • Headers and list instances will only be found at the beginning of lines, however, they may be surrounded by an amount of whitespace.
  • There will be no linked instances, e.g., *a_*a_ is not valid for our standards, nor will anything like __a__, *_a_*, or _*a*_ appear in an input.
  • A multiline header is valid if and only if the - or =s directly follows a line of text.
  • No headers will contain other markdown entities. E.g., # `code` snippet is not a valid input for our purposes
  • You do not have to account for Level 4+ headers
  • You do not have to preserve excess spaces (i.e. > 1 spaces) within the file, so it is O.K. to have **hello there** to become **hello there** but not **hellothere**. Similarly, trailing and leading spaces found on a line does not have to be preserved
  • No tabulators will be found in the input.
  • THERE WILL BE NO NESTED INSTANCES. For example, ***...*** would never occur.
  • A space will always follow an unordered bullet point (E.g., * ... not *...)
  • List items in ordered and unordered lists will always consist of a single line.
  • Unmatched pairs of characters should be ignored. E.g., ** cool and `java::def should remain the same.

Input methods

The input must be one of the following:

  1. An array/tuple/list/etc. of strings.
  2. OR a string containing newlines to separate lines.

Use your language's closest equivalent to the aforementioned data types if your language does not support them. (E.g., TI-BASIC doesn't support (1.)… not that TI-BASIC can compete, anyhow :P).

Test cases

A } signifies input, and the next line signifies output. Multiple }s signify newline-separated lines of text.

} Hello!

} That _2 + 2 = 5_ challenge sure was **intense!**
That  2  +  2  =  5  challenge sure was INTENSE!
    // note that there are spaces also padding it

} It's `s/a/e/g` **not** `sudo g/a/e/s`, stupid.
It's < s/a/e/g > NOT < sudo g/a/e/s >

} **WHAT!** He did _WHAT?!_
WHAT! He did W H A T ? !

} _WHAT_ is undefined, here!
 W H A T  is undefined, here!


} # So, you wanna be a programmer, eh?
} ## Step 1: learn recursion
} ### Learning recursion requires learning recursion
} **Programming** is a futile task. _Leave w h i l e you still can!_
{{Step 1: Learn Recursion}}
ʟᴇᴀʀɴɪɴɢ ʀᴇᴄᴜʀsɪᴏɴ ʀᴇǫᴜɪʀᴇs ʟᴇᴀʀɴɪɴɢ ʀᴇᴄᴜʀsɪᴏɴ
PROGRAMMING is a futile task.  L e a v e   w   h   i   l   e   y o u   s t i l l   c a n !  // trailing space not required

} Haha, you're a _Java_ golfer? You'd be better of with brainf***.
Haha, you're a  J a v a  golfer? You'd be better of with brainf***. // less than four asterisks, do nothing

} # Reasons why NOT to use C--:
} 1. It doesn't exist.
} 2. I don't care.
 1. It doesn't exist.
 2. I don't care.

} 1. This is a test!
} 1. <-- And this actually works in Markdown.
 1. This is a test!
 2. <-- And this actually works in Markdown. // less than three -s, ignore

} * no.
} * NOOO.
} * fine.
 o no.
 o NOOO.
 o fine.

} Python, ---34--- 3 bytes.
Python, -3-4- 3 bytes.

} ---Long line of crossed text.---
-L-o-n-g- -l-i-n-e- -o-f- -c-r-o-s-s-e-d- -t-e-x-t-.-

} ** cool!
** cool! // is not a bullet point, because a space doesn't follow the *; Isn't bold, because there is no matching **

 -- end of test cases --


  1. -19 bytes if you support the escaping of characters (so that they are treated as "normal"); you may choose any escape character, but I'd suggest \ or ^. Note that the escaping system on SO sites is different from what I am suggesting (and more complicated), so don't do it! SO would treat `\` as \, but I would want you to treat the second ` as then a regular character, and instead match the next ` character.
  • 2
    \$\begingroup\$ The spec is too weak for a golf question. \$\endgroup\$
    – feersum
    Oct 28, 2015 at 18:16
  • 4
    \$\begingroup\$ Thanks, downvoters, for telling me exactly what I am doing wrong. It really helps me make this question better. \$\endgroup\$ Oct 28, 2015 at 19:12
  • 4
    \$\begingroup\$ I think there are cases where applying one transformation could change whether another transformation applies. For example, ***word*** becomes * * w o r d * * after you apply the italics transformation, and suddenly the bold transformation doesn't apply. It's unclear how to handle this. \$\endgroup\$
    – Rainbolt
    Oct 28, 2015 at 19:26
  • 1
    \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ There are a number of issues noted in the comments, which have upvotes. I don't think downvoters are purposefully neglecting to provide feedback; they're likely just upvoting existing feedback. \$\endgroup\$
    – Alex A.
    Oct 28, 2015 at 19:33
  • 1
    \$\begingroup\$ @AlexA. When both downvotes occurred, no upvotes existed on the comments, neither for a period afterwards. \$\endgroup\$ Oct 28, 2015 at 20:37

1 Answer 1


Python 3, 652 640 bytes

import re
def N(o):c,t,_=o.groups();x=' -'[c<'_'];return['< %s >'%t,t.upper()][c<'`']if c in'**`'else x+x.join(t)+x
def f(s):
 while s:
  if n<={*'=-'}and n:s=s[1:];l='#'*('-'in n)+'# '+l
  if'# '==l[:2]:l='{%s}'%l[2:].upper()
  if'## '==l[:3]:l='{{%s}}'%l[3:].title()
  if'### '==l[:4]:l=''.join('ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ'[ord(c)-65]if'@'<c<'['else c for c in l[4:].upper())
  l=re.sub(('(\*\*|_|---|`)(.*?)'*2)[:-5],N,re.sub(r'^\s*[*] (.*)',r' o \1',l))
  if re.match(r'\s*\d+\. ',l):i+=1;l=re.sub(r'\s*\d+\.(.*)',' %d.'%i+r'\1',l)
 return S

Try it online!


Your Answer

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

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