# Gif - Jif, Jif - Gif

Stolen from @Downgoat with permission

The point of this challenge is to (not) settle the debate on the pronunciation of "gif".

"

The pronunciation of gif is debated and while it's supposed to be (and should be) pronounced jif, it's still commonly disputed.

In this challenge you will be given a set of words that have a g or j, representing the sound that the word is pronounced with. You'll also get some text in which you have to fix the incorrect spellings of gif.

Because this is the internet and everyone always wrong. It's (not) common courtesy to correct them.

An example of a wrong pronunciation would be:

There was a gif of a mouse eating a burrito

The wrong spelling of gif? Unacceptable! This must be corrected immediately:

There was a jif (as in jar) of a mouse eating a burrito

Are we done? Nope, you're still wrong.

You're always wrong

This must work the other way:

In the jif the cat wore a hat of a cat

This obvious misspelling must be fixed, we shall correct this to:

In the gif (as in graphic) the cat wore a hat of a cat

### Rules

• Input is a string (the sentence) and an array of strings (or any reasonable alternative, such as a comma separated string) in any order
• You may take the g and j words in any order. They may be taken separately.
• Every instance of gif (any case) in the sentence must be replaced with jif (as in ___) where ___ is a uniformly random selected word beginning with j from the array of strings, and vice versa for jif with words beginning with g.
• ONLY the words gif and jif should be replaced (i.e "jiffy" should not be changed). Those words have done no wrong.
• You are guaranteed that at least one word in the array begins with g and at least one begins with j.
• Case must be preserved (e.g. GiF -> JiF).
• You may write a program or a function
• Standard loopholes apply
• We need to (not) settle the debate quickly; shortest code in bytes wins

### Examples

Input and output separated by a single line:

graphic, jar, jam, gram
I saw a jif of how to pronounce gif that showed gif is pronounced jif

I saw a gif (as in graphic) of how to pronounce jif (as in jar) that showed jif (as in jam) is pronounced gif (as in gram)

gravy, jeff
G is for gIf, h is for JiF, i is for gIF, j is for JIf

G is for jIf (as in jeff), h is for GiF (as in gravy), i is for jIF (as in jeff), j is for JIf (as in gravy)

joke, june, gorilla, great
Jiffy should not be treated as a GIF or JIF, like gifted.

Jiffy should not be treated as a JIF (as in june) or GIF (as in great), like gifted.

• The pronunciation of gif is debated and while it's supposed to be (and should be) pronounced **gif,** it's still commonly disputed. FTFY ;) – Draco18s no longer trusts SE Jun 22 '17 at 21:05
• Giraffical Interchange Format :) – Mikhail V Jun 22 '17 at 22:23
• (The G is silent.) – David Conrad Jun 23 '17 at 2:06
• It's obviously jif as in Johan. Like the sound furries make. – R.. GitHub STOP HELPING ICE Jun 23 '17 at 3:17
• Tempted to downvote because it’s pronounced with a g and NOT A J – Stan Strum Dec 7 '17 at 18:26

## Mathematica, 164 165 bytes

This is an abomination, but I want someone to share my pain.

StringReplace[f[f@"g"="j"]="g";f[f@"G"="J"]="G";z=IgnoreCase->1>0;#,x:"g"|"j"~~y:"if ":>{f@x,y,"(as in ",RandomChoice@StringCases[#2,f@x~~Except[","]..,z]}<>") ",z]&


Function which expects the first argument # to be the sentence to be (in)corrected and the second argument #2 to a be comma separated string of words.

f[f@"g"="j"]="g";f[f@"G"="J"]="G" defines a function f which takes the letters g, G, j, and J to their appropriate replacements. This is ever so slightly shorter than f@"g"="j";f@"j"="g";f@"G"="J";f@"J"="G".

I also set z equal to IgnoreCase->True since I'll be using it twice.

x:"g"|"j"~~y:"if " is a StringExpression which matches "gif " or "jif ", naming the first letter x and the last three characters y. Since the option z (also known as IgnoreCase->True) is passed to StringReplace, these letters can be in any combination of upper and lower case.

I then replace every such match with

{f@x,y,"(as in ",RandomChoice@StringCases[#2,f@x~~Except[","]..,z]}<>") "


RandomChoice@StringCases[#2,f@x~~Except[","]..,z] randomly selects a word out of the second argument #2 which begins with f[x], again ignoring case because the option z is given.

• Why would you use Mathematica for this? Wow. – Neil A. Jun 22 '17 at 23:08
• IgnoreCase->True => IgnoreCase->1<2 – CalculatorFeline Jun 22 '17 at 23:38
• @CalculatorFeline I actually already abbreviated True to 1>0, just not in my explanation :) – ngenisis Jun 22 '17 at 23:40
• You use fully golfed code sinppets everywhere else. Why not there? – CalculatorFeline Jun 22 '17 at 23:41
• @CalculatorFeline I guess because in that case I wasn't quoting the code, I was describing what it did, which was to set the variable z equal to IgnoreCase->True. I did the same thing later: "which begins with f[x]" . ¯\_(ツ)_/¯ – ngenisis Jun 23 '17 at 0:16

# Ruby, 8887 91 bytes

-1 byte from ETHproductions. +4 bytes because words containing "gif" or "jif" shouldn't be replaced. -2 bytes because replacement word lists can be taken separately now.

->s,g,j{s.gsub(/\b(g|j)if\b/i){$&.tr("GgJj","JjGg")+" (as in #{($1[/g/i]?j:g).sample})"}}


Try it online!

• Could you change ([gj]) to (g|j)? (idk much Ruby but I do know regex) – ETHproductions Jun 22 '17 at 21:33

# CJam, 78 bytes

l',%:A;lS%{_ela"gifjif"3/&{_V=_el:B'g=1W?Z*+V\t" (as in "A{V=elB=!},mR')}O?S}%


Try it online!

Requires the list of replacement characters to be separated by nothing but commas.

Explanation:

l',%                        e# read line of input and split at commas
:A;                     e# store in var A and pop off the stack
lS%{...}%            e# for each word in the next line of input so:

_ela"gifjif"3/&             e#   intersection of ["gif" "jif"] and [lowercase(word)]
{...}O?      e#   if set it non-empty, run block below, otherwise do nothing (push empty string)
S     e#   push space

_V=                         e#     extract first char
_el:B                    e#     duplicate to lowercase and store in var B
'g=1W?Z*+           e#     convert g/G <=> j/J
V\t        e#     store back to word
" (as in "                  e#     push string
A{V=elB=!},      e#     filter replacements by words starting with the same char (case insensitive)
mR    e#     select random element
')  e#     push ')' char

• Doesn't work on the example where gif/jif is followed by a comma. – Michael Boger Dec 7 '17 at 0:22

# Python 3, 237 bytes

lambda s,g,j:' '.join([(w if False in(w[0]in q,w[1:2]in['i','I'],w[2:3]in['f','F'],w[3:]in",;!?.")else q[w[0]]+w[1:3]+" (as in "+choice(g if w[0]in 'jJ'else j)+')'+w[3:])for w in s.split()])
from random import*
q=dict(zip("gGjJ","jJgG"))


Try it online!

This is the best I can do -- might be some way to do it quicker (probably with regexes) but my brain hurts now.

Explanation: q is a simple dictionary mapping, I hope that's clear. s,g,j are the input string, the list of g-words, and the list of j-words. ' '.join joins together the list comprehension done across for w in s.split() is therefore for the list of words in s.

The middle bit is black magic, which I'll break down piecewise. First, the condition: False in(w[0]in q,w[1:2]in['i','I'],w[2:3]in['f','F'],w[3:]in",;!.").

w[0]in q checks the first character is in the keys of q which are 'g','G','j','J'. The reason for separating out q as a variable is we also use it as a dict/map later.

w[1:2]in ['i','I'] checks that the second character is either i or I. The :2 is necessary because just putting w[1] would result in a crash on 1-letter words, but slices don't do that for some reason (I thought they did, whatever!)

w[2:3]in ['f','F'] is analogous. I briefly had this as just 2: before I realized I needed to account for gif, or jif, followed by punctuation!

w[3:]in",;!?." checks that the subsequent character(s) are punctuation. I admit my code doesn't work if someone puts 'gif?!' but I can't be perfect. Someone else can take up the challenge of opening quotes before gif or jif, too.

False in(,,,) is basically a big NAND. It's actually the same bytecount as separating four items with and and swapping the arguments, but this looks cooler and works better if you have to extend it to a fifth anded thing.

w if means that if False is in the conditional-list, we just return the word unchanged -- it doesn't meet our criteria. else, we change it to:

q[w[0]]+w[1:3]+" (as in "+choice(g if w[0]in 'jJ'else j)+')'+w[3:]

OK. q[w[0]] substitutes the first letter correctly. w[1:3] tacks on the i or I and f or F, w[3:] tacks on any trailing punctuation. That leaves the as in clause.

" (as in "+choice(g if w[0]in 'jJ'else j)+')' puts in the obvious string literal at the start and the trailing parenthesis, the interesting bit here is choice(g if w[0]in 'jJ'else j) which randomly chooses from g or j, depending on if w[0] is in 'jJ'. and I just realized I had this bit backwards so fixing that throughout, done.

It's been a long day. choice is in the random module hence the import. I think that's everything.

(s,g,j,r=l=>l[Math.random()*l.length|0])=>s.replace(/\b[gj]if\b/gi,w=>GJgj[l=JGjg.search(w[0])]+w.slice(1)+ (as in ${r([g,j,g,j][l])}))  Takes separate g and j word lists. # Javascript(ES6), 151 bytes f=(s,g,j)=>s.replace(/\b(g|j)(if)\b/ig,(m,p,c)=>${a=g,p=="j"?"g":p=="J"?"G":(a=j,p=="g"?"j":"J")}${c}(as in${a[Math.floor(Math.random()*a.length)]}))


I probably can golf down the ternary part more, but I can't think of how right now. Also, it takes the g and j words separately.