25
\$\begingroup\$

Write a program or function that, given a string, will strip it of zalgo, if any exists.

Zalgo

For this post, zalgo is defined as any character from the following Unicode ranges:

  • Combining Diacritical Marks (0300–036F)
  • Combining Diacritical Marks Extended (1AB0–1AFF)
  • Combining Diacritical Marks Supplement (1DC0–1DFF)
  • Combining Diacritical Marks for Symbols (20D0–20FF)
  • Combining Half Marks (FE20–FE2F)

https://en.wikipedia.org/wiki/Combining_character#Unicode_ranges

Input

  • May be passed via command line arguments, STDIN, or any other standard method of input supported by your language
  • Will be a string that may or may not contain zalgo or other non-ASCII characters

Output

Output should be a string that does not contain any zalgo.

Test Cases

Input -> Output

HE̸͚ͦ ̓C͉Õ̗͕M͙͌͆E̋̃ͥT̠͕͌H̤̯͛ -> HE COMETH
C͉̊od̓e͔͝ ̆G̀̑ͧo͜l͔̯͊f͉͍ -> Code Golf
aaaͧͩa͕̰ȃ̘͕aa̚͢͝aa͗̿͢ -> aaaaaaaaa
ññ        -> ñn
⚡⃤       -> ⚡

Scoring

As this is , shortest answer in bytes wins.

\$\endgroup\$
  • 3
    \$\begingroup\$ Is the string guaranteed to only contain ASCII and/or Zalgo? Or may it contain other unicode? \$\endgroup\$ – DJMcMayhem May 6 '17 at 19:00
  • 4
    \$\begingroup\$ What about legitimate uses of those characters? Zalgo is pretty much only when those characters stack with each other in a way that was never intended. \$\endgroup\$ – Draco18s May 6 '17 at 19:16
  • \$\begingroup\$ @DJMcMayhem The input string may have other non-ASCII characters that must not be removed. \$\endgroup\$ – totallyhuman May 6 '17 at 19:16
  • 1
    \$\begingroup\$ @totallyhuman I was thinking a more generic approach: only stripping if more than one occurs after a "standard" character. That is is fine but a͕̰ gets stripped to a. (Also now, thanks to the emoji detector, I want to put diacritics on emoji...🤔̘͕̑ pfft, that looks silly) \$\endgroup\$ – Draco18s May 6 '17 at 19:25
  • 2
    \$\begingroup\$ You should add some test cases with non-ASCII output. \$\endgroup\$ – xnor May 6 '17 at 22:02

11 Answers 11

13
\$\begingroup\$

Retina, 35 bytes

T`̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯

Try it online!

Simply removes all characters in the ranges given in the challenge from the input. The code is super unreadable of course, but the code is conceptually no different from something like T`0-9A-Za-z which would delete all alphanumeric characters.

\$\endgroup\$
  • 3
    \$\begingroup\$ Seems unbeatable enough to me. \$\endgroup\$ – Erik the Outgolfer May 6 '17 at 20:12
  • \$\begingroup\$ @EriktheOutgolfer I don't know, I think Jelly might be able to generate the code point ranges more efficiently than just listing the characters. \$\endgroup\$ – Martin Ender May 6 '17 at 20:13
  • \$\begingroup\$ Actually I don't think it's able to. \$\endgroup\$ – Erik the Outgolfer May 6 '17 at 20:27
  • \$\begingroup\$ I'm surprised there is no Jelly solution yet. \$\endgroup\$ – totallyhuman May 7 '17 at 23:00
  • \$\begingroup\$ @icrieverytim here, and rip it's longer. I haven't figured out how to generate codepoints more effectively than this :P \$\endgroup\$ – HyperNeutrino Sep 14 '17 at 12:20
7
\$\begingroup\$

Python 3, 73 69 bytes

-4 bytes thanks to L3viathan.

Not sure if participating in your own challenge is ok or not but... Stole the regex and essentially the idea as well >< straight from the JS and Retina answers.

lambda s:re.sub('[̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯]','',s)
import re

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Save 4 bytes by making that a normal import statement. \$\endgroup\$ – L3viathan May 6 '17 at 21:54
  • \$\begingroup\$ You forgot to update the byte count. \$\endgroup\$ – xnor May 6 '17 at 22:15
  • \$\begingroup\$ @xnor Huh? Seems right to me. \$\endgroup\$ – totallyhuman May 7 '17 at 0:26
  • \$\begingroup\$ @totallyhuman My mistake, missed that those char are multibyte. \$\endgroup\$ – xnor May 7 '17 at 0:43
  • \$\begingroup\$ Well, it's fair to say that I stole the character range from the Retina answer. (With care though, since my editor wanted to remove the zalgo along with the `.) \$\endgroup\$ – Neil May 7 '17 at 9:40
4
\$\begingroup\$

JavaScript (ES6), 55 bytes

f=
s=>s.replace(/[̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯]/g,'')
<textarea oninput=o.textContent=f(this.value)></textarea><pre id=o>

\$\endgroup\$
4
\$\begingroup\$

Japt, 37 bytes

r"[̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯]

Try it online!

\$\endgroup\$
4
\$\begingroup\$

PHP, 67 Bytes

shorter as the write out

<?=preg_replace("#[̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯]#u","",$argn);

Try it online!

PHP, 115 Bytes

<?=preg_replace("#[\u{300}-\u{36f}\u{1ab0}-\u{1aff}\u{1dc0}-\u{1dff}\u{20d0}-\u{20ff}\u{fe20}-\u{fe2f}]#u","",$argn);

Try it online!

PHP, 35 Bytes

Valid for the given Testcases it removes all Marks

<?=preg_replace("#\pM#u","",$argn);

Try it online!

\$\endgroup\$
  • \$\begingroup\$ @FelixDombek No it replaces only all Marks in the given ranges with nothing \$\endgroup\$ – Jörg Hülsermann May 7 '17 at 12:31
3
\$\begingroup\$

Python 3, 127 118 bytes

Just a straightforward answer for now, let's see how golfable it is.

lambda y:"".join(chr(x)for x in map(ord,y)if not(767<x<880or 6831<x<6912or 7615<x<7680or 8399<x<8448or 65055<x<65072))

Changelog:

  • When will I ever learn that comprehensions are shorter than functional stuff (-9 bytes).
\$\endgroup\$
  • \$\begingroup\$ 0or is not a thing, so you have to fix it or it will raise SyntaxError. \$\endgroup\$ – Erik the Outgolfer May 6 '17 at 20:01
  • 2
    \$\begingroup\$ @EriktheOutgolfer Did you actually test it? Doesn't throw an error for me on neither Python 3 nor 2. \$\endgroup\$ – L3viathan May 6 '17 at 20:09
  • \$\begingroup\$ Oh right. I was confused for a bit. \$\endgroup\$ – Erik the Outgolfer May 6 '17 at 20:11
3
\$\begingroup\$

Bash + coreutils, 41

tr -d '̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯'

Simply strips out characters in the given ranges.

Try it online.

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Unicode), 43 bytes

'[̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯]'⎕R''

Try it online!

PCRE Replace all those with nothing


44 byte version not using RegEx or strange character literals (and thus single byte per character):

⍞~⎕UCS∊65055 8399 7615 6831 767+⍳¨16×2 6~⍨⍳7

Try it online! ⍳7 1…7 (1 2 3 4 5 6 7)

2 6~⍨ except 2 and 6 (1 3 4 5 7)

16× multiply by 16 (16 48 64 80 112)

⍳¨ 1… each (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16, 1 2 3…, …110 111 112)

+ add offset to each list (65056 65057 65058…, …877 878 879)

 enlist (flatten)

⎕UCS convert to corresponding Unicode character

⍞~ get text input and remove all such characters

\$\endgroup\$
2
\$\begingroup\$

Jelly, 32 bytes

“Żȷ'⁺¦60ƭṖ_WTɦ7Ụ|ṫYɠF’bȷ5r2/FỌḟ@

Try it online!

Explanation

“Żȷ'⁺¦60ƭṖ_WTɦ7Ụ|ṫYɠF’bȷ5r2/FỌḟ@  Main link
“Żȷ'⁺¦60ƭṖ_WTɦ7Ụ|ṫYɠF’            Base 250 compressed integer; 768008790683206911076160767908400084476505665071
                      bȷ5         Convert into base 100000; [768, 879, 6832, 6911, 7616, 7679, 8400, 8447, 65056, 65071]
                         r2/      Inclusive range on non-overlapping slices of length 2
                            F     Flatten
                             Ọ    chr; cast to character from codepoints
                              ḟ@  Filter; remove all characters from input that are in the characters generated before
\$\endgroup\$
  • \$\begingroup\$ o0 Didn't realize I bumped this question up lol. Is that b65072 what I think it is? :o \$\endgroup\$ – totallyhuman Sep 14 '17 at 12:21
  • \$\begingroup\$ @icrieverytim yes numerical list compression :D \$\endgroup\$ – HyperNeutrino Sep 14 '17 at 12:23
  • \$\begingroup\$ jelly is definitely the most zalgo language. i wonder what would happen if you ran the program on its own code? edit: unfortunately nothing \$\endgroup\$ – space junk Sep 14 '17 at 13:15
1
\$\begingroup\$

Java 8, 57 bytes

s->s.replaceAll("[̀-ͯ᪰-᫿᷀-᷿⃐-⃿︠-︯]","")

Try it here.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 32 bytes

•3xIαEλ¤’ä₆Ćkмм`0Â9"´•žHв2ôvyŸçK

Try it online!

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