g | x | w | all
Bytes Lang Time Link
269Charcoal250919T110040ZNeil
12305AB1E250917T135728ZKevin Cr
038Vyxal250917T020752Zlyxal

Charcoal, 269 bytes

¿ΣθI⊗θ«¿‹⌈θaF⁴F⪪”{⊞¶σ?~⧴θπ⪪λpAz” F⪪”{⊞‴▶Lc⧴d~dφW¶″” F⪪”{⊞‴ΣAº⧴θπ⪪λpAz” ⊞υ⁺⁺⁺×Mικλμ«≔⁺⟦⟦⟧⟧⪪”↶⌈ü?↑»lη+:,x&⪫⁻↘ξⅈ↔⟲▶M↖S₂υüXα◨…≡⧴~→*MZv℅№ⅈSU{+ⅉ◨·c↨Xcⅉ×|№O_U⁼züN÷5\δHDKθZ↖×” ηF⪪”↶±!κ⊖⍘~vd⎇¿Σ¦#¬J§c✳“εWWs⊞G⧴lºμ¤TCX” F…ηχ⊞η⪫Φ⟦ικ⟧λ F…ηχF…ηχFη⊞υ⪫Φ⟦⁺ι thousand⁺κ hundredλ⟧μ »§υ⊗⌕υθ

Try it online! Link is to verbose version of code. Handles Roman numerals up to MCMXCIX and English up to four thousand nine hundred ninety nine. Explanation:

¿Σθ

Are there any non-zero digits in the input?

I⊗θ«

If so, then treat it as a decimal number and double it. Otherwise:

¿‹⌈θa

If the input contains no lower case letters, then...

F⁴F⪪... F⪪... F⪪... ⊞υ⁺⁺⁺×Mικλμ«

Generate all the Roman numerals from (0) to 3999 by concatenating entries from compressed strings. Otherwise:

≔⁺⟦⟦⟧⟧⪪... η

Start with the words from one to nineteen, plus the empty list for zero.

F⪪... F…ηχ⊞η⪫Φ⟦ικ⟧λ 

Using the words from twenty to ninety, generate the numbers for twenty to ninety nine, and add those to the list.

F…ηχF…ηχFη⊞υ⪫Φ⟦⁺ι thousand⁺κ hundredλ⟧μ 

Taking the first ten numbers twice and then the numbers from (0) to 99, generate the numbers from (0) to 9999. Note that since 0 is represented by an empty list, appending a string to it vectorises and therefore does nothing, resulting in a falsy value, which is excluded from the final join.

»§υ⊗⌕υθ

Look up the position of the input and output the string that represents double that value.

05AB1E, 123 bytes

н.li“€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“#D9£U.•L¬M%*æsËCA…Å¡Ω‡íÖγ±γk·Θ•#D¦'…§«s„ty«DXâðý9ô.ι)˜„°¡±°#vD¯šXð«y«s‘ðý«}DIk>·<èë.v·Iai.X

Try it online or verify all test cases.

Explanation:

н.li          # If the first letter/digit of the (implicit) input is lowercase:
    “€µ...ý«} #  Push a list in the range ["one","nine thousand nine hundred ninty nine"]
              #  (explained separately below)
     D        #  Duplicate this list
      Ik      #  Pop one copy, and get the 0-based index of the input in it
        >·<   #  Increase it to a 1-based index; double; decrease back
           è  #  Index into the list again
              #  (after which it's output implicitly):
   ë          # Else:
    .v        #  Convert the (implicit) input from a Roman number to an integer
              #  (no-op for numbers)
      ·       #  Double it
       Iai    #  If the input only contains letters:
          .X  #   Convert it back to a Roman number
              #   (after which this Roman number is output implicitly)
              #  (implicit else: output the doubled number implicitly)

Explanation of creating the list in the range ["one","nine thousand nine hundred ninty nine"]:

“€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“
              # Push dictionary string "one two three four five six seven eight nine ten eleven twelve"
 #            # Split it on spaces to a list
  D           # Duplicate this list
   9£         # Only keep the first 9 items, removing ["ten","eleven","twelve"]
     U        # Pop and store this list in variable `X`
.•L¬M%*æsËCA…Å¡Ω‡íÖγ±γk·Θ•
              # Push compressed string "twen thir four fif six seven eigh nine"
  #           # Split it on spaces to a list
   D          # Duplicate
    ¦         # Remove the first item ("twen") from this copy
     '…§«    '# Append dictionary string "teen" to each
   s          # Swap to get the list again
    „ty«      # Append "ty" to each
D             # Duplicate this list as well
 Xâ           # Cartesian product with list `X` of range ["one","nine"]
   ðý         # Join each inner pair with space-delimiter
     9ô       # Split it into sublists of size 9
       .ι     # Interleave it with the ["twenty","ninety"] list
)             # Wrap everything on the stack into a list
 ˜            # Flatten this to a single list of strings
„°¡±°         # Push dictionary string "hundred thousand"
     #        # Split on the space
      v       # Loop over this pair:
       D      #  Duplicate the current list of strings
        ¯š    #  Prepend an empty list [] to this list of strings
        X     #  Push list `X` of range ["one","nine"]
         ð«   #  Append a space to each
           y« #  Append the current "hundred" or "thousand" to each
        s     #  Swap to get the list of strings we've duplicated
         â    #  Cartesian product
          €˜  #  Flatten each inner pair, to get rid of the [] again
          ðý  #  Join each inner pair with space-delimiter
            « #  Merge the two lists together
      }       # Close the loop

See this 05AB1E tip of mine (sections How to use the dictionary? and How to compress strings not part of the dictionary?) to understand why “€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“ is "one two three four five six seven eight nine ten eleven twelve"; .•L¬M%*æsËCA…Å¡Ω‡íÖγ±γk·Θ• is "twen thir four fif six seven eigh nine"; '…§« is "teen"; and „°¡±° is "hundred thousand".

Vyxal, 304 bitsv2, 38 bytes

∆ċ` λ¬ `ðV\-ðV\,-)£E±[Ed|ȧæ[øṘdøṘ|륆?=;ṅd¥†

Try it Online!

Bitstring:

0001010011000011011001111010101011000101111100011110000000110101000001100010100101101100101001111010001100000011011110000100011000101000111010001100110110101101111000010101100110101001001111100100101010100001010010110110011100101010110000011011101000010011001110000011101100010100011001110001110111111000

Honestly, the most annoying thing about this is the lack of punctuation in the english number format and that everything must be a string. I've range coded to compensate for how annoying it is :p.

Explained

∆ċ` λ¬ `ðV\-ðV\,-)£E±[Ed|ȧæ[øṘdøṘ|륆?=;ṅd¥†­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏⁠‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁤⁣‏⁠‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁢⁣​‎‏​⁢⁠⁡‌⁢⁤​‎‎⁡⁠⁢⁡⁤‏⁠‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁢⁢⁢‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁢⁣‏‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁢⁢⁤‏⁠‎⁡⁠⁢⁣⁡‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁢⁣⁢‏‏​⁡⁠⁡‌⁣⁤​‎‎⁡⁠⁢⁣⁣‏⁠‎⁡⁠⁢⁣⁤‏⁠‎⁡⁠⁢⁤⁡‏⁠‎⁡⁠⁢⁤⁢‏⁠‎⁡⁠⁢⁤⁣‏‏​⁡⁠⁡‌⁤⁡​‎‎⁡⁠⁢⁢⁣‏‏​⁡⁠⁡‌⁤⁢​‎‎⁡⁠⁣⁡⁡‏⁠‎⁡⁠⁣⁡⁢‏⁠‎⁡⁠⁣⁡⁣‏⁠‎⁡⁠⁣⁡⁤‏⁠‎⁡⁠⁣⁢⁡‏⁠‎⁡⁠⁣⁢⁢‏⁠‎⁡⁠⁣⁢⁣‏‏​⁡⁠⁡‌⁤⁣​‎‎⁡⁠⁣⁡⁢‏⁠‎⁡⁠⁣⁡⁣‏‏​⁡⁠⁡‌⁤⁤​‎‎⁡⁠⁣⁡⁤‏⁠‎⁡⁠⁣⁢⁡‏‏​⁡⁠⁡‌⁢⁡⁡​‎‎⁡⁠⁣⁢⁤‏⁠‎⁡⁠⁣⁣⁡‏⁠‎⁡⁠⁣⁣⁢‏‏​⁡⁠⁡‌­
∆ċ` λ¬ `ðV\-ðV\,-)£                           # ‎⁡Helper function to convert numbers to words that match the challenge criteria:
∆ċ                                            # ‎⁢  Convert the number to words. Normally, this'd be where it ends, but we have to also:
  ` λ¬ `ðV                                    # ‎⁣    Replace " and " with a space
          \-ðV                                # ‎⁤    Replace "-" with a space
              \,-                             # ‎⁢⁡    And remove any commas. The price I have to pay for having grammatically correct numbers.
                  £                           # ‎⁢⁢Store the helper in the register for later.
# ‎⁢⁣Alright, now for the juicy stuff :p
                   E±[Ed                      # ‎⁢⁤If the input is already a number, simply double it and call it a day. No special handling needed.
                      |                       # ‎⁣⁡Otherwise:
                       ȧæ                     # ‎⁣⁢Get the case of the input without spaces. Returns 1 if all uppercase, or 0 if all lowercase. I have to remove spaces otherwise all lowercase is considered mixed-case and returns -1. I want a simple 0/1.
                         [                    # ‎⁣⁣If it's all uppercase (i.e. Roman Numeral):
                          øṘdøṘ               # ‎⁣⁤  Convert from roman numerals, double, and convert back to roman numerals.
                      |                       # ‎⁤⁡Otherwise (i.e. english number):
                                륆?=;ṅ       # ‎⁤⁢  Find the first number where:
                                 ¥†           # ‎⁤⁣    Converting it to words with the helper function
                                   ?=         # ‎⁤⁤    equals the input
                                       d¥†    # ‎⁢⁡⁡  Double the result and convert it back to words with the helper function.
💎

Created with the help of Luminespire.