Slowly turn a string into another

The Challenge

Given two strings/an array of strings, output the first string slowly shrinking and expanding back into the second string.

You can assume the strings will always start with the same character.

Example

Input:
"Test", "Testing"

Output:
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

First you output the first word:

Test

Then you keep removing one letter until the string is one character long:

Tes
Te
T

Then keep adding one letter of the second word until it's done:

Te
Tes
Test
Testi
Testin
Testing

(if both strings are one character long, then just output one of them once.)

Test Cases

"Hello!", "Hi."
Hello!
Hello
Hell
Hel
He
H
Hi
Hi.

"O", "O"

O

"z", "zz"

z
zz

".vimrc", ".minecraft"

.vimrc
.vimr
.vim
.vi
.v
.
.m
.mi
.min
.mine
.minec
.minecr
.minecra
.minecraf
.minecraft

"     ", "   "

SSSSS
SSSS
SSS
SS
S
SS
SSS

"0123456789", "02468"

0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0
02
024
0246
02468

(note: on the space/fourth test case, replace the S with spaces)

Rules

• This is , so shortest answer in bytes wins! Tiebreaker is most upvoted post. Winner will be chosen on 09/10/2016.

• Standard loopholes are forbidden.

• Will 2 trailing newlines (one visible empty line after the sequence) be allowed or not? – seshoumara Sep 8 '16 at 10:36

Python, 88 bytes (function) (92 for lambda) (beginner)

As lambda-function (92 bytes):

f=lambda A,B:"\n".join([(A+" ")[:-i]for i in range(len(A))]+[B[:i+1]for i in range(len(B))])

As function:

def f(a,b,c=""):
while a!=band a:print(a);a=a[:-1]
while b:c+=b;b=b[1:];print(c)

In code: or 72 bytes (from 93 bytes) Shall 'a' be the word to decrease an 'b' be the word to raise up to, this should do:

for i in range(len(a)+(a!=b)):print((a+"_")[:-i])
for k in range(len(b)):print(b[:k+1])

or with 72 chars

c=""
while a!=band a:print(a);a=a[:-1]
while b:c+=b;b=b[1:];print(c)

Apart from the lambda-version my solutions will work even with the strings starting differently (overread that part o.0 )

• You can't assume the input is in a variable. – acrolith Sep 3 '16 at 23:49
• So it must be a function? @daHugLenny – Teck-freak Sep 3 '16 at 23:51
• Either take input by STDIN (input()/raw_input()) or by function arguments. Also, instead of chars, count the length in bytes. – acrolith Sep 3 '16 at 23:53
• pretty sure some people here count chars and claim bytes, but ok. Thanks @daHugLenny – Teck-freak Sep 4 '16 at 0:01

C, 100 bytes

n;f(char*c,char*s){n=strlen(c);while(n)printf("%.*s\n",n--,c);for(n=1;s[n++];)printf("%.*s\n",n,s);}

Ungolfed test

#include <stdio.h>
#include <string.h>
n;
f(char*c,char*s)
{
n=strlen(c);
while(n)
printf("%.*s\n",n--,c);
for(n=1;s[n++];)
printf("%.*s\n",n,s);
}

int main(void)
{
char * s1 = "Test";
char * s2 = "Testing";
f(s1, s2);
return 0;
}
• The shared part of two words is not always 1-char long. – Keyu Gan Sep 6 '16 at 7:53
• But shrinking ends and expanding begins from the first common character – VolAnd Sep 6 '16 at 10:13
• Several places to save a few bytes. Make n global to make it int implicitly. Convert first while to for and move n=strlen(c) into it to drop a semicolon. Replace second do-while with another for and change logic like this: for(n=1;s[n++];)printf("%.*s\n",n,s); I've got it down to 99 bytes using similar code. – aragaer Sep 6 '16 at 13:09
• @aragaer Thanks for advice – VolAnd Sep 6 '16 at 13:52

C++, 120 bytes

[](string s,string t){int n=s.length(),k=t.length(),l=n,j=0;s+=t;while(n?n:++j<k)cout<<s.substr(n?0:l,n?n--:1+j)<<endl;}

Ungolfed test

#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main(void)
{
string s1 = "Test";
string s2 = "Testing";
auto f = [](string s, string t)
{
int n = s.length(),
k = t.length(),
l = n,
j = 0;
s += t;
while (n?n:++j<k)
cout << s.substr( n?0:l, n?n--:1+j) << endl;
};
f(s1, s2);
return 0;
}

C#, 129 bytes

void f(string i, string j){for(int k=i.Length,l=0;i!=j;){Console.Write(i+'\n');i=k>1?i.Remove(--k):i+j[k+l++];}Console.Write(i);}

Ungolfed

void f(string i, string j)
{
for (int k = i.Length, l = 0; i != j; )
{
Console.Write(i+'\n');
i = k > 1 ? i.Remove(--k) : i + j[k + l++];
}
Console.Write(i);
}

param($a,$b)if($a-eq$b){$a;exit}$a.length..1|%{-join$a[0..--$_]};1..($b.length-1)|%{-join$b[0..$_]} Straightforward. Loops downward through the first string$a, then loops upward through the second string $b. Has some additional logic at the start where if the strings are equal, so that it only outputs once then exits. The loop indices are off from each other to account for fenceposting. I guess I can beat a few with Groovy here... Groovy (96 Bytes) def x(a,b,c){(a..b).each{println c.substring(0,it)}};{y,z->x(y.length(),1,y);x(1,z.length(),z);} Explanation: • X is a closure to print the substring from 0 to x from (a to b) for all integers from a to b. • The second closure passes the first word from it's length to 1 then does the second word in reverse order. Ruby, 63 bytes ->a,b{f=->s{(1..s.size).map{|l|s[0,l]}};puts f[a].reverse+f[b]} It's an anonymous function taking two strings:$ irb
2.3.0 :001 > ->a,b{f=->s{(1..s.size).map{|l|s[0,l]}};puts f[a].reverse+f[b]}["hey","you"]
hey
he
h
y
yo
you

JavaScript (ES6), 75 bytes

f=(x,y,n=1)=>x||n++<y.length?(x||y.slice(0,n))+
+f(x.slice(0,-1),y,n):''

Explanation

f=(x,y,n=1)=>               //Take 2 inputs, initialize n to 1.
x||n++<y.length?          //Increment n only if x doesn't have a value (short circuit).
(x||y.slice(0,n))+       //If x has a value, return it; otherwise, return y sliced.
+f(x.slice(0,-1),y,n):'' //Recurse, removing last char of x. No problem if x is empty.

Snippet

f=(x,y,n=1)=>x||n++<y.length?(x||y.slice(0,n))+
+f(x.slice(0,-1),y,n):''

console.log(f('Test','Testing'));
console.log(f('O','O'));
console.log(f('z','zz'));
console.log(f("0123456789", "02468"));

Gura, 115 bytes

t(a,b)={c=a.len()-1;for(i in 0..c){print(a[0..(c-i)]);println();}for(i in 1..b.len()-1){print(b[0..i]);println();}}

Just discovered this language on Github, it's pretty good !

Powershell, 88 bytes

param($a,$b)@()+($a.Length..1|%{-join$a[0..--$_]})+(2..$b.Length|%{-join$b[0..--$_]})|gu

Ungolfed test script:

$f = { param($a,$b) @()+ ($a.Length..1|%{-join$a[0..--$_]})+
(1..$b.Length|%{-join$b[0..--$_]})| gu } @( ,('O', 'O', 'O') ,('Test', 'Testing', 'Test Tes Te T Te Tes Test Testi Testin Testing') ,('Hello!', 'Hi.', 'Hello! Hello Hell Hel He H Hi Hi.') ,('z', 'zz', 'z zz') ,('.vimrc', '.minecraft', '.vimrc .vimr .vim .vi .v . .m .mi .min .mine .minec .minecr .minecra .minecraf .minecraft') ) | % {$a, $b,$e = $_$r = &$f$a $b "$r"-eq"$e"$r
''
}

Test script output:

True
O

True
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

True
Hello!
Hello
Hell
Hel
He
H
Hi
Hi.

True
z
zz

True
.vimrc
.vimr
.vim
.vi
.v
.
.m
.mi
.min
.mine
.minec
.minecr
.minecra
.minecraf
.minecraft

Expalantion:

The sum of arrays puts by pipes to gu (alias for Get-Unique). The gu eliminates double strings.

Forth (gforth), 65 bytes

: f dup 1 do 2dup cr type 1- loop 2drop 1 do dup cr i type loop ;

Try it online!

Takes arguments in order on the stack (will look like reverse order in code)

Explanation

Loops from 1 to string1-length outputting the increasingly smaller string each time. Then loops from 1 to string2-length + 1, outputting the increasingly larger string each time

Code Explanation

: f                    \ begin word definition
dup 1 do             \ duplicate the string length, then loop from 1 to string-length
2dup               \ duplicate string address and length
cr type            \ output a newline, then print the word to the given length
1-                 \ subtract 1 from string length
loop                 \ end the loop
2drop                \ drop address and string length of first string
1 do                 \ loop from 1 to string2-length
dup                \ duplicate string address
cr i type          \ output a new line then print the first i characters of the string
loop                 \ end the loop
;                      \ end the string definition

JavaScript (Node.js), 94 92 bytes

(x,y)=>[x,y].map(z=>[...z].map(e=>z.substr(0,Math.abs(i--)||--i)).join
,i=x.length).join

Try it online!

Python 2, 76 bytes

lambda s,t:'\n'.join(g(s)[:-1]+g(t)[::-1])
g=lambda s:s and[s]+g(s[:-1])or[]

Try it online!