# Challenge

¡We're going to give exclamation and question marks inverted buddies!

Given a body of text containing sentences ending in ., ?, or !, prepend inverted question marks, ¿, to interrogative sentences (sentences ending in ?) and inverted exclamation marks, ¡, to exclamatory (sentences ending in !). Sentences ending in . are to be ignored.

Sentences will be separated by whitespace (spaces, tabs, and/or newlines) and will only contain alphanumerics, commas, apostrophes, and spaces. Every sentence will have at least one word. The first word of every sentence is guaranteed to be capitalized. Input can start and end with any whitespace.

## Example

Input:

  Hello there!      What is your name?
My name is Ron. What's your name?
My name is Alex.  Nice to meet you!
Nice to meet you to!  How was your break?
It was great, I spent all my time code golfing!
What's that?
Wow, you're such a n00b! Here, let me show you.


Output:

  ¡Hello there!      ¿What is your name?
My name is Ron. ¿What's your name?
My name is Alex.  ¡Nice to meet you!
¡Nice to meet you to!  ¿How was your break?
¡It was great, I spent all my time code golfing!
¿What's that?
¡Wow, you're such a n00b! Here, let me show you.


## Rules

• All default Code Golf rules apply.
• The program with the shortest amount of bytes wins.

# Bonus (17% off) - Parse multiple marks

A sentence can also end in multiple exclamation/question marks. Give each of these marks a paired inverse exclamation/question mark for an extra 17% off your byte count.

## Example

Input:

I am a man in a can doing a dance?? Maybe...
Doing it for the views??!???!


Output:

¿¿I am a man in a can doing a dance?? Maybe...
¡¿¿¿¡¿¿Doing it for the views??!???!


Incorrect output:

¿¿I am a man in a can doing a dance?? Maybe...
¿¿¡¿¿¿¡Doing it for the views??!???!

• Do we get to choose what sort of whitespace separates the sentences, or do we have to support all 3 types? – Mego Dec 4 '15 at 9:00
• @Mego All three types should be supported. – usandfriends Dec 4 '15 at 9:01
• No, a sentence will always have at least one word in it and will end with one of the three allowed punctuation characters. I'll add that to the challenge. – usandfriends Dec 4 '15 at 9:04

## Retina, 3937 34 bytes

\w[^.]*?([!?])
$1$0
T?!¿¡\S\b


Try it online.

### Explanation

\w[^.]*?([!?])
$1$0


This matches a sentence ending in an exclamation or question mark, and prepends that punctuation character to the sentence. Now we know that all the ! or ? which are immediately followed by a non-space character must be those we inserted, because the original ones should be separated from the next character by a space.

T!?¡¿\S\b


This transliteration stage turns all ! and ? into ¡ and ¿, respectively, provided they're found in a match of \S\b, which applies only to the ones we just inserted. Replacing both in two separate substitutions in the same byte count, but I prefer the semantics of a transliteration stage here.

# Mathematica 137 bytes

Not the shortest, but it was fun to do.

TextSentences breaks up the input text into sentences and StringPosition finds the beginning and end positions of each sentence in the text. The upside down punctuation is inserted at the beginning of each sentence as required.

w=StringPosition;f[x_,y_,q_]:=StringInsert[x,q,x~w~y/.{a_,a_}->a/.(x~w~#&/@TextSentences@#&@x/.{{c_,d_}}:>d->c)];f[f[t,"!","¡"],"?","¿"]&


Usage, assuming the text is input at t,

f[f[#,"!","¡"],"?","¿"]&[t]


• Cool, a solution that doesn't use RegExp! – usandfriends Dec 4 '15 at 23:18

# Sed, 61 bytes

s/$$\s*$$$$[^.!?]*!$$/\1¡\2/g;s/$$\s*$$$$[^.!?]*?$$/\1¿\2/g


Test run :

$echo """Hello there! What is your name? My name is Ron. What's your name? My name is Alex. Nice to meet you! Nice to meet you to! How was your break? It was great, I spent all my time code golfing! What's that? Wow, you're such a n00b! Here, let me show you.""" | sed 's/$$\s*$$$$[^.!?]*!$$/\1¡\2/g;s/$$\s*$$$$[^.!?]*?$$/\1¿\2/g' ¡Hello there! ¿What is your name? My name is Ron. ¿What's your name? My name is Alex. ¡Nice to meet you! ¡Nice to meet you to! ¿How was your break? ¡It was great, I spent all my time code golfing! ¿What's that? ¡Wow, you're such a n00b! Here, let me show you.  • This is technically 61 bytes as the inverted characters count as 2 bytes. – usandfriends Dec 4 '15 at 20:28 • @usandfriends right, fixed – Aaron Dec 4 '15 at 22:38 • If you use the -r flag to (GNU) sed, you don't need to escape the ( and ) which should save you 8. You do need to add an extra point for use of this non-default option though. – Digital Trauma Dec 4 '15 at 23:41 • @DigitalTrauma I knew that trick and tried it but it didn't return the same output : "¿¡Hello there! ¿What is your name?¿" instead of "¡Hello there! ¿What is your name?" – Aaron Dec 5 '15 at 1:09 ## Javascript (ES6), 867966 63 bytes i=>i.replace(/\w[^.!?]*[!?]/g,k=>(k.slice(-1)>'>'?'¿':'¡')+k)  Ungolfed: func = inp => inp.replace(/\w[^.!?]*[!?]/g, sentence => (sentence.slice(-1) > '>' ? '¿' : '¡') + sentence)  Usage: console.log(func(Hello there! What is your name? My name is Ron. What's your name? My name is Alex. Nice to meet you! Nice to meet you to! How was your break? It was great, I spent all my time code golfing! What's that? Wow, you're such a n00b! Here, let me show you.))  Will implement bonus solution soon. Thanks to: @user81655, 86 => 79 bytes • A few improvements which save 9 bytes: i=>i.replace(/[A-Z][^.!?]*[.!?]/g,k=>(r=k.slice(-1))<'.'?'¡'+k:r>'.'?'¿'+k:k) – user81655 Dec 4 '15 at 12:25 • @user81655 It looks like it saves 7 bytes instead of 9, but regardless, thanks for that! Was able to remove even more bytes by skipping checking for sentences ending in .. – usandfriends Dec 4 '15 at 23:10 ## Mathematica, 10192 91 bytes StringReplace[#,RegularExpression@"[A-Z][^.]*?([?!])":><|"?"->"¿","!"->"¡"|>@"$1"<>"\$0"]&

• Would you explain how this works? – DavidC Jan 4 '16 at 21:17
• @DavidC It's tricky. – LegionMammal978 Jan 4 '16 at 21:33

# Python 2, 127.82 (154-17%) bytes

import re
print re.sub("([A-Z][\w ,']*)([\.!\?]+)",lambda m:''.join({'!':'¡','?':'¿','.':''}[c]for c in m.group(2))[::-1]+m.group(1)+m.group(2),input())


# 𝔼𝕊𝕄𝕚𝕟, 36 chars / 53 bytes

ïċ/\w⁅.!?]*[!?]⌿,⇏(aē-1>⍘>?⍘¿:⍘¡)+a)


Try it here (Firefox only).