11
\$\begingroup\$

The goal is really simple. Receiving a string as input, parse all the HTML entities that correspond to the following characters (including their uppercase variants):

áàãâäéèêëíìîïóòõôöúùûüýÿ

Parsing rules:

  • Each entity starts with & and ends with ;
  • The first character after the & will be the modified character (letter case is important!)
  • The remaining characters refer to the name of the accent to use (acute, grave, circ, tilde and uml). The accent name MUST be in lowercase! *
  • Any HTML entity that produces a character that isn't on that list, or that is invalid, should be left untouched (E.g.: &, &etilde;, &a;)
  • Numeric entities should be ignored, since they don't fit in the rules above

This change was introduced as of 18-02-2016. All the existing answers that accept HTML entities with uppercase accent names are valid. Any future answer must follow this rule.

Examples:

á //á
Téhèh //Téhèh
an & //an &

Output:

The output can be in ISO-8859-X (1-15), windows-1252 or UTF-8/16/32.
You can pick one and only one of the valid encodings and use it for any output. You can safely assume that the input will be in ASCII.

Any of the following is a valid output for á:

  • á (ISO-8859-1/15 or windows-1252, equivalent to \xE1)
  • á (UTF-8, equivalent to \xC3\xA1 or \u00E1)
  • (UTF-8, equivalent to a\xCC\x81 or a\u0301)
  • Any combination of diacritics, without using HTML entities.

The output has to be visually similar, when rendered/displayed, to the characters on the list.


Remember, all the standard loopholes and built-ins * are disallowed. Since this is , the shortest answer wins.

* This change was made due to the great disapproval of bonuses and penalities, and at the time of writting, doesn't invalidate any answer

\$\endgroup\$
11
  • 4
    \$\begingroup\$ I didn't vote, but I assume the downvotes are because people don't really like bonuses/penalties - They end up making one challenge into several mini-challenges. \$\endgroup\$
    – Kevin W.
    Feb 17, 2016 at 16:12
  • 1
    \$\begingroup\$ @KevinW. As I explained in the sandbox, I only left those penalities because I want to see what cool built-in stuff people can come up with. But obviously, I don't want to spoil everybody's fun. If I didn't put the penality, an answer like the Javascript example I gave, would be enough. And that required no work at all. \$\endgroup\$ Feb 17, 2016 at 16:15
  • 1
    \$\begingroup\$ IMHO, the bonuses seem arbitrary - either allow or don't allow, don't go in between. \$\endgroup\$ Feb 17, 2016 at 19:31
  • 1
    \$\begingroup\$ @IsmaelMiguel I suggest no bonuses/penalties - allow whatever programming methods they wish to use (outside of the Standard Loopholes, of course) and remove the bonuses/penalties. \$\endgroup\$ Feb 17, 2016 at 19:43
  • 2
    \$\begingroup\$ @IsmaelMiguel Nah - that was all of my cents. c: \$\endgroup\$ Feb 17, 2016 at 19:51

4 Answers 4

12
\$\begingroup\$

JavaScript (ES6), 141 122 134 bytes

a=>a.replace(/&([aeiouyAEIOUY](acute|uml)|[aeiouAEIOU](grave|circ)|[aoAO]tilde);/g,b=>b[1]+{g:"̀",a:"́",c:"̂",t:"̃",u:"̈"}[b[2]])

Followed daavko's example using diacritical marks, and I feel like an idiot for not thinking of using it sooner. Actually gets surprisingly short for JavaScript.

EDIT: Neil caught some bad cases of undefined, which are now fixed.

\$\endgroup\$
14
  • \$\begingroup\$ See? I told you that you could cut some fat! This is a really surprising answer! I trully hope you get more +1's \$\endgroup\$ Feb 17, 2016 at 19:41
  • 1
    \$\begingroup\$ This is just clever. +1 \$\endgroup\$
    – Yytsi
    Feb 17, 2016 at 20:05
  • \$\begingroup\$ I love it..! String.prototype.replace is so ridiculously golfable for string traversal. \$\endgroup\$
    – Archenoth
    Feb 17, 2016 at 23:21
  • \$\begingroup\$ I'm not convinced that this does the right thing for É (whatever that right thing is). \$\endgroup\$
    – Neil
    Feb 18, 2016 at 1:21
  • \$\begingroup\$ Sadly, @Neil is right. Uppercase HTML entities are considered invalid by browsers. But, I didn't specify that the accent name should be all in lowercase. That is entirelly my fault. I will consider this answer valid and all the ones that were already posted. But any new answer must have the accent names in lowercase. \$\endgroup\$ Feb 18, 2016 at 15:13
10
\$\begingroup\$

Retina, 115 bytes

I'm new to code-golf, but I think this might work.
This version was made before the rule, which doesn't allow replacing uppercase html entities (for example Á) was introduced.

i`&([aeiouy])acute;
$1́
i`&([aeiou])grave;
$1̀
i`&([ao])tilde;
$1̃
i`&([aeiou])circ;
$1̂
i`&([aeiouy])uml;
$1̈

Quite simple search and replace. Uses UTF-8.

Uses [letter]\xCC\x[diacritical mark hex code] approach. Diacritical mark is added after every relevant letter.

For some reason, the default Droid Sans Mono font in the interpreter can't render the "circ" and "uml" letters properly. If you change it through developer tools to something like DejaVu Sans, it shows just fine. I think this is a limitation of the font, not the program. But if it's program's fault, I'll try to fix it.

Here is a 129 byte version, which doesn't replace uppercase HTML entites (for example Á)

&([aeiouyAEIOUY])acute;
$1́
&([aeiouAEIOU])grave;
$1̀
&([aoAO])tilde;
$1̃
&([aeiouAEIOU])circ;
$1̂
&([aeiouyAEIOUY])uml;
$1̈

Try it online!
Try it online! 129-byte version

\$\endgroup\$
8
  • \$\begingroup\$ Great use of the marks there. Can't believe I didn't think of that being shorter at first >_< \$\endgroup\$
    – Mwr247
    Feb 17, 2016 at 19:26
  • \$\begingroup\$ @Mwr247 Thanks! I was searching for a way to do this, since I wanted to try to do it and the marks just showed up somewhere...I'm honestly surprised it's so short. \$\endgroup\$
    – daavko
    Feb 17, 2016 at 19:29
  • 1
    \$\begingroup\$ Nice fair-play and use of the rules! I never liked this language, but I really am loving this answer. Instant +1 \$\endgroup\$ Feb 17, 2016 at 19:39
  • \$\begingroup\$ I counted 115 bytes (110 characters + 5 extra bytes for the marks). \$\endgroup\$
    – Mwr247
    Feb 17, 2016 at 19:51
  • \$\begingroup\$ @Mwr247 Oh, you're right. I just pasted it into a text document and ran ls -l and it showed 116...seems the editor added an extra newline at the end. I'll fix it. \$\endgroup\$
    – daavko
    Feb 17, 2016 at 19:55
4
\$\begingroup\$

Japt, 81 75 bytes

Ur`&([%vYy](ac©e|uml)|%v(g?ve|circ)|[AaOo]Èìe);`@Yg +'Ì+"?????"g"gutca"bYgJ

The six ?s represent unprintable chars. Test it online!

Note: This outputs the third encoding option; that is, the letter followed by the raw UTF-8 encoding of the corresponding combining diacritical mark.

How it works

Ur"&(    );"       // Replace each ampersand and semicolon that have one of these between them:
([%vYy](acute|uml) //  A vowel or Yy followed by "acute" or "uml",
|%v(grave|circ)    //  or a vowel followed by "grave" or "circ",
|[AaOo]tilde       //  or "a" or "o" followed by "tilde";
@                  // replace each match X and its middle Y with this function:
""g"gutca"bYgJ     //  Take the unprintable at index (index of the second char in Y in "gutca") in this string.
Yg +'Ì+            //  Concatenate the first char in Y and "Ì" to the beginning.
                   // Implicit output

Hexdump of the code:

00000000: 55 72 60 26 28 5b 25 76 59 79 5d 28 61 63 a9 65  Ur`&([%vYy](ac©e
00000010: 7c 75 6d 6c 29 7c 25 76 28 67 9f 76 65 7c 63 69  |uml)|%v(g.ve|ci
00000020: 72 63 29 7c 5b 41 61 4f 6f 5d c8 ec 65 29 3b 60  rc)|[AaOo]Èìe);`
00000030: 40 59 67 20 2b 27 cc 2b 22 80 81 82 83 88 22 67  @Yg +'Ì+"....."g
00000040: 22 67 75 74 63 61 22 62 59 67 4a                 "gutca"bYgJ
\$\endgroup\$
5
  • \$\begingroup\$ It seems to work nicely. Can you please provide a hexdump? You seem to have there some "weird" characters that may not work in every encoding. \$\endgroup\$ Feb 17, 2016 at 20:20
  • \$\begingroup\$ @IsmaelMiguel I've just realized that the accents are not part of the ISO-8859-1 encoding; thus, I've uncompressed the string and switched to UTF-8 bytes. Would you still like a hexdump? \$\endgroup\$ Feb 17, 2016 at 20:27
  • \$\begingroup\$ Up to you, but your previous solution was perfectly fine. \$\endgroup\$ Feb 17, 2016 at 20:31
  • \$\begingroup\$ I think you might have a tiny bug there, your code seems to leave &Yacute; alone, but it should be changed to Ý... \$\endgroup\$
    – daavko
    Feb 17, 2016 at 20:32
  • \$\begingroup\$ @daavko Whoops, you're right! Fixed now. \$\endgroup\$ Feb 17, 2016 at 20:35
3
\$\begingroup\$

JavaScript (ES6), 288 bytes

a=>(z=(b,c=1,d=2,e=3,f=0,g=4)=>({b:b+191,grave:c,acute:d,circ:e,tilde:f,uml:g}),y={a:z(0,1,2,3,4,5),e:z(8),i:z(12),o:z(18,1,2,3,4,5),u:z(25),y:z(28,0,2,0)},a.replace(/&\w+;/gi,b=>(x=y[b[1].toLowerCase()])&&(w=x[b.slice(2,-1)])?String.fromCharCode(x.b+w+32*(b[1]>'_')+153*/Yu/.test(b)):b))

Creates a character map object (with the base numeric code for each character), and uses offsets (or 0 if non-existent) to determine if an entity should be converted and what it's character code is. Symmetry in the cases means adding 32 if lowercase, except for &Yuml;, where it uses a different offset for UTF8.

\$\endgroup\$
8
  • \$\begingroup\$ Nice! I really like your aproach, but 286 bytes is a bit long. Maybe there are a few things that can be cut off? Trimming some fat would be great \$\endgroup\$ Feb 17, 2016 at 17:32
  • \$\begingroup\$ @IsmaelMiguel 288 actually; I just realized that there is in fact a &Yuml; in UTF8: it's just in a weird place. All the same, I thought I condensed and optimized it rather well, considering a literal replace list would be over twice as long. Are you seeing something I'm not? \$\endgroup\$
    – Mwr247
    Feb 17, 2016 at 17:46
  • \$\begingroup\$ Not really... There must be a better way to make lowercase letters than using .toLowerCase(). That name is HUGE!!! Also, String.fromCharCode can accept multiple parameters, or be called as String.fromCharCode.call([...]) \$\endgroup\$ Feb 17, 2016 at 17:51
  • 1
    \$\begingroup\$ @IsmaelMiguel Seems I was right about it needing a rewrite, but wrong about it needing to be someone else. I feel this answer is more interesting, but the other one is technically more concise, so I've included them both separately. \$\endgroup\$
    – Mwr247
    Feb 17, 2016 at 18:57
  • 1
    \$\begingroup\$ Not life-changing but your regexp contains no literal letters so it doesn't need the i flag. \$\endgroup\$
    – Neil
    Feb 18, 2016 at 1:25

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.