Merging two strings

18

2

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 , so the submission with the least amount of bytes wins!

Adnan

Posted 2016-03-04T22:14:33.173

Reputation: 41 965

Is input a.....b ..c....... possible? What's the output then? – Luis Mendo – 2016-03-04T22:22:08.780

@DonMuesli That would become a.c...b.... – Adnan – 2016-03-04T22:22:43.500

Can we output a list of characters instead of a string? – Denker – 2016-03-05T00:49:55.970

@DenkerAffe No, sorry – Adnan – 2016-03-05T00:51:59.827

Can the strings be taken in the opposite order? – Mego – 2016-03-05T04:05:34.077

Possible duplicate of Unslice a string

– timmyRS – 2016-03-05T09:46:45.830

@Mego Yes, but that means that when two characters collide, the top character is used instead of the bottom. – Adnan – 2016-03-05T13:49:29.600

Answers

10

Jelly, 5 bytes

Œu»Œl

Input via command-line arguments.

Try it online!

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.

Martin Ender

Posted 2016-03-04T22:14:33.173

Reputation: 184 808

5NOOO! You can't adopt Jelly too! We will be left with all the mods as golfing masters. – Rɪᴋᴇʀ – 2016-03-05T04:47:05.177

@rikerw haha, why d'you think they're mods? cause they're good at golf :P – cat – 2016-03-05T05:07:42.640

3@RikerW I just had to preempt someone else beating me by porting my own solution to Jelly. ¯\(ツ) – Martin Ender – 2016-03-05T10:11:17.697

15

CJam, 9 bytes

leul.e>el

Test it here.

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.

Martin Ender

Posted 2016-03-04T22:14:33.173

Reputation: 184 808

4Nice eu / el trick! – Luis Mendo – 2016-03-04T22:26:16.737

6

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])

Qwertiy

Posted 2016-03-04T22:14:33.173

Reputation: 2 697

1This will fail for input such as: f('c', 'a....b') – andlrc – 2016-03-05T09:00:00.573

@dev-null, fixed – Qwertiy – 2016-03-05T21:14:39.397

5

Pyth, 11

smenD\.d.TQ

Try it online or run the Test Suite

FryAmTheEggman

Posted 2016-03-04T22:14:33.173

Reputation: 16 206

4

Seriously, 10 bytes

,û,Z`M`MΣù

Try it online!

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

Mego

Posted 2016-03-04T22:14:33.173

Reputation: 32 998

4

Octave, 50 bytes

function c=m(a,b)c=b;c(a>0)=a;i=b>46;c(i)=b(i);end

Rainer P.

Posted 2016-03-04T22:14:33.173

Reputation: 2 457

You can replace != by > – Luis Mendo – 2016-03-05T02:24:40.040

3

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!

nimi

Posted 2016-03-04T22:14:33.173

Reputation: 34 639

“you can assume that the input only contains periods and lowercase letters”, so you could check c<'a' to save a byte. – Lynn – 2016-03-05T01:28:21.770

3

Python 2, 47 bytes

lambda s,t:`map(max,s.upper(),t)`[2::5].lower()

xsot

Posted 2016-03-04T22:14:33.173

Reputation: 5 069

very golfy! I'm looking for a way to get rid of upper() and lower() but no luck so far... – Max – 2016-03-05T09:35:22.540

2

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 joined into a string and returned.

Alex A.

Posted 2016-03-04T22:14:33.173

Reputation: 23 761

2

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.

removed

Posted 2016-03-04T22:14:33.173

Reputation: 2 785

1

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).

Try it online.

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/ *//

Digital Trauma

Posted 2016-03-04T22:14:33.173

Reputation: 64 644

1The Retina version fails with a..k.f....b c...f.g...g. => .c..kffg...g – randomra – 2016-03-05T11:34:29.187

1

Python 2, 70 bytes

lambda x,y:"".join([k if k!="."and k else j for j,k in map(None,x,y)])

Try it here!

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.

Denker

Posted 2016-03-04T22:14:33.173

Reputation: 6 639

1

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

andlrc

Posted 2016-03-04T22:14:33.173

Reputation: 1 613

Pre-extend the target string (which looks very pretty too): $_^=$^I^$^I;s/\.|\0/substr$^I,pos,1or$&/ge – Ton Hospel – 2016-03-06T11:27:19.503

0

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...

streetster

Posted 2016-03-04T22:14:33.173

Reputation: 3 635

0

PHP>=7.1, 58 Bytes

for([,$x,$y]=$argv;~$c=$y[$i++];)$c<_?:$x[$i-1]=$c;echo$x;

Online Version

Jörg Hülsermann

Posted 2016-03-04T22:14:33.173

Reputation: 13 026