Introduction
Let's say that S1 = a...b
and S2 = ..c..
. If we place them on top of each other, we get:
a...b
..c..
We merge both strings, with the .
as the liquid character (which can overlapped). We get this:
a.c.b
If one of the string is longer than the other, we just apply the same algorithm:
a.....b
..c..
becomes:
a.c...b
and
a.....b
..c.......
becomes:
a.c...b...
If two characters collide, we just use the bottom character, e.g.
a..b
...c
becomes:
a..c
The Task
Given two non-empty strings, output the merged string. Note, you can assume that the input only contains periods and lowercase letters (or uppercase letters if that is more convenient).
Test cases
Input Output
a....b ..c... a.c..b
aaaaaa bbbbbb bbbbbb
ab.ab. b.b.b. bbbab.
a.......b c c.......b
This is code-golf, so the submission with the least amount of bytes wins!
19 Answers 19
CJam, 9 bytes
leul.e>el
Explanation
Makes use of the fact that '.' < upper case letters < lower case letters
. This way, when taking the element-wise maximum between two strings, any letter overrides a .
, but we can make a letter from the second input override a letter from the first if we upper case the first. Confusing? Here's one of the test cases as an example:
ab.ab.
b.b.b.
Convert first to upper case:
AB.AB.
b.b.b.
Take the element-wise maximum:
bBbAb.
Convert back to lower case:
bbbab.
And here is how the code does that:
l e# Read first line.
eu e# Convert to upper case.
l e# Read second line.
.e> e# Take element-wise maximum. If the lengths are different, the additional elements
e# from the longer list are just appended.
el e# Convert back to lower case.
-
5\$\begingroup\$ Nice
eu
/el
trick! \$\endgroup\$Luis Mendo– Luis Mendo2016年03月04日 22:26:16 +00:00Commented Mar 4, 2016 at 22:26
Jelly, 5 bytes
Œu»Œl
Input via command-line arguments.
Explanation
This is a direct port of my CJam answer (see that for an explanation why this works):
Œu # Convert first argument to upper case.
» # Element-wise maximum between both strings.
Œl # Convert result back to lower case.
-
6\$\begingroup\$ NOOO! You can't adopt Jelly too! We will be left with all the mods as golfing masters. \$\endgroup\$Riker– Riker2016年03月05日 04:47:05 +00:00Commented Mar 5, 2016 at 4:47
-
\$\begingroup\$ @rikerw haha, why d'you think they're mods? cause they're good at golf :P \$\endgroup\$cat– cat2016年03月05日 05:07:42 +00:00Commented Mar 5, 2016 at 5:07
-
4\$\begingroup\$ @RikerW I just had to preempt someone else beating me by porting my own solution to Jelly. ¯\_(ツ)_/¯ \$\endgroup\$Martin Ender– Martin Ender2016年03月05日 10:11:17 +00:00Commented Mar 5, 2016 at 10:11
Javascript ES6, (削除) 52 (削除ここまで) 55 chars
(a,b)=>b.replace(/\./g,(m,i)=>a[i]||m)+a.slice(b.length)
Test
f=(a,b)=>b.replace(/\./g,(m,i)=>a[i]||m)+a.slice(b.length)
;`
a....b ..c... a.c..b
aaaaaa bbbbbb bbbbbb
ab.ab. b.b.b. bbbab.
a.......b c c.......b
c a....b a....b
`.split('\n').filter(Boolean).map(s=>s.split(/\s+/)).every(a=>f(a[0],a[1])==a[2])
-
1\$\begingroup\$ This will fail for input such as:
f('c', 'a....b')
\$\endgroup\$Andreas Louv– Andreas Louv2016年03月05日 09:00:00 +00:00Commented Mar 5, 2016 at 9:00 -
\$\begingroup\$ @dev-null, fixed \$\endgroup\$Qwertiy– Qwertiy2016年03月05日 21:14:39 +00:00Commented Mar 5, 2016 at 21:14
Seriously, 10 bytes
,û,Z`M`MΣù
Uses the same strategy as Martin's CJam answer
Explanation:
,û,Z`M`MΣù
,û get first string, uppercase
,Z get second string, zip with first string
`M`M map maximum
Σù join and uppercase
Octave, 50 bytes
function c=m(a,b)c=b;c(a>0)=a;i=b>46;c(i)=b(i);end
-
\$\begingroup\$ You can replace
!=
by>
\$\endgroup\$Luis Mendo– Luis Mendo2016年03月05日 02:24:40 +00:00Commented Mar 5, 2016 at 2:24
Haskell, (削除) 43 (削除ここまで) 42 bytes
(a:b)#(c:d)|c<'a'=a:b#d|1<2=c:b#d
a#b=a++b
Usage example: "ab.ab." # "b.b.b."
-> "bbbab."
.
How it works:
if both list are non-empty, pick the the head of the 1st list if the head of the 2nd list is
"."
, else pick the head of the second list. Append a recursive call with the tails of the lists.if at least one list is empty, append both lists.
Edit: @Lynn saved a byte. Thanks!
-
\$\begingroup\$ "you can assume that the input only contains periods and lowercase letters", so you could check
c<'a'
to save a byte. \$\endgroup\$lynn– lynn2016年03月05日 01:28:21 +00:00Commented Mar 5, 2016 at 1:28
Python 2, 47 bytes
lambda s,t:`map(max,s.upper(),t)`[2::5].lower()
-
\$\begingroup\$ very golfy! I'm looking for a way to get rid of upper() and lower() but no luck so far... \$\endgroup\$Max– Max2016年03月05日 09:35:22 +00:00Commented Mar 5, 2016 at 9:35
-
\$\begingroup\$ @Max you sadly can't... this program uses the fact that
'.'<uppercase<lowercase
. \$\endgroup\$Joao-3– Joao-32023年01月08日 12:24:01 +00:00Commented Jan 8, 2023 at 12:24
Julia, 101 bytes
f(s,t,r=i->rpad(i,max((n=endof)(s),n(t)),"."))=join([min(a,b)<90?max(a,b):b for(a,b)=zip(r(s),r(t))])
This is a function that accepts two strings and returns a string.
We compute m
as the maximum length of the two inputs, then define a function r
that right pads its input with .
s to length m
and store that as a function argument. We then zip
the right padded inputs and check the minimum (as defined by the ASCII code) of each pair. If it's a .
, we use whichever character has the bigger code, otherwise we use whichever came from the second input. The resulting array is join
ed into a string and returned.
C, (削除) 106 (削除ここまで) 89 bytes
i,j,k;f(s,z)char*s,*z;{for(i=0,j=k=1;j|k;i++)putchar((k=k?z[i]:0)>46|!(j=j?s[i]:0)?k:j);}
Test live on ideone.
Retina, 55
$ +`(.?(\S* )(\w)|(\S)(\S* ).?)(\S* .*) 2ドル5ドル6ドル3ドル4ドル
Line 5 is a single space. Line 6 is an empty line (with no trailing newline).
I started this one in GNU sed, (with the -r option). Straightforward port to Retina once I got the regexes figured out. The sed version is:
s/$/ /
:
s/(.?(\S* )(\w)|(\S)(\S* ).?)(\S* .*)/2円5円6円3円4円/
t
s/ *//
-
1\$\begingroup\$ The Retina version fails with
a..k.f....b c...f.g...g. => .c..kffg...g
\$\endgroup\$randomra– randomra2016年03月05日 11:34:29 +00:00Commented Mar 5, 2016 at 11:34
Python 2, 70 bytes
lambda x,y:"".join([k if k!="."and k else j for j,k in map(None,x,y)])
First we create zip both strings into one list. If the second string is longer than the first, it is padded with None
(map(None,x,y)
does that).
Then we iterate over this list with j
being the character from the first string and k
the one from the second string. We choose k
if it's not a dot and otherwise j
.
This could be 61 bytes if I could output the result as list of characters instead of a string.
Perl, 48 + 3 = 51 bytes
s/\./substr($^I,$.=pos,1)||$&/ge;$_.=substr$^I,$.
Bah cannot find a shorter solution. (Same approach as @Qwertiy's JavaScript's answer).
Requires -pl
and takes input from stdin
and -i
$ perl -i'a...ce' -ple's/\./substr($^I,$.=pos,1)||$&/ge;$_.=substr$^I,$.' <<< '..b.d..f'
a.b.de..f
-
\$\begingroup\$ Pre-extend the target string (which looks very pretty too):
$_^=$^I^$^I;s/\.|0円/substr$^I,pos,1or$&/ge
\$\endgroup\$Ton Hospel– Ton Hospel2016年03月06日 11:27:19 +00:00Commented Mar 6, 2016 at 11:27
05AB1E (legacy), 6 bytes
u‚ζ€àl
Port of @MartinEnder's CJam answer
Input as two loose strings; output as a list of characters.
Try it online or verify all test cases.
Explanation:
u # Uppercase the first (implicit) input-string
‚ # Pair it together with the second (implicit) input-string
ζ # Zip/transpose; swapping rows/columns,
# implicitly using " " as filler for unequal length strings
€ # Map over each pair:
à # Leave its maximum, based on the codepoint of the character
l # Convert each character back to lowercase
# (after which the resulting character-list is output implicitly)
Uses the legacy version of 05AB1E, because the min/max builtins work on characters based on codepoints.
In the new version of 05AB1E, (削除) this would have been 7 bytes (削除ここまで) it's 6 bytes as well with I/O as character lists†:
uζε{θl
Two loose inputs as a list of characters; output as a list of characters as well.
Try it online or verify all test cases.
Explanation:
u # Uppercase the characters of the first (implicit) input-list
ζ # Zip/transpose it with the second (implicit) input-list; swapping rows/columns,
# implicitly using " " as filler for unequal length strings
ε # Map over each pair:
{ # Sort its characters from lowest to highest based on codepoints
θ # Pop and leave the last/highest character
l # Convert this character to lowercase
# (after which the resulting character-list is output implicitly)
†: With inputs as strings, it would use the uppercased first input as filler explicit filler instead of the implicit space, and will zip the second input with itself.
R, (削除) 137 (削除ここまで) 126 bytes
\(a,b,`!`=nchar,y=`if`((!b)>!a,c(a,b),c(b,a)),x=strsplit(y,""))Reduce(paste0,Map(max,names(Map(c,el(x),u<-x[[2]])),u,na.rm=T))
My answer to this challenge is the largest one because R has default vector recycling. The code's key piece is the call Map(max,a,b)
, where a
and b
are characters vectors. This outputs the list of characters with a larger value - similar to the other solutions here.
But that works only on the strings with the same size. If the strings are of different length, than the shortest one is "recycled", meaning that the missing elements are added from the beginning of the same vector. For example, strings "a.....b"
and "..c......."
will be merged to "a.c...ba.."
instead of "a.c...b..."
.
As far as I know, it is impossible to deactivate vector recycling in vector-operating functions like Map
, rbind
, paste
etc. Luckily, I have noticed that names
adds NA
s to the end if the names vector is shorter than the host. Now that the shortest vector has the proper length, it could be passed to max function with na.rm=TRUE
filter, which removes NA
s.
Finally, there is a statement y=`if`((!b)>!a,c(a,b),c(b,a))
which is choosing the shortest string and puts it to the first place, so that it will be properly converted with the names
as shown above.
Other notable tricks used here:
Reduce(paste0,x)
, 16 bytes instead ofpaste0(x,collapse="")
, 21 bytesel(x)
, 5 bytes instead ofx[[1]]
, 6 bytes.
Vanilla version - R, 122 bytes
Employs a for
cycle.
\(a,b,`!`=nchar,x=strsplit(c(a,b),""),d={}){for(j in 1:max(!a,!b))d=Reduce(paste0,c(d,max(el(x)[j],x[[2]][j],na.rm=T)));d}
-
\$\begingroup\$ Undefined constant
_
\$\endgroup\$Joao-3– Joao-32023年01月09日 12:04:31 +00:00Commented Jan 9, 2023 at 12:04
q/kdb+, (削除) 43 (削除ここまで) 40 bytes
Solution:
lower{l:max(#:)each(x;y);upper[l$x]|l$y}
Example:
q)lower{l:max(#:)each(x;y);upper[l$x]|l$y}["a..b..";"...c"]
"a..c.."
Explanation:
(#:) // k equivalent of count
max (#:) each(x;y) // takes each string, count the length, return maximum
l$x // whites-space pad string x to length l
| // take the maximum (per Martin's strategy)
upper[...] // convert padded string 1 to uppercase
lower{...} // convert result of function to lowercase
Notes:
I'm taking taking advantage of "Given two non-empty strings" and assuming that inputs are strings. In kdb "c"
is an atom, (),"c"
is a string, otherwise need to add 6 bytes to the score, as we cannot use $
to pad an atom...
C (GCC), (削除) 86 (削除ここまで) 76 bytes
-10 bytes thanks to @ceilingcat
f(x,y)char*x,*y;{for(;*x|*y;putchar(0[y=*y?y:x]-46?*y:*x),x++,y++)x=*x?x:y;}
a.....b
..c.......
possible? What's the output then? \$\endgroup\$a.c...b...
. \$\endgroup\$