-1

I'm having some issues trying to combine two multi-row strings into one after performing regular expression manipulations on those strings. As an example, I start with data in this form:

TMS: xxxxxxx11110000

TDI: xxxxxxx00001111

TMS: xxxx00001111

TDI: xxxx11110000

To get it in the form I need, I search the file for the key word "TMS: ", extract just the data, use regular expressions to remove the "x's", reverse the data, and then place each bit on its own line and store it in a string. Resultant string would look like this:

0
0
0
0
1
1
1
1

I then search the file for "TDI: " and repeat that same process. The last step would be to concatenate the first string with the second string to get the following output (given the example above):

01
01
01
01
10
10
10
10

10
10
10
10
01
01
01
01

However, when I concatenate the two strings, what I'm getting as an output right now is

0
0
0
0
1
1
1
1
1
1
1
1
0
0
0
0

1
1
1
1
0
0
0
0
0
0
0
0
1
1
1
1 

Is there a way to get the result I'm looking for without changing too much about my process? I've tried using the split command, chomp command, etc. without any luck.

3 Answers3

1

Would be good to have a minimal example to see how you're approaching this problem. Additionally, there are a lot of things about your input file that are not clear. For example, are TMS and TDI always paired in the file, or do you have to check for that? Will you always take the next TDI instance to pair with the preceeding TMS event, or can they be more disjointed? Does TMS always preceed TDI or can they be reversed?

One simple way to do this assuming that the data look just like you've indicated in your example, might be to read each line and store the data in one array for the TMS string and one array for the TDI string. If both arrays are full, then we have a pair to output, so output the pair and clear the arrays for the next events. Otherwise, read the next line to get the TDI data:

#!/usr/bin/env perl
use strict;
use warnings;

my (@first, @second);
while (my $elem = <DATA>) {
    ($elem =~ /^TMS/)
        ? (@first = read_string($elem))
        : (@second = read_string($elem));
    if (@second) {
        for my $index (0..$#first) {
            print "$first[$index]$second[$index]\n";
        }
        print "\n";
        @first = @second = ();
    }
}

sub read_string {
    my $string = shift;
    my @bits = grep {/\d/} split('', $string);
    return reverse(@bits);
}


__DATA__
TMS: xxxxxxx11110000
TDI: xxxxxxx00001111
TMS: xxxx00001111
TDI: xxxx11110000

Output from this would be:

01
01
01
01
10
10
10
10

10
10
10
10
01
01
01
01
drmrgd
  • 733
  • 5
  • 17
1

What you want is a zip operation. Conveniently List::MoreUtils provides one for you.

@x = qw/a b c d/;
@y = qw/1 2 3 4/;

# returns [a, 1], [b, 2], [c, 3], [d, 4]
@z = zip6 @x, @y;         

To get the input for zip either put your resultants into an array in the first place, or split your input string.

Holli
  • 5,072
  • 10
  • 27
0

hobbs answer from Code Golf: Lasers was solving quite a different problem, but part of the solution was about how to "rotate" a multi-line string, and it could be useful here.

First, don't put each bit on its own line, just separate bits from different rows of input on different lines. Put the multi-line string into $_.

$_ = '0000111111110000
1111000000001111';

Now execute the following code:

$_ = do {
    my $o;
    $o .= "\n" while s/^./$o.=$&,""/meg;
    $o };

(the substitution in hobbs's algorithm started with s/.$/.../. By using s/^./.../, it becomes an algorithm for transposition rather than for rotation)

Input:

$_ = '0000111111110000
1111000000001111';

Output:

01
01
01
01
10
10
10
10
10
10
10
10
01
01
01
01

This algorithm easily generalizes to any number of rows and columns in the input.

Input:

$_='ABCDE
12345
FGHIJ
67890';

Output:

A1F6
B2G7
C3H8
D4I9
E5J0
mob
  • 117,087
  • 18
  • 149
  • 283