Selectively replace multiple instances of a character within a string: Difference between revisions
(Added Ada version) |
|||
(22 intermediate revisions by 20 users not shown) | |||
Line 21: | Line 21: | ||
{{Template:Strings}} |
{{Template:Strings}} |
||
<br> |
<br> |
||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">V rep = [‘a’ = [1 = ‘A’, 2 = ‘B’, 4 = ‘C’, 5 = ‘D’], ‘b’ = [1 = ‘E’], ‘r’ = [2 = ‘F’]] |
|||
F trstring(oldstring, repdict) |
|||
DefaultDict[Char, Int] seen |
|||
V newchars = ‘’ |
|||
L(c) oldstring |
|||
V i = ++seen[c] |
|||
newchars ‘’= I c C repdict & i C repdict[c] {repdict[c][i]} E c |
|||
R newchars |
|||
print(‘abracadabra -> ’trstring(‘abracadabra’, rep))</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
abracadabra -> AErBcadCbFD |
|||
</pre> |
|||
=={{header|Ada}}== |
|||
<syntaxhighlight lang="ada"> |
|||
-- Selectively replace multiple instances of a character within a string |
|||
-- J. Carter 2024 Jun |
|||
with Ada.Strings.Fixed; |
|||
with Ada.Text_IO; |
|||
procedure Selectively_Replace is |
|||
procedure Replace |
|||
(Letter : in Character; Occurrence : in Positive; Within : in String; By : in Character; Into : in out String) |
|||
with Pre => Into'First = Within'First and Into'Last = Within'Last; |
|||
-- Finds the index of the Occurrence-th instance of Letter in Within and sets the character in Into at that index to By |
|||
-- If there is no such index, has no effect |
|||
-- Before the first call to replace, Within should be = Into |
|||
procedure Replace |
|||
(Letter : in Character; Occurrence : in Positive; Within : in String; By : in Character; Into : in out String) |
|||
is |
|||
Start : Natural := 0; |
|||
begin -- Replace |
|||
Find : for I in 1 .. Occurrence loop |
|||
Start := Ada.Strings.Fixed.Index (Within, Letter & "", Start + 1); |
|||
if Start = 0 then -- Within has fewer than Occurrence instances of Letter |
|||
return; |
|||
end if; |
|||
end loop Find; |
|||
Into (Start) := By; |
|||
end Replace; |
|||
Source : constant String := "abracadabra"; |
|||
Result : String := Source; |
|||
begin -- Selectively_Replace |
|||
Replace (Letter => 'a', Occurrence => 1, Within => Source, By => 'A', Into => Result); |
|||
Replace (Letter => 'a', Occurrence => 2, Within => Source, By => 'B', Into => Result); |
|||
Replace (Letter => 'a', Occurrence => 4, Within => Source, By => 'C', Into => Result); |
|||
Replace (Letter => 'a', Occurrence => 5, Within => Source, By => 'D', Into => Result); |
|||
Replace (Letter => 'b', Occurrence => 1, Within => Source, By => 'E', Into => Result); |
|||
Replace (Letter => 'r', Occurrence => 2, Within => Source, By => 'F', Into => Result); |
|||
Ada.Text_IO.Put_Line (Item => Source & " => " & Result); |
|||
end Selectively_Replace; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
abracadabra => AErBcadCbFD |
|||
</pre> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
< |
<syntaxhighlight lang="algol68">CO in the string "abracadabra", replace the first 'a' with 'A', the second 'a' with 'B' |
||
, the fourth 'a' with 'C', the fifth 'a' with 'D' |
, the fourth 'a' with 'C', the fifth 'a' with 'D' |
||
the first 'b' with 'E', the second 'r' with 'F' |
the first 'b' with 'E', the second 'r' with 'F' |
||
Line 52: | Line 123: | ||
IF output /= "AErBcadCbFD" THEN print( ( " ** UNEXPECTED RESULT" ) ) FI; |
IF output /= "AErBcadCbFD" THEN print( ( " ** UNEXPECTED RESULT" ) ) FI; |
||
print( ( newline ) ) |
print( ( newline ) ) |
||
END</ |
END</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
"abracadabra" -> "AErBcadCbFD" |
"abracadabra" -> "AErBcadCbFD" |
||
</pre> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="arturo">replacement: function [rule,ch,order][ |
|||
loop rule 'r -> |
|||
if r\[0] = order -> return r\[1] |
|||
return ch |
|||
] |
|||
multiReplace: function [str, rules][ |
|||
cntr: #.raw flatten couple keys rules repeat 0 size rules |
|||
join map str 'ch [ |
|||
(key? cntr ch)? [ |
|||
cntr\[ch]: cntr\[ch] + 1 |
|||
replacement rules\[ch] ch dec cntr\[ch] |
|||
] -> ch |
|||
] |
|||
] |
|||
print multiReplace "abracadabra" #[ |
|||
a: [[0 `A`][1 `B`][3 `C`][4 `D`]] |
|||
b: [[0 `E`]] |
|||
r: [[1 `F`]] |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre>AErBcadCbFD</pre> |
|||
=={{header|AutoHotkey}}== |
|||
<syntaxhighlight lang="autohotkey">str := "abracadabra" |
|||
steps := [[1, "a", "A"] |
|||
, [2, "a", "B"] |
|||
, [4, "a", "C"] |
|||
, [5, "a", "D"] |
|||
, [1, "b", "E"] |
|||
, [2, "r", "F"]] |
|||
MsgBox % result := Selectively_replace(str, steps) |
|||
return |
|||
Selectively_replace(str, steps){ |
|||
Res := [], x := StrSplit(str) |
|||
for i, step in steps { |
|||
n := step.1, L := step.2, R := step.3, k := 0 |
|||
for j, v in x |
|||
if (v=L) && (++k = n) { |
|||
Res[j] := R |
|||
break |
|||
} |
|||
} |
|||
for j, v in x |
|||
result .= Res[j] = "" ? x[j] : Res[j] |
|||
return result |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>AErBcadCbFD</pre> |
|||
=={{header|C}}== |
|||
<syntaxhighlight lang="c"> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
int main(void) { |
|||
const char string[] = "abracadabra"; |
|||
char *replaced = malloc(sizeof(string)); |
|||
strcpy(replaced, string); |
|||
// Null terminated replacement character arrays |
|||
const char *aRep = "ABaCD"; |
|||
const char *bRep = "E"; |
|||
const char *rRep = "rF"; |
|||
for (char *c = replaced; *c; ++c) { |
|||
switch (*c) { |
|||
case 'a': |
|||
if (*aRep) |
|||
*c = *aRep++; |
|||
break; |
|||
case 'b': |
|||
if (*bRep) |
|||
*c = *bRep++; |
|||
break; |
|||
case 'r': |
|||
if (*rRep) |
|||
*c = *rRep++; |
|||
break; |
|||
} |
|||
} |
|||
printf("%s\n", replaced); |
|||
free(replaced); |
|||
return 0; |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
AErBcadCbFD |
|||
</pre> |
</pre> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp">#include <map> |
||
#include <iostream> |
#include <iostream> |
||
#include <string> |
#include <string> |
||
Line 82: | Line 254: | ||
std::cout << magic << "\n"; |
std::cout << magic << "\n"; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
<pre> |
|||
AErBcadCbFD |
|||
</pre> |
|||
=={{header|Delphi}}== |
|||
{{works with|Delphi|6.0}} |
|||
{{libheader|SysUtils,StdCtrls}} |
|||
<syntaxhighlight lang="Delphi"> |
|||
var TestStr: string = 'abracadabra'; |
|||
function FindNthChar(C: char; S: string; N: integer): integer; |
|||
{Routine to find the Nth version of C, string S} |
|||
begin |
|||
for Result:=1 to Length(S) do |
|||
if S[Result]=C then |
|||
begin |
|||
Dec(N); |
|||
if N<=0 then exit; |
|||
end; |
|||
Result:=-1; |
|||
end; |
|||
procedure ReplaceNthChar(COld,CNew: char; var S: string; N: integer); |
|||
{Find and replace the Nth version COld with CNew} |
|||
var Inx: integer; |
|||
begin |
|||
Inx:=FindNthChar(COld,S,N); |
|||
if Inx<1 then exit; |
|||
S[Inx]:=CNew; |
|||
end; |
|||
procedure SelectivelyReplaceChars(Memo: TMemo); |
|||
var I: integer; |
|||
begin |
|||
Memo.Lines.Add('Before: '+TestStr); |
|||
{Do the replacement toward the end of string first} |
|||
ReplaceNthChar('a','D',TestStr,5); |
|||
ReplaceNthChar('a','C',TestStr,4); |
|||
ReplaceNthChar('a','B',TestStr,2); |
|||
ReplaceNthChar('r','F',TestStr,2); |
|||
ReplaceNthChar('a','A',TestStr,1); |
|||
ReplaceNthChar('b','E',TestStr,1); |
|||
Memo.Lines.Add('After: '+TestStr); |
|||
end; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Before: AErBcadCbFD |
|||
After: AErBcAdCEFD |
|||
Elapsed Time: 1.749 ms. |
|||
</pre> |
|||
=={{header|EMal}}== |
|||
<syntaxhighlight lang="emal"> |
|||
fun transmogrify = text by text input, Map replacements |
|||
Map indexes = text%int[] |
|||
text result = "" |
|||
for each text ch in input |
|||
result.append(when(replacements.has(++indexes[ch] + ch), replacements[indexes[ch] + ch], ch)) |
|||
end |
|||
return result |
|||
end |
|||
writeLine(transmogrify("abracadabra", |
|||
text%text["1a" => "A", "2a" => "B", "4a" => "C", "5a" => "D", "1b" => "E", "2r" => "F"])) |
|||
</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 90: | Line 337: | ||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
{{works with|Factor|0.99 2022-04-03}} |
{{works with|Factor|0.99 2022-04-03}} |
||
< |
<syntaxhighlight lang="factor">USING: assocs formatting grouping kernel random sequences ; |
||
CONSTANT: instrs { |
CONSTANT: instrs { |
||
Line 112: | Line 359: | ||
"abracadabra" test |
"abracadabra" test |
||
"abracadabra" randomize test</ |
"abracadabra" randomize test</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 120: | Line 367: | ||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
< |
<syntaxhighlight lang="freebasic">Function replaceChar(Byref S As String) As String |
||
Dim As String A = "ABaCD", B = "Eb", R = "rF" |
Dim As String A = "ABaCD", B = "Eb", R = "rF" |
||
Dim As Byte pA = 1, pB = 1, pR = 1 |
Dim As Byte pA = 1, pB = 1, pR = 1 |
||
Line 144: | Line 391: | ||
S = "caarabadrab" |
S = "caarabadrab" |
||
Print S; " -> "; replaceChar(S) |
Print S; " -> "; replaceChar(S) |
||
Sleep</ |
Sleep</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>abracadabra -> AErBcadCbFD |
<pre>abracadabra -> AErBcadCbFD |
||
caaarrbabad -> cABarFECbDd</pre> |
caaarrbabad -> cABarFECbDd</pre> |
||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
void local fn DoIt |
|||
long a = 0, b = 0, r = 0, length, i |
|||
CFMutableStringRef string = fn MutableStringWithString( @"abracadabra" ) |
|||
CFStringRef s |
|||
length = len(string) |
|||
for i = 0 to length - 1 |
|||
s = NULL |
|||
select ( mid(string,i,1) ) |
|||
case @"a" |
|||
a++ |
|||
select ( a ) |
|||
case 1 : s = @"A" |
|||
case 2 : s = @"B" |
|||
case 4 : s = @"C" |
|||
case 5 : s = @"D" |
|||
end select |
|||
case @"b" |
|||
b++ |
|||
if ( b == 1 ) then s = @"E" |
|||
case @"r" |
|||
r++ |
|||
if ( r == 2 ) then s = @"F" |
|||
end select |
|||
if ( s ) then mid(string,i,1) = s |
|||
next |
|||
NSLog(@"%@",string) |
|||
end fn |
|||
fn DoIt |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
AErBcadCbFD |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{trans|Wren}} |
{{trans|Wren}} |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 176: | Line 467: | ||
s = strings.Replace(s, "F", "r", 1) |
s = strings.Replace(s, "F", "r", 1) |
||
fmt.Println(s) |
fmt.Println(s) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 185: | Line 476: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
As a map-accumulation: |
As a map-accumulation: |
||
< |
<syntaxhighlight lang="haskell">import Data.List (mapAccumL) |
||
import qualified Data.Map.Strict as M |
import qualified Data.Map.Strict as M |
||
import Data.Maybe (fromMaybe) |
import Data.Maybe (fromMaybe) |
||
Line 213: | Line 504: | ||
('b', [Just 'E']), |
('b', [Just 'E']), |
||
('r', [Nothing, Just 'F']) |
('r', [Nothing, Just 'F']) |
||
]</ |
]</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>AErBcadCbFD</pre> |
<pre>AErBcadCbFD</pre> |
||
Line 219: | Line 510: | ||
=={{header|J}}== |
=={{header|J}}== |
||
< |
<syntaxhighlight lang="j"> upd=: {{ x (n{I.y=m)} y }} |
||
'ABCD' 'a' upd 0 1 3 4 'E' 'b' upd 0 'F' 'r' upd 1 'abracadabra' |
'ABCD' 'a' upd 0 1 3 4 'E' 'b' upd 0 'F' 'r' upd 1 'abracadabra' |
||
AErBcadCbFD</ |
AErBcadCbFD</syntaxhighlight> |
||
<tt>upd</tt> here takes four arguments -- two on the left (replacement characters, original character) and two on the right(index values for which instances to replace, and the original string). |
<tt>upd</tt> here takes four arguments -- two on the left (replacement characters, original character) and two on the right(index values for which instances to replace, and the original string). |
||
Line 227: | Line 518: | ||
However, here's a more compact approach (the first item in the left argument is the target, and the rest of the left argument explicitly provides values for every instance of that item in the right argument): |
However, here's a more compact approach (the first item in the left argument is the target, and the rest of the left argument explicitly provides values for every instance of that item in the right argument): |
||
< |
<syntaxhighlight lang="j"> chg=: {{ (}.x) (I.y={.x)} y}} |
||
'aABaCD' chg 'bEb' chg 'rrF' chg 'abracadabra' |
'aABaCD' chg 'bEb' chg 'rrF' chg 'abracadabra' |
||
AErBcadCbFD</ |
AErBcadCbFD</syntaxhighlight> |
||
=={{header|Java}}== |
|||
{{trans|JavaScript}} |
|||
Here's an example translated from JavaScript. |
|||
<syntaxhighlight lang="java"> |
|||
int findNth(String s, char c, int n) { |
|||
if (n == 1) return s.indexOf(c); |
|||
return s.indexOf(c, findNth(s, c, n - 1) + 1); |
|||
} |
|||
String selectiveReplace(String s, Set... ops) { |
|||
char[] chars = s.toCharArray(); |
|||
for (Set set : ops) |
|||
chars[findNth(s, set.old, set.n)] = set.rep; |
|||
return new String(chars); |
|||
} |
|||
record Set(int n, char old, char rep) { } |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="java"> |
|||
selectiveReplace("abracadabra", |
|||
new Set(1, 'a', 'A'), |
|||
new Set(2, 'a', 'B'), |
|||
new Set(4, 'a', 'C'), |
|||
new Set(5, 'a', 'D'), |
|||
new Set(1, 'b', 'E'), |
|||
new Set(2, 'r', 'F')); |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>AErBcadCbFD</pre> |
|||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
< |
<syntaxhighlight lang="javascript">function findNth(s, c, n) { |
||
if (n === 1) return s.indexOf(c); |
if (n === 1) return s.indexOf(c); |
||
return s.indexOf(c, findNth(s, c, n - 1) + 1); |
return s.indexOf(c, findNth(s, c, n - 1) + 1); |
||
Line 254: | Line 577: | ||
[2, "r", "F"], // the second 'r' with 'F' |
[2, "r", "F"], // the second 'r' with 'F' |
||
]) |
]) |
||
);</ |
);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>AErBcadCbFD</pre> |
<pre>AErBcadCbFD</pre> |
||
Line 260: | Line 583: | ||
Or, expressed as a map-accumulation: |
Or, expressed as a map-accumulation: |
||
< |
<syntaxhighlight lang="javascript">(() => { |
||
"use strict"; |
"use strict"; |
||
Line 273: | Line 596: | ||
const ds = a[c]; |
const ds = a[c]; |
||
return |
return Boolean(ds.length) ? [ |
||
Object.assign(a, {[c]: ds.slice(1)}), |
Object.assign(a, {[c]: ds.slice(1)}), |
||
ds[0] || c |
ds[0] || c |
||
] : [a, c]; |
] : [a, c]; |
||
})() : [a, c] |
})() : [a, c] |
||
)(ruleMap) |
)(Object.assign({}, ruleMap))( |
||
[...s] |
|||
)[1].join(""); |
|||
// ---------------------- TEST ----------------------- |
// ---------------------- TEST ----------------------- |
||
const main = () => |
const main = () => |
||
// Instance-specific character replacement rules. |
|||
nthInstanceReplaced({ |
nthInstanceReplaced({ |
||
a: ["A", "B", null, "C", "D"], |
a: ["A", "B", null, "C", "D"], |
||
Line 321: | Line 646: | ||
// MAIN -- |
// MAIN -- |
||
return main(); |
return main(); |
||
})();</ |
})();</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>AErBcadCbFD</pre> |
<pre>AErBcadCbFD</pre> |
||
=={{header|jq}}== |
|||
In this section, array-indexing and occurrence-counting are both 0-based except for the transcription of the task in `steps`. |
|||
'''Generic functions''' |
|||
<syntaxhighlight lang="jq"> |
|||
# Emit empty if the stream does not have an $n-th item |
|||
# Note: jq's nth/2 does not serve our purposes. |
|||
def n_th($n; stream): |
|||
if $n < 0 then empty |
|||
else foreach stream as $x (-1; .+1; if . == $n then $x else empty end) |
|||
end; |
|||
def positions(stream; $v): |
|||
foreach stream as $x (-1; .+1; if $v == $x then . else empty end); |
|||
# Input: an array or string. |
|||
# Output: the input with an occurrence of $old replaced by $new. |
|||
# . and $reference are assumed to be of the same type and length. |
|||
# The search occurs in $reference and the corresponding spot in . is modified. |
|||
def replace_nth($occurrence; $old; $new; $reference): |
|||
if type == "array" |
|||
then ($reference | n_th($occurrence; positions(.[]; $old)) // null) as $ix |
|||
| if $ix then .[:$ix] + [$new] + .[$ix + 1:] else . end |
|||
else explode |
|||
| replace_nth($occurrence; $old|explode|first; $new|explode|first; $reference|explode) |
|||
| implode |
|||
end; |
|||
</syntaxhighlight> |
|||
'''The task''' |
|||
<syntaxhighlight lang="jq"> |
|||
def steps: |
|||
[1, "a", "A"], |
|||
[2, "a", "B"], |
|||
[4, "a", "C"], |
|||
[5, "a", "D"], |
|||
[1, "b", "E"], |
|||
[2, "r", "F"]; |
|||
def task(steps): |
|||
. as $reference |
|||
| reduce steps as [$occurrence, $old, $new] (.; |
|||
replace_nth($occurrence - 1; $old; $new; $reference )); |
|||
"abracadabra" | task(steps) |
|||
</syntaxhighlight> |
|||
{{Output}} |
|||
<pre> |
|||
AErBcadCbFD |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
<syntaxhighlight lang="julia"> |
|||
<lang ruby> |
|||
rep = Dict('a' => Dict(1 => 'A', 2 => 'B', 4 => 'C', 5 => 'D'), 'b' => Dict(1 => 'E'), 'r' => Dict(2 => 'F')) |
rep = Dict('a' => Dict(1 => 'A', 2 => 'B', 4 => 'C', 5 => 'D'), 'b' => Dict(1 => 'E'), 'r' => Dict(2 => 'F')) |
||
Line 340: | Line 716: | ||
println("abracadabra -> ", trstring("abracadabra", rep)) |
println("abracadabra -> ", trstring("abracadabra", rep)) |
||
</ |
</syntaxhighlight>{{out}}Same as Perl. |
||
=={{header|Lambdatalk}}== |
=={{header|Lambdatalk}}== |
||
Line 353: | Line 729: | ||
Then we add to the existing set of array functions a new one finding the indexes of some value in a given array. |
Then we add to the existing set of array functions a new one finding the indexes of some value in a given array. |
||
<syntaxhighlight lang="scheme"> |
|||
<lang Scheme> |
|||
{def A.findindexes |
{def A.findindexes |
||
Line 373: | Line 749: | ||
-> [0,3,5,7,10] |
-> [0,3,5,7,10] |
||
... and so on |
... and so on |
||
</syntaxhighlight> |
|||
</lang> |
|||
Using findindexes we can translate the aA1 aB2 aC4 aD5 bE1 rF2 sequence into a new one where numbers are replaced by indexes in the given string, here abracadabra. |
Using findindexes we can translate the aA1 aB2 aC4 aD5 bE1 rF2 sequence into a new one where numbers are replaced by indexes in the given string, here abracadabra. |
||
<syntaxhighlight lang="scheme"> |
|||
<lang Scheme> |
|||
{def replacements.rules |
{def replacements.rules |
||
{lambda {:w :r} |
{lambda {:w :r} |
||
Line 390: | Line 766: | ||
-> aA0 |
-> aA0 |
||
... and so on |
... and so on |
||
</syntaxhighlight> |
|||
</lang> |
|||
Finally the replacements function will apply this sequence of rules to the word. |
Finally the replacements function will apply this sequence of rules to the word. |
||
<syntaxhighlight lang="scheme"> |
|||
<lang Scheme> |
|||
{def replacements |
{def replacements |
||
Line 419: | Line 795: | ||
-> cABarFECbDd |
-> cABarFECbDd |
||
(cABarFECbDd) |
(cABarFECbDd) |
||
</syntaxhighlight> |
|||
</lang> |
|||
2) second answer using regexps |
2) second answer using regexps |
||
Line 425: | Line 801: | ||
Here is a quick & dirty answer using the S.replace_once primitive. |
Here is a quick & dirty answer using the S.replace_once primitive. |
||
<syntaxhighlight lang="scheme"> |
|||
<lang Scheme> |
|||
{def multrepl_rex |
{def multrepl_rex |
||
{lambda {:word :rules} |
{lambda {:word :rules} |
||
Line 446: | Line 822: | ||
-> AErBcadCbFD |
-> AErBcadCbFD |
||
(AErBcadCbFD) |
(AErBcadCbFD) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="Nim">import std/tables |
|||
type |
|||
# Table of replacements for a character. |
|||
Replacements = Table[int, char] |
|||
# Table mapping characters to their replacement table. |
|||
ReplacementTable = Table[char, Replacements] |
|||
const ReplTable = {'a': {1: 'A', 2: 'B', 4: 'C', 5: 'D'}.toTable, |
|||
'b': {1: 'E'}.toTable, |
|||
'r': {2: 'F'}.toTable |
|||
}.toTable |
|||
proc replace(text: string; replTable: ReplacementTable): string = |
|||
var counts: Table[char, int] # Follow count of characters. |
|||
for c in text: |
|||
if c in replTable: |
|||
counts.mgetOrPut(c, 0).inc # Update count for this char. |
|||
let pos = counts[c] |
|||
result.add replTable[c].getOrDefault(pos, c) |
|||
else: |
|||
result.add c |
|||
echo replace("abracadabra", ReplTable) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>AErBcadCbFD |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">use strict; |
||
use warnings; |
use warnings; |
||
use feature 'say'; |
use feature 'say'; |
||
Line 463: | Line 870: | ||
my $word = 'abracadabra'; |
my $word = 'abracadabra'; |
||
say "$word -> " . transmogrify $word, 'a' => 'AB_CD', 'r' => '_F', 'b' => 'E';</ |
say "$word -> " . transmogrify $word, 'a' => 'AB_CD', 'r' => '_F', 'b' => 'E';</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>abracadabra -> AErBcadCbFD</pre> |
<pre>abracadabra -> AErBcadCbFD</pre> |
||
Line 471: | Line 878: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Couldn't really decide which I prefer so posted both. |
Couldn't really decide which I prefer so posted both. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">function</span> <span style="color: #000000;">replace_nth</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> |
<span style="color: #008080;">function</span> <span style="color: #000000;">replace_nth</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> |
||
Line 495: | Line 902: | ||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},</span><span style="color: #008000;">'r'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"F"</span><span style="color: #0000FF;">}}</span> |
<span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},</span><span style="color: #008000;">'r'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"F"</span><span style="color: #0000FF;">}}</span> |
||
<span style="color: #0000FF;">?</span><span style="color: #000000;">replace_nths</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"abracadabra"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> |
<span style="color: #0000FF;">?</span><span style="color: #000000;">replace_nths</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"abracadabra"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 501: | Line 908: | ||
"AErBcadCbFD" |
"AErBcadCbFD" |
||
</pre> |
</pre> |
||
=={{header|Phixmonti}}== |
|||
<syntaxhighlight lang="Phixmonti">/# Rosetta Code problem: https://rosettacode.org/wiki/Selectively_replace_multiple_instances_of_a_character_within_a_string |
|||
by Galileo, 11/2022 #/ |
|||
include ..\Utilitys.pmt |
|||
"ABaCD" var A "Eb" var B "rF" var R |
|||
"abracadabra" len for >ps |
|||
tps get tochar |
|||
dup "a" == if drop A pop var A tps set else |
|||
dup "b" == if drop B pop var B tps set else |
|||
"r" == if R pop var R tps set |
|||
endif endif endif |
|||
ps> drop |
|||
endfor |
|||
pstack</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
["AErBcadCbFD"] |
|||
=== Press any key to exit ===</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{trans|Julia}} |
{{trans|Julia}} |
||
< |
<syntaxhighlight lang="python">from collections import defaultdict |
||
rep = {'a' : {1 : 'A', 2 : 'B', 4 : 'C', 5 : 'D'}, 'b' : {1 : 'E'}, 'r' : {2 : 'F'}} |
rep = {'a' : {1 : 'A', 2 : 'B', 4 : 'C', 5 : 'D'}, 'b' : {1 : 'E'}, 'r' : {2 : 'F'}} |
||
Line 517: | Line 948: | ||
print('abracadabra ->', trstring('abracadabra', rep)) |
print('abracadabra ->', trstring('abracadabra', rep)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Alternative=== |
===Alternative=== |
||
< |
<syntaxhighlight lang="python">import functools |
||
from typing import Iterable |
from typing import Iterable |
||
Line 553: | Line 984: | ||
], |
], |
||
) |
) |
||
)</ |
)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>AErBcadCbFD</pre> |
<pre>AErBcadCbFD</pre> |
||
Line 559: | Line 990: | ||
Or, as a map-accumulation: |
Or, as a map-accumulation: |
||
< |
<syntaxhighlight lang="python">'''Instance-specific character replacement rules''' |
||
from functools import reduce |
from functools import reduce |
||
Line 568: | Line 999: | ||
def nthInstanceReplaced(ruleMap): |
def nthInstanceReplaced(ruleMap): |
||
def go(a, c): |
def go(a, c): |
||
ds = a.get(c, None) |
|||
return ( |
|||
dict(a, **{c: ds[1:]}), |
|||
ds[0] or c |
|||
) if ds else (a, c) |
|||
) if ds else (a, c) |
|||
else: |
|||
return a, c |
|||
return lambda s: ''.join( |
return lambda s: ''.join( |
||
Line 624: | Line 1,052: | ||
# MAIN --- |
# MAIN --- |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
main()</ |
main()</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>AErBcadCbFD</pre> |
|||
=={{header|Quackery}}== |
|||
If there is no nth instance of a particular character in the string, <code>selectivereplace</code> will disregard it. For example, if the nest of replacements in the example included <code>[ 1 char z char ! ]</code> the output would be the same, as there is no z in "abracadabra". |
|||
<syntaxhighlight lang="Quackery"> [ dup size temp put |
|||
witheach |
|||
[ over = if |
|||
[ swap 1 - |
|||
tuck 0 = if |
|||
[ i^ temp replace |
|||
conclude ] ] ] |
|||
2drop |
|||
temp take ] is nfind ( n c $ --> n ) |
|||
[ temp put |
|||
[] [] rot witheach |
|||
[ 2 pluck |
|||
dip rot join unrot |
|||
nested join ] |
|||
[] swap witheach |
|||
[ do |
|||
temp share nfind |
|||
join ] |
|||
temp take 0 join unrot |
|||
witheach |
|||
[ dip [ behead rot ] |
|||
poke swap ] |
|||
drop |
|||
-1 split drop ] is selectivereplace ( [ $ --> $ ) |
|||
' [ [ 1 char a char A ] |
|||
[ 2 char a char B ] |
|||
[ 4 char a char C ] |
|||
[ 5 char a char D ] |
|||
[ 1 char b char E ] |
|||
[ 2 char r char F ] ] |
|||
$ "abracadabra" |
|||
selectivereplace echo$</syntaxhighlight> |
|||
{{out}} |
|||
<pre>AErBcadCbFD</pre> |
<pre>AErBcadCbFD</pre> |
||
Line 631: | Line 1,103: | ||
Set up to not particularly rely on absolute structure of the word. Demonstrate with both the original 'abracadabra' and with a random shuffled instance. |
Set up to not particularly rely on absolute structure of the word. Demonstrate with both the original 'abracadabra' and with a random shuffled instance. |
||
<lang |
<syntaxhighlight lang="raku" line>sub mangle ($str is copy) { |
||
$str.match(:ex, 'a')».from.map: { $str.substr-rw($_, 1) = 'ABaCD'.comb[$++] }; |
$str.match(:ex, 'a')».from.map: { $str.substr-rw($_, 1) = 'ABaCD'.comb[$++] }; |
||
$str.=subst('b', 'E'); |
$str.=subst('b', 'E'); |
||
Line 640: | Line 1,112: | ||
say $_, ' -> ', .&mangle given 'abracadabra'; |
say $_, ' -> ', .&mangle given 'abracadabra'; |
||
say $_, ' -> ', .&mangle given 'abracadabra'.comb.pick(*).join;</ |
say $_, ' -> ', .&mangle given 'abracadabra'.comb.pick(*).join;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 646: | Line 1,118: | ||
caarabadrab -> cABraECdFDb</pre> |
caarabadrab -> cABraECdFDb</pre> |
||
=={{header| |
=={{header|RPL}}== |
||
The character "-" in the rule string means that no replacement should be made for the occurrence concerned. Any other character can be chosen by modifying the code appropriately. |
|||
Due to the use of <code>INCR</code> and <code>REPL</code> instructions, this program will only work directly on HP48 compatible RPL versions. HP28 users must have programmed their own version of these instructions. |
|||
{| class="wikitable" |
|||
! RPL code |
|||
! Comment |
|||
|- |
|||
| |
|||
≪ 0 → car rule occ |
|||
≪ 1 OVER SIZE '''FOR''' j |
|||
'''IF''' DUP j DUP SUB car == '''THEN''' |
|||
rule 'occ' INCR DUP SUB |
|||
'''IF''' DUP "-" == '''THEN''' DROP '''ELSE''' j SWAP REPL '''END''' |
|||
'''END NEXT''' |
|||
≫ ≫ ''''REPLR'''' STO |
|||
| |
|||
'''REPLR''' ''( "string" "character" "rule" -- "string" ) '' |
|||
loop for j = 1 to string length |
|||
if string[j] == character |
|||
get todo = rule[++occ] |
|||
replace if todo is different from "-" |
|||
end if end loop |
|||
return string |
|||
|} |
|||
{{in}} |
|||
<pre> |
|||
"abracadabra" |
|||
≪ "a" "AB-CD" REPLR "b" "E" REPLR "r" "-F" REPLR ≫ EVAL |
|||
</pre> |
|||
{{out}} |
|||
<pre> |
|||
1: "AErBcadCbFD" |
|||
</pre> |
|||
=={{header|Ruby}}== |
|||
<syntaxhighlight lang="ruby">str = "abracadabra" |
|||
rules = [ |
|||
["a", 1, "A"], |
|||
["a", 2, "B"], |
|||
["a", 4, "C"], |
|||
["a", 5, "D"], |
|||
["b", 1, "E"], |
|||
["r", 2, "F"]] |
|||
indices = Hash.new{[]} |
|||
str.each_char.with_index{|c, i| indices[c] <<= i} |
|||
rules.each{|char, i, to| str[indices[char][i-1]] = to} |
|||
p str</syntaxhighlight> |
|||
{{out}} |
|||
<pre>"AErBcadCbFD" |
|||
</pre> |
|||
=={{header|sed}}== |
|||
<syntaxhighlight lang="sed">s/a\([^a]*\)a\([^a]*a[^a]*\)a\([^a]*\)a/A\1B\2C\3D/ |
|||
s/b/E/ |
|||
s/\(r[^r]*\)r/\1F/</syntaxhighlight> |
|||
=={{header|V (Vlang)}}== |
|||
A similar approach to the C++ entry. |
A similar approach to the C++ entry. |
||
< |
<syntaxhighlight lang="ruby">fn selectively_replace_chars(s string, char_map map[string]string) string { |
||
mut bytes := s.bytes() |
mut bytes := s.bytes() |
||
mut counts := { |
mut counts := { |
||
Line 675: | Line 1,206: | ||
println('$old -> $new') |
println('$old -> $new') |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 688: | Line 1,219: | ||
{{libheader|Wren-regex}} |
{{libheader|Wren-regex}} |
||
Not particularly succinct but, thanks to a recently added library method, better than it would have been :) |
Not particularly succinct but, thanks to a recently added library method, better than it would have been :) |
||
< |
<syntaxhighlight lang="wren">import "./seq" for Lst |
||
import "./str" for Str |
import "./str" for Str |
||
Line 699: | Line 1,230: | ||
s = Str.replace(s, "b", "E", 1) |
s = Str.replace(s, "b", "E", 1) |
||
s = Str.replace(s, "r", "F", 2, 1) |
s = Str.replace(s, "r", "F", 2, 1) |
||
System.print(s)</ |
System.print(s)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 707: | Line 1,238: | ||
Alternatively, using regular expressions (embedded script) producing output as before. |
Alternatively, using regular expressions (embedded script) producing output as before. |
||
< |
<syntaxhighlight lang="wren">import "./regex" for Regex |
||
var s = "abracadabra" |
var s = "abracadabra" |
||
Line 717: | Line 1,248: | ||
s = Regex.compile("b").replace(s, "E") |
s = Regex.compile("b").replace(s, "E") |
||
s = Regex.compile("r").replaceAll(s, "F", 2, 1) |
s = Regex.compile("r").replaceAll(s, "F", 2, 1) |
||
System.print(s)</ |
System.print(s)</syntaxhighlight> |
||
=={{header|XPL0}}== |
=={{header|XPL0}}== |
||
< |
<syntaxhighlight lang="xpl0">string 0; |
||
proc Mangle(S); |
proc Mangle(S); |
||
char S, A, B, R; |
char S, A, B, R; |
||
Line 739: | Line 1,270: | ||
S:= "caarabadrab"; |
S:= "caarabadrab"; |
||
Text(0, S); Text(0, " -> "); Mangle(S); Text(0, S); CrLf(0); |
Text(0, S); Text(0, " -> "); Mangle(S); Text(0, S); CrLf(0); |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
Revision as of 12:55, 20 June 2024
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
This is admittedly a trivial task but I thought it would be interesting to see how succinctly (or otherwise) different languages can handle it.
Given the string: "abracadabra", replace programatically:
- the first 'a' with 'A'
- the second 'a' with 'B'
- the fourth 'a' with 'C'
- the fifth 'a' with 'D'
- the first 'b' with 'E'
- the second 'r' with 'F'
Note that there is no replacement for the third 'a', second 'b' or first 'r'.
The answer should, of course, be : "AErBcadCbFD".
- Metrics
- Counting
- Word frequency
- Letter frequency
- Jewels and stones
- I before E except after C
- Bioinformatics/base count
- Count occurrences of a substring
- Count how many vowels and consonants occur in a string
- Remove/replace
- XXXX redacted
- Conjugate a Latin verb
- Remove vowels from a string
- String interpolation (included)
- Strip block comments
- Strip comments from a string
- Strip a set of characters from a string
- Strip whitespace from a string -- top and tail
- Strip control codes and extended characters from a string
- Anagrams/Derangements/shuffling
- Word wheel
- ABC problem
- Sattolo cycle
- Knuth shuffle
- Ordered words
- Superpermutation minimisation
- Textonyms (using a phone text pad)
- Anagrams
- Anagrams/Deranged anagrams
- Permutations/Derangements
- Find/Search/Determine
- ABC words
- Odd words
- Word ladder
- Semordnilap
- Word search
- Wordiff (game)
- String matching
- Tea cup rim text
- Alternade words
- Changeable words
- State name puzzle
- String comparison
- Unique characters
- Unique characters in each string
- Extract file extension
- Levenshtein distance
- Palindrome detection
- Common list elements
- Longest common suffix
- Longest common prefix
- Compare a list of strings
- Longest common substring
- Find common directory path
- Words from neighbour ones
- Change e letters to i in words
- Non-continuous subsequences
- Longest common subsequence
- Longest palindromic substrings
- Longest increasing subsequence
- Words containing "the" substring
- Sum of the digits of n is substring of n
- Determine if a string is numeric
- Determine if a string is collapsible
- Determine if a string is squeezable
- Determine if a string has all unique characters
- Determine if a string has all the same characters
- Longest substrings without repeating characters
- Find words which contains all the vowels
- Find words which contains most consonants
- Find words which contains more than 3 vowels
- Find words which first and last three letters are equals
- Find words which odd letters are consonants and even letters are vowels or vice_versa
- Formatting
- Substring
- Rep-string
- Word wrap
- String case
- Align columns
- Literals/String
- Repeat a string
- Brace expansion
- Brace expansion using ranges
- Reverse a string
- Phrase reversals
- Comma quibbling
- Special characters
- String concatenation
- Substring/Top and tail
- Commatizing numbers
- Reverse words in a string
- Suffixation of decimal numbers
- Long literals, with continuations
- Numerical and alphabetical suffixes
- Abbreviations, easy
- Abbreviations, simple
- Abbreviations, automatic
- Song lyrics/poems/Mad Libs/phrases
- Mad Libs
- Magic 8-ball
- 99 Bottles of Beer
- The Name Game (a song)
- The Old lady swallowed a fly
- The Twelve Days of Christmas
- Tokenize
- Text between
- Tokenize a string
- Word break problem
- Tokenize a string with escaping
- Split a character string based on change of character
- Sequences
11l
V rep = [‘a’ = [1 = ‘A’, 2 = ‘B’, 4 = ‘C’, 5 = ‘D’], ‘b’ = [1 = ‘E’], ‘r’ = [2 = ‘F’]]
F trstring(oldstring, repdict)
DefaultDict[Char, Int] seen
V newchars = ‘’
L(c) oldstring
V i = ++seen[c]
newchars ‘’= I c C repdict & i C repdict[c] {repdict[c][i]} E c
R newchars
print(‘abracadabra -> ’trstring(‘abracadabra’, rep))
- Output:
abracadabra -> AErBcadCbFD
Ada
-- Selectively replace multiple instances of a character within a string
-- J. Carter 2024 Jun
with Ada.Strings.Fixed;
with Ada.Text_IO;
procedure Selectively_Replace is
procedure Replace
(Letter : in Character; Occurrence : in Positive; Within : in String; By : in Character; Into : in out String)
with Pre => Into'First = Within'First and Into'Last = Within'Last;
-- Finds the index of the Occurrence-th instance of Letter in Within and sets the character in Into at that index to By
-- If there is no such index, has no effect
-- Before the first call to replace, Within should be = Into
procedure Replace
(Letter : in Character; Occurrence : in Positive; Within : in String; By : in Character; Into : in out String)
is
Start : Natural := 0;
begin -- Replace
Find : for I in 1 .. Occurrence loop
Start := Ada.Strings.Fixed.Index (Within, Letter & "", Start + 1);
if Start = 0 then -- Within has fewer than Occurrence instances of Letter
return;
end if;
end loop Find;
Into (Start) := By;
end Replace;
Source : constant String := "abracadabra";
Result : String := Source;
begin -- Selectively_Replace
Replace (Letter => 'a', Occurrence => 1, Within => Source, By => 'A', Into => Result);
Replace (Letter => 'a', Occurrence => 2, Within => Source, By => 'B', Into => Result);
Replace (Letter => 'a', Occurrence => 4, Within => Source, By => 'C', Into => Result);
Replace (Letter => 'a', Occurrence => 5, Within => Source, By => 'D', Into => Result);
Replace (Letter => 'b', Occurrence => 1, Within => Source, By => 'E', Into => Result);
Replace (Letter => 'r', Occurrence => 2, Within => Source, By => 'F', Into => Result);
Ada.Text_IO.Put_Line (Item => Source & " => " & Result);
end Selectively_Replace;
- Output:
abracadabra => AErBcadCbFD
ALGOL 68
CO in the string "abracadabra", replace the first 'a' with 'A', the second 'a' with 'B'
, the fourth 'a' with 'C', the fifth 'a' with 'D'
the first 'b' with 'E', the second 'r' with 'F'
CO
BEGIN
[,]STRING replacements = ( ( "a", "ABaCD" ), ( "b", "E" ), ( "r", "rF" ) );
[ 1 LWB replacements : 1 UPB replacements ]INT position;
STRING input = "abracadabra";
[ LWB input : UPB input ]CHAR output;
FOR i FROM LWB position TO UPB position DO position[ i ] := LWB replacements[ i, 2 ] OD;
FOR c pos FROM LWB input TO UPB input DO
CHAR c = input[ c pos ];
output[ c pos ] := c;
BOOL found := FALSE;
FOR r pos FROM 1 LWB replacements TO 1 UPB replacements WHILE NOT found DO
STRING r = replacements[ r pos, 1 ];
IF c = r[ LWB r ] THEN
found := TRUE;
IF position[ r pos ] <= UPB replacements[ r pos, 2 ] THEN
output[ c pos ] := replacements[ r pos, 2 ][ position[ r pos ] ];
position[ r pos ] +:= 1;
found := TRUE
FI
FI
OD
OD;
print( ( """", input, """ -> """, output, """" ) );
IF output /= "AErBcadCbFD" THEN print( ( " ** UNEXPECTED RESULT" ) ) FI;
print( ( newline ) )
END
- Output:
"abracadabra" -> "AErBcadCbFD"
Arturo
replacement: function [rule,ch,order][
loop rule 'r ->
if r\[0] = order -> return r\[1]
return ch
]
multiReplace: function [str, rules][
cntr: #.raw flatten couple keys rules repeat 0 size rules
join map str 'ch [
(key? cntr ch)? [
cntr\[ch]: cntr\[ch] + 1
replacement rules\[ch] ch dec cntr\[ch]
] -> ch
]
]
print multiReplace "abracadabra" #[
a: [[0 `A`][1 `B`][3 `C`][4 `D`]]
b: [[0 `E`]]
r: [[1 `F`]]
]
- Output:
AErBcadCbFD
AutoHotkey
str := "abracadabra"
steps := [[1, "a", "A"]
, [2, "a", "B"]
, [4, "a", "C"]
, [5, "a", "D"]
, [1, "b", "E"]
, [2, "r", "F"]]
MsgBox % result := Selectively_replace(str, steps)
return
Selectively_replace(str, steps){
Res := [], x := StrSplit(str)
for i, step in steps {
n := step.1, L := step.2, R := step.3, k := 0
for j, v in x
if (v=L) && (++k = n) {
Res[j] := R
break
}
}
for j, v in x
result .= Res[j] = "" ? x[j] : Res[j]
return result
}
- Output:
AErBcadCbFD
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char string[] = "abracadabra";
char *replaced = malloc(sizeof(string));
strcpy(replaced, string);
// Null terminated replacement character arrays
const char *aRep = "ABaCD";
const char *bRep = "E";
const char *rRep = "rF";
for (char *c = replaced; *c; ++c) {
switch (*c) {
case 'a':
if (*aRep)
*c = *aRep++;
break;
case 'b':
if (*bRep)
*c = *bRep++;
break;
case 'r':
if (*rRep)
*c = *rRep++;
break;
}
}
printf("%s\n", replaced);
free(replaced);
return 0;
}
- Output:
AErBcadCbFD
C++
#include <map>
#include <iostream>
#include <string>
int main()
{
std::map<char, std::string> rep =
{{'a', "DCaBA"}, // replacement string is reversed
{'b', "E"},
{'r', "Fr"}};
std::string magic = "abracadabra";
for(auto it = magic.begin(); it != magic.end(); ++it)
{
if(auto f = rep.find(*it); f != rep.end() && !f->second.empty())
{
*it = f->second.back();
f->second.pop_back();
}
}
std::cout << magic << "\n";
}
- Output:
AErBcadCbFD
Delphi
var TestStr: string = 'abracadabra';
function FindNthChar(C: char; S: string; N: integer): integer;
{Routine to find the Nth version of C, string S}
begin
for Result:=1 to Length(S) do
if S[Result]=C then
begin
Dec(N);
if N<=0 then exit;
end;
Result:=-1;
end;
procedure ReplaceNthChar(COld,CNew: char; var S: string; N: integer);
{Find and replace the Nth version COld with CNew}
var Inx: integer;
begin
Inx:=FindNthChar(COld,S,N);
if Inx<1 then exit;
S[Inx]:=CNew;
end;
procedure SelectivelyReplaceChars(Memo: TMemo);
var I: integer;
begin
Memo.Lines.Add('Before: '+TestStr);
{Do the replacement toward the end of string first}
ReplaceNthChar('a','D',TestStr,5);
ReplaceNthChar('a','C',TestStr,4);
ReplaceNthChar('a','B',TestStr,2);
ReplaceNthChar('r','F',TestStr,2);
ReplaceNthChar('a','A',TestStr,1);
ReplaceNthChar('b','E',TestStr,1);
Memo.Lines.Add('After: '+TestStr);
end;
- Output:
Before: AErBcadCbFD After: AErBcAdCEFD Elapsed Time: 1.749 ms.
EMal
fun transmogrify = text by text input, Map replacements
Map indexes = text%int[]
text result = ""
for each text ch in input
result.append(when(replacements.has(++indexes[ch] + ch), replacements[indexes[ch] + ch], ch))
end
return result
end
writeLine(transmogrify("abracadabra",
text%text["1a" => "A", "2a" => "B", "4a" => "C", "5a" => "D", "1b" => "E", "2r" => "F"]))
- Output:
AErBcadCbFD
Factor
USING: assocs formatting grouping kernel random sequences ;
CONSTANT: instrs {
CHAR: a 1 CHAR: A
CHAR: a 2 CHAR: B
CHAR: a 4 CHAR: C
CHAR: a 5 CHAR: D
CHAR: b 1 CHAR: E
CHAR: r 2 CHAR: F
}
: counts ( seq -- assoc )
H{ } clone swap [ 2dup swap inc-at dupd of ] zip-with nip ;
: replace-nths ( seq instrs -- seq' )
[ counts ] dip 3 group [ f suffix 2 group ] map substitute keys ;
: test ( str -- )
dup instrs replace-nths "" like "%s -> %s\n" printf ;
"abracadabra" test
"abracadabra" randomize test
- Output:
abracadabra -> AErBcadCbFD caaarrbabad -> cABarFECbDd
FreeBASIC
Function replaceChar(Byref S As String) As String
Dim As String A = "ABaCD", B = "Eb", R = "rF"
Dim As Byte pA = 1, pB = 1, pR = 1
For i As Byte = 0 To Len(S)
Select Case Mid(S,i,1)
Case "a"
Mid(S,i,1) = Mid(A,pA,1)
pA += 1
Case "b"
Mid(S,i,1) = Mid(B,pB,1)
pB += 1
Case "r"
Mid(S,i,1) = Mid(R,pR,1)
pR += 1
End Select
Next i
Return S
End Function
Dim As String S
S = "abracadabra"
Print S; " -> "; replaceChar(S)
S = "caarabadrab"
Print S; " -> "; replaceChar(S)
Sleep
- Output:
abracadabra -> AErBcadCbFD caaarrbabad -> cABarFECbDd
FutureBasic
include "NSLog.incl"
void local fn DoIt
long a = 0, b = 0, r = 0, length, i
CFMutableStringRef string = fn MutableStringWithString( @"abracadabra" )
CFStringRef s
length = len(string)
for i = 0 to length - 1
s = NULL
select ( mid(string,i,1) )
case @"a"
a++
select ( a )
case 1 : s = @"A"
case 2 : s = @"B"
case 4 : s = @"C"
case 5 : s = @"D"
end select
case @"b"
b++
if ( b == 1 ) then s = @"E"
case @"r"
r++
if ( r == 2 ) then s = @"F"
end select
if ( s ) then mid(string,i,1) = s
next
NSLog(@"%@",string)
end fn
fn DoIt
HandleEvents
- Output:
AErBcadCbFD
Go
package main
import (
"fmt"
"strings"
)
func main() {
s := "abracadabra"
ss := []byte(s)
var ixs []int
for ix, c := range s {
if c == 'a' {
ixs = append(ixs, ix)
}
}
repl := "ABaCD"
for i := 0; i < 5; i++ {
ss[ixs[i]] = repl[i]
}
s = string(ss)
s = strings.Replace(s, "b", "E", 1)
s = strings.Replace(s, "r", "F", 2)
s = strings.Replace(s, "F", "r", 1)
fmt.Println(s)
}
- Output:
AErBcadCbFD
Haskell
As a map-accumulation:
import Data.List (mapAccumL)
import qualified Data.Map.Strict as M
import Data.Maybe (fromMaybe)
---------- POSITIONAL CHARACTER-REPLACEMENT RULES --------
nthCharsReplaced :: M.Map Char [Maybe Char] -> String -> String
nthCharsReplaced ruleMap = snd . mapAccumL go ruleMap
where
go a c =
case M.lookup c a of
Nothing -> (a, c)
Just [] -> (a, c)
Just (d : ds) ->
( M.insert c ds a,
fromMaybe c d
)
--------------------------- TEST -------------------------
main :: IO ()
main = putStrLn $ nthCharsReplaced rules "abracadabra"
rules :: M.Map Char [Maybe Char]
rules =
M.fromList
[ ('a', (Just <$> "AB") <> [Nothing] <> (Just <$> "CD")),
('b', [Just 'E']),
('r', [Nothing, Just 'F'])
]
- Output:
AErBcadCbFD
J
upd=: {{ x (n{I.y=m)} y }}
'ABCD' 'a' upd 0 1 3 4 'E' 'b' upd 0 'F' 'r' upd 1 'abracadabra'
AErBcadCbFD
upd here takes four arguments -- two on the left (replacement characters, original character) and two on the right(index values for which instances to replace, and the original string).
However, here's a more compact approach (the first item in the left argument is the target, and the rest of the left argument explicitly provides values for every instance of that item in the right argument):
chg=: {{ (}.x) (I.y={.x)} y}}
'aABaCD' chg 'bEb' chg 'rrF' chg 'abracadabra'
AErBcadCbFD
Java
Here's an example translated from JavaScript.
int findNth(String s, char c, int n) {
if (n == 1) return s.indexOf(c);
return s.indexOf(c, findNth(s, c, n - 1) + 1);
}
String selectiveReplace(String s, Set... ops) {
char[] chars = s.toCharArray();
for (Set set : ops)
chars[findNth(s, set.old, set.n)] = set.rep;
return new String(chars);
}
record Set(int n, char old, char rep) { }
selectiveReplace("abracadabra",
new Set(1, 'a', 'A'),
new Set(2, 'a', 'B'),
new Set(4, 'a', 'C'),
new Set(5, 'a', 'D'),
new Set(1, 'b', 'E'),
new Set(2, 'r', 'F'));
- Output:
AErBcadCbFD
JavaScript
function findNth(s, c, n) {
if (n === 1) return s.indexOf(c);
return s.indexOf(c, findNth(s, c, n - 1) + 1);
}
function selectiveReplace(s, ops) {
const chars = Array.from(s);
for ([n, old, rep] of ops) {
chars[findNth(s, old, n)] = rep;
}
return chars.join("");
}
console.log(
selectiveReplace("abracadabra", [
[1, "a", "A"], // the first 'a' with 'A'
[2, "a", "B"], // the second 'a' with 'B'
[4, "a", "C"], // the fourth 'a' with 'C'
[5, "a", "D"], // the fifth 'a' with 'D'
[1, "b", "E"], // the first 'b' with 'E'
[2, "r", "F"], // the second 'r' with 'F'
])
);
- Output:
AErBcadCbFD
Or, expressed as a map-accumulation:
(() => {
"use strict";
// -- INSTANCE-SPECIFIC CHARACTER REPLACEMENT RULES --
// # nthInstanceReplaced :: Dict Char [(Null | Char)] ->
const nthInstanceReplaced = ruleMap =>
// A string defined by replacements specified for
// the nth instances of various characters.
s => mapAccumL(
(a, c) => c in a ? (() => {
const ds = a[c];
return Boolean(ds.length) ? [
Object.assign(a, {[c]: ds.slice(1)}),
ds[0] || c
] : [a, c];
})() : [a, c]
)(Object.assign({}, ruleMap))(
[...s]
)[1].join("");
// ---------------------- TEST -----------------------
const main = () =>
// Instance-specific character replacement rules.
nthInstanceReplaced({
a: ["A", "B", null, "C", "D"],
b: ["E"],
r: [null, "F"]
})(
"abracadabra"
);
// --------------------- GENERIC ---------------------
// mapAccumL :: (acc -> x -> (acc, y)) -> acc ->
// [x] -> (acc, [y])
const mapAccumL = f =>
// A tuple of an accumulation and a list
// obtained by a combined map and fold,
// with accumulation from left to right.
acc => xs => [...xs].reduce(
([a, bs], x) => second(
v => [...bs, v]
)(
f(a, x)
),
[acc, []]
);
// second :: (a -> b) -> ((c, a) -> (c, b))
const second = f =>
// A function over a simple value lifted
// to a function over a tuple.
// f (a, b) -> (a, f(b))
([x, y]) => [x, f(y)];
// MAIN --
return main();
})();
- Output:
AErBcadCbFD
jq
In this section, array-indexing and occurrence-counting are both 0-based except for the transcription of the task in `steps`.
Generic functions
# Emit empty if the stream does not have an $n-th item
# Note: jq's nth/2 does not serve our purposes.
def n_th($n; stream):
if $n < 0 then empty
else foreach stream as $x (-1; .+1; if . == $n then $x else empty end)
end;
def positions(stream; $v):
foreach stream as $x (-1; .+1; if $v == $x then . else empty end);
# Input: an array or string.
# Output: the input with an occurrence of $old replaced by $new.
# . and $reference are assumed to be of the same type and length.
# The search occurs in $reference and the corresponding spot in . is modified.
def replace_nth($occurrence; $old; $new; $reference):
if type == "array"
then ($reference | n_th($occurrence; positions(.[]; $old)) // null) as $ix
| if $ix then .[:$ix] + [$new] + .[$ix + 1:] else . end
else explode
| replace_nth($occurrence; $old|explode|first; $new|explode|first; $reference|explode)
| implode
end;
The task
def steps:
[1, "a", "A"],
[2, "a", "B"],
[4, "a", "C"],
[5, "a", "D"],
[1, "b", "E"],
[2, "r", "F"];
def task(steps):
. as $reference
| reduce steps as [$occurrence, $old, $new] (.;
replace_nth($occurrence - 1; $old; $new; $reference ));
"abracadabra" | task(steps)
- Output:
AErBcadCbFD
Julia
rep = Dict('a' => Dict(1 => 'A', 2 => 'B', 4 => 'C', 5 => 'D'), 'b' => Dict(1 => 'E'), 'r' => Dict(2 => 'F'))
function trstring(oldstring, repdict)
seen, newchars = Dict{Char, Int}(), Char[]
for c in oldstring
i = get!(seen, c, 1)
push!(newchars, haskey(repdict, c) && haskey(repdict[c], i) ? repdict[c][i] : c)
seen[c] += 1
end
return String(newchars)
end
println("abracadabra -> ", trstring("abracadabra", rep))
- Output:
Same as Perl.
Lambdatalk
1) first answer
We first translate the replacements program into a sequence of rules
the first 'a' with 'A' -> aA1 ...and so on
Then we add to the existing set of array functions a new one finding the indexes of some value in a given array.
{def A.findindexes
{def A.findindexes.rec
{lambda {:v :a :b :i}
{if {A.empty? :a}
then :b
else {A.findindexes.rec :v {A.rest :a}
{if {W.equal? {A.first :a} :v}
then {A.addlast! :i :b}
else :b}
{+ :i 1}} }}}
{lambda {:v :a}
{A.findindexes.rec :v :a {A.new} 0} }}
-> A.findindexes
{A.findindexes a {A.split abracadabra}}
-> [0,3,5,7,10]
... and so on
Using findindexes we can translate the aA1 aB2 aC4 aD5 bE1 rF2 sequence into a new one where numbers are replaced by indexes in the given string, here abracadabra.
{def replacements.rules
{lambda {:w :r}
{A.new
{W.get 0 :r}
{W.get 1 :r}
{A.get {- {W.get 2 :r} 1} // arrays begin at 0
{A.findindexes {W.get 0 :r} {A.split :w}}}}}}
-> replacements.rules
{A.join {replacements.rules abracadabra aA1}}
-> aA0
... and so on
Finally the replacements function will apply this sequence of rules to the word.
{def replacements
{def replacements.rec
{lambda {:word :rules}
{if {A.empty? :rules}
then {A.join :word}
else {replacements.rec {A.set! {A.get 2 {A.first :rules}}
{A.get 1 {A.first :rules}}
:word}
{A.rest :rules}} }}}
{lambda {:word :rules}
{replacements.rec
{A.split :word}
{A.map {replacements.rules :word} {A.new :rules}} }}}
-> replacements
{replacements abracadabra aA1 aB2 aC4 aD5 bE1 rF2}
-> AErBcadCbFD
(AErBcadCbFD)
{replacements caaarrbabad aA1 aB2 aC4 aD5 bE1 rF2}
-> cABarFECbDd
(cABarFECbDd)
2) second answer using regexps
Here is a quick & dirty answer using the S.replace_once primitive.
{def multrepl_rex
{lambda {:word :rules}
{if {A.empty? :rules}
then :word
else {multrepl_rex
{S.replace_once {W.first {A.first :rules}}
by {W.last {A.first :rules}}
in :word }
{A.rest :rules}} }}}
-> multrepl_rex
{multrepl_rex
abracadabra
{A.new
aA aB a3 aC aD 3a // save third "a" as "3" and restore it
bE // first "b"
r1 rF 1r // save first "r" as "1" and restore it
}}
-> AErBcadCbFD
(AErBcadCbFD)
Nim
import std/tables
type
# Table of replacements for a character.
Replacements = Table[int, char]
# Table mapping characters to their replacement table.
ReplacementTable = Table[char, Replacements]
const ReplTable = {'a': {1: 'A', 2: 'B', 4: 'C', 5: 'D'}.toTable,
'b': {1: 'E'}.toTable,
'r': {2: 'F'}.toTable
}.toTable
proc replace(text: string; replTable: ReplacementTable): string =
var counts: Table[char, int] # Follow count of characters.
for c in text:
if c in replTable:
counts.mgetOrPut(c, 0).inc # Update count for this char.
let pos = counts[c]
result.add replTable[c].getOrDefault(pos, c)
else:
result.add c
echo replace("abracadabra", ReplTable)
- Output:
AErBcadCbFD
Perl
use strict;
use warnings;
use feature 'say';
sub transmogrify {
my($str, %sub) = @_;
for my $l (keys %sub) {
$str =~ s/$l/$_/ for split '', $sub{$l};
$str =~ s/_/$l/g;
}
$str
}
my $word = 'abracadabra';
say "$word -> " . transmogrify $word, 'a' => 'AB_CD', 'r' => '_F', 'b' => 'E';
- Output:
abracadabra -> AErBcadCbFD
Phix
Couldn't really decide which I prefer so posted both.
with javascript_semantics function replace_nth(string s, r) string res = s for i=1 to length(r) by 3 do res[find_all(r[i],s)[r[i+1]-'0']] = r[i+2] end for return res end function ?replace_nth("abracadabra","a1Aa2Ba4Ca5Db1Er2F") -- Alternative version function replace_nths(string s, sequence r) for icr in r do {sequence idx, integer ch, string reps} = icr s = reinstate(s,extract(find_all(ch,s),idx),reps) end for return s end function constant r = {{{1,2,4,5},'a',"ABCD"}, {{1},'b',"E"}, {{2},'r',"F"}} ?replace_nths("abracadabra",r)
- Output:
"AErBcadCbFD" "AErBcadCbFD"
Phixmonti
/# Rosetta Code problem: https://rosettacode.org/wiki/Selectively_replace_multiple_instances_of_a_character_within_a_string
by Galileo, 11/2022 #/
include ..\Utilitys.pmt
"ABaCD" var A "Eb" var B "rF" var R
"abracadabra" len for >ps
tps get tochar
dup "a" == if drop A pop var A tps set else
dup "b" == if drop B pop var B tps set else
"r" == if R pop var R tps set
endif endif endif
ps> drop
endfor
pstack
- Output:
["AErBcadCbFD"] === Press any key to exit ===
Python
from collections import defaultdict
rep = {'a' : {1 : 'A', 2 : 'B', 4 : 'C', 5 : 'D'}, 'b' : {1 : 'E'}, 'r' : {2 : 'F'}}
def trstring(oldstring, repdict):
seen, newchars = defaultdict(lambda:1, {}), []
for c in oldstring:
i = seen[c]
newchars.append(repdict[c][i] if c in repdict and i in repdict[c] else c)
seen[c] += 1
return ''.join(newchars)
print('abracadabra ->', trstring('abracadabra', rep))
Alternative
import functools
from typing import Iterable
from typing import Tuple
@functools.cache
def find_nth(s: str, sub: str, n: int) -> int:
assert n >= 1
if n == 1:
return s.find(sub)
return s.find(sub, find_nth(s, sub, n - 1) + 1)
def selective_replace(s: str, ops: Iterable[Tuple[int, str, str]]) -> str:
chars = list(s)
for n, old, new in ops:
chars[find_nth(s, old, n)] = new
return "".join(chars)
print(
selective_replace(
"abracadabra",
[
(1, "a", "A"), # the first 'a' with 'A'
(2, "a", "B"), # the second 'a' with 'B'
(4, "a", "C"), # the fourth 'a' with 'C'
(5, "a", "D"), # the fifth 'a' with 'D'
(1, "b", "E"), # the first 'b' with 'E'
(2, "r", "F"), # the second 'r' with 'F'
],
)
)
- Output:
AErBcadCbFD
Or, as a map-accumulation:
'''Instance-specific character replacement rules'''
from functools import reduce
# nthInstanceReplaced :: Dict Char [(None | Char)] ->
# String -> String
def nthInstanceReplaced(ruleMap):
def go(a, c):
ds = a.get(c, None)
return (
dict(a, **{c: ds[1:]}),
ds[0] or c
) if ds else (a, c)
return lambda s: ''.join(
mapAccumL(go)(ruleMap)(s)[1]
)
# ------------------------- TEST -------------------------
def main():
'''Rule-set applied to a given string.'''
print(
nthInstanceReplaced({
'a': ['A', 'B', None, 'C', 'D'],
'b': ['E'],
'r': [None, 'F']
})(
"abracadabra"
)
)
# ----------------------- GENERIC ------------------------
# mapAccumL :: (acc -> x -> (acc, y)) ->
# acc -> [x] -> (acc, [y])
def mapAccumL(f):
'''A tuple of an accumulation and a map
with accumulation from left to right.
'''
def go(a, x):
return second(lambda v: a[1] + [v])(
f(a[0], x)
)
return lambda acc: lambda xs: reduce(
go, xs, (acc, [])
)
# second :: (a -> b) -> ((c, a) -> (c, b))
def second(f):
'''A simple function lifted to a function over a tuple,
with f applied only to the second of two values.
'''
return lambda xy: (xy[0], f(xy[1]))
# MAIN ---
if __name__ == '__main__':
main()
- Output:
AErBcadCbFD
Quackery
If there is no nth instance of a particular character in the string, selectivereplace
will disregard it. For example, if the nest of replacements in the example included [ 1 char z char ! ]
the output would be the same, as there is no z in "abracadabra".
[ dup size temp put
witheach
[ over = if
[ swap 1 -
tuck 0 = if
[ i^ temp replace
conclude ] ] ]
2drop
temp take ] is nfind ( n c $ --> n )
[ temp put
[] [] rot witheach
[ 2 pluck
dip rot join unrot
nested join ]
[] swap witheach
[ do
temp share nfind
join ]
temp take 0 join unrot
witheach
[ dip [ behead rot ]
poke swap ]
drop
-1 split drop ] is selectivereplace ( [ $ --> $ )
' [ [ 1 char a char A ]
[ 2 char a char B ]
[ 4 char a char C ]
[ 5 char a char D ]
[ 1 char b char E ]
[ 2 char r char F ] ]
$ "abracadabra"
selectivereplace echo$
- Output:
AErBcadCbFD
Raku
Set up to not particularly rely on absolute structure of the word. Demonstrate with both the original 'abracadabra' and with a random shuffled instance.
sub mangle ($str is copy) {
$str.match(:ex, 'a')».from.map: { $str.substr-rw($_, 1) = 'ABaCD'.comb[$++] };
$str.=subst('b', 'E');
$str.substr-rw($_, 1) = 'F' given $str.match(:ex, 'r')».from[1];
$str
}
say $_, ' -> ', .&mangle given 'abracadabra';
say $_, ' -> ', .&mangle given 'abracadabra'.comb.pick(*).join;
- Output:
abracadabra -> AErBcadCbFD caarabadrab -> cABraECdFDb
RPL
The character "-" in the rule string means that no replacement should be made for the occurrence concerned. Any other character can be chosen by modifying the code appropriately.
Due to the use of INCR
and REPL
instructions, this program will only work directly on HP48 compatible RPL versions. HP28 users must have programmed their own version of these instructions.
RPL code | Comment |
---|---|
≪ 0 → car rule occ ≪ 1 OVER SIZE FOR j IF DUP j DUP SUB car == THEN rule 'occ' INCR DUP SUB IF DUP "-" == THEN DROP ELSE j SWAP REPL END END NEXT ≫ ≫ 'REPLR' STO |
REPLR ( "string" "character" "rule" -- "string" ) loop for j = 1 to string length if string[j] == character get todo = rule[++occ] replace if todo is different from "-" end if end loop return string |
- Input:
"abracadabra" ≪ "a" "AB-CD" REPLR "b" "E" REPLR "r" "-F" REPLR ≫ EVAL
- Output:
1: "AErBcadCbFD"
Ruby
str = "abracadabra"
rules = [
["a", 1, "A"],
["a", 2, "B"],
["a", 4, "C"],
["a", 5, "D"],
["b", 1, "E"],
["r", 2, "F"]]
indices = Hash.new{[]}
str.each_char.with_index{|c, i| indices[c] <<= i}
rules.each{|char, i, to| str[indices[char][i-1]] = to}
p str
- Output:
"AErBcadCbFD"
sed
s/a\([^a]*\)a\([^a]*a[^a]*\)a\([^a]*\)a/A\1B\2C\3D/
s/b/E/
s/\(r[^r]*\)r/\1F/
V (Vlang)
A similar approach to the C++ entry.
fn selectively_replace_chars(s string, char_map map[string]string) string {
mut bytes := s.bytes()
mut counts := {
'a': 0
'b': 0
'r': 0
}
for i := s.len - 1; i >= 0; i-- {
c := s[i].ascii_str()
if c in ['a', 'b', 'r'] {
bytes[i] = char_map[c][counts[c]]
counts[c]++
}
}
return bytes.bytestr()
}
fn main() {
char_map := {
'a': 'DCaBA'
'b': 'bE'
'r': 'Fr'
}
for old in ['abracadabra', 'caaarrbabad'] {
new := selectively_replace_chars(old, char_map)
println('$old -> $new')
}
}
- Output:
abracadabra -> AErBcadCbFD caaarrbabad -> cABarFECbDd
Wren
Not particularly succinct but, thanks to a recently added library method, better than it would have been :)
import "./seq" for Lst
import "./str" for Str
var s = "abracadabra"
var sl = s.toList
var ixs = Lst.indicesOf(sl, "a")[2]
var repl = "ABaCD"
for (i in 0..4) sl[ixs[i]] = repl[i]
s = sl.join()
s = Str.replace(s, "b", "E", 1)
s = Str.replace(s, "r", "F", 2, 1)
System.print(s)
- Output:
AErBcadCbFD
Alternatively, using regular expressions (embedded script) producing output as before.
import "./regex" for Regex
var s = "abracadabra"
var split = Regex.compile("a").split(s)
var repl = "ABaCD"
var res = ""
for (i in 0...split.count-1) res = res + split[i] + repl[i]
s = res + split[-1]
s = Regex.compile("b").replace(s, "E")
s = Regex.compile("r").replaceAll(s, "F", 2, 1)
System.print(s)
XPL0
string 0;
proc Mangle(S);
char S, A, B, R;
[A:= "ABaCD"; B:= "Eb"; R:= "rF";
while S(0) do
[case S(0) of
^a: [S(0):= A(0); A:= A+1];
^b: [S(0):= B(0); B:= B+1];
^r: [S(0):= R(0); R:= R+1]
other [];
S:= S+1;
];
];
char S;
[S:= "abracadabra";
Text(0, S); Text(0, " -> "); Mangle(S); Text(0, S); CrLf(0);
S:= "caarabadrab";
Text(0, S); Text(0, " -> "); Mangle(S); Text(0, S); CrLf(0);
]
- Output:
abracadabra -> AErBcadCbFD caarabadrab -> cABraECdFDb