Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The idea is simple. You've to create a "visualised" letter-replacement, by providing 3 strings (input can be comma separated, separate inputs, or as an array). The first segment is the word you want to correct, and the second segment is the letters you want to replace, and the third segment is the replacement for the letters in segment 2.

For example:

|    | Input                       | Starting Word | Output      |
|----|-----------------------------|---------------|-------------|
| #1 | Hello world -wo -ld +Ea +th | Hello world   | Hello Earth |
| #2 | Hello World -wo -ld +Ea +th | Hello World   | Hello Worth |
| #3 | Hello -llo +y               | Hello         | Hey         |
| #4 | Red -R -d +Gr +en           | Red           | Green       |
| #5 | mississippi -is -i +lz +p   | mississippi   | mlzslzspppp |
| #6 | Football -o -a +a +i        | Football      | Fiitbill    |
| #7 | mississippi -is -i +iz +p   | mississippi   | mpzspzspppp |

Explanation

The replacements are to be done step-by-step with their respective pair. Here's an illustration with an input of mississippi -is -i +iz +p to give the output mpzspzsppp (see example #7 above)

| Step  | Input                         | Output        |
|------ |---------------------------    |-------------  |
| #1    | mississippi -is -i +iz +p     |               |
| #2    | mississippi -is +iz           | mizsizsippi   |
| #3    | mizsizsippi -i +p             | mpzspzspppp   |

Rules

  • Inputs are always in this order <starting_string> <list_of_letters_to_replace> <replacement_letters>.
  • Letters to replace and replacement groups will never be mixed (ie: there will never be -a +i -e +o).
  • Letters to replace are always prefixed with - and replacement letters are always prefixed with +. (The prefix is mandatory)
  • There may be more than one set of letters to replace, so you'd need to look at the prefix.
  • Assume the amount of letter groups to replace and the amount of replacement letter groups are always equal (ie: there will never be -a -e +i)
  • Replacements are case-sensitive (see example #1 and #2).
  • Replacements are done in the order they were given in the input.
  • Letter replacements can be replaced with other replacements. See example #6.
  • The first segment (starting word) will never include - or + characters.
  • This is code-golf so shortest bytes win.

Leaderboards

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

var QUESTION_ID=96473,OVERRIDE_USER=38505;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"http://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

share|improve this question
1  
Given rules 2 and 5, you really don't need to look at the prefix. With n inputs, input 0 is the base string, inputs 1 to int(n/2) are letter to replace (with prefix -) and input int(n/2)+1 to n-1 are replacement (with prefix +) – edc65 yesterday
    
@edc65 100% true, although the challenge was designed to have the prefix (and I could make up some weird explanation that I'm an alien who cannot process letter replacements without their prefix) but in reality, it's just another barrier to stop this being too trivial - though looking at the current answers (all are great by the way) it wasn't a complex barrier. Also fun fact, the idea behind this challenge was spawned from my friend in a Skype chat. He'd mis-spell a word (gello), and then send me the letter replacements (-g +h) because he wanted to be annoying instead of sending hello*. – ʰᵈˑ yesterday
1  
Inputs are always in this order Why so restrictive? – Luis Mendo yesterday
    
@LuisMendo I guess it doesn't really matter - but it's the way my friend and I formatted it, but since answers have been posted to this requirement, I cannot really make a rule change. It wasn't questioned on the sandbox, so I didn't think of it as a negative. – ʰᵈˑ yesterday
1  
@udioica is perfecly right and it in fact support the "Replacements are case-sensitive" rule. Run the snippet in the JavaScript answer to see it implemented. (#1 world` vs #2 World) – edc65 yesterday

15 Answers 15

JavaScript (ES6), 85 83 bytes

f=(s,n=1,l=s.split(/ \W/))=>(r=l[n+l.length/2|0])?f(s.split(l[n]).join(r),n+1):l[0]

Test cases

f=(s,n=1,l=s.split(/ \W/))=>(r=l[n+l.length/2|0])?f(s.split(l[n]).join(r),n+1):l[0]

console.log(f("Hello world -wo -ld +Ea +th"));
console.log(f("Hello World -wo -ld +Ea +th"));
console.log(f("Hello -llo +y"));
console.log(f("Red -R -d +Gr +en"));
console.log(f("mississippi -is -i +lz +p"));
console.log(f("Football -o -a +a +i"));
console.log(f("mississippi -is -i +iz +p"));

share|improve this answer

Pyke, 13 11 bytes

z[zdcmt)[.:

Try it here!

z           - input()
 [zdcmt)    - def func():
  zdc       -  input().split(" ")
     mt     -  map(>[1:], ^)
            - func()
        [   - func()
         .: - translate()

Or 2 bytes if in a different input format:

.:

Try it here!

share|improve this answer
    
Does this produce the required intermediate results? – Luis Mendo yesterday
    
At work catbus.co.uk is blocked. Are you able to link an alternative test suite please? – ʰᵈˑ yesterday
2  
@ʰᵈˑ I don't believe conforming to your (arbitrary) work firewall settings is reasonable. – orlp yesterday
    
@orlp - I agree, it's shit. But I don't set the firewall settings. I just wanted to test it out – ʰᵈˑ yesterday
2  
@hd you can download Pyke at github.com/muddyfish/pyke – muddyfish yesterday

05AB1E, 15 17 bytes

IIð¡€áIð¡€á‚øvy`:

Try it online!

Explanation

I                   # read starting string
 I                  # read letters to be replaced
  ð¡                # split on space
    ۇ              # and remove "-"
      I             # read replacement letters
       ð¡           # split on space
         ۇ         # and remove "+"
           ‚ø       # zip to produce pairs of [letters to replace, replacement letters]
             vy`:   # for each pair, replace in starting string

Or with a less strict input format

vy`:

Try it online

share|improve this answer

Perl, 58 bytes

57 bytes code + 1 for -p.

Requires first item on one line, then the replacements on the next. Big thanks to @Dada who came up with a different approach to help reduce by 4 bytes!

$a=<>;1while$a=~s%-(\S*)(.*?)\+(\S*)%"s/$1/$3/g;q{$2}"%ee

Usage

perl -pe '$a=<>;1while$a=~s%-(\S*)(.*?)\+(\S*)%"s/$1/$3/g;q{$2}"%ee' <<< 'Football
-o -a +a +i'
Fiitbill
perl -pe '$a=<>;1while$a=~s%-(\S*)(.*?)\+(\S*)%"s/$1/$3/g;q{$2}"%ee' <<< 'mississippi
-is -i +iz +p'
mpzspzspppp
perl -pe '$a=<>;1while$a=~s%-(\S*)(.*?)\+(\S*)%"s/$1/$3/g;q{$2}"%ee' <<< 'mississippi
-ippi -i -mess +ee +e +tenn'
tennessee
share|improve this answer
    
4 bytes longer, there is perl -pE 's/(.*?) -(\S*)(.*?)\+(\S*)/"(\$1=~s%$2%$4%gr).\"$3\""/ee&&redo'. I can't manage to get it any shorter, but maybe you can :) – Dada yesterday
1  
Gotcha! 58 bytes : perl -pE '$a=<>;1while$a=~s%-(\S*)(.*?)\+(\S*)%"s/$1/$3/g;q{$2}"%ee'. (takes the string on one line, and the "flags" on the next line) – Dada 23 hours ago
1  
Awesome! I'm not at a computer but I'll update that tomorrow! Thanks! – Dom Hastings 20 hours ago
    
Are you sure about removing the q{} surrounding $2 ? Wouldn't this fail when there are 3 - and 3 + switches? (I can't test it now, so maybe you were right so remove it ;) ) – Dada 5 hours ago
    
@Dada ahhh, I did wonder why you'd added it, I tested all the cases in the test suite, but didn't think about a 3 for 3 replacement... – Dom Hastings 5 hours ago

GNU sed 86 Bytes

Includes +1 for -r

:;s,^([^-]*)(\w+)([^-]*-)\2( [^+]*\+)(\w*),\1\5\3\2\4\5,
t;s,-[^-+]*,,;s,\+[^-+]*,,;t

Try it online!

Example:

$ echo 'Hello world -wo -ld +Ea +th'|sed -rf replace.sed
Hello Earth
share|improve this answer

PHP, 98 97 bytes

for($s=$argv[$i=1];$v=$argv[++$i];)$r[$v[0]>'+'][]=substr($v,1);echo str_replace($r[1],$r[0],$s);

This challenge describes the exact behaviour of str_replace so for php it's all about making the arrays of replacements. I tried to do it using only one "substring" but that might not be the best solution. Use like:

php -r "for($s=$argv[$i=1];$v=$argv[++$i];)$r[$v[0]>'+'][]=substr($v,1);echo str_replace($r[1],$r[0],$s);" "mississippi" "-is" "-i" "+iz" "+p"

edit: 1 byte saved thanks to Titus

share|improve this answer
    
This is probably the shortest thing possible. But $v[0]>'+' saves one byte over $v[0]=='-'. You could also use ord($v)&4 instead. – Titus 21 hours ago

Java 7, 153 133 bytes

String c(String[]a){String r=a[0],z[]=a[1].split(" ?-");for(int i=0;i<z.length;r=r.replace(z[i],a[2].split(" ?[+]")[i++]));return r;}

Ungolfed & test code:

Try it here.

class M{
  static String c(String[] a){
    String r = a[0],
           z[] = a[1].split(" ?-");
    for(int i = 0; i < z.length; r = r.replace(z[i], a[2].split(" ?[+]")[i++]));
    return r;
  }

  public static void main(String[] a){
    System.out.println(c(new String[]{ "Hello world", "-wo -ld", "+Ea +th" }));
    System.out.println(c(new String[]{ "Hello World", "-wo -ld", "+Ea +th" }));
    System.out.println(c(new String[]{ "Hello", "-llo", "+y" }));
    System.out.println(c(new String[]{ "Red", "-R -d", "+Gr +en" }));
    System.out.println(c(new String[]{ "mississippi", "-is -i", "+lz +p" }));
    System.out.println(c(new String[]{ "Football", "-o -a", "+a +i" }));
    System.out.println(c(new String[]{ "mississippi", "-is -i", "+iz +p" }));
  }
}

Output:

Hello Earth
Hello Worth
Hey
Green
mlzslzspppp
Fiitbill
mpzspzspppp
share|improve this answer
    
Does this work for the input new String[]{'Rom Ro. Rom", "-Ro." , "+No."}? Just writing something that (hopefully) matches a wrong regex. – Roman Gräf 11 hours ago
    
@RomanGräf Yes, works and outputs Rom No. Rom. Btw, you can try it yourself by clicking the Try it here. link in the post, and then fork it. :) – Kevin Cruijssen 10 hours ago
    
I know but I'm currently on my mobile. :( – Roman Gräf 9 hours ago

PHP, 164 Bytes

preg_match_all("#^[^-+]+|-[\S]+|[+][\S]+#",$argv[1],$t);for($s=($a=$t[0])[0];++$i<$c=count($a)/2;)$s=str_replace(trim($a[+$i],"-"),trim($a[$i+$c^0],"+"),$s);echo$s;
share|improve this answer

Convex, 19 bytes

¶:äz{S*"-+"-ä~@\ò}/

Try it online!

share|improve this answer

R, 98 94 bytes

Edit: saved 4 bytes thanks to @rturnbull

i=scan(,"");s=i[1];i=gsub("\\+|-","",i[-1]);l=length(i)/2;for(j in 1:l)s=gsub(i[j],i[l+j],s);s

Ungolfed and test cases

Because scan (reads input from stdin) doesn't work properly in R-fiddle I showcase the program by wrapping it in a function instead. Note that the function takes a vector as an input and can be run by e.g.: f(c("Hello world", "-wo", "-ld", "+Ea", "+th")). The gofled program above would prompt the user to input using stdin whereby typing "Hello world" -wo -ld -Ea +th in the console would yield the same result.

Run the code on R-fiddle

f=function(i){
    s=i[1]                                   # Separate first element
    i=gsub("\\+|-","",i[-1])                 # Remove + and - from all elements except first, store as vector i
    l=length(i)/2                            # calculate the length of the vector i (should always be even)
    for(j in 1:l)s=gsub(i[j],i[l+j],s)       # iteratively match element j in i and substitute with element l+j in i
    s                                        # print to stdout
}
share|improve this answer
    
Can you provide a test suite link also, please? – ʰᵈˑ yesterday
    
@ʰᵈˑ added an R-fiddle test suite. Note that the test suite uses a function instead of reading input from stdin as explained in the edited answer. – Billywob yesterday
    
Is this answer valid, since you have to use " around the input string? – rturnbull 19 hours ago
    
@rturnbull I don't see why not. Wrapping every entry with quotes and pressing enter would yield the equivalent result (e.g.: "Hello world" => enter => "-wo" => enter => "-ld" => enter => "+Ea" => enter =>"+th") which is usually how strings are read anyways. – Billywob 19 hours ago
1  
Yeah it's really up to the OP! I personally like your answer as-is, but I was worried that it might be invalid. Looking at answers for other languages it seems like quotes are pretty accepted. While I have your attention, I think you can golf off 4 bytes by changing l=length(i) to l=length(i)/2 and updating the later references to l. – rturnbull 19 hours ago

Python 3, 93 byte

def f(s):
  s,m,p=s
  for n,o in zip(m.split(),p.split()):s=s.replace(n[1:],o[1:])
  return s

Try it online!

Input is a list with strings, replacement strings are space separated.

Example input: ['mississippi','-is -i','+iz +p']

share|improve this answer
    
Are you able to add a test suite link, please? – ʰᵈˑ yesterday
    
Link provided and also reduced size a little. – Gábor Fekete yesterday
    
Awesome! thanks – ʰᵈˑ yesterday

Vim, 25 bytes

qq+dE+r-PdiW:1s<C-R>"-g<CR>@qq@q

Assumes input in this format:

mississippi
-is -i
+lz +p
  • +dE+r-PdiW: Combines - and + into single register, with the + turned into a -.
  • :1s<C-R>"-g: Uses the register as a code snippet, inserted directly into the :s command, with - as the separator.
share|improve this answer

PowerShell v2+, 90 bytes

param($a,$b,$c)-split$b|%{$a=$a-creplace($_-replace'-'),((-split$c)[$i++]-replace'\+')};$a

Takes input as three arguments, with the - and + strings space-separated. Performs a -split on $b (the -split when acting in a unary fashion splits on whitespace), then loops |%{...} through each of those. Every iteration we're removing the -, finding the next [$i++] replacement string and removing the + from it, and using the -creplace (case-sensitive replacement) to slice and dice $a and store it back into $a. Then, $a is left on the pipeline and output is implicit.

PS C:\Tools\Scripts\golfing> .\letter-replacement-challenge.ps1 'mississippi' '-is -i' '+iz +p'
mpzspzspppp

PS C:\Tools\Scripts\golfing> .\letter-replacement-challenge.ps1 'Hello world' '-wo -ld' '+Ea +th'
Hello Earth

PS C:\Tools\Scripts\golfing> .\letter-replacement-challenge.ps1 'Hello World' '-wo -ld' '+Ea +th'
Hello Worth
share|improve this answer

Haskell, 85 bytes

import Data.Lists
g=map tail.words
(a#b)c=foldl(\z(x,y)->replace x y z)a$zip(g b)$g c

Usage example: ("mississippi" # "-is -i") "+lz +p" -> "mlzslzspppp".

How it works:

g=map tail.words              -- helper function that splits a string into a
                              -- list of words (at spaces) and drops the first
                              -- char of each word

                zip(g b)$g c  -- make pairs of strings to be replaced and its
                              -- replacement
foldl(\z(x,y)->replace x y z) -- execute each replacement, starting with the
                              -- original string
share|improve this answer

PHP, 106 bytes

for($s=($v=$argv)[$i=1];$i++<$n=$argc/2;)$s=str_replace(substr($v[$i],1),substr($v[$n+$i-1],1),$s);echo$s;

straight forward approach. Run with php -r '<code> <arguments>.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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