What my dog really hears

83

14

My dog is called Rex. Every time I scold him, he seems not very impressed and the only times I see him react is when I pronounce his name. If I say

Rex, I told you not to do this! You're making me angry Rex!

all he hears is

Rex, * **** *** *** ** ** ****! ***'** ****** ** ***** Rex!

The challenge : given an input string, your program must output the same string where all alphabetic characters have been turned to stars, except the characters in the appearances of the word Rex, who must be left untouched. The non-alphabetic characters are also left untouched.

Details : The challenge is case-insensitive, thus rex must be left untouched also. The word Rex can be part of another word, so for example anorexic must be rendered as ***rex**.

Update : as the initial text of this challenge did not clarify how underscores or numbers or accentuated characters should be treated, I do not make any special requirement on those characters. Thus, a solution is valid as long as characters in a-zA-Z (and also the one mentioned in the examples, ,!".) are handled correctly.

Test cases :

Input : Rex lives in Rexland.

Output : Rex ***** ** Rex****.

Input : To call Rex, just say "Rex".

Output : ** **** Rex, **** *** "Rex".

Input : My cat is getting anorexic.

Output : ** *** ** ******* ***rex**.

Ewan Delanoy

Posted 2017-05-09T08:07:29.990

Reputation: 995

Will the string contain newlines? – Neil – 2017-05-09T09:12:08.587

27Test case: Hello! Isn't this ... a nice challenge? Can you dog hear *****! ***'* *** ... * **** *********?? If so, you might consider communicating in morse from now on... – Stewie Griffin – 2017-05-09T09:16:17.173

2Do we only need to support a-zA-Z, or also 0-9 and/or äëïöüÿãõñáéíóúýàèìòùç etc. etc.? And could you add some test cases regarding these? – Kevin Cruijssen – 2017-05-09T09:20:41.320

2@KevinCruijssen Since $0-9$ or accented characters are not mentioned in the initial challenge, do not consider them as part of the challenge. – Ewan Delanoy – 2017-05-09T09:23:29.447

@Shaggy I think we can assume standard ASCII, but replace digits or not is a good question. – Titus – 2017-05-09T10:47:45.713

@Shaggy The non-alphabetic characters are also left untouched. Alphabetic characters don't include digits. – 2501 – 2017-05-09T10:55:50.767

Can I have an additional new line character at the end? – Christoph – 2017-05-09T10:57:41.153

Will there be newlines in the middle of the string? – Mego – 2017-05-09T11:30:21.950

7

Since "dogs don't get the difference between lowercase and uppercase", may the output case be different to the input? (For example: input="Rex lives in Rexland.", output="rex ***** ** rex****."; or alternatively input="My cat is getting anorexic.", output="** *** ** ******* ***Rex**.")

– Jonathan Allan – 2017-05-09T16:02:44.450

I once had a dog that could spell. – Joshua – 2017-05-10T18:07:27.967

@Joshua Really ? – Ewan Delanoy – 2017-05-10T18:12:12.810

@EwanDelanoy: Yeah really. We're pretty sure it came from spelling words we didn't want him to overhear. Near the end we were pretty sure he could spell any word he knew, which was quite a few. – Joshua – 2017-05-10T18:14:17.477

1Does Rex not respond to [Dog park, walk, treat]? When my dog was shaking I made a joke about him having "Dog parkinsons" and he definitely only heard "Dog park******" – Nic Robertson – 2017-05-10T21:36:02.907

@Adám Indeed. Sorry for the mistake, I just corrected it – Ewan Delanoy – 2017-05-11T09:22:36.680

@EwanDelanoy You may want to wait more than two days before accepting an answer, for two reasons: Challenges with no accepted submission may be less attractive, and you are likely to have to reaccept (which could cause bad feelings). I generally wait a week or so, except if there is a 0-2 byte solution. – Adám – 2017-05-11T09:25:25.070

@Adám Thanks you for your advice. I don't have much experience for participating in this forum. At least my motives for reaccepting are crystal clear (number of bytes). – Ewan Delanoy – 2017-05-11T09:35:24.970

Ewan, we still need an answer to @Adám's question about underscores.

– Shaggy – 2017-05-11T12:07:56.047

@Adám Yes, I wasn't sure about the best way to fix the challenge and had forgotten about my earlier comment. Hope it's all OK now – Ewan Delanoy – 2017-05-11T13:31:57.623

@EwanDelanoy Yes, thank you. – Adám – 2017-05-11T13:35:46.707

Thanks, @Adám & Ewan; that saves me 3 bytes :)

– Shaggy – 2017-05-11T13:55:52.187

5

Why did this challenge use asterisks instead of "blah"s???

– hBy2Py – 2017-05-11T19:44:53.517

1

Idea possibly from Far Side.

– imallett – 2017-05-13T06:49:15.763

This answer is shorter than my accepted one. – Adám – 2017-06-27T02:25:22.617

My new answer is shorter than the newly accepted one. – Adám – 2017-06-27T09:16:53.240

Answers

25

Retina, 24 21 bytes

i`(rex)|(\w)
$1$#2$**

Try it online!

Explanation

Skipping rexs is easiest by matching them as well, because matches can't overlap. So if we give priority to rex over other letters, those will be covered in a single match and not touched by the individual-letter matches.

But how do we do different things depending on the alternative that was used for the match? Unfortunately, Retina doesn't (yet) have any conditional substitution syntax like the Boost regex flavour. But we can fake it by including both substitutions in a single replacement and making sure that only one of them is non-empty:

  • $1 is the first capturing group, i.e. the (rex). If we did match rex this simply writes it back (so it does nothing), but if we didn't match rex then $1 is an empty string and vanishes.
  • $#2$** should be read as ($#2)$*(*). $#2 is the number of times group 2 was used, i.e. the (\w). If we matched rex this is 0, but if we matched any other individual letter, this is 1. $* repeats the next character as many times as its left-hand operand. So this part inserts a single * for individual-letter matches and nothing at all for rex.

Martin Ender

Posted 2017-05-09T08:07:29.990

Reputation: 184 808

Doesn't retina have \a for [a-z] z.B.? – Leaky Nun – 2017-05-09T12:44:27.737

@LeakyNun no. I'd have to tokenise the regex (or even implement my own flavour) to add any features to the regex flavour itself. – Martin Ender – 2017-05-09T12:45:52.593

163

**REXX 151 148 141 bytes **

(Kinda seemed appropriate)

i=arg(1)
m=i
o=translate(m,'',xrange('A','z'),'*')
p=0
do forever
   p=pos('REX',m,p+1)
   if p=0 then leave
   o=overlay(substr(i,p,3),o,p)
end
say o

Try it here

Notes for non-REXXers:

  1. translate is a character replacement function (name comes from an assembler instruction on IBM MF). It searches string1 for the characters in string3. Every time it finds one it replaces it with the same positioned one in string2. If string2 is too short it is padded with the pad character.

See here for translate function

  1. overlay simply overlays the string1 on top of string2 at the specified position.

See here for overlay function

theblitz

Posted 2017-05-09T08:07:29.990

Reputation: 1 201

52... but the dog thought he programmed it in REX*. – GuitarPicker – 2017-05-09T13:24:08.313

10How many of these upvotes are purely for the choice of language?! :D – Shaggy – 2017-05-09T15:05:29.210

72@Shaggy At least all of them – TheLethalCoder – 2017-05-09T15:39:54.820

24

JavaScript (ES6), 42 41 38 bytes

s=>s.replace(/rex|\w/gi,m=>m[1]?m:"*")

Try It

o.innerText=(f=

s=>s.replace(/rex|\w/gi,m=>m[1]?m:"*")

)(i.value="Rex, I told you not to do this! You're making me angry Rex!")
oninput=_=>o.innerText=f(i.value)
<input id=i><pre id=o>


Explanation

s=>            :Anonymous function that takes the string as an argument via parameter s.
s.replace(x,y) :Replace x in s with y.
/rex|\w/gi     :Case-insenstive regular expression that globally matches all occurrences
                of "rex" or any single letter, number or underscore.
                (numbers & underscores will never be included in the input.)
m=>            :Anonymous function that takes each match as an argument via parameter m.
m[1]?          :If string m has a second character, ...
                (Equivalent to m.charAt(1))
m              :Return m, ...
:"*"           :Otherwise return "*".

Shaggy

Posted 2017-05-09T08:07:29.990

Reputation: 24 623

1nice solution!. – Steve Bennett – 2017-05-09T10:49:55.243

13

APL (Dyalog Unicode), 22 bytesSBCS

'rex' '\w'⎕R'\0' '*'⍠1

Try it online!

Simple PCRE Replace.

⍠1 sets case insensitivity. Simply replaces rex with itself and all other word characters with asterisks.

Adám

Posted 2017-05-09T08:07:29.990

Reputation: 37 779

\w includes the underscore character, assuming this is RegEx - I don't know APL. – Shaggy – 2017-05-09T22:10:24.283

@Shaggy Yeah, Dyalog APL uses PCRE, but it is not certain from OP that underscores will occur. E.g. digits will not. – Adám – 2017-05-09T22:13:13.553

Do we not have to assume they can occur, unless told otherwise? – Shaggy – 2017-05-09T22:15:50.667

@Shaggy Normally, yes, but this seems to indicate that what isn't mentioned will not occur. OP only mentions comma, period, space, and exclamation point.

– Adám – 2017-05-09T22:17:58.000

Hmm ... I think I'll wait for confirmation that they won't occur, seeing as I've left that comment about \w on a few answers now! – Shaggy – 2017-05-10T08:41:18.043

11

Perl 5, 24 bytes

23 bytes of code + -p flag.

I used Martin Ender's regex from his Retina answer (which happens to be shorter in Perl, thanks to \pl), and only had to adapt the right side of the s///.

s%(rex)|\pl%$1//"*"%gie

Try it online!

Dada

Posted 2017-05-09T08:07:29.990

Reputation: 8 279

8

Retina, 32 31 bytes

iS`(rex)
%iT`Ll`*`^(?!rex).*
¶

Try it online! Explanation: Splits the string into occurrences of the word rex and everything else, but keeps the matches. Then, on lines that don't begin rex (i.e. the "everything else"), change letters to *s. Finally, join everything back together.

Neil

Posted 2017-05-09T08:07:29.990

Reputation: 95 035

3This is at least the second time that I'm thinking transliteration mode could use an option to transliterate the non-matches... – Martin Ender – 2017-05-09T09:49:19.930

@MartinEnder too late :-D – John Dvorak – 2017-05-09T13:50:10.577

8

C, 99 97 92 86 74 73 72 65 bytes

f(char*s){*s&&f(s+=strnicmp("Rex",s,3)?!isalpha(*s)||(*s=42):3);}

Pelles IDE environment provides (compile with /Go) the function strnicmp. This function is identical to strncasecmp. See it work here (with the replacement function).

The output is stored in the first parameter which is an in/out parameter.

Thanks to Johan du Toit for letting me know that recursion is slightly shorter.

2501

Posted 2017-05-09T08:07:29.990

Reputation: 748

There exists a C environment that provided strncmpi so you can get it in 69. I've got it on CD. – Joshua – 2017-05-10T20:52:25.587

1@Joshua Thanks. What is CD? – 2501 – 2017-05-10T20:56:46.887

Borland C++ 4.5 – Joshua – 2017-05-10T21:14:13.817

7

Ruby, 36 35 32 bytes

->s{s.gsub(/(rex)|\w/i){$1||?*}}

As a test:

f=->s{s.gsub(/(rex)|\w/i){$1||?*}}

tests = [
  ["Rex, I told you not to do this! You're making me angry Rex!", "Rex, * **** *** *** ** ** ****! ***'** ****** ** ***** Rex!"],
  ["Rex lives in Rexland.", "Rex ***** ** Rex****."],
  ["To call Rex, just say \"Rex\".", %q(** **** Rex, **** *** "Rex".)],
  ["My cat is getting anorexic.", "** *** ** ******* ***rex**."]
] 

tests.each do |input, output|
  if f.call(input) == output
    puts "Fine for #{input.inspect}"
  else
    puts "Problem with :\n#{input.inspect}"
    puts f.call(input)
    puts output
  end
  puts
end

It outputs:

Fine for "Rex, I told you not to do this! You're making me angry Rex!"

Fine for "Rex lives in Rexland."

Fine for "To call Rex, just say \"Rex\"."

Fine for "My cat is getting anorexic."

Eric Duminil

Posted 2017-05-09T08:07:29.990

Reputation: 701

6

PHP, 78 Bytes

<?=preg_replace("#[a-df-qs-wyz]|r(?!ex)|(?<!r)e|e(?!x)|(?<!re)x#i","*",$argn);

Try it online!

PHP, 84 Bytes

<?=preg_replace_callback("#(rex)|\pL#i",function($t){return$t[1]?$t[1]:"*";},$argn);

-1 Byte \w instead \pl in this case underscore and numbers are replaced too

\pL is shorter as [a-z] or [[:alpha:]]

Try it online!

Jörg Hülsermann

Posted 2017-05-09T08:07:29.990

Reputation: 13 026

You can use \w instead of \pL. – Adám – 2017-05-11T14:07:04.500

@Adám Thank you it makes my longer approach only 1 Byte shorter and not really clearer what should make in case of underscore or number – Jörg Hülsermann – 2017-05-11T14:20:04.370

The input will never have any underscores or numbers.. – Adám – 2017-05-11T14:23:32.587

@Adám I have make an extra point for it and have edit the longer approach why I have found an other improvement – Jörg Hülsermann – 2017-05-11T14:50:43.133

5

C (GCC on POSIX), 167 118 93 87 bytes

i,j;f(char*s){for(i=0;j=s[i];i++)strncasecmp("Rex",s+i,3)?s[i]=isalpha(j)?42:j:(i+=2);}

Try it online!

betseg

Posted 2017-05-09T08:07:29.990

Reputation: 8 493

f(char*s){for(;*s;s++)strncasecmp("Rex",s,3)?putchar(isalpha(*s)?42:*s):write(1,s-2,3,s+=2);}. What kind of sorcery is f(s)char*s;{}? I've never seen this syntax before. – Christoph – 2017-05-09T10:35:23.407

Oh, it used to have another parameter but i forgot to remove that. – betseg – 2017-05-09T11:13:13.793

@2501 thanks, fixed. – betseg – 2017-05-09T18:49:46.040

5

Java 8, 187 192 168 164 159 138 bytes

s->{for(int i=0;i<s.length();System.out.print(s.regionMatches(0<1,i,"rex",0,3)?s.substring(i,i+=3):s.replaceAll("\\w","*").charAt(i++)));}

-28 bytes thanks to @OlivierGrégoire.

Explanation:

Try it online.

s->{                         // Method with String parameter and no return-type
  for(int i=0;i<s.length();  //  Loop over the characters of the input-String
    System.out.print         //   Print:
     s.regionMatches(1>0,i,"rex",0,3)? 
                             //    If we've found "rex" (case-insensitive):
      s.substring(i,i+=3)    //     Print this REX-word (case-sensitive)
     :                       //    Else:
      s.replaceAll("\\w","*").charAt(i++));
                             //     Print the current character,
                             //     or '*' if it's an alpha-numeric character

Kevin Cruijssen

Posted 2017-05-09T08:07:29.990

Reputation: 67 575

@Shaggy Should be fixed now. This was posted before it was specified in the comments that 0-9 and accented characters shouldn't be included, only a-zA-Z should. – Kevin Cruijssen – 2017-05-09T14:35:53.440

Could you replace "[a-zA-z]" with /[a-z]/i? – Shaggy – 2017-05-09T14:38:03.983

@Shaggy Yes/no. Java uses a slightly different regex syntax than python or C# for example. So yes, it is possible to use a case-insensitive regex, but it will be one byte longer: "[a-zA-Z]" -> "(?i)[a-z]". – Kevin Cruijssen – 2017-05-09T14:43:40.657

1I think you should use s.regionMatches(0<1,i,"rex",0,3) instead of s.toLowerCase().substring(i,i+(i>l-3?1:3)).equals("rex"). – Olivier Grégoire – 2017-05-09T14:44:49.757

1@KevinCruijssen Take the current code that you have (at 168 bytes), remove the variable l and save 4 bytes. – Olivier Grégoire – 2017-05-09T19:39:41.690

5

Python 2 or 3, 75 73 70 bytes

import re;f=lambda s:re.sub('(?i)(rex)|\w',lambda x:x.group(1)or'*',s)

Basically the same as my Ruby's answer.

-2 bytes thanks to @Wondercricket.

As a test:

tests = [
  ["Rex, I told you not to do this! You're making me angry Rex!", "Rex, * **** *** *** ** ** ****! ***'** ****** ** ***** Rex!"],
  ["Rex lives in Rexland.", "Rex ***** ** Rex****."],
  ["To call Rex, just say \"Rex\".", "** **** Rex, **** *** \"Rex\"."],
  ["My cat is getting anorexic.", "** *** ** ******* ***rex**."]
]


for test_in, test_out in tests:
    print(test_in)
    print(f(test_in))
    print(f(test_in) == test_out)

Eric Duminil

Posted 2017-05-09T08:07:29.990

Reputation: 701

1You could save 2 bytes by removing the spacing between x.group(1) or '*' – Wondercricket – 2017-05-09T15:25:13.030

@Wondercricket: Thank you very much, it's my first golf answer in Python. – Eric Duminil – 2017-05-09T16:16:13.427

4

Python 2, 87 Bytes

import re
print re.sub(r'(?i)[a-df-qs-wyz]|r(?!ex)|(?<!r)e|e(?!x)|(?<!re)x','*',input())

I guess that can be shortened? :)

erbsenhirn

Posted 2017-05-09T08:07:29.990

Reputation: 81

1You can get rid of the spaces after the commas between arguments for 2 bytes off. – Mego – 2017-05-09T11:34:23.367

4

sed, 37 33 bytes

36 bytes sourcecode + 1 byte for -r flag.

s:(rex)|\w:\1*:Ig
s:(rex)\*:\1:Ig

Try it online!

Maxim Mikhaylov

Posted 2017-05-09T08:07:29.990

Reputation: 571

@Shaggy Thanks for the heads up! – Maxim Mikhaylov – 2017-05-11T14:01:11.863

You use use . instead of \* – user41805 – 2019-08-28T05:39:39.587

3

Retina, 54 50 49 bytes

Golfed 5 bytes thanks to @MartinEnder

Retina, 49 bytes

i(`[\w-[rex]]
*
(?<!r)e|e(?!x)|r(?!ex)|(?<!re)x
*

Try it online!

user41805

Posted 2017-05-09T08:07:29.990

Reputation: 16 320

@Emigna Just realised that my solution does not work for dex, it gives *e* while yours gives **x. – user41805 – 2017-05-09T09:21:01.090

If you group both stages by putting ( after the first i you don't need to configure the second stage. – Martin Ender – 2017-05-09T11:44:54.207

And your first regex can be written as [a-z-[rex]]. – Martin Ender – 2017-05-09T11:46:05.057

@MartinEnder Thanks, this is the first time I'm seeing character classes where you can exclude certain characters – user41805 – 2017-05-10T15:49:46.957

they exist in several flavours but I believe .NET's syntax for them is unique. – Martin Ender – 2017-05-10T17:09:39.310

3

Gema, 25 characters

/[rR][eE][xX]/=$0
<L1>=\*

Sample run:

bash-4.3$ gema '/[rR][eE][xX]/=$0;<L1>=\*' <<< "Rex, I told you not to do this! You're making me angry Rex!
Rex lives in Rexland.
To call Rex, just say \"Rex\".
My cat is getting anorexic."
Rex, * **** *** *** ** ** ****! ***'** ****** ** ***** Rex!
Rex ***** ** Rex****.
** **** Rex, **** *** "Rex".
** *** ** ******* ***rex**.

Painful fact that could be \CRex=$0;<L1>=\*, but unfortunately $0 contains the template, not the match. ☹

manatwork

Posted 2017-05-09T08:07:29.990

Reputation: 17 865

3

PowerShell, 60 bytes

{$args|%{$_-replace'(rex)|\p{L}','$1*'-replace'(x)\*','$1'}}

Try it online

Andrei Odegov

Posted 2017-05-09T08:07:29.990

Reputation: 939

My fault. I've replace \w to \p{L}. – Andrei Odegov – 2017-05-09T13:22:52.280

Interesting idea. Note that using $args as an array has consequences when things are quoted, as in one example. And if you're only using the first argument anyway, you don't need the foreach. – Joey – 2017-05-10T17:02:54.240

@AndreiOdegov You can go back to \w. Side note: Are the braces in \p{L} really needed? – Adám – 2017-05-11T14:06:26.993

1very nice Regex, "$args"-replace'(rex)|\p{L}','$1*'-replace'(x)\*','$1' is much shorter overall, wrapping $args in quotes turns it all into a single string and saves you a lot. – colsw – 2017-05-11T15:39:16.973

@Adám The curly braces in .NET is required. – Andrei Odegov – 2017-05-11T17:35:33.360

@ConnorLSW Thanks for the valuable pointing. – Andrei Odegov – 2017-05-11T18:07:55.943

3

QuadR, 11 10 + 1 = 11 bytes

+1 byte for the i flag.

rex
\w
&
*

Try it online!

Explanation: Case-insensitively replace rex and word-chars with itself and asterisks, respectively.

Adám

Posted 2017-05-09T08:07:29.990

Reputation: 37 779

2

Python 2, 93 92 bytes

f=lambda s:s and("rex"==s[:3].lower()and s[:3]+f(s[3:])or("*"+s)[s[0].isalpha()<1]+f(s[1:]))

Try it online!

ovs

Posted 2017-05-09T08:07:29.990

Reputation: 21 408

2

MATL, 24 bytes

42y3Y2mFGk'rex'Xf!3:q+((

The input is a string enclosed in single quotes.

Try it online!

Explanation

Consider input 'Rex lives in Rexland.'

42    % Push 42 (ASCII for '*')
      % STACK: 42
y     % Implicit input. Duplicate from below
      % STACK: 'Rex lives in Rexland.', 42, 'Rex lives in Rexland.'
3Y2   % Push string 'ABC...YZabc...yz'
      % STACK: 'Rex lives in Rexland.', 42, 'Rex lives in Rexland.', 'ABC...YZabc...yz'
m     % Ismember
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0]
F     % Push false
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0], 0
Gk    % Push input lower-cased
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0], 0, 'rex lives in rexland'
'rex' % Push this string
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0], 0, 'rex lives in rexland', 'rex'
Xf!   % Strfind and transpose: gives indices of matchings as a column vector
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0], 0, [1; 14]
3:q   % Push [0 1 2]
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0], 0, [1; 14], [0 1 2]
+     % Addition, element-wise with broadcast
      % STACK: 'Rex lives in Rexland.', 42, [1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0], 0, [1 2 3; 14 15 16]
(     % Assignment indexing: sets indicated entries to 0
      % STACK: 'Rex lives in Rexland.', 42, [0 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0]
(     % Assignment indexing: sets indicated entries to 42 (that is, '*'). Implicit display
      % 'Rex ***** ** Rex****.'

Luis Mendo

Posted 2017-05-09T08:07:29.990

Reputation: 87 464

2

Bash, 128 bytes

r=REXrex;a=`tr -c $r'",. !
' l<<<$1`;for i in {r,R}{e,E}{x,X};{
a=`echo ${a[@]//$i/$(tr $r f-k<<<$i)}`;}
tr $r l<<<$a|tr f-l $r*

Try it online!

I'm sticking to tr on my previous answer, non-functional bash array string replace and no preg replace!

Less golfed:

    a=`echo $1 |tr -c 'REXrex.,\"! ' 'z'`;        -> a replaces with z chars in input not matching REXrex or punctuation
    for i in {r,R}{e,E}{x,X}; {                   -> iterates over rex .. rEx .. REX
      j=$(tr 'REXrex' 'ABCabc' <<<$i)}            -> holds a for r, A for R, ando so on
      a=`echo ${a[@]//$i/$j`;                     -> replace each combination of rex .. rEx .. REX with abc ... aBc.. ABC
    }
    tr 'REXrex' 'z' <<<$a |tr 'ABCabcz' 'REXrex*' -> replaces each remainig r,e,x,R,E,X with z and finally each ABC with REX and z with *

Had to use z instead of * because of expansion

marcosm

Posted 2017-05-09T08:07:29.990

Reputation: 986

2looks its not the right tool :P – marcosm – 2017-05-09T15:07:24.363

1You can save a couple of characters by not quoting tr's parameters when they contain nothing expandable. – manatwork – 2017-05-09T15:46:08.470

In regards to your other bash answer: Feel free to fix, and then flag for mod attention requesting undeletion. – Rɪᴋᴇʀ – 2017-05-09T17:53:55.813

1Looking again, there are quite many rexes for a r=REXrex variable to worth. – manatwork – 2017-05-10T11:20:58.493

If you keep $r out of quoted string, you not need to change the surrounding ' to ", so no need to escape the literal ". Of course, then you write a literal newline by breaking the line in that place instead of \n: $r'",. ! '. – manatwork – 2017-05-10T12:14:57.813

:) I wonder if I can change echo and for with tr to have tr only answer – marcosm – 2017-05-10T13:03:23.930

2

C#, 93 90 bytes

s=>System.Text.RegularExpressions.Regex.Replace(s,"(?i)rex|\w",m=>m.Length>1?m.Value:"*");

Believe this is the first time I've used a regex in a C# answer here because of the long namespace System.Text.RegularExpressions.


Didn't realise it when I wrote my answer but this seems to be the C# version of @Shaggy's JavaScript answer.

TheLethalCoder

Posted 2017-05-09T08:07:29.990

Reputation: 6 930

1Thanks for the mention, even though you came up with your answer independently of mine. – Shaggy – 2017-05-09T17:26:23.033

@Shaggy Ah thanks didn't know it had been updated – TheLethalCoder – 2017-05-11T20:37:35.517

2

Java 7, 96 98 97 96 bytes

+2 bytes for missing e's preceded by r or followed by x but not both

-1 byte for changing [a-z&&[^rex]] to (?![rex])\\w

String a(String s){return s.replaceAll("(?i)r(?!ex)|(?<!r)e|e(?!x)|(?<!re)x|(?![rex])\\w","*");}

Try it online!

A regex version for replacing using Java

Replaces everything in this regex with a * (note in Java \w has to be escaped as \\w)

(?i)r(?!ex)|(?<!r)e|e(?!x)|(?<!re)x|(?![rex])\w

(?i)                                                   // Case Insensitive
    r(?!ex)                                            // Any r not followed by ex
           |(?<!r)e                                    // Or any e not preceded by r
                   |e(?!x)                             // Or any e not followed by x
                          |(?<!re)x                    // Or any x not preceded by re
                                   |(?![rex])\w        // Or any other word character

PunPun1000

Posted 2017-05-09T08:07:29.990

Reputation: 973

2

Perl, 31 bytes

s/(rex)|[a-z]/$1||"*"/ieg;print

Invoke perl with -n option. For example:

echo 'To call rex, just say "Rex".'| perl -ne 's/(rex)|[a-z]/$1||"*"/ieg;print'
** **** rex, **** *** "Rex".

gogators

Posted 2017-05-09T08:07:29.990

Reputation: 191

[a-z] can now be replaced with \w as the input will never contain numbers or underscores. – Shaggy – 2017-05-11T13:59:25.717

You can use -p instead of -n and remove ;print – wastl – 2018-03-14T16:12:59.150

1

CJam, 39 bytes

q{_3<_el"rex"=3{elc_'{,97>&'*@?1}?\o>}h

Try it online!

How it works

q           e# Read the input.
{           e# Do:
 _3<        e#  Copy the string and get its first three characters.
 _el"rex"=  e#  Check case-insensitively if they equal "rex".
  3         e#   If they do, push 3.
  {         e#   If they don't:
   elc_     e#    Take the first character of the three, and make it lowercase.
   '{,97>&  e#    Take its set intersection with the lowercase alphabet. Returns a non-empty
            e#      string (truthy) if it's a letter or an empty string (falsy) if not.
   '*@?     e#    Push a * if the char is a letter, or itself if it's not.
   1        e#    Push 1.
  }?        e#  (end if)
 \o         e#  Print the second-from-the-top stack item.
 >          e#  Slice the string after the first 3 or 1 characters, depending on previous outcome.
}h          e# Repeat the above until the string is empty.

Business Cat

Posted 2017-05-09T08:07:29.990

Reputation: 8 927

1

VimScript, 34 bytes

s/\v(rex|r@<=ex|(re)@<=x)@!\w/*/gi

And here's an interesting substitution that almost works:

s/\vr(ex)@!|<e|<x|[rex]@!\w/*/gi

Imagine running this repeatedly on the string Rex, dex, I told you not to do this! You're making me angry Rex! After the first line, the string is Rex, *ex, * **** *** *** ** ** ****! ***'*e ****** *e ***** Rex! The second pass will result in Rex, **x, * **** *** *** ** ** ****! ***'** ****** ** ***** Rex!, and the third pass will finish it. Any subsequent passes will not change the string. However, it could take more than 3 substitutions to get there, for example on string xxxxxxxx. So, if there were an easy way to run the above substitution until it stopped changing things, or as many times as the length of the input, that would be another solution. I bet it could be done in V, but it would still probably be longer than 34 bytes.

Brian McCutchon

Posted 2017-05-09T08:07:29.990

Reputation: 503

Thanks for the idea! Here's a V answer. :)

– James – 2018-01-05T00:25:33.420

1

Jelly, 23 bytes

No response in over 24 hours to my question regarding case, so I'll post this tentative 23 byter.

“rex”
Œlœṣ¢µØaW;”*yµ€j¢

See the test cases at Try it online!

How?

“rex” - Link 1, get "rex": no arguments
“rex” - literal "rex"

Œlœṣ¢µØaW;”*yµ€j¢ - Main link: string s (or list of characters)
Œl                - convert s to lowercase
    ¢             - call the last link (1) as a nilad (get "rex")
  œṣ              - split left (s) at sublists equal to right ("rex")
     µ            - call the result t
             µ€   - for each word, w, in t:
      Øa          -   literal: lowercase alphabet
        W         -   wrap it in a list
          ”*      -   literal: '*'
         ;        -   concatenate the wrapped alphabet with the asterisk
            y     -   translate: replace all lowercase letters with asterisks.
                ¢ - call the last link (1) as a nilad (get "rex")
               j  - join left (translated, split text) with copies of right ("rex")

Jonathan Allan

Posted 2017-05-09T08:07:29.990

Reputation: 67 804

I'm not sure this is valid. It doesn't match the test cases. – Okx – 2017-05-10T19:24:59.403

See my note right at the top, and my question to OP. – Jonathan Allan – 2017-05-10T19:25:24.057

( although unfortunately the comment I linked to where the OP said "dogs don't get the difference between lowercase and uppercase" has now gone) – Jonathan Allan – 2017-05-10T19:27:42.823

1

CJam, 26 bytes (uppercase output) / 36 bytes (case-preserving)

qeu"REX":R/{__el-'*@?}f%R*

Try it online!

If letter case needs to be preserved (since that's still a little bit unclear), that can be accomplished with 10 extra bytes:

q_32f&:i\eu"REX":R/{__el-'*@?}f%R*.|

Try it online!

By the way, while writing this answer, I found what I would consider to be a design bug in CJam: the bitwise operators & and | are not defined between two char values, so I can't use .| to take the bitwise OR of two strings. The solution, which ended up costing me two extra bytes, is to first convert one of the strings with :i into an array of integers, which then can be ORed with the other string. (Actually it cost me three bytes, because if & worked between two chars, I could've also used Sf& instead of 32f& to save the letter case information.)

On the positive side, I did discover that {...}f% indeed works as expected for iterating over the characters in an array of strings. Nice.

Anyway, here's a (lightly) commented version of the 36-byte code:

q                                       "read input";
 _32f&:i\                               "save the case bit of each input char";
         eu"REX":R/                     "uppercase input and split it on 'REX'";
                   {                    "start code block:"
                    __el-'*@?           "c = (c != lowercase(c) ? '*' : c)";
                             }f%        "apply block to chars in each substring";
                                R*      "join the substrings with 'REX' again";
                                  .|    "bitwise OR the case bits back in";

The case-saving trick works because the case of ASCII letters is solely determined by the fifth bit of the ASCII code: this bit is 0 for uppercase and 1 for lowercase letters. Thus, taking the bitwise AND of the character code with 32 = 25 extracts the case bit, and bitwise ORing this bit with the uppercased letters restores their original case.

Of course, non-alphabetic characters may have arbitrary values for the fifth bit (although, due to the way ASCII characters are organized, most punctuation characters have the fifth bit set to 1) but this doesn't matter, since those characters are left untouched by uppercasing and the letter censoring loop anyway, and ORing a character with its own fifth bit does't change it. Also, conveniently, the * character already has the fifth bit set, so it is also left unchanged by the final .|.

Ilmari Karonen

Posted 2017-05-09T08:07:29.990

Reputation: 19 513

1

Japt, 21 20 19 17 bytes

A port of my JavaScript solution, with a little help from Oliver. Would be 16 in Japt v2 but RegEx is very bugged right now.

r`(x)|%l`Ϫ'*}'i

Try it

Japt v2.0a0, 12 bytes

If, as some other solutions assume, output case is irrelevant.

v Ër\l'*}`x

Try it

Shaggy

Posted 2017-05-09T08:07:29.990

Reputation: 24 623

1

Pip, 21 19 bytes

qR-`(rex)|\w`{b|'*}

Takes input from stdin, outputs to stdout. Try it online!

Explanation

q                    Read a line of stdin
 R                   and replace
   `(rex)|\w`          a regex matching `rex` or any single alphanumeric character,
  -                    case-insensitive
             {    }  with this callback function:
              b|'*     If the 1st capture group (rex) matched, return it, else asterisk
                       The result of the replacement is auto-printed

DLosc

Posted 2017-05-09T08:07:29.990

Reputation: 21 213

1

SNOBOL4 (CSNOBOL4), 147 bytes

	L =INPUT
	K =ANY(&UCASE &LCASE)
B	L ARB . X (('R' | 'r') 'ex') . Y REM . L	:F(O)
R	X K ='*'	:S(R)
	O =O X Y :(B)
O	L K ='*'	:S(O)
	OUTPUT =O L
END

Try it online!

Previous version did not properly handle non-alphabetic characters.

Giuseppe

Posted 2017-05-09T08:07:29.990

Reputation: 21 077

1

V, 27, 24 bytes

I'm leaving both answers up, because I think they're equally interesting.

27 bytes

òÓãr¨ex©À!ü¼eü¼xü[rex]À!÷/*

Try it online!

Thanks to Brian McCutchon for his idea to do this in V

Hexdump:

00000000: f2d3 e372 a865 78a9 c021 fcbc 65fc bc78  ...r.ex..!..e..x
00000010: fc5b 7265 785d c021 f72f 2a              .[rex].!./*

Explanation:

ò                           " Until the output stops changing...
 Óãr¨ex©À!ü¼eü¼xü[rex]À!÷/* " Run the compressed vim regex:

:s/\vr(ex)@!|<e|<x|[rex]@!\w/*/gi

24 bytes

Óãrex/ò&ò
HòÓ÷/*/e
jjòÍî

Try it online!

Ó           " Substitute
 ã          "   (case-insensitive)
  rex       "   'rex'
     /      " with
       &    "   'rex'
      ò ò   "   Surrounded in new lines
ò           " Recursively...
 Ó          "   Substitute...
  ÷         "     A word character
   /        "   with
    *       "     An asterisk
     /e     "     (don't break if there are 0 matches)
jj          "   Move down 2 lines
  ò         " end the recursive loop
   Íî       " Remove all newlines

James

Posted 2017-05-09T08:07:29.990

Reputation: 54 537

1

05AB1E, 21 bytes

l…rex©₄ç:AS'*:₄ç®:s.Ï

I've assumed the input can contain any ASCII character and only upper and lowercase letters are replaced with asterisks. It could be 2 bytes less if we assume the input will never contain substring 1000, in which case both ç can be removed.

Try it online.

Explanation:

l           # Convert the (implicit) input to lowercase
 …rex       # Push string "rex"
     ©      # Store it in the register (without popping)
      ₄ç    # Push 1000 and convert it to a character: "Ϩ"
        :   # Replace all "rex" with "Ϩ"
AS          # Push the lowercase alphabet, and convert it to a list of characters
  '*       '# Push "*"
    :       # Replace every letter in the alphabet with "*"
₄ç          # Push "Ϩ" again
  ®         # Push "rex" from the register
   :        # Replace all "Ϩ" with "rex"
s           # Swap to take the (implicit) input again at the top of the stack
 .Ï         # Match the case of the lowercase "rex" with that of the input
            # (and output implicitly)

Kevin Cruijssen

Posted 2017-05-09T08:07:29.990

Reputation: 67 575

0

PegJS + ES6, 50 bytes

C=a:("rex"i/[a-z]i{return'*'}/.)*{return a.join``}

Online interpreter

The lack of lambda syntax for the expression returns hurts the size.

user5090812

Posted 2017-05-09T08:07:29.990

Reputation: 101

[a-z] can now be replaced with \w as the input will never contain numbers or underscores. – Shaggy – 2017-05-11T13:59:31.463

PegJS is an implementation of Parsing Expression Grammar. While the overall grammar can accept many more things than regular expressions, the individual [a-z] construct is not a regular expression; it is only a simple character class matcher and doesn't have \w or any equivalent. – user5090812 – 2017-05-11T14:56:15.377

0

Julia, 69 50 bytes.

f(x)=replace(x,r"rex|[a-z]"i,a->length(a)>1?a:"*")

Took some ideas from more concise entries, now it works like them.

eaglgenes101

Posted 2017-05-09T08:07:29.990

Reputation: 577

[a-z] can now be replaced with \w as the input will never contain numbers or underscores. – Shaggy – 2017-05-11T13:59:44.077

0

Japt 2.0a0, 17 bytes

r/(Rex)|\l/i@Yª'*

Try it online!

Unpacked & How it works

Ur/(Rex)|\l/iXYZ{Y||'*

Ur  Replace on input...
/(Rex)|\l/i  Match this regex globally...
             (`\l` stands for [A-Za-z], and Japt regexes have `g` by default)
XYZ{Y||'*    and replace anything that isn't Rex into '*'.

S.r uses JS's String.replace which can accept a function as 2nd input, but unfortunately, the Japt doc doesn't mention it.

Idea adapted from Martin Ender's Retina answer.

Bubbler

Posted 2017-05-09T08:07:29.990

Reputation: 16 616

0

K4, 56 bytes

Solution:

{@[;r;:;x@r:,/ss[_x;"rex"]+\:!3]@[x;&(_x)in .Q.a;:;"*"]}

Examples:

q)k){@[;r;:;x@r:,/ss[_x;"rex"]+\:!3]@[x;&(_x)in .Q.a;:;"*"]}"Rex lives in Rexland."
"Rex ***** ** Rex****."
q)k){@[;r;:;x@r:,/ss[_x;"rex"]+\:!3]@[x;&(_x)in .Q.a;:;"*"]}"To call Rex, just say \"Rex\"."
"** **** Rex, **** *** \"Rex\"."
q)k){@[;r;:;x@r:,/ss[_x;"rex"]+\:!3]@[x;&(_x)in .Q.a;:;"*"]}"My cat is getting anorexic."
"** *** ** ******* ***rex**."

Explanation:

No regular expressions here... Change everything non-alphabetic into stars, put back any occurences of Rex:

{@[;r;:;x@r:,/ss[_x;"rex"]+\:!3]@[x;&(_x)in .Q.a;:;"*"]} / the solution
{                                                      } / lambda taking implicit x
                                @[x;            ;:;"*"]  / apply (@) assignment (:) of "*" at indices...
                                         in .Q.a         / in lowercase alphabet?
                                     (_x)                / lowercase (_) x       
                                    &                    / indices where true                                  
 @[; ;:;                       ]                         / another application of assignment
                             !3                          / range til 3 -> 0 1 2
                          +\:                            / add (+) to each left (\:)
              ss[_x;"rex"]                               / string-search for "rex" in lowercase (_) x
            ,/                                           / flatten
          r:                                             / assign to r
        x@                                               / index into x
    r                                                    / indices to modify

streetster

Posted 2017-05-09T08:07:29.990

Reputation: 3 635

0

Dart, 99 bytes

f(s)=>s.replaceAllMapped(RegExp(r'(rex)|(\w)',caseSensitive:false),(Match m)=>m[1]!=null?m[1]:'*');

Try it online!

Elcan

Posted 2017-05-09T08:07:29.990

Reputation: 913

0

Stax, 18 bytes

ùV:┬KsS•u┤8α╞"T-┤☼

Run and debug it

recursive

Posted 2017-05-09T08:07:29.990

Reputation: 8 616

-1

JS (ES5), 75 bytes

function r(l){return l.replace(/rex|\w/gi,function(c){return c[1]?c:"*"})}

Based on this

user68614

Posted 2017-05-09T08:07:29.990

Reputation:

1

Is "porting" an answer to another version of the same language permitted? I don't know. But you should at least include a credit in your answer by linking to the original as TheLethalCoder did (unnecessarily, in that case) in their answer.

– Shaggy – 2017-05-09T17:24:24.173

1You may replace [a-z] with \w. – Adám – 2017-05-11T14:08:37.410