94
\$\begingroup\$

Once I wrote a JavaScript program that would take as input a string and a character and would remove all characters except for the first one and the character given as input, one by one.

For example, computing this with inputs codegolf.stackexchange.com and e for the character yields:

codegolf.stackexchange.com
cdegolf.stackexchange.com
cegolf.stackexchange.com
ceolf.stackexchange.com
celf.stackexchange.com
cef.stackexchange.com
ce.stackexchange.com
cestackexchange.com
cetackexchange.com
ceackexchange.com
ceckexchange.com
cekexchange.com
ceexchange.com
ceechange.com
ceehange.com
ceeange.com
ceenge.com
ceege.com
ceee.com
ceeecom
ceeeom
ceeem
ceee

It keeps the first character and all es. All other characters are removed one by one.

Your task is to write a program (or function) that takes two inputs and outputs (or returns) a string that accomplishes this effect.

Specifications

  • You can assume that the string will not contain any newlines.
  • The second input will always be one character.
  • If the answer is in the form of a function, you may return an array of strings containing each line in the output.
  • The output can contain a trailing newline.

Test Cases

Test Cases, s:

Test Cases
Tst Cases
Ts Cases
TsCases
Tsases
Tsses
Tsss

Make a "Ceeeeeeee" program, e:

Make a "Ceeeeeeee" program
Mke a "Ceeeeeeee" program
Me a "Ceeeeeeee" program
Mea "Ceeeeeeee" program
Me "Ceeeeeeee" program
Me"Ceeeeeeee" program
MeCeeeeeeee" program
Meeeeeeeee" program
Meeeeeeeee program
Meeeeeeeeeprogram
Meeeeeeeeerogram
Meeeeeeeeeogram
Meeeeeeeeegram
Meeeeeeeeeram
Meeeeeeeeeam
Meeeeeeeeem
Meeeeeeeee

Hello World!, !:

Hello World!
Hllo World!
Hlo World!
Ho World!
H World!
HWorld!
Horld!
Hrld!
Hld!
Hd!
H!

Hello World!, z:

Hello World!
Hllo World!
Hlo World!
Ho World!
H World!
HWorld!
Horld!
Hrld!
Hld!
Hd!
H!
H

alphabet, a:

alphabet
aphabet
ahabet
aabet
aaet
aat
aa

upperCASE, e:

upperCASE
uperCASE
uerCASE
ueCASE
ueASE
ueSE
ueE
ue

This is , so the shortest code (in bytes) wins.

\$\endgroup\$
  • 25
    \$\begingroup\$ Kinda random, but +1 \$\endgroup\$ – TuxCrafting Nov 19 '16 at 19:28
  • 24
    \$\begingroup\$ +1 for Meeeeeeeeegram \$\endgroup\$ – FlipTack Nov 19 '16 at 20:15
  • \$\begingroup\$ In the case that it returns an array, do each of the elements have to include a trailing newline? \$\endgroup\$ – Brad Gilbert b2gills Nov 19 '16 at 20:24
  • \$\begingroup\$ @BradGilbertb2gills No. \$\endgroup\$ – Esolanging Fruit Nov 19 '16 at 20:40
  • 4
    \$\begingroup\$ Meeeeeeeeeeeeem \$\endgroup\$ – Mathime Nov 23 '16 at 7:52

52 Answers 52

5
\$\begingroup\$

V, 12 bytes

òYpó.“„a]òd

Try it online!

Hexdump:

00000000: f259 70f3 2e93 8412 615d f264            .Yp.....a].d

I have tested this with the latest version of V available before the challenge, and everything runs correctly, making this answer competing.

Explanation:

ò         ò    " Recursively:
 Yp            "   Duplicate this line
   ó           "   Remove:
    .a]      "     A compressed regex
            d  " Delete our extra line

The compressed regex translates to

.\zs[^e]

Which means

.           " Any character
 \zs        " Leave the previous character out of the selection
    [^e]    " Any character except for 'e' (Or whatever is given for input)

Non-competing version (11 bytes)

This version uses a shortcut for Yp that wasn't available when this challenge was posted.

\$\endgroup\$
  • \$\begingroup\$ @challenger5 Awesome! I'll check out an old version and verify that it works correctly. I might have to modify it slightly. I'll ping you once I've updated. \$\endgroup\$ – DJMcMayhem Feb 14 '17 at 19:59
  • \$\begingroup\$ @Challenger5 I have edited the answer, and verified that this version worked when the challenge was posted. \$\endgroup\$ – DJMcMayhem Feb 14 '17 at 23:27
  • \$\begingroup\$ How would I execute a bunch of Vim commands stored in a file on a Linux system? Would i cat filename | vim or would I do something else? \$\endgroup\$ – ckjbgames Feb 15 '17 at 0:43
31
\$\begingroup\$

Vim, 27, 26, 25 bytes

DJqqYp:s/.\zs[^<C-r>-]<CR>@qq@qD

Try it online!

Input comes in this format:

e
codegolf.stackexchange.com

My naive first approach is three bytes longer:

i:s/.\zs[^<Right>]<Esc>"addqqYp@a@qq@qdd

I'm also happy with this answer because it starts with my name.

DJqq:t$|s/.\zs[^<C-r>"]<CR>@qq@qD
DJMcMayhem

See the similarity? Eh?

Less successful approaches:

i:s/.\zs[^<Right>]<Esc>"addqqYp@a@qq@qdd
i:s/.\zs[^<Right>]<CR>@q<Esc>"adkqqYp@aq@qdd
DJ:s/.\zs[^<C-r>"]<CR>uqqYp@:@qq@qdd
DJqq:t.|$s/.\zs[^<C-r>"]<CR>@qq@qdd

Explanation:

D                                   " Delete everything on this first line
 J                                  " Remove this empty line
  qq                                " Start recording into register 'q'
    Y                               " Yank this line
     p                              " And paste it
      :s/                           " Run a substitute command on the last line in the buffer. Remove:
         .                          "   Any character
          \zs                       "   Move the selection forward (so we don't delete the first one)
             [^<C-r>-]              "   Followed by anything *except* for the character we deleted
                      <CR>          " Run the command
                          @q        " Call register 'q'
                            q       " Stop recording
                             @q     " Run the recursive macro
                               D    " Delete our extra line
\$\endgroup\$
  • 1
    \$\begingroup\$ I think you got a typo there where the input is given there is a k too much :) \$\endgroup\$ – geisterfurz007 Nov 21 '16 at 10:52
  • \$\begingroup\$ @geisterfurz007 I'm not sure if I get what you mean? \$\endgroup\$ – DJMcMayhem Nov 22 '16 at 23:33
  • \$\begingroup\$ It says (...)comk In line 5 currently. \$\endgroup\$ – geisterfurz007 Nov 22 '16 at 23:37
  • \$\begingroup\$ There's no reason to use :t here. Normal Yp would save a byte. You'll have to switch to <C-R>- of course. Typical PPCG rules are frustrating, because for any reasonable test case, :t.|s with 99@: or even 999@: would be correct, but there's no good way to get an infinite repeat that way. You're forced to use less interesting strats. \$\endgroup\$ – udioica Nov 29 '16 at 21:55
22
\$\begingroup\$

MATL, 20 16 bytes

y-f1X-"t[]@X@q-(

Try it online! Or verify test cases: 1, 2, 3, 4, 5.

Bonus

Modified code to see the string being gradually shrunk (offline compiler):

y-f1X-"tt.3Y.XxD[]@X@q-(].3Y.XxDvx

enter image description here

Or try it at MATL Online!

Explanation

y        % Implicitly input string and char. Duplicate string onto top
-        % Subtract. Gives nonzero for chars in the input string that are
         % different from the input char
f        % Array of indices of nonzero values
1X-      % Remove 1 from that array. This gives an array of the indices of 
         % chars to be removed from the string
"        % For each
  t      %   Duplicate previous string
  []     %   Push empty array
  @      %   Push index of char to be removed. But this index needs to be 
         %   corrected to account for the fact that previous chars have
         %   already been removed...
  X@q-   %   ... So we correct by subtracting the 0-based iteration index
  (      %   Assign empty array to that position, to remove that char
         % Implicitly end for each
         % Implicitly display
\$\endgroup\$
  • 3
    \$\begingroup\$ GIFS! gifs are cool! \$\endgroup\$ – Brain Guider Nov 21 '16 at 13:22
20
\$\begingroup\$

Haskell, 50 bytes

w@(a:x)%c|(d,_:y)<-span(==c)x=w:(a:d++y)%c|0<1=[w]

Defines a function (%) returning a list of strings.

Explanation

(%) is called as w%c, with w being the input string, and c the character to keep. In short, this definition works by separating w into the first character (a) and the remainder (x), splitting x at the first occurrence of a character other than c, and recursively calling itself with that one character dropped.

w@(a:x)%c              -- define (%) with w separated into a and x.
 |(d,_:y)<-span(==c)x  -- split x; bind the string of `c` to d, and the rest
                       -- to _:y, dropping first character and calling the rest y.
  =w:(a:d++y)%c        -- if there was a character to drop, cons w onto the
                       -- sequence gained by recursively calling (%) with that
                       -- character removed (i.e. call with a:d++y).
 |0<1=[w]              -- if nothing needed to be dropped, the result sequence is
                       -- simply the one-element list [w]
\$\endgroup\$
  • 3
    \$\begingroup\$ Can you explain the code? \$\endgroup\$ – bli Nov 22 '16 at 11:52
  • 1
    \$\begingroup\$ @bli Done! Hopefully this helps? \$\endgroup\$ – dianne Nov 23 '16 at 2:18
14
\$\begingroup\$

Retina, 28 27 bytes

Byte count assumes ISO 8859-1 encoding.

;{G*1`
R1r`(?!^|.*¶?\1$)(.)

Try it online!

Explanation

;{G*1`

There's a lot of configuration here. The stage itself is really just G1`, which keeps only the first line, discarding the input character. * turns it into a dry run, which means that the result (i.e. the first line of the string) is printed without actually changing the string. { tells Retina to run both stages in a loop until the string stops changing and ; prevents output at the end of the program.

R1r`(?!^|.*¶?\1$)(.)

This discards the first character which a) isn't at the beginning of the input, b) isn't equal to the separate input character.

\$\endgroup\$
10
\$\begingroup\$

Pip, 22 26 24 22 bytes

Lv+#Paa@oQb?++oPaRA:ox

Takes string as first command-line argument, character as second. Try it online!

Explanation

Loops over characters of input; if the character equals the special character, move on to the next one; if not, delete it and print the string.

An ungolfed version (a, b get cmdline args; o starts with a value of 1, x is ""):

P a         Print a
L #a-1      Loop len(a)-1 times:
 I a@o Q b   If a[o] string-eQuals b:
  ++o         Increment o
 E {         Else:
  a RA: o x   In-place in a, Replace char At index o with x (i.e. delete it)
  P a         Print a
 }

Golfing tricks:

  • The loop header for L is only evaluated once, so we can sneak the initial print in there. #Pa-1 won't work because P is low-precedence (it would parse as #P(a-1)), but we can rearrange it to v+#Pa, using the v variable preinitialized to -1.
  • The RA: operator returns the new value of a, so we can print that expression instead of having a separate Pa statement.
  • Now both of the branches of the if statement are single expressions, so we can use the ternary operator ? instead.
\$\endgroup\$
10
\$\begingroup\$

Perl 5, 29 bytes

I got 35 bytes using Strawberry Perl: 31 bytes, plus 1 for -nE instead of -e, plus 3 for space + -i (used for the single-letter input; the longer string is from STDIN).

chomp;say;s/(.)[^$^I]/$1/&&redo

However, I've no doubt this is doable without chomp; using <<<, which is 29 bytes, even though I can't test it myself using Strawberry.

say;s/(.)[^$^I]/$1/&&redo

Thus:

perl -im -nE'say;s/(.)[^$^I]/$1/&&redo' <<< "example"
\$\endgroup\$
  • \$\begingroup\$ You can just specify "no newline in the input" (which is how the second program works). If you badly need to remove newlines in the input, look into the -l option, which turns on an automatic newline handling mode in which print prints an additional newline (irrelevant here) and -p/-n input removes the newline (very relevant). Also, it's deprecated, but I think you can replace the ^I with a literal control-I for an extra byte of savings. Finally, I think s/.\K[^$^I]/redo/e would be one character shorter, although I'm not 100% sure that's a legal place to put a redo. \$\endgroup\$ – user62131 Nov 19 '16 at 23:19
  • \$\begingroup\$ @ais523, thanks for the newline advice, but I guess I handled the issue well enough already. Re literal ^I, that's true for most of the control-letter variables, but not this one, IIRC. Re \K and putting redo in the replacement with /e, thanks! I'll test it when I have a chance to…. \$\endgroup\$ – msh210 Nov 20 '16 at 5:03
  • \$\begingroup\$ ... and it doesn't work. @ais523 \$\endgroup\$ – msh210 Nov 21 '16 at 23:15
8
\$\begingroup\$

Perl 6,  47 40  38 bytes

->\a,\b{a,{S/^(."{b}"*:)./$0/}...^{$^a eq $^b}}
->\a,\b{a,{S/^(."{b}"*:)./$0/}...^&[eq]}
{$^b;$^a,{S/^(."$b"*:)./$0/}...^&[eq]}

Expanded:

{       # lambda with two placeholder parameters 「$a」 and 「$b」

  $^b;    # declare second parameter

  $^a,    # declare first parameter, and use it to seed the sequence

  {       # bare block lambda with implicit parameter 「$_」
    S/      # string replace and return
      ^       # beginning of string
      (       # capture into 「$0」
        .       # the first character
        "$b"*   # as many 「$b」 as possible
        :       # don't allow backtracking
      )
      .       # any character ( the one to be removed )

    /$0/      # put the captured values back into place
  }

  ...^      # repeat that until: ( and throw away the last value )

  &[eq]     # the infix string equivalence operator/subroutine

}

The reason ...^ was used instead of ... is that &[eq] wouldn't return True until the last value was repeated.

\$\endgroup\$
7
\$\begingroup\$

05AB1E, 26 25 bytes

¬ˆ[¦Ðg_#¬²k0Qi²ˆë¯J?,]¯J?

¬ˆ                         Put the first character into an array
  [                        While true
   ¦                       Remove the first character
    Ð                      Triplicate
     g_#                   if the string is empty, break
        ¬²k0Qi             if the first character is equal to the one specified in the input
              ²ˆ           Add it to the array
                ë          Else
                 ¯J?       Display the array
                    ,      Display the remaining string
                     ]     End while
                      ¯J?  Display the last string

Try it online!

Please note that ¬²k0Q could be rewritten ¬²Q, but for some reason it doesn't work when the current character is a quote mark: Q returns the actual string instead of a boolean and it causes an infinite loop.

This code can be golfed further since ¯J? is duplicated. Moving this part in the loop would remove the duplication and would also allow to drop the closing square bracket.

\$\endgroup\$
  • \$\begingroup\$ DˆćUΔD²KRнõ.;DXìˆ}¯¨» for 21, but that uses new commands. \$\endgroup\$ – Magic Octopus Urn May 21 '18 at 17:12
6
\$\begingroup\$

Python 2, 71 66 bytes:

f,m=input();k=f[0]
while f:a=f[0]==m;k+=f[0]*a;f=f[1+a:];print k+f

A full program. Takes 2 inputs through STDIN in the format '<String>','<Char>'.

Also, here is a recursive solution currently at 140 bytes:

Q=lambda c,p,k='',j=1,l=[]:c and Q(c[1:],p,k+c[0]*(j<2)+c[0]*(c[0]==p),j+1,l+[k+c])or'\n'.join(sorted({*l},key=l.index))+('\n'+k)*(k not in l)

This one should be called in the format print(Q('<String>','<Char>')).

\$\endgroup\$
  • \$\begingroup\$ I'm no python buff, but shouldn't this print only one line? \$\endgroup\$ – Conor O'Brien Nov 19 '16 at 20:08
  • \$\begingroup\$ @ConorO'Brien Yeah, I misread the post before. It's fixed now. \$\endgroup\$ – R. Kap Nov 20 '16 at 1:45
6
\$\begingroup\$

JavaScript (ES6), 74 bytes

(s,c)=>[...t=s.slice(1)].map(d=>c!=d?s+=`
`+s[0]+(t=t.replace(d,``)):s)&&s
\$\endgroup\$
  • \$\begingroup\$ I think this produces incorrect output for f('test cases', 's') (ending with stss, rather than tsss). I think this is because replace removes the first occurance so it removes the first t rather than the second t in the fourth iteration of the map loop. \$\endgroup\$ – Lmis Nov 21 '16 at 14:00
  • \$\begingroup\$ @Lmis Thanks for pointing that out, I think I was able to fix one of my versions for "only" a 7 byte penalty. \$\endgroup\$ – Neil Nov 21 '16 at 19:19
6
\$\begingroup\$

Python 3, 72 bytes

def e(i,k):
 for r in i:
  if r!=k:i=i[0]+i[1:].replace(r,'',1);print(i)

Try it online!

e('😋🥕🍎🥓🥑🥓🥑🥒🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆','🥓')

Go on a diet:

😋🥕🍎🥓🥑🥓🥑🥒🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🍎🥓🥑🥓🥑🥒🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥑🥓🥑🥒🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🥑🥒🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🥒🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🍆🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🥔🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🍆🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🥓🍅🥜🥓🥔🍅🍄🍆
😋🥓🥓🥓🥜🥓🥔🍅🍄🍆
😋🥓🥓🥓🥓🥔🍅🍄🍆
😋🥓🥓🥓🥓🍅🍄🍆
😋🥓🥓🥓🥓🍄🍆
😋🥓🥓🥓🥓🍆
😋🥓🥓🥓🥓
\$\endgroup\$
5
\$\begingroup\$

Ruby, 148 139 97 90 83 77 62 bytes

a,c=$*;p s=""+a;i=1;while d=s[i];(d!=c)?(s[i]="";p s):i+=1;end

Not sure if amateur code is accepted on this exchange but I'm interested in learning to code golf although I'm terrible at it, any help on how I'd get this program looking as small as the others here?

EDIT:

Replaced puts with p

Removed a tonne of whitespace and counted bytes correctly thanks to Wheat Wizard

Thanks to challenger5 went from s=gets.chop;c=gets.chop; to s,c=gets.chop,gets.chop;

replaced then with ; and gets.chop with gets[0] thanks Mhutter!

Taking input as command line variables now, eg. prog.rb helloworld l

Thanks to numerous improvements by jeroenvisser101 replacing a=s.dup with s=""+a and the previous if statement if s[i]!=c;s[i]="";p s;else i+=1;end with (d!=c)?(s[i]="";p s):i+=1; huge improvement!

\$\endgroup\$
  • \$\begingroup\$ Welcome to the site! I am not an expert in Ruby golfing but it looks like you have extra whitespace. Particularly around the =s. For more comprehensive tips you can visit our tips page. \$\endgroup\$ – Sriotchilism O'Zaic Nov 21 '16 at 5:19
  • \$\begingroup\$ The easiest way to remove bytes is to eliminate excess whitespace, for example s=gets.chomp. I'm not sure if you can do this in Ruby but in some languages like Python you can combine multiple assignments into one statement, like a,b,c=0,1,2. \$\endgroup\$ – Esolanging Fruit Nov 21 '16 at 5:23
  • \$\begingroup\$ Hey thanks for the tip about whitespace read the ruby documentation and realised semicolons can replace them for ending statements :') as for making the s=gets.chop and c=gets.chop i cant do s,c=gets.chop or anything like that unfortunately theyre definitely the largest part of the code and I'd like to remove that lengthy statement.. \$\endgroup\$ – Ben Hili Nov 21 '16 at 5:26
  • \$\begingroup\$ You still have some extra spaces particularly before keywords (do,then and end), and around the fourth =. \$\endgroup\$ – Sriotchilism O'Zaic Nov 21 '16 at 5:27
  • \$\begingroup\$ It looks like you are short changing yourself on the byte count. I only count 90 bytes myself. \$\endgroup\$ – Sriotchilism O'Zaic Nov 21 '16 at 5:36
4
\$\begingroup\$

c90, 129 125 bytes

with whitespace:

main(q, x)
{
    for (char **v = x, *a = v[1], *b = a, *c;*b++;)
        for (c = a; c == a | *c == *v[2] && *b != *v[2] && putchar(*c),
            ++c != b || *b != *v[2] && !puts(b););
}

without whitespace:

main(q,x){for(char**v=x,*a=v[1],*b=a,*c;*b++;)for(c=a;c==a|*c==*v[2]&&*b!=*v[2]&&putchar(*c),++c!=b||*b!=*v[2]&&!puts(b););}

ungolfed:

#include <stdio.h>
int main(int argc, char **argv)
{
    char *a = argv[1];
    for (char *b = a + 1; *b; b++) {
        if (*b == *argv[2]) {
            continue;
        }
        putchar(*a);
        for (char *c = a + 1; c != b; c++) {
            if (*c == *argv[2]) {
                putchar(*c);
            }
        }
        puts(b);
    }
}

This takes a pointer to the start of the string, and loops, iterating this pointer until it reaches the end of the string. Within the loop, it prints the first character, then any instances of the second argument it finds between the start of the string and the pointer. After this, it calls puts on the pointer, printing out the rest of the string.

This must be compiled on a system where sizeof(int) == sizeof(char*). +3 bytes otherwise.

This is the first time I've tried code golfing here, so I'm sure there are some optimizations to be made.

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

Dyalog APL, 27 bytes

{×i←⊃1+⍸⍺≠1↓⎕←⍵:⍺∇⍵/⍨i≠⍳≢⍵}

is the excluded character, is the initial string

print argument; find index i of the first non- after the first char; if found, call recursively with i removed

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

Mathematica, 64 bytes

Most@FixedPointList[StringReplace[#,b_~~Except@a:>b,1]&,a=#2;#]&

Anonymous function. Takes two strings as input, and returns a list of strings as output. Works by repeatedly removing the first non-instance of the character.

\$\endgroup\$
  • \$\begingroup\$ I am definitely going to start using FixedPointList. \$\endgroup\$ – ngenisis Dec 1 '16 at 20:37
3
\$\begingroup\$

05AB1E, 26 24 23 bytes

Thanks @Kade for 2 bytes!
Thanks @Emigna for 1 byte!

¬UDvy²k0Êiy¡¬s¦yý«Xs«=¦

Uses the CP-1252 encoding. Try it online!

y²k0Ê could be y²Ê but the " messes it up.

This probably could be golfed more because « is repeated twice. Please leave a comment if you have any suggestions or ways to golf it down more.

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

Java 10, 155 140 139 124 bytes

c->s->{var r=s+"\n";for(int i=0;++i<s.length();)if(s.charAt(i)!=c)r+=(s=s.substring(0,i)+s.substring(i--+1))+"\n";return r;}

Try it online.

Explanation:

c->s->{          // Method with character and String parameters and String return-type
  var r=s+"\n";  //  Result-String, starting at the input-String with trailing new-line
  for(int i=0;++i<s.length();)
                 //  Loop over the characters of the String, skipping the first
    if(s.charAt(i)!=c)
                 //   If the current character and the input-character are equal
      r+=(s=s.substring(0,i)+s.substring(i--+1))
                 //     Remove this character from the String `s`
         +"\n";  //     And append the new `s` with trailing new-line to the result-String
  return r;}     //  Return the result-String

Old 139 bytes recursive answer:

void c(String s,int c){System.out.println(s);for(int i=1;i<s.length();)if(s.charAt(i++)!=c){c(s.substring(0,i-1)+s.substring(i),c);break;}}

-1 bytes thanks to @Eugene. (Next time make a comment instead of editing someone else's post, please.)

Try it online.

Explanation:

void c(String s,int c){     // Method with String and integer parameters and no return-type
  System.out.println(s);    //  Print the input-String with trailing new-line
  for(int i=1;i<s.length();)//  Loop over the characters of the String, skipping the first
    if(s.charAt(i++)!=c){   //   If the current character and the input-character are equal
      c(s.substring(0,i-1)+s.substring(i),c); 
                            //    Remove this character, and do a recursive call
      break;}}              //    And stop the loop
\$\endgroup\$
  • \$\begingroup\$ Wouldn't it be much shorter to not bother with a char[], and just use s.charAt()? \$\endgroup\$ – dpa97 Nov 21 '16 at 17:12
  • \$\begingroup\$ @dpa97 Ah, you're completely right. I used a foreach loop at first, but changed it to a regular for-loop. Forgot to remove the char-array. Thanks. \$\endgroup\$ – Kevin Cruijssen Nov 21 '16 at 17:52
2
\$\begingroup\$

PHP, 88 84 86 85 82 81 78 bytes

1 byte saved thanks to @IsmaelMiguel, 3 bytes thanks to @user59178, 3 bytes inspired by @user59178

while($b=substr("$argv[1]\n",$i++))$a>""&$b[0]!=$argv[2]?print$a.$b:$a.=$b[0];

takes input from command line arguments; run with php -r <code> '<string>' <character>


  • appends a newline to the input for an implicit final print.
    That adds 5 4 bytes of code, but saves on the output and an additional echo$a;.
\$\endgroup\$
  • 1
    \$\begingroup\$ $argv[1]."\n" can be written as "$argv[1]\n" \$\endgroup\$ – Ismael Miguel Nov 20 '16 at 2:14
  • 1
    \$\begingroup\$ As $b gets a newline added to it it will always by truthy as long as it has length >= 1. As such the ""< is unnecessary. \$\endgroup\$ – user59178 Nov 21 '16 at 12:03
  • \$\begingroup\$ You can save another byte by using a ternary in the substr() rather than assigning $b. \$\endgroup\$ – user59178 Nov 21 '16 at 14:33
  • \$\begingroup\$ @user59178 I didn´t really catch you there: I need the substr result for both the condition and the print; so I should assign it somewhere. But You inspired me. \$\endgroup\$ – Titus Nov 21 '16 at 15:10
  • \$\begingroup\$ I meant for(;$b=substr($b?:".$argv[1]\n",1);) but what you have now even better. \$\endgroup\$ – user59178 Nov 21 '16 at 17:48
2
\$\begingroup\$

C#, 122 117 112 bytes

IEnumerable F(string s,char c){for(int i=0;i<s.Length;++i)if(i<1||s[i]!=c)yield return i>0?s=s.Remove(i--,1):s;}

Ungolfed :

public IEnumerable F(string s, char c) {
    for (int i = 0; i < s.Length; ++i) {
        if (i < 1 || s[i] != c)
            yield return i > 0 ? s = s.Remove(i--, 1) : s;
    }
}

Returns a collection of strings.

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice trick with using not generic collection. But it won't work, if last char is not special char c. In that case loop will try to work forever. \$\endgroup\$ – paldir Nov 21 '16 at 13:44
  • 1
    \$\begingroup\$ @paldir Woops, you're right ! Turning my brain on this time, found a better (and shorter !) way. \$\endgroup\$ – psycho Nov 21 '16 at 14:48
  • \$\begingroup\$ You could remove the parenthesis of the for loop to save 2 bytes. \$\endgroup\$ – PmanAce Nov 21 '16 at 17:32
  • \$\begingroup\$ @PmanAce Sorry, what do you mean ? Which parenthesis ? \$\endgroup\$ – psycho Nov 21 '16 at 17:46
  • \$\begingroup\$ public IEnumerable F(string s, char c) { for (int i = 0; i < s.Length; ++i) if (i < 1 || s[i] != c) yield return i > 0 ? s = s.Remove(i--, 1) : s; } \$\endgroup\$ – PmanAce Nov 21 '16 at 19:00
2
\$\begingroup\$

TSQL, 127 bytes(Excluding variable definitions)

DECLARE @1 VARCHAR(100)='codegolf.stackexchange.com'
DECLARE @2 CHAR(1) = 'o'

DECLARE @ char=LEFT(@1,1)WHILE patindex('%[^'+@2+']%',@1)>0BEGIN SET @1=STUFF(@1,patindex('%[^'+@2+']%',@1),1,'')PRINT @+@1 END

Formatted:

DECLARE @1 VARCHAR(100) = 'codegolf.stackexchange.com'
DECLARE @2 CHAR(1) = 'o'
DECLARE @ CHAR = LEFT(@1, 1)

WHILE patindex('%[^' + @2 + ']%', @1) > 0
BEGIN
    SET @1 = STUFF(@1, patindex('%[^' + @2 + ']%', @1), 1, '')

    PRINT @ + @1
END
\$\endgroup\$
  • \$\begingroup\$ Good use of patindex, but the alphabet example doesn't seem quite right, it displays aaphabet down through aaa. Also worth mentioning this should be run on a server or database with a case-sensitive collation, otherwise the upperCASE example also fails, displaying ueE on its final row. \$\endgroup\$ – BradC May 21 '18 at 16:54
2
\$\begingroup\$

C#, 135 138 :( 137 bytes

Golfed:

IEnumerable<string>F(string s,char c){int i=1,l;for(;;){yield return s;l=s.Length;while(i<l&&s[i]==c)i++;if(i==l)break;s=s.Remove(i,1);}}

Ungolfed:

    IEnumerable<string> F(string s, char c)
    {
        int i = 1, l;

        for (;;)
        {
            yield return s;

            l = s.Length;

            while (i < l && s[i] == c)
                i++;

            if (i == l)
                break;

            s = s.Remove(i, 1);
        }
    }

Function returns collection of strings.

EDIT1: @psycho noticed that algorithm was not implemented properly.

EDIT2: Created variable for s.Length. One byte saved thanks to @TheLethalCoder.

\$\endgroup\$
  • 1
    \$\begingroup\$ Won't work if the input char is present more than once in a row. Ex : codeegolf e would give ce instead of cee. \$\endgroup\$ – psycho Nov 21 '16 at 12:56
  • \$\begingroup\$ @psycho I swapped if with while and it works. \$\endgroup\$ – paldir Nov 21 '16 at 13:14
  • \$\begingroup\$ Better ! But it can be shorter. I'll post my own ! \$\endgroup\$ – psycho Nov 21 '16 at 13:31
  • 1
    \$\begingroup\$ Create a variable for s.Length to save one byte: int i=1,l;for(;;){yield return s;l=s.Length;while(i<l&&s[i]==c)i++;if(i>=l)break;s=s.Remove(i,1);}} \$\endgroup\$ – TheLethalCoder Nov 22 '16 at 9:30
2
\$\begingroup\$

Python 2 - 65 73 Bytes

lambda s,c:[s[0]+c*s[1:i].count(c)+s[i+1:]for i in range(len(s))]

And a 76 Bytes recursive solution, because despite being longer than the firt one, I kinda like it better:

f=lambda s,c,i=1:s[i:]and[[s]+f(s[:i]+s[i+1:],c,i),f(s,c,i+1)][s[i]==c]or[s]
\$\endgroup\$
2
\$\begingroup\$

Racket 194 bytes

(let p((s s)(n 1)(t substring)(a string-append))(displayln s)(cond[(>= n(string-length s))""]
[(equal? c(string-ref s n))(p(a(t s 0 n)(t s n))(+ 1 n)t a)][else(p(a(t s 0 n)(t s(+ 1 n)))n t a)]))

Ungolfed:

(define (f s c)
  (let loop ((s s)
             (n 1))
    (displayln s)
    (cond
      [(>= n (string-length s))""]
      [(equal? c (string-ref s n))
       (loop (string-append (substring s 0 n) (substring s n))
             (add1 n))]
      [else
       (loop (string-append (substring s 0 n) (substring s (add1 n)))
             n)])))

Testing:

(f "Test cases" #\s)
(f "codegolf.stackexchange.com" #\e)

Output:

Test cases
Tst cases
Tst cases
Ts cases
Tscases
Tsases
Tsses
Tsses
Tsss
Tsss
""
codegolf.stackexchange.com
cdegolf.stackexchange.com
cegolf.stackexchange.com
cegolf.stackexchange.com
ceolf.stackexchange.com
celf.stackexchange.com
cef.stackexchange.com
ce.stackexchange.com
cestackexchange.com
cetackexchange.com
ceackexchange.com
ceckexchange.com
cekexchange.com
ceexchange.com
ceexchange.com
ceechange.com
ceehange.com
ceeange.com
ceenge.com
ceege.com
ceee.com
ceee.com
ceeecom
ceeeom
ceeem
ceee
""
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 64 69

Returning a single string with newlines

s=>c=>[...s].map((x,i,z)=>i&&x!=c&&(z[i]='',s+=`
`+z.join``))&&s

F=
s=>c=>[...s].map((x,i,z)=>i&&x!=c&&(z[i]='',s+=`
`+z.join``))&&s
  

function update() {
  var s=S.value,c=C.value[0]
  O.textContent=F(s)(c)
}

update()
<input id=S value='Hello world!' oninput='update()'>
<input id=C value='!' oninput='update()'>
<pre id=O></pre>

\$\endgroup\$
  • \$\begingroup\$ Slightly odd in that it doesn't take two arguments but one argument and then returns another function where you need to give the second argument. I'm not sure this was the expected behaviour. \$\endgroup\$ – MT0 Nov 21 '16 at 15:51
  • \$\begingroup\$ @MT0 I's odd but it's accepted for a function with 2 arguments, as it saves 1 byte. I'll give you a reference when I find one. Here it is meta.codegolf.stackexchange.com/a/8427/21348 \$\endgroup\$ – edc65 Nov 21 '16 at 16:18
  • \$\begingroup\$ Great technique, I didn't realize that modifying the third argument to .map was cumulative. I saw the .map().filter() and thought "This would make a great array comprehension!", but the lack of index in array comprehensions killed it and it ended up at the same length: s=>c=>[for(x of(i=0,z=[...s]))if(--i&&x!=c)(z[~i]=~i?'':x,z.join``)] (btw, I count 68 bytes for all of these.) \$\endgroup\$ – ETHproductions Nov 23 '16 at 1:46
  • 1
    \$\begingroup\$ Actually, by rearranging the params you can get the array comprehension down to 66: ([...z],c,i=0)=>[for(x of z)if(--i&&x!=c)(z[~i]=~i?'':x,z.join``)] \$\endgroup\$ – ETHproductions Nov 23 '16 at 1:51
  • \$\begingroup\$ @ETHproductions can't believe I was wrong in byte count again. Anyway, thanks to making me think again about it, so I got 64 with standard ES6 \$\endgroup\$ – edc65 Nov 23 '16 at 8:23
2
\$\begingroup\$

Swift 3 - 151 147 bytes

Swift isn't the ideal language for golfing, particularly when it relates to string indexing. This is the best I could do:

func c(a:String,b:String){print(a);var q=Array(a.characters),i=1;while i<q.count{if "\(q[i])" != b{q.remove(at:i);c(a:String(q),b:b);break};i=i+1}}

Unfortunately, Swift needs spaces around != (but not for ==), and Swift 3 dropped the ++ operator. The trick for both of these is to convert to a character array which allows integer indexing, and using string interpolation of a character to convert back to a String ("\(c)").

Ungolfed:

func c(a:String, b:String) {
    print(a)
    var q = Array(a.characters)
    var i = 1
    while i < q.count {
        if "\(q[i])" != b {
            q.remove(at:i)
            c(a: String(q), b: b)
            break
        }
        i=i+1
    }
}

Previous, non-recursive solution

func c(a:String,b:String){var q=Array(a.characters),e={q.removeFirst()},z="\(e())";print(a);while !q.isEmpty{"\(e())"==b ? z=z+b : print(z+String(q))}}
func c(a:String, b:String) {
    var q = Array(a.characters)
    var z = "\(q.removeFirst())"
    print(a)
    while !q.isEmpty {
        if "\(q.removeFirst())" == b {
            z = z + b
        }else{
            print(z + String(q))
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! Can some of the whitespace towards the end of the code be removed? \$\endgroup\$ – ETHproductions Dec 2 '16 at 3:00
  • \$\begingroup\$ @ETHproductions unfortunately not, the ternary operator and the while need spaces to compile. I also played with typealiasing String and trying to set print to a closure, but they didn't save any space. \$\endgroup\$ – rabidaudio Dec 2 '16 at 5:10
2
\$\begingroup\$

Pyke, 26 19 17 bytes

jljjhF3<Q/Q*jih>s

Try it here!

                  - Q = input
j                 - j = input_2
 ljjhF3           - for (i, j, j[0]) for i in range(len(j))
       <          -     j[:i]
        Q/        -    ^.count(Q)
          Q*      -   ^*Q
                s -  sum(j[0], ^, V)
            jih>  -   j[i+1:]
\$\endgroup\$
  • \$\begingroup\$ Could you add an explanation? \$\endgroup\$ – Esolanging Fruit Dec 2 '16 at 22:50
  • \$\begingroup\$ @Challenger5 done and golfed 2 bytes! \$\endgroup\$ – Blue Dec 3 '16 at 11:24
1
\$\begingroup\$

Mathematica, 78 bytes

Damn you Martin Ender, I was almost first :p

(i=2;a={c=#};While[i<=Length@c,If[c[[i]]==#2,i++,c=c~Drop~{i};a=a~Append~c]];a)&

Unnamed function; straightforward implementation with a While loop and a few temporary variables.

\$\endgroup\$
  • \$\begingroup\$ Oh, c'mon, we both know that Mathematica isn't imperative \$\endgroup\$ – LegionMammal978 Nov 20 '16 at 2:50
  • 1
    \$\begingroup\$ <waves a white flag> \$\endgroup\$ – Greg Martin Nov 20 '16 at 19:15
1
\$\begingroup\$

JavaScript ES6, 89 bytes

I thought this would be an easy challenge, but I'm pretty sure I'm missing something here..

Uses recursion and returns an array of strings

(c,i=1,r)=>f=a=>a[i]?a[i++]==c?f(a):f(g=a.slice(0,i-1)+a.slice(i--),(r=r||[a]).push(g)):r

F=
  (c,i=1,r)=>f=a=>a[i]?a[i++]==c?f(a):f(g=a.slice(0,i-1)+a.slice(i--),(r=r||[a]).push(g)):r

G=_=>A.value.length>1 && (O.innerHTML = F(E.value)(A.value).join`
`)

G()
<input id=A oninput='G()' value='alphabet'>
<input id=E oninput='G()' value='a'>
<pre id=O>

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

Groovy, 34 bytes

{a,b->a.inject{i,r->i+=r==b?b:""}}
\$\endgroup\$
  • 1
    \$\begingroup\$ Its so weird to get an old answer upvoted... \$\endgroup\$ – Magic Octopus Urn Apr 28 '17 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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