35
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ Will 2 trailing newlines (one visible empty line after the sequence) be allowed or not? \$\endgroup\$
    – seshoumara
    Sep 8, 2016 at 10:36

49 Answers 49

1
2
1
\$\begingroup\$

PHP, 117 109 bytes

for($i=strlen($a=$argv[1]);$i>1;)echo" ".substr($a,0,$i--);
for(;$j<strlen($b=$argv[2]);)echo" ".$c.=$b[$j++];

for($i=strlen($a=$argv[1]);$i>1;)echo substr($a,0,$i--)." ";
for(;$i<=strlen($b=$argv[2]);)echo substr($b,0,$i++)." ";

PHP, 107 bytes (not working with strings containing 0)

for($a=$argv[1];$a[$i];)echo substr($a.a,0,-++$i)." ";
for($b=$argv[2];$b[$j];)echo substr($b,0,++$j+1)." ";
\$\endgroup\$
1
\$\begingroup\$

C, 111 bytes

f(char*a, char*b){int l=strlen(a),k=1;while(*a){printf("%s\n",a);a[--l]=0;}while(b[k]) printf("%.*s\n",++k,b);}

Ungolfed test

#include <stdio.h>
#include <string.h>

f(char*a, char*b) {
  int l=strlen(a), k=1;
  while(*a) {
    printf("%s\n",a);
    a[--l]=0;
  }
  while(b[k])
    printf("%.*s\n",++k,b);
}

int main() {
  char a[10] = {0};
  char b[10] = {0};

  for (int i=0; i<5; ++i) {
    a[i] = 'a' + i;
    b[i] = 'a' + i*2;
  }

  f(&(a[0]), &(b[0]));
}
\$\endgroup\$
1
\$\begingroup\$

brainfuck, 162 bytes

,[>,]++++++++++[[-<]>[->]<]++++++++++[<[+<]<[+<]>[+>]>[+>]<---]<[<]<[<]>[[.>]++++++++++.----------<[-]<[[->+<]<]>>]>[<+>-]>[[<+>-]<[<]>[.>]++++++++++.---------->]

Try it here

Input takes the two strings separated by a linefeed.

First program with brianfuck and first code golf so I'm sure there is plenty of optimization to be done. Had fun doing it though.

Ungolfed

,[>,] Read all input
++++++++++ Flag for 10
[                   Subtract 10 from each cell to flag space for blank
    [-<]            
    >
        [->]
        <
]
++++++++++ Flag for 10
[                   Add 10 back to each cell with value in it
    <[+<]<[+<]
    >[+>]>[+>]<---
]
<[<]<[<]>               goto first cell in first string string      

[                           Print first word subtracting one each time
    [.>]                    Print first string
    ++++++++++.----------   Print new line
    <[-]                    Kill last letter of first string
    <                       Back one
    [                       Move each first string character up one
          [->+<]
          <
    ]>>
]
>[<+>-]>                    Move to first letter of scond string back one goto second letter
[                               
    [<+>-]                  Move next letter back
    <[<]>                   Move to start of string
    [.>]                    Print string
    ++++++++++.----------   Print new line
    >
]
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG! Impressive first post! \$\endgroup\$
    – Riker
    Sep 9, 2016 at 22:16
1
\$\begingroup\$

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!=b[0]and a:print(a);a=a[:-1]
 while b:c+=b[0];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[0]!=b[0])):print((a+"_")[:-i])
for k in range(len(b)):print(b[:k+1])

or with 72 chars

c=""
while a!=b[0]and a:print(a);a=a[:-1]
while b:c+=b[0];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 )

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

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;
}
\$\endgroup\$
4
  • \$\begingroup\$ The shared part of two words is not always 1-char long. \$\endgroup\$
    – Keyu Gan
    Sep 6, 2016 at 7:53
  • \$\begingroup\$ But shrinking ends and expanding begins from the first common character \$\endgroup\$
    – VolAnd
    Sep 6, 2016 at 10:13
  • \$\begingroup\$ 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. \$\endgroup\$
    – aragaer
    Sep 6, 2016 at 13:09
  • \$\begingroup\$ @aragaer Thanks for advice \$\endgroup\$
    – VolAnd
    Sep 6, 2016 at 13:52
1
\$\begingroup\$

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;
}
\$\endgroup\$
1
\$\begingroup\$

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);
}
\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

Vyxal j, 45 bitsv2, 5.625 bytes

¦Ṙ?¦ḢJ

Try it Online!

Explained

¦Ṙ?¦ḢJ­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁢‏‏​⁡⁠⁡‌⁤​‎‏​⁢⁠⁡‌­
¦Ṙ      # ‎⁡[prefixes of the first string] reversed
  ?¦Ḣ   # ‎⁢[prefixes of the second string] with the first prefix removed
     J  # ‎⁣Merged into a single list
# ‎⁤Joined on newlines by the j flag
💎

Created with the help of Luminespire.

\$\endgroup\$
1
\$\begingroup\$

Alice, 29 bytes

/OM!w@On;?$!?/
KMd!h.$t..wKh\

Try it online!

/MM!w.Ot;.$K?h!w?.n$@h!dOK    Full program untangled
/MM                           Puts the two arguments as strings on the stack
   !                          Pops the second string and save it on the tape
    w    .$K                  While the string still have characters
     .O                       Print the string
       t;                     Remove the last character from the string
                              First string done, now second one
                              As the first letter is the same:
            ?                 Get the string from the tape
             h!               Keep the first character on the stack, save the rest on the tape
               w?.n$@    K    While there are still characters to read on the tape
                     h!       Get the first character, put the rest on the tape
                       dO     Join the stack into a new string and print it
\$\endgroup\$
1
\$\begingroup\$

Raku (Perl 6) (rakudo), 56 bytes

{join "\n",reverse([\~] $^a.comb),([\~] $^b.comb)[1..*]}

Attempt This Online!

\$\endgroup\$
0
\$\begingroup\$

PowerShell v2+, 99 bytes

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.

\$\endgroup\$
0
\$\begingroup\$

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);}

Try it: https://groovyconsole.appspot.com/script/5190971159478272

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.
\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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"));

\$\endgroup\$
0
\$\begingroup\$

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 !

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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
     
 
\$\endgroup\$
0
\$\begingroup\$

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!

\$\endgroup\$
1
2

Your Answer

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

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