15
\$\begingroup\$

The Language: Oppification

A funny language to speak is created by applying the following process to each word:

  1. Place op after each consonant. So Code becomes Copodope.

Yes, that's it. For the purpose of this challenge, y is always a consonant.

The Challenge: De-oppification

Given an oppified word, return the original word. Input will only contain letters. The first letter may be capitalized. The original word will never be empty and will always contain a vowel.

Test Cases:

Oppified      ->         Original 
a                        a
I                        I
itop                     it
opop                     op
Opop                     Op
popopop                  pop
Copopop                  Cop
opopopop                 opop
Kopicopkop               Kick
Asopia                   Asia
soptopopop               stop
hopoopopsop              hoops
hopoopopedop             hooped
ooooohop                 oooooh
aaaopopaaa               aaaopaaa
Popopopsopicoplope       Popsicle
gopaloplopopopinopgop    galloping
aopopbopopopcopopop      aopbopcop
\$\endgroup\$
9
  • 8
    \$\begingroup\$ None of your test cases contain a vowel followed by op, so an answer along the lines of replace(/(.)op/, '\1') won't fail any of them. I suggest that you add a word like hoop or looped to the test cases. \$\endgroup\$
    – Doorknob
    Jun 5, 2017 at 19:35
  • \$\begingroup\$ @mbomb007 I added some more tricky test cases. \$\endgroup\$
    – xnor
    Jun 5, 2017 at 20:09
  • \$\begingroup\$ Does the answer only have to work for preoppified inputs or all inputs? \$\endgroup\$ Jun 6, 2017 at 2:51
  • \$\begingroup\$ @CalculatorFeline "Given an oppified word" \$\endgroup\$
    – mbomb007
    Jun 6, 2017 at 4:21
  • 2
    \$\begingroup\$ Can we add "mopmopmopbopopop" as a test case? :) \$\endgroup\$ Jun 6, 2017 at 7:31

18 Answers 18

12
\$\begingroup\$

Retina, 9 bytes

(?!\G)op

Try it online!

Instead of checking that the preceding character is a consonant, we just make sure that the current op is not adjacent to either the beginning of the string or the previous match. The only case where we could match an incorrect op is if the original string contained an op (resulting in opop). But in that case we'll just remove the first op instead of the second and the result will be the same.

\$\endgroup\$
7
  • \$\begingroup\$ Wouldn't this give an incorrect answer for an input like loop? \$\endgroup\$
    – Leo
    Jun 6, 2017 at 7:27
  • 4
    \$\begingroup\$ @Leo loop is not a valid input because you can't obtain it from oppifying another word. \$\endgroup\$ Jun 6, 2017 at 7:39
  • \$\begingroup\$ @MartinEnder But lopoop (the oppified version of loop) is valid, and doesn't get de-oppified to loop. \$\endgroup\$
    – Imus
    Jun 6, 2017 at 11:48
  • \$\begingroup\$ @Imus no, the oppified version of loop is lopoopop. \$\endgroup\$ Jun 6, 2017 at 11:49
  • \$\begingroup\$ realised my mistake as well shortly after posting it :) was too slow in deleting. Good point. \$\endgroup\$
    – Imus
    Jun 6, 2017 at 11:50
10
\$\begingroup\$

V, 12, 5 bytes

Í.“op

Try it online!

00000000: cd2e 936f 70                             ...op

Saved 7 bytes thanks to @Xnor's realization that since the input must always be opped, we don't have to check for vowels.

\$\endgroup\$
2
  • \$\begingroup\$ Hmm, this seems so hard to beat... \$\endgroup\$ Jun 5, 2017 at 20:08
  • 4
    \$\begingroup\$ The hex dump: ...op Is making me laugh way harder than it should \$\endgroup\$
    – nmjcman101
    Jun 6, 2017 at 11:33
10
\$\begingroup\$

Python, 42 bytes

lambda s:re.sub('(.)op',r'\1',s)
import re

Try it online!

If I'm not mistaken, you can just substitute all ?op with ? without caring about vowels. If the original string contains op, then it's oppified to opop, and the replacement returns it to op and no further. This is because the pattern matches for ?op cannot overlap, so only one op is removed.

A non-regex solution is 5 bytes longer.

Python, 47 bytes

f=lambda s:s and s[0]+f(s[1+2*(s[1:3]=='op'):])

Try it online

\$\endgroup\$
4
  • 3
    \$\begingroup\$ You can import re after you reference it‽ \$\endgroup\$
    – Adám
    Jun 5, 2017 at 20:57
  • 4
    \$\begingroup\$ @Adám Python doesn't evaluate it when the function is defined, only when it's called. \$\endgroup\$
    – xnor
    Jun 5, 2017 at 20:59
  • 4
    \$\begingroup\$ Wow, it's been a while since I've seen anyone use an interrobang. I guess that's a way to golf your comment a little. \$\endgroup\$
    – Baldrickk
    Jun 6, 2017 at 12:24
  • 1
    \$\begingroup\$ @Baldrickk But in bytes, the interrobang has >= bytes than just the string "?!" \$\endgroup\$
    – MilkyWay90
    Jun 15, 2019 at 15:39
5
\$\begingroup\$

Perl 5, 10 + 1 = 11 bytes

s/.\Kop//g

Try it online!

Run with -p (1 byte penalty); golfing languages might do implicit I/O automatically, but Perl needs an option for it.

When I saw @xnor's answer, I realised it could be improved using a Perl-specific regex feature; s/a\Kb/c/g is equivalent to s/ab/ac/g (in other words, the s/// only replaces the things after the first \K). So here's how it looks in Perl.

\$\endgroup\$
5
\$\begingroup\$

Retina, 15 8 bytes

(.)op
$1

Try it online!

-7 bytes thanks to Kevin Cruijssen

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

Go, 103 92 bytes

Must... compile... Go built-in functions have weird names. :P

import."regexp"
func f(s string)string{return MustCompile("(.)op").ReplaceAllString(s,"$1")}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Haskell (93 62 61 Bytes)

a(x:'o':'p':r)|notElem x"aeiouAEIOU"=x:a r
a(x:r)=x:a r
a x=x

thanks to @nimi suggestions in comments!

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Some tips: as you are using v and o only once, you can inline it. notElem is shorter than not(...elem...). You can replace the && in a guard with a ,. The last case for a can be written as a x=x. No need for () in x:(a r). \$\endgroup\$
    – nimi
    Jun 5, 2017 at 20:56
  • 1
    \$\begingroup\$ ... oh, and the test for =="op" can be replaced with a literal pattern match: a(x:'o':'p':r)|notElem x"aeiouAEIOU"=x:a r \$\endgroup\$
    – nimi
    Jun 5, 2017 at 20:59
  • \$\begingroup\$ Updated. thanks @nimi \$\endgroup\$ Jun 5, 2017 at 21:13
  • 1
    \$\begingroup\$ One more byte to save: you can omit the space between x and ". \$\endgroup\$
    – nimi
    Jun 5, 2017 at 21:21
3
\$\begingroup\$

PHP, 36 bytes

<?=preg_replace("#.\Kop#","",$argn);

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ How is this supposed to be run? \$\endgroup\$
    – Titus
    Jun 6, 2017 at 21:00
  • \$\begingroup\$ It fails for the first two test cases. Use preg_replace to fix. \$\endgroup\$
    – Titus
    Jun 6, 2017 at 21:03
  • \$\begingroup\$ You can save 3 bytes by renaming the variable to any single character, $a for instance \$\endgroup\$ Jun 7, 2017 at 2:45
  • \$\begingroup\$ @junkfoodjunkie $argn is a reserved variable which is availbale when PHP is run with the -ROption from the command line \$\endgroup\$ Jun 7, 2017 at 9:30
  • \$\begingroup\$ Ah, okay, didn't know that. The online tester doesn't account for it. :-) \$\endgroup\$ Jun 7, 2017 at 9:34
2
\$\begingroup\$

Japt, 9 bytes

r"%Vop"_g

Try it online

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

JavaScript (ES6), 35 bytes

Add f= at beginning and invoke like f(arg).

s=>s.replace(/([^aeiou])op/gi,"$1")

I am surprised no one posted a JavaScript solution yet....

Test Snippet

let f=
s=>s.replace(/([^aeiou])op/gi,"$1")

console.log("a" + " -> " + f("a"));
console.log("I" + " -> " + f("I"));
console.log("itop" + " -> " + f("itop"));
console.log("opop" + " -> " + f("opop"));
console.log("Opop" + " -> " + f("Opop"));
console.log("popopop" + " -> " + f("popopop"));
console.log("Copopop" + " -> " + f("Copopop"));
console.log("opopopop" + " -> " + f("opopopop"));
console.log("Kopicopkop" + " -> " + f("Kopicopkop"));
console.log("Asopia" + " -> " + f("Asopia"));
console.log("soptopopop" + " -> " + f("soptopopop"));
console.log("hopoopopsop" + " -> " + f("hopoopopsop"));
console.log("hopoopopedop" + " -> " + f("hopoopopedop"));
console.log("ooooohop" + " -> " + f("ooooohop"));
console.log("aaaopopaaa" + " -> " + f("aaaopopaaa"));
console.log("Popopopsopicoplope" + " -> " + f("Popopopsopicoplope"));
console.log("gopaloplopopopinopgop" + " -> " + f("gopaloplopopopinopgop"));
console.log("aopopbopopopcopopop" + " -> " + f("aopopbopopopcopopop"));

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

C (gcc), 83 bytes

main(c,v)char**v;{for(;*v[1];strchr("aAeEiIoOuU",putchar(*v[1]++))?:printf("op"));}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

///, 18 bytes

/op/.//../o\p//.//

Try it online!

Note that this snippet wants to replace op with a ., but later on there is a replacement defined where op is being put back into the string. That second instruction would have the op replaced by a . (and thus insert a . into the end result), so I've used a \ between the o and p to break the pattern.

\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog), 13 bytes

'(.)op'⎕R'\1'

Try it online!

Simply PCRE Replace any character followed by "op" with the character itself.

\$\endgroup\$
0
\$\begingroup\$

Crystal, 39 Bytes

def o(s)s.gsub(/([^aeiou])op/,"\\1")end

How it works

It simply searches for each consonant, followed by the sequence op. If so, replace that sequence only with the consonant found before: ([^aeiou]).

Try it online

\$\endgroup\$
0
\$\begingroup\$

Java 8, 36 26 bytes

s->s.replaceAll("(.)op","$1")

-10 bytes by replacing [^aeiou] with ., thanks to @xnor's explanation in his Python answer.

Try it here.

\$\endgroup\$
0
0
\$\begingroup\$

Ruby, 34 27 22 + 1 = 23 bytes

-4 bytes thanks to RJHunter.

+1 byte for the -p flag.

$_.gsub!(/(.)op/,'\1')

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Using Ruby's -p option will cost a byte but allow your script to start directly with gsub. \$\endgroup\$
    – RJHunter
    Jun 6, 2017 at 1:08
0
\$\begingroup\$

sed, 22 bytes

sed -E 's/(.)op/\1/g'

Reads from STDIN until EOF and outputs de-oppified string
Uses same length reduction technique from @xnor's Python answer

\$\endgroup\$
0
\$\begingroup\$

R, 29 bytes

gsub("(.)op","\\1",scan(,''))

Try it online!

Much like most other solutions here, captures character followed by op, replaces it with character itself.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.