6
\$\begingroup\$

Challenge

In this challenge, you are to code in any language a program or function that will take a string and replace certain characters within it with different characters.

Input

The input is the same for both functions and full programs:

[string] [char1] [char2]
  • string will be an indefinite line of characters surrounded by quotation mars, such as "Hello, World!" or "1 plus 2 = 3".

  • char1 will be a single character within string.

  • char2 will be a single character not necessarily in string.

Output

[modified string]

Your output will take string and replace all instances of char1 with char2, then output the result as modified string. Case should be ignored, so the input "yolO" o u should output yulu.

Examples

Input

"Hello, World!" l r

Output

Herro, Worrd!

Input

"Slithery snakes slurp Smoothies through Silly Straws" s z

Output

zlithery znakez zlurp zmoothiez through zilly ztrawz

Input

"Grant Bowtie: Only the best future bass artist ever" : -

Output

Grant Bowtie- Only the best future bass artist ever

Input

"019 + 532 * 281 / ? = waht/?" / !

Output

019 + 532 * 281 ! ? = waht!?

Other details

This is code golf, so the shortest answer (in bytes) at the end of the week (the 14th of September) wins. Also, anything not specified in this challenge is fair game, meaning that stuff I don't explain is up to you.

\$\endgroup\$
13
  • 4
    \$\begingroup\$ Are functions allowed? \$\endgroup\$
    – Downgoat
    Commented Sep 8, 2015 at 3:22
  • 2
    \$\begingroup\$ @AlexA. Isn't that only if it's not specified? In this case, it says "a program". In the past, that meant that you had to provide a full program. \$\endgroup\$ Commented Sep 8, 2015 at 3:27
  • 2
    \$\begingroup\$ @vihan Functions are allowed. \$\endgroup\$ Commented Sep 8, 2015 at 5:03
  • 6
    \$\begingroup\$ So the second character can be upper case, and the replaced character is lower case? That doesn't make much sense to me. So if functions are allowed, but it specifically says that the input string has quotes, will the function receive a string that has quotes inside the string? Well, frankly, I'm probably done with this challenge anyway. Changing about 3 rules after there are already 10 answers is very unfortunate. \$\endgroup\$ Commented Sep 8, 2015 at 5:34
  • 4
    \$\begingroup\$ That part about all replacements needing to be lowercase is new. The original statement said, that case should be ignored. For me this means, that lower and upper case letters should be replaced, but not that I should change the replacement letter... \$\endgroup\$
    – Cabbie407
    Commented Sep 8, 2015 at 5:35

28 Answers 28

12
\$\begingroup\$

Vim, 18 keystrokes

$bD:s/<C-R>"<Left><BS>/<Right>/i<CR>x$x

Assuming the cursor is on the first column of the first line, and the open file contains this:

"yolO" o u

The file will end up containing:

"yulu" 
\$\endgroup\$
3
  • 1
    \$\begingroup\$ +1 for Vim ... not something oft-seen :) \$\endgroup\$ Commented Sep 8, 2015 at 14:35
  • 1
    \$\begingroup\$ Your ending file shouldn't contain the quotation marks \$\endgroup\$ Commented Sep 9, 2015 at 13:20
  • \$\begingroup\$ @NathanMerrill Fixed. \$\endgroup\$
    – orlp
    Commented Sep 13, 2015 at 5:38
10
\$\begingroup\$

JavaScript ES6, 28 bytes

(s,a,b)=>s.replace(a,b,'gi')

Firefox only as it uses a mozilla-specific feature.

\$\endgroup\$
2
  • \$\begingroup\$ That was quick. I appear to have made this too easy again... \$\endgroup\$ Commented Sep 8, 2015 at 1:46
  • 8
    \$\begingroup\$ Is it correct to use 3 arguments instead of 1 string? \$\endgroup\$
    – Qwertiy
    Commented Sep 8, 2015 at 9:44
6
\$\begingroup\$

Pyth, 10 bytes

XQr*2w4*2w

Try in online: Demonstration or Test Suite

Explanation:

 Q             read a line and evaluates (reads a string with quotes)
     w         reads a char: a (actually reads a line)
   *2          make it twice as long: aa (repeat the char)
  r   4        capitalize this string: Aa
       *2w     read another char and repeat it: bb
X              replace the letters Aa by bb in Q
\$\endgroup\$
6
\$\begingroup\$

Retina, 29 bytes

i`(.)(?=.*\1 (.)$)|"|....$
$2

For scoring purposes each line goes in a separate file, but for convenience you can run the above from a single file with the -s flag.

As this is just a single regex replacement, you can test it here.

The regex consists of three parts, one to do the substitution and two to clean up the rest of the input. This is the substitution part:

(.)       # Match a character and capture it in group 1.
(?=       # Lookahead to ensure that this is the character we're searching for.
  .*      # Consume arbitrary characters to move to the end of the string.
  \1 (.)$ # Ensure we can match the captured character, then a space, then
          # another character and then the end of input. That other character
          # is captured in group 2.
)

This match is replaced by $2, i.e. the character to be substituted in.

The other two possibilities are either to match a ", or to match the last four characters of the input. In either case group two is empty, so the replacement string $2 evaluates to an empty string and the match is simply removed from the input. This cleans up the quotes and the characters at the end.

i` simply activates case insensitive matching.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ How does this work? \$\endgroup\$
    – mbomb007
    Commented Sep 8, 2015 at 21:59
  • \$\begingroup\$ @mbomb007 Edited. Let me know if you have further questions. \$\endgroup\$ Commented Sep 9, 2015 at 9:20
5
\$\begingroup\$

gawk - 48

IGNORECASE=gsub(/"/,_),gsub($(NF-1),$NF)+(NF-=2)

That IGNORECASE hurts...

How to use

In bash enter: awk 'IGNORECASE=gsub(/"/,_),gsub($(NF-1),$NF)+(NF-=2)'

Then enter a string in quotes and the two characters. In front of some characters ("[" and "(" I know of) you have to enter a backslash, because awk would try to interpret them as regular expression instead.

\$\endgroup\$
7
  • \$\begingroup\$ This doesn't work. \$\endgroup\$ Commented Sep 9, 2015 at 9:52
  • \$\begingroup\$ Hmm... it works with gawk and mawk... \$\endgroup\$
    – Cabbie407
    Commented Sep 9, 2015 at 11:23
  • \$\begingroup\$ Doesn't work with my Gawk, what version are you using? Why is there a comma between the 2 gsubs ? Nvm, didn't work properly with STDIN because i didn't escape the quotes... Still don't need that comma though or the + as they are doing nothing. \$\endgroup\$ Commented Sep 9, 2015 at 12:24
  • 1
    \$\begingroup\$ Few less characters awk 'IGNORECASE=gsub(/"/,x)gsub($(NF-1),$NF)(NF-=2)' \$\endgroup\$ Commented Sep 9, 2015 at 12:27
  • 1
    \$\begingroup\$ Oh, great, thanks. :) This does not set IGNORECASE for the first input. But I got fooled by the syntax highlighting in my editor for that quote regexp ;) \$\endgroup\$
    – Cabbie407
    Commented Sep 9, 2015 at 12:35
4
\$\begingroup\$

Octave, 28

An anonymous function using built in functions.

@(W,T,F)strrep(lower(W),T,F)

Assuming it is stored in f we can call it as follows:

f('Slithery snakes slurp Smoothies through Silly Straws','s','z')
\$\endgroup\$
1
  • \$\begingroup\$ Word list, Template, Fill-in? \$\endgroup\$
    – ಠ_ಠ
    Commented Sep 13, 2015 at 9:16
3
\$\begingroup\$

R, 28

function(s,c,r)gsub(c,r,s,T)

Had the order of the arguments been (c,r,s), I thought of doing

functional::Curry(gsub,i=T)

functional is a 3rd-party package whose Curry functional allows redefining function arguments: here, returns a function like gsub but with the modified ignore.case = TRUE.

\$\endgroup\$
5
  • \$\begingroup\$ You can save two bytes using positional parameters rather than named parameters with partial matching. That is, you can use gsub(c,r,s,T) since ignore.case is the fourth positional argument. \$\endgroup\$
    – Alex A.
    Commented Sep 8, 2015 at 2:16
  • \$\begingroup\$ Also this is 30 bytes, not 29. \$\endgroup\$
    – Alex A.
    Commented Sep 8, 2015 at 2:18
  • 1
    \$\begingroup\$ For the same length function(s,c,r)chartr(c,r,s) \$\endgroup\$
    – MickyT
    Commented Sep 8, 2015 at 3:24
  • \$\begingroup\$ @MickyT, but chartr is case-sensitive. \$\endgroup\$
    – flodel
    Commented Sep 10, 2015 at 23:04
  • \$\begingroup\$ My bad sorry. I didn't think it through properly. \$\endgroup\$
    – MickyT
    Commented Sep 10, 2015 at 23:10
3
\$\begingroup\$

CJam, 18 17 bytes

Kind of awkward handling the quotes and upper vs. lower case. But I believe it works for all cases:

l'"%~S%(eu_el+\er

Try it online

Thanks to @Dennis for golfing 1 byte.

Note that this is a full program that takes the input exactly as specified in the question. I can make this shorter if the input requirements are interpreted more flexibly.

Explanation:

l     Get input.
'"%   Split at quotes. This separates the string from the remaining arguments,
      and gets rid of the quotes.
~     Unwrap the list. We now have two strings on the stack, the input text
      and a string containing the two letters.
S%    Split the string containing the two letters.
(     Pop off the first ("source") letter.
eu    Convert it to upper case.
_el   Copy and convert to lower case.
+     Concatenate the two, giving us a string with upper and lower case.
\     Swap the second ("target") letter to top.
er    Transliterate.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You don't need the last ~. The result won't be a string, but the output won't look different. \$\endgroup\$
    – Dennis
    Commented Sep 8, 2015 at 3:57
3
\$\begingroup\$

Scala, 59 bytes

(s:String,a:Char,b:Char)=>(s"(?i)$a"r).replaceAllIn(s,""+b)

An anonymous function that uses s"" alongwith ""r to dynamically build a case-insensitive regex.

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

Ruby, 17 bytes

f=->s,*r{s.tr *r}

For example:

> f["Hello there!", ?e, ?a]
=> Hallo thara!
\$\endgroup\$
3
\$\begingroup\$

PowerShell, 33 30 Bytes

param($a,$b,$c)$a-replace$b,$c

Expects input via command-line argument. PowerShell has many built-in case-insensitive operators that just tack on an i in front of the usual operator -- here as -ireplace instead of -replace -- so the case-insensitive matching was actually pretty easy.

PS C:\Tools\Scripts\golfing> .\string-shenanigans.ps1 "Hello, World!" l r
Herro, Worrd!

PS C:\Tools\Scripts\golfing> .\string-shenanigans.ps1 "Slithery snakes slurp Smoothies through Silly Straws" s z
zlithery znakez zlurp zmoothiez through zilly ztrawz

PS C:\Tools\Scripts\golfing> .\string-shenanigans.ps1 "019 + 532 * 281 / ? = waht/?" / !
019 + 532 * 281 ! ? = waht!?

Saved 3 bytes thanks to briantist

\$\endgroup\$
3
  • \$\begingroup\$ You can make this shorter: param($a,$b,$c)$a-replace$b,$c . Powershell is case insensitive by default, no need to be explicit with -ireplace here, saves 1 byte, and by removing () from the replace you can save 2 more bytes. \$\endgroup\$
    – briantist
    Commented Sep 8, 2015 at 21:35
  • \$\begingroup\$ @briantist That's a good point. One of the test cases I came up with yesterday broke without the i, but now I can't seem to duplicate that. And good call on removing the parens, too. I miss those more often than not. Regarding the regex ... the input requirements explicitly list "single character" so unless $b is a ., we'll be fine. \$\endgroup\$ Commented Sep 9, 2015 at 13:11
  • \$\begingroup\$ You're correct; I've removed my comments about the regex, it's not an issue. \$\endgroup\$
    – briantist
    Commented Sep 9, 2015 at 18:40
2
\$\begingroup\$

Pyth, 7 19? / 15 bytes

jwcjrz1cwrz0rz1

Example Input

(My second Pyth program, ever). Any tips on golfing are welcome. A lot of the bytes are going to the repeated rz1/rz0. I could chop some of these I could be guaranteed the case.


If quotes are required, a slightly larger 19-byte program handles that:

jwcjrz1c:w1_1rz0rz1

Explanation:

This basically. Takes a string:

Slithery snaKEs

Then, chops all lowercase instances of the the character to replace.

['Slithery ','naKE','']

Then joins with the uppercase instance:

Slithery SnaKES

Then chops on the uppercase instance:

['','lithery ','naKE']

Then joins with the new character:

qlithery qnaKEq
\$\endgroup\$
6
  • \$\begingroup\$ no it doesn't. It lower cases the entire thing. \$\endgroup\$
    – Maltysen
    Commented Sep 8, 2015 at 2:36
  • \$\begingroup\$ @Maltysen fixed \$\endgroup\$
    – Downgoat
    Commented Sep 8, 2015 at 2:48
  • \$\begingroup\$ This does not take the specified input format. All 3 inputs are on a single line, in the given order. More importantly, the input string is in quotes, while the output string is not. Just try copying and pasting the sample inputs to see if your solutions work or not. \$\endgroup\$ Commented Sep 8, 2015 at 3:14
  • \$\begingroup\$ @RetoKoradi I don't think input is that strict. If that were true majority of the answers would work. \$\endgroup\$
    – Downgoat
    Commented Sep 8, 2015 at 3:15
  • 1
    \$\begingroup\$ The order might be flexible, not sure how the rules would handle that. But it clearly says "an indefinite line of characters surrounded by quotation marks". So that part is definitely not optional. \$\endgroup\$ Commented Sep 8, 2015 at 3:17
2
\$\begingroup\$

Pyth - 11 bytes

A simple regexp solution with case insensitive. Will try to translate to Retina if I get it to compile.

:Q+"(?i)"ww

Test Suite.

\$\endgroup\$
3
  • \$\begingroup\$ I don't think this meets the input requirements. It says that "an indefinite line of characters surrounded by quotation marks", while the output does not have quotation marks. If I run your code with quotation marks, they also show up in the output. \$\endgroup\$ Commented Sep 8, 2015 at 3:21
  • 1
    \$\begingroup\$ @RetoKoradi sorry, fixing. \$\endgroup\$
    – Maltysen
    Commented Sep 8, 2015 at 3:37
  • 1
    \$\begingroup\$ It looks like we don't have consensus on the input requirements. Some people interpret them differently. \$\endgroup\$ Commented Sep 8, 2015 at 3:47
2
\$\begingroup\$

mSL, 68 bytes

$replace($gettok($1-,-3-1,32),$gettok($1-,-2,32),$gettok($1-,-1,32))
\$\endgroup\$
2
\$\begingroup\$

Bash 4.0+, 21 bytes

Command-line arguments.

tr ${2^}${2,} $3<<<$1
\$\endgroup\$
2
\$\begingroup\$

C#, 93 120 124 123 bytes

class A{static void Main(string[]a){System.Console.Write(a[0].Replace(a[1].ToLower(),a[2]).Replace(a[1].ToUpper(),a[2]));}}

Not sure if I can golf this much better than this, but surprisingly low byte count for C# =D

EDIT: Thanks, Reto Koradi for pointing out the case sensitivity.

EDIT 2: More stuff I missed out on. Maybe doing this during a break in work isn't the best time.

\$\endgroup\$
6
  • \$\begingroup\$ Does this replace both upper and lower case letters? I don't know C# at all, but I would be surprised if a simple Replace() method replaces in a case insensitive way. \$\endgroup\$ Commented Sep 8, 2015 at 15:56
  • \$\begingroup\$ 1. Why do you assume that the char to replace in in lower case? 2. Why are you writing the full program if you can write a function? 3. You don't need using if use string and System.Console. Anyway, I think, it can be ignored in case of a function. \$\endgroup\$
    – Qwertiy
    Commented Sep 8, 2015 at 16:15
  • \$\begingroup\$ Thanks for the tip regarding the using @Qwertiy. Dunno what I was thinking there. In terms of writing a program, the question is asking for a program. \$\endgroup\$
    – rp.kelly
    Commented Sep 8, 2015 at 16:28
  • 1
    \$\begingroup\$ string with lowercase first letter. With uppercase one it requires System. And you can remove space after []. \$\endgroup\$
    – Qwertiy
    Commented Sep 8, 2015 at 16:34
  • 1
    \$\begingroup\$ By the way - great idea to allow command line to parse the string. \$\endgroup\$
    – Qwertiy
    Commented Sep 8, 2015 at 16:37
2
\$\begingroup\$

Shell 15 bytes:

sed s/$1/$2/gi

Save as submission.sh and run as:

$ echo "Hello, World" | ./submission.sh h e
eello, World

Explanation:

sed (stream editor) has a substitute command, which parses standard input and substitutes string $1 for string $2. The g modifier substitutes globally in the input string, and i modifier produces a case-insensitive match.

Old Solution:

Shell, 14 bytes submission_1.sh

tr $2 $3<<<$1

Call with

$ ./submission_1.sh 'hello there!lgge lfewf lger3%#@ %@#T @EG' l r
herro there!rgge rfewf rger3%#@ %@#T @EG

Alternate, Shell 9 bytes: submission_2.sh (May be too rule-bendy)

tr $1 $2

Call with

$ ./submission_2.sh l r <<<'hello there!lgge lfewf lger3%#@ %@#T @EG'
herro there!rgge rfewf rger3%#@ %@#T @EG

Explanation

tr by default (without any flags) replaces all chars in the first set with the chars in the second set, completing the operation with the data on standard input.

I'm using this to my advantage by calling TR with the arguments in the correct order, and (in the alternate submission) taking advantage of the handling of standard input by Bourne Shell (sh) to pass standard input to tr without any additional code.

\$\endgroup\$
3
  • \$\begingroup\$ This doesn't seem to comply with “Case should be ignored, so the input "yolO" o u should output yulu.” \$\endgroup\$
    – manatwork
    Commented Sep 9, 2015 at 9:48
  • \$\begingroup\$ WRT your new solution, does the input not all have to be a single list of args ? \$\endgroup\$ Commented Sep 9, 2015 at 13:30
  • \$\begingroup\$ @User112638726 It accepts three args, two presented on the command line, and one presented on standard input. Does this answer your question? \$\endgroup\$
    – Tyzoid
    Commented Sep 9, 2015 at 20:12
2
\$\begingroup\$

Sed, 43 Chars

:;s/(.)(.*\1 (.))$/\3\2/I;t;s/(. .$|")//g

Invoked with the -r flag for extended regex.

\$\endgroup\$
4
  • \$\begingroup\$ The flag actually costs 3 bytes (one of the surrounding spaces is counted as well). That is, unless you would invoke with sed with something like -e anyway and adding the flag would turn this into -re in which case you'd only count 1 byte. See here, section "Special invocations" for the official consensus. \$\endgroup\$ Commented Sep 9, 2015 at 13:05
  • \$\begingroup\$ @MartinBüttner Ok thanks,updated :) \$\endgroup\$ Commented Sep 9, 2015 at 13:16
  • \$\begingroup\$ @MartinBüttner Would using a flag to indicate that it should be run as a script file be counted? What about c++ compiler flags etc? \$\endgroup\$ Commented Sep 9, 2015 at 13:34
  • \$\begingroup\$ I think flags to run the code from the file would be considered standard and not counted. Compiler flags on the other hand generally are counted (except stuff that you need anyway like linker flags). \$\endgroup\$ Commented Sep 9, 2015 at 13:39
2
\$\begingroup\$

C++ 11, Stand-alone: 213 202 198 bytes

Since I haven't seen a solution on C++ yet, I decided to try something myself. This is my first version and I will try to optimize it later.

Source code running:

Live Version: 213 202 198 bytes

#include <algorithm>
#include <iostream>
using namespace std;int main(){string a;getline(cin,a);char b,c;cin.get(b);cin.get(c);replace_if(begin(a),end(a),[b](char d){return!((d-b)%32);},c);cout<<a;}

.

Only the replace function: 121 110 107 bytes

getline(cin,a);cin.get(b);cin.get(c);replace_if(begin(a),end(a),[b](char d){return!((d-b)%32);},c);cout<<a;

.

Feedback is welcome.

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

Python, 58 bytes

Uses case-insensitive regex for substitution.

from re import*
lambda s,t,u:compile(escape(t),I).sub(u,s)
\$\endgroup\$
0
1
\$\begingroup\$

Javascript ES6, 54 chars

f=s=>s.replace(/(.)(?=.* \1 (.)$)/ig,"$2").slice(1,-5)
\$\endgroup\$
1
\$\begingroup\$

PHP, 44 Bytes

<?=str_ireplace($argv[2],$argv[3],$argv[1]);

Called from the command line via php golf.php "Grant Bowtie: Only the best future bass artist ever" : -

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

Python 2.7, 117 bytes

def r(s): print ''.join([list(s)[-1]  if x.lower() == list(s)[-3] else x if x != '\"' else '' for x in list(s)][:-4])

Python certainly won't compare to other golfing languages for this challenge, but nothing beats it for list (in)comprehensions.

If you want it to be a 'standalone' program it increases the size to about 120

import sys
if __name__ == "__main__":
  l, y, z = sys.argv[1:]
  print ''.join([z  if x.lower() == y else x for x in l])
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Hey, welcome to PPCG! Your code can be shortened a bunch by dropping whitespace and converting it to a lambda. I also believe you can take the input as 3 separate arguments, which would shorten your code again. Happy golfing! :) \$\endgroup\$ Commented Sep 8, 2015 at 19:26
1
\$\begingroup\$

Shell, 34 27 35 bytes

#!/bin/sh
echo $1|sed "s/$2/$3/gi"
\$\endgroup\$
1
\$\begingroup\$

Lua, 36 bytes

a=arg[1]:gsub(arg[2],arg[3])print(a)
\$\endgroup\$
1
  • \$\begingroup\$ This doesn't seem to comply with “Case should be ignored, so the input "yolO" o u should output yulu.” \$\endgroup\$
    – manatwork
    Commented Sep 9, 2015 at 13:46
1
\$\begingroup\$

Gema, 40 characters

"*" ? ?=@subst{\\C@quote{?}=@quote{?};*}

Sample run:

bash-4.3$ gema '"*" ? ?=@subst{\\C@quote{?}=@quote{?};*}' <<< '"Hello, World!" l r'
Herro, Worrd!
\$\endgroup\$
1
\$\begingroup\$

O, 31 bytes

i`' /l3-{' \++}d`'"-"(?i)"@+@%p
\$\endgroup\$
0
\$\begingroup\$

Perl, 33 chars (without !#) 48 (including !#)

#!/usr/bin/perl
($_,$b,$c)=@ARGV;
s/$b/$c/i;
print;

My first golf, one of my first perl programs. Probably could be golfed a little more

\$\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.