8
\$\begingroup\$

The Challenge

Given two strings containing only lowercase letters and no spaces, the result should be the shorter string, followed by an underscore, followed by the longer string with the first instance of a character removed for each character it contains that is in the shorter string.

You can assume the strings will always be different lengths.

Test Cases:

sale
salinewater
Result: sale_inwater (only the first 'a' in salinewater is removed)

jostling
juggle
Result: juggle_ostin (juggle is the shorter string)

juggle
juggler
Result: juggle_r (a 'g' is removed for every 'g' in the shorter string)

Rules

This is code-golf, so shortest answer in bytes wins!

\$\endgroup\$
13
  • 2
    \$\begingroup\$ What does "remove the first occurrence" mean when the shorter string has duplicate characters? \$\endgroup\$ Commented Sep 21, 2016 at 7:21
  • 2
    \$\begingroup\$ Four days is very short to pick a winner, I'd suggest at least a couple of week at minimum. Also, in the future I'd suggest first posting to the Sandbox where challenges can be clarified and improved before going live. \$\endgroup\$
    – xnor
    Commented Sep 21, 2016 at 7:21
  • 3
    \$\begingroup\$ smaller string is shorter string......sorry for my bad english \$\endgroup\$
    – Ajay
    Commented Sep 21, 2016 at 7:30
  • 6
    \$\begingroup\$ What should the output for juggle juggler be? juggle_r (remove for each character instance) or juggle_gr (remove for each distinct character)? \$\endgroup\$ Commented Sep 21, 2016 at 8:06
  • 2
    \$\begingroup\$ @Pietu1998 That's a good point. We should put this on hold until clarified \$\endgroup\$
    – Luis Mendo
    Commented Sep 21, 2016 at 8:09

10 Answers 10

5
\$\begingroup\$

Pyth, 13 bytes

++hAlDQ\_.-HG

Try it online.

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

JavaScript (ES6), 78 75 69 Bytes

const 
     g=(x,y)=>x[y.length]?g(y,x):[...x].map(c=>y=y.replace(c,''))&&x+'_'+y
;

console.log(g.toString().length + 2);   // 69
console.log(g('sale', 'salinewater'))   // sale_inwater
console.log(g('juggle', 'juggler'))     // juggle_r
console.log(g('jostling','juggle'))     // juggle_ostin

Breakdown

x[y.length]?g(y,x):        \\ Make sure that x is the shorter string
[...x]                     \\ Spread string in array of characters
.map(c=>y=y.replace(c,'')) \\ For each character remove its first occurence in y
&&x+'_'+y                  \\ Concat x and changed y 
\$\endgroup\$
2
\$\begingroup\$

Haskell, 56 55 bytes

import Data.List
x%y|(0<$y)<(0<$x)=y%x|z<-y\\x=x++'_':z

-1 byte thanks to @xnor

\$\endgroup\$
4
  • \$\begingroup\$ You can cut a byte by binding y\\x for the 0<1 otherwise guard. \$\endgroup\$
    – xnor
    Commented Sep 23, 2016 at 9:10
  • \$\begingroup\$ filter(`notElem`x)y is shorter than y\\x with import \$\endgroup\$
    – Damien
    Commented Sep 23, 2016 at 16:10
  • \$\begingroup\$ @Damien I think that would remove all occurrences of elements of x, not just the first ones. \$\endgroup\$
    – dianne
    Commented Sep 23, 2016 at 16:23
  • \$\begingroup\$ Oh, yes you are right. \$\endgroup\$
    – Damien
    Commented Sep 23, 2016 at 16:26
1
\$\begingroup\$

Java 7, 262 bytes

import java.util.*;String c(String z,String y){int i=0,l=y.length();if(z.length()>l)return c(y,z);List x=new ArrayList();for(;i<l;x.add(y.toCharArray()[i++]));for(Object q:z.toCharArray())x.remove(q);String r="";for(i=0;i<x.size();r+=x.get(i++));return z+"_"+r;}

Can probably be golfed some more by just using arrays without the lists..

Ungolfed & test cases:

Try it here.

import java.util.*;
class M{
  static String c(String z, String y){
    int i = 0,
        l = y.length();
    if(z.length() > l){
      return c(y, z);
    }
    List x = new ArrayList();
    for(; i < l; x.add(y.toCharArray()[i++]));
    for(Object q : z.toCharArray()){
      x.remove(q);
    }
    String r = "";
    for(i = 0; i < (x.size()); r += x.get(i++));
    return z+"_"+r;
  }

  public static void main(String[] a){
    System.out.println(c("sale", "salinewater"));
    System.out.println(c("jostling", "juggle"));
    System.out.println(c("juggle", "juggler"));
  }
}

Output:

sale_inwater
juggle_ostin
juggle_r
\$\endgroup\$
1
\$\begingroup\$

Java 8, 156 Bytes

String a(String x,String y){int l=x.length(),m=y.length();String b=l>m?x:y,s=m<l?y:x;for(char c:s.toCharArray()){b=b.replaceFirst(""+c,"");}return s+"_"+b;}

This can probably be golfed some more.

Ungolfed & test cases

interface A {
    static String a(String x,String y){
        int l=x.length(),m=y.length();
        String b=l>m?x:y,s=m<l?y:x;
        for(char c:s.toCharArray()){
            b=b.replaceFirst(""+c,"");
        }
        return s+"_"+b;
    }
    
    static void main(String[]a) {
        System.out.println(a("sale","salinewater"));
        System.out.println(a("jostling","juggle"));
        System.out.println(a("juggle","juggler"));
    }
}
\$\endgroup\$
1
\$\begingroup\$

Ruby, 65 bytes

->a,b{a,b=b,a if a.size>b.size;a.chars.map{|e|b.sub!e,""};a+?_+b}

ungolfed

->a, b{
  a, b = b, a if a.size > b.size
  a.chars.map { |e|
    b.sub! e, ""
  }
  a + ?_ + b
}

61 bytes(in case the argument is an array of strings)

->a{a.sort_by!(&:size);a[0].chars.map{|c|a[1].sub!c,""};a*?_‌​}

Thank you, m-chrzan!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ gsub! doesn't work here - you're supposed to remove the first occurance of each letter. Fortunately, sub!, which does exactly that, is a byte shorter. \$\endgroup\$
    – m-chrzan
    Commented Sep 23, 2016 at 14:23
  • 1
    \$\begingroup\$ Also, I think you need to name the lambda in this case, since you do end up calling it. However, doing a,b=b,a if a.size>b.size to exchange the strings is non-recursive, and saves you another byte. \$\endgroup\$
    – m-chrzan
    Commented Sep 23, 2016 at 14:39
  • \$\begingroup\$ @m-chrzan Oh, I didn't observe carefully the question. Thanks! \$\endgroup\$
    – cia_rana
    Commented Sep 23, 2016 at 15:00
  • \$\begingroup\$ 61 bytes, input as an array of strings: ->a{a.sort_by!(&:size);a[0].chars.map{|c|a[1].sub!c,""};a*?_} \$\endgroup\$
    – m-chrzan
    Commented Sep 23, 2016 at 15:01
  • \$\begingroup\$ @m-chrzan Great! I added your answer. \$\endgroup\$
    – cia_rana
    Commented Sep 23, 2016 at 15:14
0
\$\begingroup\$

PHP, 154 Bytes

list($f,$s)=strlen($b=$argv[2])<strlen($a=$argv[1])?[$b,$a]:[$a,$b];foreach(str_split($f)as$x)$s=preg_replace("#(.*?)".$x."(.*)#","$1$2",$s);echo$f."_$s";

Instead of $s=preg_replace("#(.*?)".$x."(.*)#","$1$2",$s); you can also use if($z=strstr($s,$x))$s=strstr($s,$x,1).substr($z,1);

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

R, 161 bytes

This turned out to be much longer than I expected, albeit, string manipulation is usually tedious in R. I feel that this should easily be golfable by just using another approach.

function(x,y){s=strsplit;if(nchar(x)>nchar(y)){v=y;w=x}else{v=x;w=y};v=s(v,"")[[1]];w=s(w,"")[[1]];j=0;for(i in v){j=j+1;if(i==w[j])w[j]=""};cat(v,"_",w,sep="")}

Ungofled

function(x,y){
    s=strsplit                      # alias for stringsplit
    if(nchar(x)>nchar(y)){v=y;w=x}  # assign v/w for the short/long strings
    else{v=x;w=y}
    v=s(v,"")[[1]]                  # split short string into vector
    w=s(w,"")[[1]]                  # split long string into vector
    j=0
    for(i in v){                    # for each char in short string, check
        j=j+1                       # if is equal to corresponding char in
        if(i==w[j])w[j]=""          # long, replace long with "" if true
    }
    cat(v,"_",w,sep="")             # insert _ and print
}
\$\endgroup\$
0
\$\begingroup\$

Python 2, 81 72 bytes

a,b=sorted(input(),key=len)
for c in a:b=b.replace(c,"",1)
print a+"_"+b

Try it online

\$\endgroup\$
1
  • 2
    \$\begingroup\$ I think you can save 9 bytes by replacing the first two lines with a,b=sorted(input(),key=len) \$\endgroup\$
    – dianne
    Commented Sep 23, 2016 at 8:07
0
\$\begingroup\$

Scala, 78 bytes

def f(a:String,b:String):String={if(a.size>b.size)f(b,a)else
a+"_"+(b diff a)}

Explanation:

def f(a:String,b:String):String={ //define a method f which has two String parameters and returns a String
                                  //(because it's recursive, scala can't figure out the return type)
  if (a.size > b.size)            //make sure that a is the shorter string
    f(b, a)
  else
    a+"_"+(b diff a)              //`b diff a` removes all elements/chars of a from b
}
\$\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.