Introduction

Try to convert words to two different unicode fonts.

Challenge

Your task is to transform your input string into the 𝖬𝖺𝗍𝗁 𝖲𝖺𝗇𝗌 and 𝗠𝗮𝘁𝗵 𝗦𝗮𝗻𝘀 𝗕𝗼𝗹𝗱 unicode characters.

All uppercase words should become lowercase 𝗠𝗮𝘁𝗵 𝗦𝗮𝗻𝘀 𝗕𝗼𝗹𝗱 words.

• For Example: WORD -> 𝘄𝗼𝗿𝗱

All lowercase words should become 𝖬𝖺𝗍𝗁 𝖲𝖺𝗇𝗌 words

• For example: other words -> 𝗈𝗍𝗁𝖾𝗋 𝗐𝗈𝗋𝖽𝗌

All mixed case words should remain unchanged

• For example: Mixed Case Words -> Mixed Case Words

Periods and spaces should remain unchanged.

Words are separated by spaces or periods

• For example (highlighted things are words):

Hello. This is a word. S.O. are these

• Inputs: A string containing letters, spaces, and periods ([A-Za-z .]+)
• Output: The formatted string

As this is a golfing challenge, the lowest number of bytes wins

Example Input and Output

Input:

This is an example STRING that c.o.U.L.d. be INPUTTED. It can CONTAIN multiple sentences.

Output:

This 𝗂𝗌 𝖺𝗇 𝖾𝗑𝖺𝗆𝗉𝗅𝖾 𝘀𝘁𝗿𝗶𝗻𝗴 𝗍𝗁𝖺𝗍 𝖼.𝗈.𝘂.𝗹.𝖽. 𝖻𝖾 𝗶𝗻𝗽𝘂𝘁𝘁𝗲𝗱. It 𝖼𝖺𝗇 𝗰𝗼𝗻𝘁𝗮𝗶𝗻 𝗆𝗎𝗅𝗍𝗂𝗉𝗅𝖾 𝗌𝖾𝗇𝗍𝖾𝗇𝖼𝖾𝗌.

Reference

Math Sans Bold: 𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇 (characters 120302 through 120327)

Math Sans: 𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓 (characters 120250 through 120275)

• Welcome to PPCG! – Laikoni Jan 25 '18 at 23:26
• ♫ Philosophy's just 𝗆𝖺𝗍𝗁 𝗌𝖺𝗇𝗌 rigor, sense, and practicality... ♫ – Esolanging Fruit Jan 26 '18 at 5:12
• Whoa! You got a title in bold in the sidebar? What? I... don't understand.... is the internet breaking? Have you broken the internet? – Zizouz212 Jan 26 '18 at 6:38
• i.stack.imgur.com/R4V3C.png I came here thinking this challenge was about stacking boxes, bar charts or something... – Matteo Italia Jan 26 '18 at 7:29
• This shouldn't have been close hammered. This problem is significantly more difficult than a simple character transliteration. The leading answer in the cited challenge can not easily nor competitively be transferred using that same method (afaict, my retina isn't great) – Conor O'Brien Jan 26 '18 at 15:20

-2 thanks to ngn.

\w+
⎕UCS a+(2>≢b)×120153+84×⊃b←∪96>a←⎕UCS⍵M


Since TIO scrambles Unicode output from QuadR, here is a screenshot of using QuadR as an APL library in an interactive session:

\w+ replace words with the result of applying the following code to them:

⍵M the found word
⎕UCS the Universal Character Set code points of that
a← store that in a
96> 0 or 1 for whether 96 is greater than each of those
∪ take just the unique; [0] or [1] or [0,1] or [1,0]
b← store that in b
⊃ pick the first from that
84× multiply 84 with that
120153+ add 120153 to that
()× multiply the following with that:
≢b the tally (length) of b (1 if single-case, 2 if mixed-case)
2> 0 or 1 for whether two is greater than that (1 if single-case, 0 if mixed-case)
a+ the original code points added to that
⎕UCS convert the resulting code points back to characters

APL (Dyalog Unicode), 6357 53 bytes

-6 thanks to Erik the Outgolfer. -4 thanks to ngn.

Anonymous tacit prefix function.

'\w+'⎕R{⎕UCS a+(2>≢b)×120153+84×⊃b←∪96>a←⎕UCS⍵.Match}


Since TIO scrambles Unicode output from Dyalog APL, here is a screenshot of the code in action:

'\w+'⎕R PCRE Replace words with the result of applying the following…

{...} anonymous lambda:

⍵.Match the found word

⎕UCS the Universal Character Set code points of that

a← store that in a

96> 0 or 1 for whether 96 is greater than each of those

∪ take just the unique; [0] or [1] or [0,1] or [1,0]

b← store that in b

⊃ pick the first from that

84× multiply 84 with that

120153+ add 120153 to that

()× multiply the following with that:

≢b the tally (length) of b (1 if single-case, 2 if mixed-case)

2> 0 or 1 for whether two is greater than that (1 if single-case, 0 if mixed-case)

a+ the original code points added to that

⎕UCS convert the resulting code points back to characters

• 57 bytes: '\b([A-Z]+|[a-z]+)\b'⎕R{⎕UCS(⎕UCS+120153+84×∊∘⎕A)⍵.Match} – Erik the Outgolfer Feb 20 '18 at 12:55
• @EriktheOutgolfer Thanks. Why didn't I think of going tacit‽ – Adám Feb 20 '18 at 14:36
• I don't know, but it happens to me when I'm tired. :) – Erik the Outgolfer Feb 20 '18 at 14:39
• @EriktheOutgolfer Actually, I think I wrote this one from home using my wife's computer without APL keyboard layout… – Adám Feb 20 '18 at 14:47
• @Adám that regex is too long; you're better off using \w+ and computing the amount to add to the codepoints in the dfn: '\w+'⎕R{⎕UCS a+(2>≢b)×120153+84×⊃b←∪96>a←⎕UCS⍵.Match} – ngn Feb 20 '18 at 20:27

Clean, 268265232 224 bytes

As a neat bonus, this works with strings containing any character. Including nulls.

import StdLib,StdInt,StdBool,Text.Unicode,Text.Unicode.UChar
u=isUpper
l=isAlpha
$c|l c=fromInt(toInt c+120153+if(u c)84 0)=c ?[h,s:t]=[if(u h<>isLower s)($c)c\\c<-[h,s:t]]

Jelly, 34 bytes

e€ØBŒg
ṁÇµŒl,Œuiị“¡ẓƬ“¡ẓġ“’×Ç+OỌµ€


Try it online!

Full program.

• It's probably obvious to professional Jellyists, but could you add a brief explanation to show ẇƬƒ is going on here? – Mick Mnemonic Jan 26 '18 at 23:21
• @MickMnemonic sorry, right now I don't have time to – Erik the Outgolfer Jan 26 '18 at 23:29

Retina, 84 bytes

/\b[A-Z]+\b/_(.
ĵ$& )TLۮ-܇ /\b[a-z]+\b/_(. ĵ$&
)Tlں-ۓ
Tÿ-߿퟿-


Try it online! Explanation: Retina is a .NET application and therefore works in UTF-16 internally. Unfortunately as the Math Sans characters aren't in the BMP I can't directly transliterate them because the number of code points differs. Worse, I can't use unpaired surrogates at all. Instead, I shift the appropriate words into characters in the range 0xFF-0x7FF which conveniently only take two bytes to encode, plus I also prefix them with the 0x135 character. Finally I map that range onto the a range that overlaps the unpaired surrogates, creating valid BMP pairs.

Python 3, 173122 120 bytes

lambda s:''.join(chr(ord(c)+120153*t.islower()+120237*t.isupper())for t in re.split(r'\b(\w+)\b',s)for c in t)
import re


-51 bytes from ShreevatsaR

-2 bytes from abccd

Try it online!

Splits on word boundaries (re.split(r'\b(\w+)\b',s)), then maps lowercase words to 𝗅𝗈𝗐𝖾𝗋𝖼𝖺𝗌𝖾 𝗆𝖺𝗍𝗁 𝗌𝖺𝗇𝗌 (+120153*t.islower()), and uppercase words to 𝗯𝗼𝗹𝗱 𝗺𝗮𝘁𝗵 𝘀𝗮𝗻𝘀 (+120237*t.isupper()), and leaves mixed-case words alone, then joins the words back up.

Ungolfed and un-lambda-ed:

def f(s):
words = re.split(r'\b(\w+)\b', s)
ret = ''
for word in words:
for char in word:
if word.isupper():
ret += chr(ord(c) + 120237)
elif word.islower():
ret += chr(ord(c) + 120153)
else:
ret += c
return ret

• could it be less bytes if you set a variable to either 120237 or 120153 depending on if it was upper or lower? It looks like it might – pfg Jan 26 '18 at 19:08
• @pfg Indeed, can easily shave off 13 bytes (down to 160). – ShreevatsaR Jan 26 '18 at 20:10
• @pfg Actually, replacing the map-lambda with (easier to read) comprehensions brings it down to 149 bytes. – ShreevatsaR Jan 26 '18 at 20:18
• 122 :-) I'll stop here; quite proud of how golfing it further has made it easier to read. Only in Python! – ShreevatsaR Jan 26 '18 at 21:20
• -2 by getting rid of spaces before for – abccd Jan 27 '18 at 6:00

Japt, 343332 31 bytes

Includes an unprintable (charcode 153) after the last #.

rV="%b%A+%b"Èc+#x#í
rVv Èc+#x#


Try it

Explanation

                        :Implicit input of string U
r                       :Replace
"%b%A+%b"            :/\b[A-Z]+\b/g
V=                     :Assign ^that to variable V
È           :Run each match through a function
c          :Map over the codepoints of the current match
\n                      :Assign the result of that replacement to variable U
rVv                     :Another replacement, this time with V lowercased to give us the RegEx /\b[a-z]+\b/g
Èc+#x#              :And, again, map over the codepoints of each match, this time adding 120153 to each


Original 32 Byte Japt v2 Solution

r/\b(\A+|\a+)\b/Èc_+#x#+#T*(X¶u


Try it

r                                     :Replace
/\b(\A+|\a+)\b/                      :...all matches of this RegEx (\A=[A-Z], \a=[a-z])
È                     :Pass each match through a function, with X being the current match
c_                   :Pass the codepoints of X through a function
+                  :Add to the current codepoint
#x#               :120153 (there's an unprintable after the second #)
+#T           :Plus 84
*          :  Multiplied by
(X¶u      :  Is X equal to its uppercase self

• Mind adding an XXD dump? – Stan Strum Jan 27 '18 at 5:15
• A reversible hexdump? For the unprintables. – Stan Strum Jan 27 '18 at 22:26

05AB1E, 33 bytes

€aγ€g£εÐ.u•1Ù„•*s.l•1Ùm•*+sÇ+çJ}J


Try it online!

JavaScript (ES6), 99114 113 bytes

s=>s.replace(/\b([A-Z]+|[a-z]+)\b/g,e=>e.replace(/./g,f=>String.fromCodePoint(f.charCodeAt()+120153+(f<'a')*84)))


(Thanks to @pfg for pointing out an important flaw in my first solution.)

-1 bytes thanks to @Neil.

Snippet:

let f =

s=>s.replace(/\b([A-Z]+|[a-z]+)\b/g,e=>e.replace(/./g,f=>String.fromCodePoint(f.charCodeAt()+120153+(f<'a')*84)))

d.innerHTML=f('This is an example STRING that c.o.U.L.d. be INPUTTED. It can CONTAIN multiple sentences.');
<p id="d">

• This only works with the HTML because of the &#, to do it with pure JS you would need to use String.fromCodePoint(120237) which would increase the size – pfg Jan 26 '18 at 21:30
• Don't yet grok that, but I'll come back to it later, thanks. – Rick Hitchcock Jan 26 '18 at 21:33
• let a = s=>s.replace(/\b([A-Z]+|[a-z]+)\b/g,e=>e.replace(/./g,f=>String.fromCodePoint(f.charCodeAt(0)+120153+(f<'a')*84))) works pure JS but adds many extra bytes – pfg Jan 26 '18 at 21:33
• Ah, I understand! Daggum. – Rick Hitchcock Jan 26 '18 at 21:38
• Save 1 byte by using charCodeAt() without the 0. – Neil Jan 27 '18 at 0:22