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!
10 Answers 10
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
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
-
\$\begingroup\$ You can cut a byte by binding
y\\x
for the0<1
otherwise guard. \$\endgroup\$xnor– xnor2016年09月23日 09:10:07 +00:00Commented Sep 23, 2016 at 9:10 -
\$\begingroup\$
filter(`notElem`x)y
is shorter thany\\x
with import \$\endgroup\$Damien– Damien2016年09月23日 16:10:04 +00:00Commented 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– dianne2016年09月23日 16:23:57 +00:00Commented Sep 23, 2016 at 16:23 -
\$\begingroup\$ Oh, yes you are right. \$\endgroup\$Damien– Damien2016年09月23日 16:26:16 +00:00Commented Sep 23, 2016 at 16:26
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:
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
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"));
}
}
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!
-
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– m-chrzan2016年09月23日 14:23:11 +00:00Commented 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– m-chrzan2016年09月23日 14:39:05 +00:00Commented Sep 23, 2016 at 14:39 -
\$\begingroup\$ @m-chrzan Oh, I didn't observe carefully the question. Thanks! \$\endgroup\$cia_rana– cia_rana2016年09月23日 15:00:14 +00:00Commented 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– m-chrzan2016年09月23日 15:01:20 +00:00Commented Sep 23, 2016 at 15:01 -
\$\begingroup\$ @m-chrzan Great! I added your answer. \$\endgroup\$cia_rana– cia_rana2016年09月23日 15:14:18 +00:00Commented Sep 23, 2016 at 15:14
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);
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
}
Python 2, (削除) 81 (削除ここまで) 72 bytes
a,b=sorted(input(),key=len)
for c in a:b=b.replace(c,"",1)
print a+"_"+b
-
2\$\begingroup\$ I think you can save 9 bytes by replacing the first two lines with
a,b=sorted(input(),key=len)
\$\endgroup\$dianne– dianne2016年09月23日 08:07:38 +00:00Commented Sep 23, 2016 at 8:07
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
}
juggle juggler
be?juggle_r
(remove for each character instance) orjuggle_gr
(remove for each distinct character)? \$\endgroup\$