Zip

ambs on 2004-07-08T18:24:36

I work at a University (well, I'm preparing to start a PhD). Meanwhile, I've been helping giving an exam (programming and C). One of the questions was to write a zip function: given two strings with the same size (say, "abcd" and "efgh"), print the zipped version ("aebfcgdh").

During the exam I (and other Perl programmer) were talking about how to do it in Perl, but different: $a and $b has each string, and we want to create in memory the zipped string.

I came across with this (I think, interesting) solution:

 @b = split //, $b;
 $a =~ s!.!$&.shift@b!ge

Other suggestions of "interesting" ways to do it?


Another way

vsergu on 2004-07-08T18:35:15

$a=~s/(?<=.)/$b=~m|.|g;$&/ge;

Re:Another way

ambs on 2004-07-08T19:10:18

hmms... nice bunch of characters :-) Interesting result :-) Perl rockz :-) You Rockz :)

Re:Another way

vsergu on 2004-07-08T19:22:24

Actually I originally did it like this, just to have a substitution inside a substitution:

$a=~s/(?<=.)/$b=~s|.||;$&/ge;

But I decided that destroying $b in the process might not be acceptable.

chop chop

jmm on 2004-07-08T18:40:38

sub zip {
    my( $a, $b ) = @_;
    my $res;
    $res .= chop($b).chop($a) for 1..length($a);
    scalar(reverse $res);
}

Re:chop chop

ambs on 2004-07-08T19:03:01

Nice. We all forget chop :-)

Re:chop chop

jmm on 2004-07-08T19:11:03

I long ago proposed, on perl5-porters, an operator "chip" that would take one char from the front of a string, the way chop takes a character from the end. That would get around the need to reverse the chopped together $res.

Re:chop chop

ambs on 2004-07-08T19:25:34

Chip sounds cool... can remember computer chips but also food O:-)

During our discussion about an "interesting" solution, we could take advantage of chip. We thought of unshift, but that doesn't work for arrays.

Re:chop chop

jmm on 2004-07-08T19:43:28

The computer chip I referred to in the original proposal was Chip Salzenburg, who was working on Topaz (the original potential perl6) at the time, had established The Perl Foundation, and was the original pumpking (after Larry), so sneaking an honorarium mention of him into the language seemed reasonable.

Re:chop chop

jmm on 2004-07-08T19:48:31

We thought of unshift, but that doesn't work for arrays. s/arrays/strings/;

Much like your original proposal, you can use:

@a = split //, $a;
@b = split //, $b;
my $res .= (shift @a) . (shift @b) while @a;

Re:chop chop

ambs on 2004-07-08T19:59:34

That was almost my first solution:
@a = split //, $a;
@b = split //, $b;
while (@a) {
  push @c, shift(@a), shift(@b)
}
$c = join "",@c;

use perl6

jmm on 2004-07-08T19:38:27

Just wait a while, perl6 will have a zip operator (the Yen currency symbol) that merges two lists in interleaved order.

Re:use perl6

ambs on 2004-07-08T19:49:04

Hyperoperator (>>) is just anything I'm waiting for :-D

Re:use perl6

ambs on 2004-07-08T19:51:34

>> >>

HTML suckz.

Re:use perl6

ambs on 2004-07-08T19:52:06

I'm really stupid, today :)

>> <<

Re:use perl6

jmm on 2004-07-08T19:53:46

The quote of the moment seems to fit: &more_coffee for 1..3; -- Jarkko Hietaniemi

I measure neat in strokes

cwest on 2004-07-08T20:23:39

$b=~s!!$a=~/./g;$&!ge

The zip in my solution is in $b.

Re:I measure neat in strokes

ambs on 2004-07-09T08:00:07

Simpler than vsergu solution and based on the match "between" characters... Smart :-D