19
\$\begingroup\$

Write a program to replace all occurrences of "force" with "first" and all occurrences of "first" with "force", keeping the original case for all character positions:

"ForcefoRcefOrcE" -> "FirstfiRstfIrsT"
"FirstfiRstfIrsT" -> "ForcefoRcefOrcE"

The rest of the string must stay unchanged, and so running your program twice shall return the original string:

"thirst of forces" -> "thirst of firsts" -> "thirst of forces"

Your program should work on any initial string. So as a hint, you better avoid using magic characters as intermediate representation, because if you try a three pass replacement ("force" -> "zzzzz", "first" -> "force", "zzzzz" -> "first"), it will fail on strings containing "zzzzz".

You should support the full range of characters allowed in a definition of a String by your programming language (in most cases, it's Unicode). Example, using JSON-style representation for non-printable characters (\u + 4 digits):

"\u0000\u0001\u0002\u0003the Force of the firsT"
                     |
                     V
"\u0000\u0001\u0002\u0003the First of the forcE"
\$\endgroup\$
  • 1
    \$\begingroup\$ Atta boy. Remind people that the tag has the winning criterion' \$\endgroup\$ – Christopher May 1 '17 at 0:19
  • 1
    \$\begingroup\$ @Challenger5 No I don't think so since if the leading [Ff] isn't there then you must not replace the word. \$\endgroup\$ – Erik the Outgolfer May 1 '17 at 7:57
  • 2
    \$\begingroup\$ May May first be with you. (Commented on May 1st) \$\endgroup\$ – Esolanging Fruit May 1 '17 at 9:03
  • 19
    \$\begingroup\$ Shouldn't it be "May the fourth be with you"? \$\endgroup\$ – wizzwizz4 May 1 '17 at 9:16
  • 3
    \$\begingroup\$ @mbomb007 "fourth" and "force" do not have the same number of letters, making it incompatible for keeping same character case. \$\endgroup\$ – Cœur May 1 '17 at 15:27

20 Answers 20

6
\$\begingroup\$

Retina, 33 bytes

iT`\OC\E\ocetsiTSI`Ro`first|force

Try it online!

Edit: Saved 5 bytes thanks to @MartinEnder for pointing out what Ro does.

\$\endgroup\$
  • \$\begingroup\$ Yep, was going to post once the OP replies to my comment. You can save a few bytes by reordering the first set so that the second one can be Ro. \$\endgroup\$ – Martin Ender May 1 '17 at 9:21
  • \$\begingroup\$ @MartinEnder The documentation confused me by paying too much attention to R's effect on ranges; for instance I would never have realised that RE is equivalent to 86420 if you hadn't pointed it out. \$\endgroup\$ – Neil May 1 '17 at 9:37
  • \$\begingroup\$ thanks for letting me know. I'll try to make that clearer in the docs. \$\endgroup\$ – Martin Ender May 1 '17 at 11:03
9
\$\begingroup\$

JavaScript (ES6), 93 88 bytes

f=
s=>s.replace(/force|first/gi,s=>s.replace(/./g,c=>s[s.search(c)^1]||c,s="oicsetOICSET"))
<textarea oninput=o.textContent=f(this.value)></textarea><pre id=o>

Edit: Saved 5 bytes by optimising the unchanged letter case.

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

APL (Dyalog), 61 bytes

Requires ⎕IO←0 which is default on many systems. Can be four characters shorter using the Unicode symbol instead of ⎕OPT .

(t←'force' 'first')⎕R{(m∊⎕A)c¨t⊃⍨~t⍳(c←819⌶)⊂m←⍵.Match}⎕OPT 1

Try it online!

\$\endgroup\$
4
\$\begingroup\$

PHP, 88 Bytes

Online Versions

<?=preg_replace_callback("#first|force#i",function($t){return$t[0]^first^force;},$argn);

PHP, 110 Bytes

<?=preg_replace_callback("#first|force#i",function($t){return strtr($t[0],iIsStToOcCeE,oOcCeEiIsStT);},$argn);
\$\endgroup\$
  • 3
    \$\begingroup\$ You could save a few bytes with $t[0]^first^force instead of strtr(). \$\endgroup\$ – user63956 May 1 '17 at 6:52
  • \$\begingroup\$ @user63956 Thank You for the learning effort \$\endgroup\$ – Jörg Hülsermann May 1 '17 at 9:36
4
\$\begingroup\$

Perl 5, 52 bytes

51 bytes of code + -p flag.

s%first|force%$&=~y/oceOCEistIST/istISToceOCE/r%eig

Try it online!

Nothing too crazy going on. Find the occurrences of force and first non-case-sensitive (s%force|first%%gi), and then transliterates the characters to convert one to the other.

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

CJam, 66 bytes

qY5m*_"force"{f{_eu}3/:z{~?}f%}:K~\"first"K.{[\]:P~@\/\f/P~@\f*\*}

Goes through every case variation of "first" and "force" and tries to split on it. If it can, it then joins it back with the reverse words.

Pseudocode:

input_chars = list(read_all_input()) # CJam: q
power = cartesian_power(2, 5) # CJam: Y4m*_
def case_variations(s): # CJam: {...}:K
    temp0 = [[i, j, upper(j)] for i, j in zip(power, s)] # CJam: f{_eu}3/
    temp1 = map(transpose, temp0) # CJam: :z
    ret = []
    for i in ret:
        for j in i: # CJam: {...}f%
            ret.append(j[1] if j[0] else j[2]) # CJam: ~?
    return ret
force_var = K("force") # CJam: "force"{...}:K~
first_var = K("first") # CJam: \"first"K
for force, first in zip(force_var, first_var): # CJam: .{...}
    current = [force, first] # CJam: [\]:P~
    input_chars = list_split(input_chars, force) # CJam: @\/
    input_chars = [list_split(i, first) for i in input_chars] # CJam: \f/
    input_chars = [list_join(i, force) for i in input_chars] # CJam: P~@\f*
    input_chars = list_split(input_chars, first) # CJam: \*
\$\endgroup\$
  • \$\begingroup\$ Surely the f is relevant to avoid changing thirst into thorce or divorce into divirst? \$\endgroup\$ – Neil May 1 '17 at 8:47
  • \$\begingroup\$ @Neil True, edited. \$\endgroup\$ – Esolanging Fruit May 1 '17 at 9:01
  • \$\begingroup\$ @Cœur Try it online! \$\endgroup\$ – Esolanging Fruit May 1 '17 at 16:47
3
\$\begingroup\$

Java 7, 318 310 bytes

String c(String s){String x=s.toLowerCase();int i=x.indexOf("force")+1,j=x.indexOf("first")+1,t=i>0&j>i?0:j>0?1:0;return i>0|j>0?s.substring(0,t>0?(i=j):i)+(char)(s.charAt(i++)-(t>0?-6:6))+s.charAt(i++)+(char)(s.charAt(i++)+(t>0?-16:16))+(char)(s.charAt(i++)+(t>0?-15:15))+c(s.length()>i?s.substring(i):""):s;}

Ok, this was pretty hard in Java..

Explanation:

String c(String s){                       // Method with String parameter and String return-type
  String x=s.toLowerCase();               //  Temp String as lowercase of the input
  int i=x.indexOf("force")+1,             //  Index of "force" + 1 (becomes 0 if NOT present; >=1 if it is present)
      j=x.indexOf("first")+1,             //  Index of "first" + 1 (becomes 0 if NOT present; >=1 if it is present)
      t=i>0&j>i?0:j>0?1:0;                //  Temp integer: 0 if "force" is found first; 1 if "first" is found first
  return i>0|j>0?                         //  If either "force" or "first" is found:
    s.substring(0,t>0?(i=j):i)            //   Return the substring before that (if any) + ('f' or 'F')
     +(char)(s.charAt(i++)-(t>0?-6:6))    //   + 'i' <-> 'o', or 'I' <-> 'O'
     +s.charAt(i++)                       //   + 'r' or 'R'
     +(char)(s.charAt(i++)+(t>0?-16:16))  //   + 's' <-> 'c', or 'S' <-> 'C'
     +(char)(s.charAt(i++)+(t>0?-15:15))  //   + 't' <-> 'e', or 'T' <-> 'E'
     +c(s.length()>i?s.substring(i):"")   //   + a recursive call for the rest of the input-String (if any)
   :                                      //  Else:
    s;                                    //   Return the input-String
}                                         // End of method

Test code:

Try it here.

class M{
  static String c(String s){String x=s.toLowerCase();int i=x.indexOf("force")+1,j=x.indexOf("first")+1,t=i>0&j>i?0:j>0?1:0;return i>0|j>0?s.substring(0,t>0?(i=j):i)+(char)(s.charAt(i++)-(t>0?-6:6))+s.charAt(i++)+(char)(s.charAt(i++)+(t>0?-16:16))+(char)(s.charAt(i++)+(t>0?-15:15))+c(s.length()>i?s.substring(i):""):s;}

  public static void main(String[] a){
    System.out.println(c("Force"));
    System.out.println(c("First"));
    System.out.println(c("foRce"));
    System.out.println(c("fiRst"));
    System.out.println(c("fOrcE"));
    System.out.println(c("fIrsT"));
    System.out.println(c("\u0000\u0001\u0002\u0003the Force of the firsT"));
    System.out.println(c("May the first be with you"));
    System.out.println(c(c("May the first be with you"))); // 2x
    System.out.println(c("The fIrSt of the First of the fORCE of the FIRST of the FoRCe"));
  }
}

Output:

First
Force
fiRst
foRce
fIrsT
fOrcE
 ���the First of the forcE
May the force be with you
May the first be with you
The fOrCe of the Force of the fIRST of the FORCE of the FiRSt
\$\endgroup\$
  • 1
    \$\begingroup\$ I appreciate that you provided a symmetric example c(c("..."))! \$\endgroup\$ – Cœur May 1 '17 at 15:23
3
\$\begingroup\$

Jelly, 37 36 bytes

Is there is a way to use a reduce across slices of length 5 instead?

®‘©ị“Ɓu“¡Ḣƭ»
Œlœṣ¢œṣ€¢j€¢j¢Œu⁸=ŒuT¤¦

Try it online!

How?

®‘©ị“Ɓu“¡Ḣƭ» - Link 1 helper that fetches the next word to use: no arguments
®            - recall value from register (initially zero)
 ‘           - increment
  ©          - place the result into the register
    “Ɓu“¡Ḣƭ» - literal dictionary compressed string list ["first","force"]
   ị         - index into (1-indexed and modular)
             - so this link first yields "first", then "force", then "first" and so on.

Œlœṣ¢œṣ€¢j€¢j¢Œu⁸=ŒuT¤¦ - Main link: list of characters, S
Œl                      - convert S to lower case
  œṣ                    - split on sublists equal to:
    ¢                   -   call the last link (1) as a nilad ("first")
     œṣ€                - split €ach on sublists equal to:
        ¢               -   call the last link (1) as a nilad ("force")
         j€             - join €ach with:
           ¢            -   call the last link (1) as a nilad ("first")
            j           - join with:
             ¢          -   call the last link (1) as a nilad ("force")
                      ¦ - apply a link to sparse indices:
              Œu        -   convert to upper case
                     ¤  -   nilad followed by link(s) as a nilad:
                ⁸       -     chain's left argument, S
                  Œu    -     convert to upper case
                 =      -     equal to S? (vectorises)
                    T   -     truthy indexes (indexes at which input is upper case)
\$\endgroup\$
  • \$\begingroup\$ Pyth and Jelly are equal :o \$\endgroup\$ – Leaky Nun May 1 '17 at 12:01
  • \$\begingroup\$ There must be a golfier way :D \$\endgroup\$ – Jonathan Allan May 1 '17 at 12:07
  • \$\begingroup\$ Yes, and I just found it :D \$\endgroup\$ – Leaky Nun May 1 '17 at 12:07
2
\$\begingroup\$

MATL, 47 bytes

5W:qB!"o['first';'force']@!32*-cZ}_Zt5M_6MoZt|c

Try it online!

This uses negative values as the intermediate step, and after the two passes it takes the absolute value.

\$\endgroup\$
2
\$\begingroup\$

Pyth, 36 35 bytes

K"first"srVjJ"force"mjKcdJcr0QKqVr1

Try it online!

Pyth is not especially good at string manipulations.

\$\endgroup\$
  • \$\begingroup\$ yet, you're holding second place currently \$\endgroup\$ – Cœur May 1 '17 at 15:01
2
\$\begingroup\$

Flex (lexer), 72 bytes

%%
 #define x(a) yytext[a]^=
(?i:first|force) x(1)6;x(3)16;x(4)17;ECHO;

To compile and run:

flex first.l
gcc lex.yy.c -lfl # -ll on Macs, apparently
./a.out
\$\endgroup\$
  • \$\begingroup\$ first.l:3: EOF encountered inside an action (oh, nevermind: it requires a newline at the end) \$\endgroup\$ – Cœur May 2 '17 at 1:46
  • \$\begingroup\$ ld: library not found for -lfl (oh never mind, command is gcc lex.yy.c -ll on macOS) \$\endgroup\$ – Cœur May 2 '17 at 1:58
  • \$\begingroup\$ Tested and approved. \$\endgroup\$ – Cœur May 2 '17 at 2:00
2
\$\begingroup\$

Python 2, 171 bytes

I wanted to try to do this using built-ins, but it can't beat the messy method with all the splitting and zipping.

import re,string as g
def f(s):f="istISTECOeco";l=re.split("(first|force)",s,0,re.IGNORECASE);l[1::2]=[t.translate(g.maketrans(f,f[::-1]))for t in l[1::2]];print"".join(l)

I think it's pretty clear what I'm doing here. Split the string on instances of first and force (case-insensitive), replace those instances with versions translated using str.translate, and join it back into a string again.

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 2.7, 173 165 bytes

8 bytes saved by quintopia

This one got gross:

lambda S:`[(t[0],t[0].upper())[t[1]]for t in zip("".join("first".join(s.replace("first","force")for s in S.lower().split("force"))),[l.isupper() for l in S])]`[2::5]

Try it online

Breaking it down step by step:

  1. S.lower().split("force"): take the string, unify to lowercase, split into substrings separated by "force"
  2. s.replace("first","force")for s in <STEP 1>: Replace all "first"'s with "force"
  3. _`.join("first".join(<STEP 2>)`[2::5]`_: replace all "force"'s with "first" by recombining the "force" delineated substrings with "first" and rejoin into single string (underscores added to get tick marks correct)
  4. zip(<STEP 3>,[(2,1)[l.isupper()]for l in S]): zip each character of replaced phrase with case encoding of original string (2 for lowercase, 1 for uppercase)
  5. _`[(t[0],t[0].upper())[t[1]==1]for t in <STEP 4>]`[2::5]`_: Restore original casing, converts list to string (underscores added to get tick marks correct)
\$\endgroup\$
  • \$\begingroup\$ You can save 8 bytes by encoding upper as True and lower as False: Try it online! \$\endgroup\$ – quintopia May 3 '17 at 4:27
2
\$\begingroup\$

C (clang), 201 183 226 214 bytes

Had some bugs... Still needs to be golfed down quite a lot

(saved 12 thanks to ceilingcat)

char*s,*p,*q;main(i,v)char**v;{puts(s=v[1]);do{p=strcasestr(s,"first");q=strcasestr(s,"force");if(p&&(!q|p<q))p[1]+=6,p[3]-=16,p[4]-=15;else if(q)q[1]-=6,q[3]+=16,q[4]+=15;s=p&&(!q|p<q)?p:q;}while(s++);puts(v[1]);}

Try it online!

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

C# 273 bytes

string c(string s){var x=s.ToLower();int i=x.IndexOf("force")+1,j=x.IndexOf("first")+1,t=i>0&j>i?0:j>0?1:0;return i>0|j>0?s.Substring(0,t>0?(i=j):i)+(char)(s[i++]-(t>0?-6:6))+s[i++]+(char)(s[i++]+(t>0?-16:16))+(char)(s[i++]+(t>0?-15:15))+c(s.Length>i?s.Substring(i):""):s;}

Try it online!

Direct port of Kevin Cruijssen's Java answer, turns out when it comes to getting the char in a string at a given index, C# is much golfier than java (s[i++] instead of s.charAt(i++))

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

Japt, 41 bytes

r"first|force"_d"i1o s1c t1e"¸m²®+ZuÃq}'i

Try it online!

This would be considerably shorter if Japt had a sane transliterate function...

Alternate version:

r"first|force"_d"io sc te"¸®¬¸²Ã®+ZuÃq}'i

Try it online!

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

C#, 235 chars

string a(string s){var l=s.ToLower();int f=l.IndexOf("first"),F=l.IndexOf("force"),m=f<F&f>-1?f:F>-1?F:f;return ++m>0?s.Substring(0,m)+(char)(s[m]^6)+s[m+1]+(char)(s[m+2]^16)+(char)(s[m+3]^17)+(s.Length-m>5?c(s.Substring(m+4)):""):s;}
\$\endgroup\$
1
\$\begingroup\$

Ruby, 55 bytes

gsub(/first|force/i){$&.tr(s="iIsStTEeCcOo",s.reverse)}

Try it online!

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

Java, 382 bytes non-comptent

Try Online

String f(String t){String s="";for(String w:t.split(" "))if(w.equalsIgnoreCase("force")|w.equalsIgnoreCase("first"))s+=" "+w.charAt(0)+(char)(w.charAt(1)+(w.charAt(1)=='o'|w.charAt(1)=='O'?-6:6))+w.charAt(2)+(char)(w.charAt(3)+(w.charAt(3)=='c'|w.charAt(3)=='C'?16:-16))+(char)(w.charAt(4)+(w.charAt(4)=='e'|w.charAt(4)=='E'?15:-15));else s+=" "+w;return s.substring(1,s.length());}
\$\endgroup\$
  • 3
    \$\begingroup\$ Hmm, this only works if all the words are divided by spaces, but what about commas, or weird strings like "The first, force,|first'forced!"? Also, you can golf your current code a bit: if(w.equalsIgnoreCase("force")|w.equalsIgnoreCase("first")) -> ,z after String s="" and z=w.toLowerCase();if(z.equals("force")|z.equals("first")). Also, 'O' can be 79, 'C' can be 67 and 'E' can be 69. And the if else can be replace with one big ternary if-else, since both do s+=. \$\endgroup\$ – Kevin Cruijssen May 1 '17 at 10:40
  • \$\begingroup\$ I confirm that this solution does not qualify, as it fails on "forceforce" for instance. \$\endgroup\$ – Cœur May 1 '17 at 15:47
  • \$\begingroup\$ @Cœur I've added non competent in the title \$\endgroup\$ – Khaled.K May 1 '17 at 18:46
0
\$\begingroup\$

C# (269 Bytes)

string s(string z){var u=z.ToUpper();var a=new[]{"FIRST","FORCE"};return String.Join("",u.Split(a,StringSplitOptions.None).Aggregate((c,n)=>c+(u.Substring(c.Length,5)==a[0]?a[1]:a[0])+n).Select((c,i)=>Char.IsLower(z[i])?Char.ToLower(c):c));}

yet another c# solution, only the second-smallest because I declared two variables and so can't use lambda syntax. oh well, I had fun. :)

explanation:

  • upshift the original string, then split on "FORCE" and "FIRST".

  • aggregate the results and on every split, find the five-character substring that was used to split the original string using the length so far of the string being aggregated. if it was "force" make it "first" and vice versa

  • select all the characters of the newly created all caps string and check if the original string was lowercase at the same index. if yes, return lowercased character at that index in the new string, otherwise return the uppercase character
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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