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\$
  • 4
    \$\begingroup\$ Are functions allowed? \$\endgroup\$ – Downgoat Sep 8 '15 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\$ – Reto Koradi Sep 8 '15 at 3:27
  • 2
    \$\begingroup\$ @vihan Functions are allowed. \$\endgroup\$ – The_Basset_Hound Sep 8 '15 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\$ – Reto Koradi Sep 8 '15 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 Sep 8 '15 at 5:35

28 Answers 28

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\$
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\$
  • 1
    \$\begingroup\$ +1 for Vim ... not something oft-seen :) \$\endgroup\$ – AdmBorkBork Sep 8 '15 at 14:35
  • 1
    \$\begingroup\$ Your ending file shouldn't contain the quotation marks \$\endgroup\$ – Nathan Merrill Sep 9 '15 at 13:20
  • \$\begingroup\$ @NathanMerrill Fixed. \$\endgroup\$ – orlp Sep 13 '15 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\$
  • \$\begingroup\$ That was quick. I appear to have made this too easy again... \$\endgroup\$ – The_Basset_Hound Sep 8 '15 at 1:46
  • 8
    \$\begingroup\$ Is it correct to use 3 arguments instead of 1 string? \$\endgroup\$ – Qwertiy Sep 8 '15 at 9:44
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\$
  • 1
    \$\begingroup\$ How does this work? \$\endgroup\$ – mbomb007 Sep 8 '15 at 21:59
  • \$\begingroup\$ @mbomb007 Edited. Let me know if you have further questions. \$\endgroup\$ – Martin Ender Sep 9 '15 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\$
  • \$\begingroup\$ This doesn't work. \$\endgroup\$ – User112638726 Sep 9 '15 at 9:52
  • \$\begingroup\$ Hmm... it works with gawk and mawk... \$\endgroup\$ – Cabbie407 Sep 9 '15 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\$ – User112638726 Sep 9 '15 at 12:24
  • 1
    \$\begingroup\$ Few less characters awk 'IGNORECASE=gsub(/"/,x)gsub($(NF-1),$NF)(NF-=2)' \$\endgroup\$ – User112638726 Sep 9 '15 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 Sep 9 '15 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\$
  • \$\begingroup\$ Word list, Template, Fill-in? \$\endgroup\$ – ಠ_ಠ Sep 13 '15 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\$
  • \$\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. Sep 8 '15 at 2:16
  • \$\begingroup\$ Also this is 30 bytes, not 29. \$\endgroup\$ – Alex A. Sep 8 '15 at 2:18
  • 1
    \$\begingroup\$ For the same length function(s,c,r)chartr(c,r,s) \$\endgroup\$ – MickyT Sep 8 '15 at 3:24
  • \$\begingroup\$ @MickyT, but chartr is case-sensitive. \$\endgroup\$ – flodel Sep 10 '15 at 23:04
  • \$\begingroup\$ My bad sorry. I didn't think it through properly. \$\endgroup\$ – MickyT Sep 10 '15 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
    \$\begingroup\$ You don't need the last ~. The result won't be a string, but the output won't look different. \$\endgroup\$ – Dennis Sep 8 '15 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\$
  • \$\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 Sep 8 '15 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\$ – AdmBorkBork Sep 9 '15 at 13:11
  • \$\begingroup\$ You're correct; I've removed my comments about the regex, it's not an issue. \$\endgroup\$ – briantist Sep 9 '15 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\$
  • \$\begingroup\$ no it doesn't. It lower cases the entire thing. \$\endgroup\$ – Maltysen Sep 8 '15 at 2:36
  • \$\begingroup\$ @Maltysen fixed \$\endgroup\$ – Downgoat Sep 8 '15 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\$ – Reto Koradi Sep 8 '15 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 Sep 8 '15 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\$ – Reto Koradi Sep 8 '15 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\$
  • \$\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\$ – Reto Koradi Sep 8 '15 at 3:21
  • 1
    \$\begingroup\$ @RetoKoradi sorry, fixing. \$\endgroup\$ – Maltysen Sep 8 '15 at 3:37
  • 1
    \$\begingroup\$ It looks like we don't have consensus on the input requirements. Some people interpret them differently. \$\endgroup\$ – Reto Koradi Sep 8 '15 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\$
  • \$\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\$ – Reto Koradi Sep 8 '15 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 Sep 8 '15 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 Sep 8 '15 at 16:28
  • 1
    \$\begingroup\$ string with lowercase first letter. With uppercase one it requires System. And you can remove space after []. \$\endgroup\$ – Qwertiy Sep 8 '15 at 16:34
  • 1
    \$\begingroup\$ By the way - great idea to allow command line to parse the string. \$\endgroup\$ – Qwertiy Sep 8 '15 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\$
  • \$\begingroup\$ This doesn't seem to comply with “Case should be ignored, so the input "yolO" o u should output yulu.” \$\endgroup\$ – manatwork Sep 9 '15 at 9:48
  • \$\begingroup\$ WRT your new solution, does the input not all have to be a single list of args ? \$\endgroup\$ – User112638726 Sep 9 '15 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 Sep 9 '15 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\$
  • \$\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\$ – Martin Ender Sep 9 '15 at 13:05
  • \$\begingroup\$ @MartinBüttner Ok thanks,updated :) \$\endgroup\$ – User112638726 Sep 9 '15 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\$ – User112638726 Sep 9 '15 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\$ – Martin Ender Sep 9 '15 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\$
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
    \$\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\$ – FryAmTheEggman Sep 8 '15 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\$
  • \$\begingroup\$ This doesn't seem to comply with “Case should be ignored, so the input "yolO" o u should output yulu.” \$\endgroup\$ – manatwork Sep 9 '15 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, privacy policy and cookie policy

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