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!

xnor
149k26 gold badges286 silver badges673 bronze badges
asked Sep 21, 2016 at 7:13
\$\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\$ Commented Sep 21, 2016 at 7:21
  • 3
    \$\begingroup\$ smaller string is shorter string......sorry for my bad english \$\endgroup\$ 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\$ Commented Sep 21, 2016 at 8:09

10 Answers 10

5
\$\begingroup\$

Pyth, 13 bytes

++hAlDQ\_.-HG

Try it online.

answered Sep 21, 2016 at 8:03
\$\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 
answered Sep 21, 2016 at 7:28
\$\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

answered Sep 23, 2016 at 5:37
\$\endgroup\$
4
  • \$\begingroup\$ You can cut a byte by binding y\\x for the 0<1 otherwise guard. \$\endgroup\$ Commented Sep 23, 2016 at 9:10
  • \$\begingroup\$ filter(`notElem`x)y is shorter than y\\x with import \$\endgroup\$ 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\$ Commented Sep 23, 2016 at 16:23
  • \$\begingroup\$ Oh, yes you are right. \$\endgroup\$ 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
answered Sep 21, 2016 at 8:34
\$\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"));
 }
}
answered Sep 23, 2016 at 7:56
\$\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!

answered Sep 23, 2016 at 10:45
\$\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\$ 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\$ Commented Sep 23, 2016 at 14:39
  • \$\begingroup\$ @m-chrzan Oh, I didn't observe carefully the question. Thanks! \$\endgroup\$ 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\$ Commented Sep 23, 2016 at 15:01
  • \$\begingroup\$ @m-chrzan Great! I added your answer. \$\endgroup\$ 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);

answered Sep 23, 2016 at 8:56
\$\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
}
answered Sep 23, 2016 at 11:51
\$\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

answered Sep 22, 2016 at 20:48
\$\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\$ 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
}
answered Sep 23, 2016 at 15:43
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.