20
\$\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\$
11
  • 1
    \$\begingroup\$ Atta boy. Remind people that the tag has the winning criterion' \$\endgroup\$
    – user63187
    May 1, 2017 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\$ May 1, 2017 at 7:57
  • 2
    \$\begingroup\$ May May first be with you. (Commented on May 1st) \$\endgroup\$ May 1, 2017 at 9:03
  • 19
    \$\begingroup\$ Shouldn't it be "May the fourth be with you"? \$\endgroup\$
    – wizzwizz4
    May 1, 2017 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, 2017 at 15:27

23 Answers 23

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\$
7
\$\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\$
3
  • \$\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\$ May 1, 2017 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, 2017 at 9:37
  • \$\begingroup\$ thanks for letting me know. I'll try to make that clearer in the docs. \$\endgroup\$ May 1, 2017 at 11:03
7
\$\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\$
6
\$\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\$
2
  • 3
    \$\begingroup\$ You could save a few bytes with $t[0]^first^force instead of strtr(). \$\endgroup\$
    – user63956
    May 1, 2017 at 6:52
  • \$\begingroup\$ @user63956 Thank You for the learning effort \$\endgroup\$ May 1, 2017 at 9:36
6
\$\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\$

Java 10, 318 310 284 279 277 271 256 bytes

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

-34 bytes thanks to @ceilingcat.

Try it online.

Explanation:

String c(String s){                     // Recursive method with String as both parameter and return-type
  var 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|j<1?1:-1;               //  Temp integer: -1 if "force" is found first; 1 if "first" is found first
  var y=s.toCharArray();                //  Convert the string to a character-array
  return-j<i?                           //  If either "force" or "first" is found:
    s.substring(0,i=t<0?j:i)            //   Return the substring before that (if any) + ('f' or 'F')
     +(y[i++]-=t*6)                     //   + 'i'↔'o' or 'I'↔'O'
     +y[i++]                            //   + 'r' or 'R'
     +(y[i++]+=t*16)                    //   + 's'↔'c' or 'S'↔'C'
     +(y[i++]+=t*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 as is
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I appreciate that you provided a symmetric example c(c("..."))! \$\endgroup\$
    – Cœur
    May 1, 2017 at 15:23
  • \$\begingroup\$ @ceilingcat Thanks! Your character-array approach also opened up a golf for 15 more bytes due to implicit casting. :) \$\endgroup\$ Feb 12 at 7:34
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\$
3
  • \$\begingroup\$ Surely the f is relevant to avoid changing thirst into thorce or divorce into divirst? \$\endgroup\$
    – Neil
    May 1, 2017 at 8:47
  • \$\begingroup\$ @Neil True, edited. \$\endgroup\$ May 1, 2017 at 9:01
  • \$\begingroup\$ @Cœur Try it online! \$\endgroup\$ May 1, 2017 at 16:47
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\$
3
  • \$\begingroup\$ Pyth and Jelly are equal :o \$\endgroup\$
    – Leaky Nun
    May 1, 2017 at 12:01
  • \$\begingroup\$ There must be a golfier way :D \$\endgroup\$ May 1, 2017 at 12:07
  • \$\begingroup\$ Yes, and I just found it :D \$\endgroup\$
    – Leaky Nun
    May 1, 2017 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\$
1
  • \$\begingroup\$ yet, you're holding second place currently \$\endgroup\$
    – Cœur
    May 1, 2017 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\$
3
  • \$\begingroup\$ first.l:3: EOF encountered inside an action (oh, nevermind: it requires a newline at the end) \$\endgroup\$
    – Cœur
    May 2, 2017 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, 2017 at 1:58
  • \$\begingroup\$ Tested and approved. \$\endgroup\$
    – Cœur
    May 2, 2017 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\$
4
  • \$\begingroup\$ Further golfing and switching to Python 3.8 brings it down to 113 bytes \$\endgroup\$
    – movatica
    Feb 12 at 19:19
  • \$\begingroup\$ @movatica yes that's a much smarter way to go about it \$\endgroup\$
    – quintopia
    2 days ago
  • \$\begingroup\$ You can update your post accordingly :) \$\endgroup\$
    – movatica
    yesterday
  • 1
    \$\begingroup\$ @movatica no thanks. that's your solution. post it yourself. \$\endgroup\$
    – quintopia
    yesterday
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\$
2
  • \$\begingroup\$ You can save 8 bytes by encoding upper as True and lower as False: Try it online! \$\endgroup\$
    – quintopia
    May 3, 2017 at 4:27
  • \$\begingroup\$ 131 bytes \$\endgroup\$
    – movatica
    Feb 12 at 19:07
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
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\$
1
\$\begingroup\$

05AB1E, 21 20 bytes

„€Û‹›#`UVlY¡XY:Xý¹.Ï

Try it online!

I could not figure out a way of doing this shorter without using variables, so here we are. I'm sure someone more versed with stack manipulation can figure it out

How?

„€Û‹›#`UVlY¡XY:Xý¹.Ï
„€Û‹›#`UV               X = "first" Y="force"
         l              Lower case the input
          Y¡            Split on "force"
            XY:         Relpace "first" with "force"
               Xý       Join on "first"
                 ¹.Ï    Apply capitalization of input
\$\endgroup\$
1
  • \$\begingroup\$ Thanks, and good job on the split-replace-join. Now write a program that replaces "Relpace" with "Replace". ;) \$\endgroup\$
    – Cœur
    7 hours ago
1
\$\begingroup\$

Vyxal r, 21 20 19 18 bytes

⇩1∆o‛°⇩"JḂǓ"ƛ÷V;•F

Try it Online!

Neat. String compression helps here but honestly the hard part was figuring out how to set up the lists with minimal repetition.

-1 because I never actually use the register in my final answer

-1 by switching the last two elements to remove the duplication

-1 again for redoing how the lists are created

⇩1∆o‛°⇩"JḂǓ"ƛ÷V;•F­⁡​‎‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁣⁢‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁣‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁣⁤‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁤‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏⁠‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏‏​⁡⁠⁡‌­
 1∆o                # ‎⁡"first"
    ‛°⇩             # ‎⁢"force"
⇩      "J           # ‎⁣pair the two and append the lowercase input
         Ḃ          # ‎⁤push ["force", "first", input] and its reverse
          Ǔ         # ‎⁢⁡rotate the reverse so its in the order ["first", "force", input]
           "        # ‎⁢⁢pair the two
            ƛ  ;    # ‎⁢⁣map over each list
             ÷V     # ‎⁢⁤replacement of first/force
                •F  # ‎⁣⁡copy capitalization of input and remove the one identical to the input
💎

Created with the help of Luminespire.

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

Python 3.8 (pre-release), 113 102 bytes

-11 bytes thanx to naffetS

lambda s:re.sub("(?i:first|force)",lambda m:m[0].translate(' tf Io RCE i  rceS TF  Os'*9),s)
import re

Try it online!

Inspired by quintopias answer.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 102 \$\endgroup\$
    – naffetS
    20 hours ago
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
  • 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\$ May 1, 2017 at 10:40
  • \$\begingroup\$ I confirm that this solution does not qualify, as it fails on "forceforce" for instance. \$\endgroup\$
    – Cœur
    May 1, 2017 at 15:47
  • \$\begingroup\$ @Cœur I've added non competent in the title \$\endgroup\$
    – Khaled.K
    May 1, 2017 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 and acknowledge you have read our privacy policy.

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