1
\$\begingroup\$

Introduction

Given a set of text-based "screenshots" consisting of printable ASCII chars merge them so that all of them form one long screenshot so that nobody has to do it themselves when reading it.

Challenge

Take input as a list of strings (referred to as "screenshots"). Each screenshot consists of several lines of text.

To merge two screenshots:

  1. Starting from the first line, check if that line occurs in the second screenshot

    • If it does, cut the first screenshot so it ends at this duplicated line and cut the second screenshot so it begins one line after the duplicated line
    • Concatenate these two together with the cuts
  2. If they do not have a line of text in common, just append the second screenshot to the first (starting on a new line).

Your output should be a single string merging all of the screenshots together. Screenshot merging is not associative, so you should merge in the following order: merge the first and the second screenshot, then the resulting screenshot with the third, then the result with the fourth screenshot, and so on, until only one screenshot is left.

Example with explanation

Input:

Screenshot 1:

> hi
      hi <
> how are you doing
    good <

Screenshot 2:

      hi <
> how are you doing
    good <
> good
     yes <

Output:

> hi
      hi <
> how are you doing
    good <
> good
     yes <

Explanation:

Going from top to bottom, find the first line on both the first and second screenshot

> how are you doing

Take the first half of this screenshot above and including the line

> hi
      hi <
> how are you doing
--remove everything below--

Find the first line where it is duplicated in the next screenshot and cut one below there

--remove everything including and above--
    good <
> good
     yes <

Concatenate the two sections

> hi
      hi <
> how are you doing
--join them together--
    good <
> good
     yes <

Test Cases

Input:

line 1
line 2
line 3

line 2
line 3
line 4

Output:

line 1
line 2
line 3
line 4

Input:

line 1
line 2
line 10

line 10
line 2
line 3

Output:

line 1
line 2
line 3

Note that even though line 10 is duplicated, line 2 is duplicated first and split there.

Input:

words
really long repeated words
456

hi
really long repeated words
hmm
really long repeated words
kthxbye

Output:

words
really long repeated words
hmm
really long repeated words
kthxbye

Note that really long repeated words appears twice in the result because the one in the first screenshot and the other in the second screenshot is included

Input:

======= 10:42 ========
~~~ p1: hi
            hi :p2 ~~~
~~~ p1: yes
            no :p2 ~~~
v     -----------    v


======= 10:43 ========
            no :p2 ~~~
~~~ p1: why?
       because :p2 ~~~
~~~ p1: ok fine
v     -----------    v


======= 10:44 ========
       because :p2 ~~~
~~~ p1: ok fine
~~~                ~~~
~~~                ~~~
v     -----------    v

Output:

======= 10:42 ========
~~~ p1: hi
            hi :p2 ~~~
~~~ p1: yes
            no :p2 ~~~
~~~ p1: why?
       because :p2 ~~~
~~~ p1: ok fine
~~~                ~~~
~~~                ~~~
v     -----------    v

Note that the clock increases in time meaning that the clock is not the first duplicated input. Because it is before the first duplicated input, it gets ignored the second and third time.

Edge Case Input:

> hello
   oh hi <

> how are you doing
    good <

Output:

> hello
   oh hi <
> how are you doing
    good <

Note that nothing is duplicated here so just append them together

As this is , smallest submission in bytes wins.

\$\endgroup\$
5
  • \$\begingroup\$ Why is merging no associative? \$\endgroup\$ Jan 30, 2018 at 6:52
  • 1
    \$\begingroup\$ I suggest you add a test case where the other way around won't work. Just a suggestion. If you think it will make people even more confused, you can ignore my suggestion. \$\endgroup\$ Jan 30, 2018 at 7:01
  • \$\begingroup\$ Given the screenshots 1/2, 2/1, and 3/2, merging them left-to-right yields 1/3/2 and merging them right-to-left yields 1/2. \$\endgroup\$ Jan 31, 2018 at 4:45
  • \$\begingroup\$ Can we take input as a list of lists of lines and output a list of lines? \$\endgroup\$
    – kamoroso94
    Feb 22, 2018 at 14:03
  • 1
    \$\begingroup\$ @kamoroso94 yes \$\endgroup\$
    – pfg
    Feb 22, 2018 at 17:33

3 Answers 3

3
\$\begingroup\$

JavaScript (ES6), 112 bytes

Takes input as a list of lists of lines, outputs a list of lines.

s=>s.reduce((a,b)=>(i=a.findIndex(x=>(j=b.indexOf(x))>=0))<0?a.concat(b):a.slice(0,i+1).concat(b.slice(j+1)),[])

const f =
s=>s.reduce((a,b)=>(i=a.findIndex(x=>(j=b.indexOf(x))>=0))<0?a.concat(b):a.slice(0,i+1).concat(b.slice(j+1)),[])
;
const tests = [
[`line 1
line 2
line 3`,
`line 2
line 3
line 4`],
[`line 1
line 2
line 10`,
`line 2
line 10
line 3`],
[`words
really long repeated words
456`,
`hi
really long repeated words
hmm
really long repeated words
kthxbye`],
[`======= 10:42 ========
~~~ p1: hi
            hi :p2 ~~~
~~~ p1: yes
            no :p2 ~~~
v     -----------    v`,
`======= 10:43 ========
            no :p2 ~~~
~~~ p1: why?
       because :p2 ~~~
~~~ p1: ok fine
v     -----------    v`,
`======= 10:44 ========
       because :p2 ~~~
~~~ p1: ok fine
~~~                ~~~
~~~                ~~~
v     -----------    v`],
[`> hello
   oh hi <`,
`> how are you doing
    good <`]
];

for(let test of tests) {
  console.log('Input:', test=test.map(x=>x.split('\n')));
  console.log('Output:', f(test));
}

\$\endgroup\$
2
\$\begingroup\$

Jelly, 29 bytes

Ỵ€ð¹Ƥp¹ÐƤ}Ṛ⁼"¥Ḣ¥/ÐfḢṖ;¥/ȯ;µ/Y

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 2, 124 bytes

def f(S):
 x=[]
 for y in S:
	y=y.split('\n');x+=y;i=0
	while(x[i]in y)<1:i+=1
	x=x[:i]+y[y.index(x[i]):]
 print'\n'.join(x)

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.