3
\$\begingroup\$

Your task is to write a program that will filter out some characters in a string, so that the remaining spells out (part of) the other string.

Let's say we received the string "123456781234567812345678", and the second string is "314159".

First, we put a pointer on the second string:

314159
^

So the pointer is now on 3, and we replace the not-3 characters with a hashtag until the first 3:

##3456781234567812345678

We then move the pointer to the next character until we have iterated through the string.

Specs

  • You may use any character to replace "#", and the first string will not contain the hashtag (or the replaced hashtag).
  • The second string will always be longer than enough.
  • Both strings will only contain ASCII printable characters (U+0020-U+007F).

Testcases

input1: 123456781234567812345678
input2: 314159
output: ##3#####1##4####1###5###

input1: abcdefghijklmnopqrstuvwxyz
input2: dilemma
output: ###d####i##l##############
\$\endgroup\$
9
  • 7
    \$\begingroup\$ @KennyLau could always have waited a minute to explain your question before posting it lmao \$\endgroup\$ Commented May 3, 2016 at 23:31
  • 13
    \$\begingroup\$ @KennyLau You're posting a lot of challenges, which is great, but I feel like you could do better taking more time to improve and clarify each one before posting it. \$\endgroup\$
    – xnor
    Commented May 3, 2016 at 23:38
  • 4
    \$\begingroup\$ Could you edit to specify which approximations to pi are acceptable? Otherwise I can save a lot of bytes by using the traditional approximation 3. \$\endgroup\$ Commented May 3, 2016 at 23:42
  • 4
    \$\begingroup\$ Really, this whole use of pi seems gratuitous. The string to keep could be any string, or an input. Pi just means languages with it built in have it shorter. \$\endgroup\$
    – xnor
    Commented May 3, 2016 at 23:43
  • 2
    \$\begingroup\$ Does "The second string will always be longer than enough." mean that it will always contain the first string as a subsequence? \$\endgroup\$
    – xnor
    Commented May 4, 2016 at 9:31

19 Answers 19

2
\$\begingroup\$

Python 3, 69

def f(a,b,c=''):
 for x in a:y=x==b[0];c+=x*y or'#';b=b[y:]
 return c

Uses the hash for the replacement char, and take the original and replacement as a and b respectively.

Test case:

assert f('123456781234567812345678', '314159') == '##3#####1##4####1###5###'
\$\endgroup\$
2
\$\begingroup\$

Javascript ES6, 46 bytes

a=>b=>a.replace(/./g,x=>x==b[i]?(i++,x):0,i=0)

Uses 0 as the replacement char.

\$\endgroup\$
1
  • \$\begingroup\$ I think you should be able to save 3 bytes by using replace instead. \$\endgroup\$
    – Neil
    Commented May 8, 2016 at 0:29
2
\$\begingroup\$

C#6, 112 bytes

string c(string h,string n)=>h==""?"":h[0]==n[0]?h[0]+c(h.Substring(1),n.Substring(1)):"#"+c(h.Substring(1),n);

Recursive function, takes haystack h (input1) and needles n (input2).

  • If Haystack is empty, return it.
  • if first characters of haystack and needle are equal, keep the first character and call recursively while skipping the first char on both parameters
  • else return the replacement character (fixed to # here) followed by a recursive call again skipping the first character from haystack only.

Major factor for the length is the long name of Substring, but it's not long enough (compared to the number of usages) that a wrapping function would help to reduce further.

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

Python, 115 Bytes

n,f=input()
for a in str(f):
 x,r=0,""
 for b in str(n):
  if x==0and b==a:c,x="#",1
  else:c=b
  r+=c
 n=r
print n
\$\endgroup\$
1
\$\begingroup\$

Ruby, 44 bytes

If someone helps me golf it down by any amount, then I can say crossed-out 44 is still 44

->s,r{s.gsub(/./){$&==r[0]?(r[0]='';$&):?#}}
\$\endgroup\$
1
\$\begingroup\$

Perl, 77 bytes

sub _{$p=substr$f,0,1,''}($_,$f)=@ARGV;_;print map{$_ eq$p?_&&$_||$_:'#'}/./g
\$\endgroup\$
1
\$\begingroup\$

𝔼𝕊𝕄𝕚𝕟, 18 chars / 23 bytes

îⓢ⒨≔í⟨Ḁ?(Ḁ⧺,$):0)⨝

Try it here (Firefox only).

Ayyy not bad. Uses 0 as the replacement char. It's just the same algorithm that I used in my JS answer.

\$\endgroup\$
2
  • \$\begingroup\$ Seems to work on Chrome for me. \$\endgroup\$
    – Okx
    Commented Mar 15, 2017 at 10:45
  • \$\begingroup\$ Yeah, this answer was made back when Firefox was still the only browser with enough ES6 support for 𝔼𝕊𝕄𝕚𝕟. \$\endgroup\$ Commented Mar 16, 2017 at 0:28
1
\$\begingroup\$

I realize that there's already another JS-based solution posted using the .replace method that's shorter, but I'd like to submit my answers anyways...

CoffeeScript, 55 bytes

Builds a string and returns it:

f=(a,b,i=0,s='')->s+=c==b[i]&&b[i++]||'#'for j,c of a;s

JavaScript, 53 bytes

Operates on an array of characters from the original string:

f=(a,b,i=0)=>[...a].map(c=>c==b[i]?b[i++]:`#`).join``
\$\endgroup\$
1
  • \$\begingroup\$ You can drop the f= in both. \$\endgroup\$
    – cat
    Commented May 8, 2016 at 15:53
1
\$\begingroup\$

C, 81 bytes

A[99];char*b=A,*a=A+50;main(){gets(a),gets(b);while(*a)putchar(*a++^*b?35:*b++);}
\$\endgroup\$
0
\$\begingroup\$

Haskell, 56 bytes

""%_="";(a:b)%l|a==head(l++"é")=a:b%(tail l)|0<1='#':b%l
\$\endgroup\$
1
  • \$\begingroup\$ You can pattern match the head and tail together with @ for the whole list. I don't think you need ++"é", because of the 2nd spec: "The second string will always be longer than enough". (a:b)%l@(c:d)|a==c=a:b%d|0<1='#':b%l. \$\endgroup\$
    – nimi
    Commented May 5, 2016 at 8:22
0
\$\begingroup\$

Mathcad, [tbd] bytes

enter image description here


Mathcad byte equivalence to be determined. Note that the programming operators "while", "break" and "on error" only require 1 key-combination to enter (ctl-], ctl-{ and ctl-', respectively) - they cannot be typed verbatim. What you see in the image is exactly what gets entered onto the Mathcad worksheet and the results are live - change a or b, or the function arguments, and the results update accordingly.

\$\endgroup\$
0
\$\begingroup\$

PowerShell v2+, 72 bytes

param($a,$b)$i=0;-join([char[]]$a|%{if($_-ceq$b[$i]){$_;$i++}else{'#'}})

Takes input $a and $b, sets $i to 0 (our pointer). Then, we cast $a as a char-array and pump it through a loop |%{...}. Each iteration, we check if the current character is case-sensitive-equal to the character in $b under the pointer. If it is, add it to the pipeline with $_ and increment our counter. Otherwise, add a '#' to the pipeline. All of those characters are then gathered up (...) and -joined into one string, which is then re-placed onto the pipeline. Output is implicit.

Example

PS C:\Tools\Scripts\golfing> .\filter-this-string.ps1 "Programming Puzzles & Code Golf" "PPCG"
P###########P#########C####G###
\$\endgroup\$
0
\$\begingroup\$

PHP(271)

This is my first php code so it is stronly likely that it can be golfed more

    function g($s,$b){$r='';foreach(str_split(strrev($b))as $i) $r='([^'.$i.']*?)(?:([^'.$i.']$)|'.$i.$r.')';$line=preg_replace_callback('/'.$r.'/',function ($m) {$a='';for($i=1;$i<count($m);$i=$i+2)$a=$a.$m[$i].$m[$i+1].'#';return $a;},$s);echo substr($line,0,strlen($s));}
  • I used non-recursive regex where I am certain that a recursive breakthrough is available.
  • Test it

    <?php
    g("uuuuaaaaavabbbbccccd","abcd");
    function g($s,$b){$r='';foreach(str_split(strrev($b))as $i) $r='([^'.$i.']*?)(?:([^'.$i.']$)|'.$i.$r.')';$line=preg_replace_callback('/'.$r.'/',function ($m) {$a='';for($i=1;$i<count($m);$i=$i+2)$a=$a.$m[$i].$m[$i+1].'#';return $a;},$s);echo substr($line,0,strlen($s));}
    
    • In/Outputs

       uuuuaaaaavabbbbccccd
       abcd
      
       uuuu#aaaava#bbb#ccc#
      
\$\endgroup\$
0
\$\begingroup\$

Java, 136 bytes

void i(int[]a,int[]b){int i=0,j=0,n=a.length;for(;i<b.length;i++)for(;j<n;j++)if(a[j]==b[i]){j++;break;}else a[j]=0;for(;j<n;)a[j++]=0;}

Ungolfed

void i(int[] a, int[] b) {
    int i = 0, j = 0, n = a.length;
    for (; i < b.length; i++)
        for (; j < n; j++)
            if (a[j] == b[i]) {
                j++;
                break;
            } else a[j] = 0;
    for (; j < n; ) a[j++] = 0;
}

Notes

  • Uses the NUL character as replacement, any of the first 10 would do. If you wanted a visible replacement character, this would be one byte longer.

  • Input are two integer arrays of charcodes. int[] is one byte shorter than char[].

Outputs

Input 1:    123456781234567812345678
Input 2:    314159
Output:       3     1  4    1   5   
Input 1:    abcdefghijklmnopqrstuvwxyz
Input 2:    dilemma
Output:        d    i  l              
Input 1:    314asd159asdasd
Input 2:    314159
Output:     314   159      
\$\endgroup\$
0
\$\begingroup\$

05AB1E, 5 bytes

Code:

.o²g£

Explanation:

.o     # Overlap function.
         12345 and 1456 yields:
         1  456
  ²    # Get the second input.
   g   # Take the length.
    £  # Take the substring [0:length] and implicitly output.
  

Uses CP-1252 encoding. Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 3, 197 bytes

I was determined to solve this with regex, and I did. I did not really think it would be short.

def f(n,h):r=re.match(("([^{}]*)(.)"*len(n)).format(*n),h).groups();return"".join([i if i in n else"#"for i in"".join(["".join(d)for d in zip(["#"*len(i)for i in r[::2]],r[::-1][::2][::-1])])])

Ungolfed:

def fs(needle, haystack):
    rx = "([^{}]*)(.)"
    rx *= len(needle)
    rx = rx.format(*needle)
    r  = re.match(rx, haystack).groups()
    nd = r[::-1][::2][::-1]
    hs = r[::2]
    hs = ["#" * len(i) for i in hs]
    nh = "".join([i if i in needle else "#" for i in "".join(["".join(d) for d in zip(hs, nd)])])
    return nh

I wanted to do it with regex so I can do it again in Factor which, as a point-free functional language, does not do explicit looping. Haskell also does not do explicit looping and the Haskell solution does not use pattern matching but I don't understand the Haskell solution.

Here's what I used to come up with the regex.

\$\endgroup\$
0
\$\begingroup\$

Python 3.5, 67

def f(a,b):b=[*b];return"".join(y==b[0]and b.pop(0)or"#"for y in a)

Ungolfed:

def f(a, b):
    b = [*b] #Convert string to list; yeah Python 3.5
    c = []
    for y in a:
       if y==b[0]:
          c.append(b.pop(0))
       else:
          c.append("#")
    return "".join(c)

Try it here

\$\endgroup\$
0
\$\begingroup\$

PHP, 65 bytes

function f($s,$t){for(;a&$c=$s[$i++];)echo$c==$t[$k]?$t[$k++]:_;}
\$\endgroup\$
0
\$\begingroup\$

REXX, 97 bytes

arg a b
o=
do while b>''
  parse var b n+1 b
  parse var a p (n)h+1 a
  o=o||translate(p,,p)h
  end
say o

As usual, readability is severely hampered by skipping every possible whitespace and abuttal operator.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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