Normal and inverted exclamation and question mark pairs

13

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??!???!

usandfriends

Posted 2015-12-04T08:53:35.320

Reputation: 687

Do we get to choose what sort of whitespace separates the sentences, or do we have to support all 3 types? – Mego – 2015-12-04T09:00:56.043

@Mego All three types should be supported. – usandfriends – 2015-12-04T09:01:24.227

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 – 2015-12-04T09:04:11.243

Answers

5

Retina, 39 37 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.

Martin Ender

Posted 2015-12-04T08:53:35.320

Reputation: 184 808

3

Javascript (ES6), 86 79 66 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

usandfriends

Posted 2015-12-04T08:53:35.320

Reputation: 687

1A few improvements which save 9 bytes: i=>i.replace(/[A-Z][^.!?]*[.!?]/g,k=>(r=k.slice(-1))<'.'?'¡'+k:r>'.'?'¿'+k:k) – user81655 – 2015-12-04T12:25:36.247

@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 – 2015-12-04T23:10:57.683

3

Mathematica, 101 92 91 bytes

StringReplace[#,RegularExpression@"[A-Z][^.]*?([?!])":><|"?"->"¿","!"->"¡"|>@"$1"<>"$0"]&

LegionMammal978

Posted 2015-12-04T08:53:35.320

Reputation: 15 731

Would you explain how this works? – DavidC – 2016-01-04T21:17:53.407

1@DavidC It's tricky. – LegionMammal978 – 2016-01-04T21:33:23.823

3

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]

output

DavidC

Posted 2015-12-04T08:53:35.320

Reputation: 24 524

1Cool, a solution that doesn't use RegExp! – usandfriends – 2015-12-04T23:18:17.417

3

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.

Aaron

Posted 2015-12-04T08:53:35.320

Reputation: 3 689

1This is technically 61 bytes as the inverted characters count as 2 bytes. – usandfriends – 2015-12-04T20:28:34.383

@usandfriends right, fixed – Aaron – 2015-12-04T22:38:27.073

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 – 2015-12-04T23:41:12.413

@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 – 2015-12-05T01:09:23.487

1

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())

TFeld

Posted 2015-12-04T08:53:35.320

Reputation: 19 246

1

, 36 chars / 53 bytes

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

Try it here (Firefox only).

Mama Fun Roll

Posted 2015-12-04T08:53:35.320

Reputation: 7 234