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

10
\$\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\$
8
\$\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
8
\$\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\$
7
\$\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
7
\$\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
  • 1
    \$\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 were holding second place for 7 years. Now fourth place, behind Vyxal, 05AB1E and Retina. \$\endgroup\$
    – Cœur
    Mar 1 at 2:32
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
    Feb 27 at 4:07
  • \$\begingroup\$ You can update your post accordingly :) \$\endgroup\$
    – movatica
    Feb 27 at 21:37
  • 1
    \$\begingroup\$ @movatica no thanks. that's your solution. post it yourself. \$\endgroup\$
    – quintopia
    Feb 27 at 23:06
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
2
\$\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\$
3
2
\$\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
    Feb 28 at 23:12
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\$

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:         Replace "first" with "force"
               Xý       Join on "first"
                 ¹.Ï    Apply capitalization of input
\$\endgroup\$
1
  • \$\begingroup\$ Thanks, and good job on the split-replace-join. You're on second place after Vyxal currently. \$\endgroup\$
    – Cœur
    Mar 1 at 2:28
1
\$\begingroup\$

C#, 234 bytes

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?a(s.Substring(m+4)):""):s;}

Try it online!

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

Swift, 127 247 225 219 208 bytes

var b="force",c="first",a=b,d=a,x={(a=$0,d=$3,($1+"").lowercased().ranges(of:$2+"").map{a.replaceSubrange($0,with:zip(d,a[$0]).map{$1.isLowercase ?$0:.init($0.uppercased())})},a).3},f={x(x($0,$0,b,c),$0,c,b)}

Built and tested with Swift 5.9, so TIO is out of the window. Here's a JDoodle link instead.


The following explanation is outdated, and refers to this similar, yet slightly less complicated version:

let f={let b="force",c="first",s=$0+"",x={var a=$0+"",d=$2+""
s.lowercased().ranges(of:$1+"").map{a.replaceSubrange($0,with:zip(d,a[$0]).map{$1.isLowercase ?$0:.init($0.uppercased())})}
return a}
return x(x(s,b,c),c,b)}

The current revision isn't much different in principle; the major differences are:

  • Tuples are exploited to allow for one-line closures, which lets us use implicit return statements.
  • All declarations are merged into a single var statement.
  • The s variable is no longer used, and has been replaced with an extra parameter to x.
  • Empty strings used for type inference have been replaced with references to other strings; this saves a byte wherever it's used.

With whitespace restored:

let f = {
  let b = "force", c = "first", s = $0 + "", x = {
    var a = $0 + "", d = $2 + ""
    s.lowercased().ranges(of: $1 + "").map {
      a.replaceSubrange($0, with: zip(d, a[$0]).map {
        $1.isLowercase ? $0 : .init($0.uppercased())
      })
    }
    return a
  }
  return x(x(s, b, c), c, b)}

Explanation

There's a lot to follow here, so I'll try and step you through the least Swifty Swift code I've ever written. Knowledge of Swift's intricacies is invaluable in understanding this gibberish.

Fair warning: Most of the identifiers used here are completely arbitrary.

Line 1

let f = { /* ... */ }

Since function declarations are generally not small, I've opted for a closure instead, so that the compiler can infer the parameter and return types. Plus, this means we don't have any pesky argument labels to deal with.

Line 2

let b = "force", c = "first", s = $0 + "", x = { /* ... */ }

b and c are simply there to shave off a few bytes, since I use each of those strings twice.

s serves a dual purpose. It lets me use the closure parameter (the original string) inside of more closures, since implicit closure parameters can only be used one level deep; and concatenating "" to it lets the type checker know that it's a String, meaning I don't have to specify that directly.

x is simply another closure definition. It takes three parameters:

  • the string to replace characters in
  • the search string
  • the replacement string

Line 3

var a = $0 + "", d = $2 + ""

a is there so I have a mutable copy of the string to work with. I also use the trick I used with s above to help out the type checker.

d serves the same purpose as s above (except for it being used differently, of course).

Line 4

s.lowercased().ranges(of: $1 + "").map { /* ... */ }

This lowercases the original string (to effectively make the substring search case insensitive) before finding all ranges containing the search string ($1, with "" appended to assist the type checker). These ranges allow us to refer to discovered words in the string even after we start replacing them.

The call to map here serves the same purpose as a for-in loop, just with less bytes (and a warning since we don't use the result -- if you don't want a warning, replace map with forEach).

Line 5

a.replaceSubrange($0, with: zip(d, a[$0]).map { /* ... */ }

This line does the actual replacing. In this method call, $0 is one of the ranges containing a word we want to replace. a[$0] gets the actual contents of the string in that range.

replaceSubrange(_:with:) unfortunately does not have a non-mutating counterpart, which is why we declare a above as a var instead of a let.

The call to zip allows us to iterate over the original string and the replacement string simultaneously, allowing us to keep case unchanged. Speaking of which...

Line 6

$1.isLowercase ? $0 : .init($0.uppercased())

Here, $1 is a character from the original string, and $0 is the corresponding character from the replacement string.

  • If $1 is lowercase, we return $0 unchanged (since I hardcoded the replacement strings to be lowercase).
  • If $1 is uppercase (or if it isn't cased at all), we return the result of uppercasing $0 (if it isn't cased, this call does nothing).

We have to wrap the call to uppercased() in a call to Character.init(_:) since uppercased() on Character returns a String (blame Swift's Unicode support).

Line 9

return a

The only line of this program that actually makes sense.

Line 11

return x(x(s, b, c), c, b)

Remember: b == "force", and c == "first".

  • We call our closure with the original string first, telling it to replace "force" with "first".
  • We then call the closure again with the result, and replace "first" with "force".

    We avoid replacing words we've already replaced by referencing the original, unmodified string when finding ranges.

  • Finally, we return the result of that and leave the miniature catastrophe that is the f closure.

But why, tho?

I've probably overcomplicated a good chunk of this program, but if we're being honest here, Swift was not designed with code golfing in mind. Still, that's what makes golfing fun in the first place!

\$\endgroup\$
1
  • \$\begingroup\$ I'd also specify that this is Swift 5 (since TIO is currently only supporting Swift 4). \$\endgroup\$
    – Cœur
    Mar 1 at 2:24
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.