How to transpose a matrix with PowerShell using regex? - powershell

To accomplish with powershell:
Original
Transposed
0 1 2 3a b c d# $ # %
0 a #1 b $2 c #3 d %
how can a magic number be used (some regex in practice) where each original row has a variable number of columns so that only when the keyword occurs does that initiate a transpose?
Assuming that the original matrix is nx2 so something like:
a 1
b 2
c 3
d 4
a 5
d 6
a 7
b 8
c 9
The resulting matrix may very well be sparse, but each occurrence of a would signify a new column of output.

To transpose Rows to column conversion of file with powershell:
(Note that there is nothing in the referral that shows how magic numbers should be used to accomplish this)
$Orginal = #'
0 1 2 3
a b c d
# $ # %
'#
$Transposed = [Collections.ObjectModel.Collection[Object]]::new()
$Lines = $Orginal -Split '\r?\n'
for ($y = 0; $y -lt $Lines.Count; $y++) {
$Items = $lines[$y] -Split '\s+'
for ($x = 0; $x -lt $Items.Count; $x++) {
if ($x -ge $Transposed.Count) { $Transposed.Add((,#() * $Lines.Count)) }
$Transposed[$x][$y] = $Items[$x]
}
}
$Transposed |Foreach-Object { "$_" }
0 a #
1 b $
2 c #
3 d %

Related

It there a way in powershell to make a positive number to a negative number whitout using multiplication?

I was wondering if there is a way to make a positive number into a negative number whitout using a multiplication like $b = $a * -1
I'm looking for the most cost sensible way because I'm gonna do this a lot of times in a script.
-edit
At this point I'm using this, but lookes very costly computation wise:
$temp_array = New-Object 'object[,]' $this.row,$this.col
for ($i=0;$i -le $this.row -1 ; $i++) {
for ($j=0;$j -le $this.col -1 ; $j++) {
$digit = $this.data[$i,$j] * -1
$temp_array[$i,$j] = 1 / ( 1 + [math]::exp( $digit ) )
#[math]::Round( $digit ,3)
}
}
$this.data = $temp_array
To unconditionally turn a positive number into its negative equivalent (or, more generally, flip a number's sign), simply use the unary - operator:
PS> $v = 10; -$v
-10
Applied to your case:
$digit = -$this.data[$i,$j]
As an aside: If performance matters, you can speed up your loops by using .., the range operator to create the indices to iterate over:
$temp_array = New-Object 'object[,]' $this.row,$this.col
for ($i in 0..($this.row-1)) {
for ($j in 0..($this.col-1)) {
$digit = - $this.data[$i,$j]
$temp_array[$i,$j] = 1 / ( 1 + [math]::exp( $digit ) )
}
}
$this.data = $temp_array

Minimum bytes required to represent a signed hexadecimal value

Can anyone tell me is there any function in Perl which converts signed decimal to Hex with minimum number of bytes.
ex: -555(dec) => FFFFFDD5(hex) [ converted using $Hex = sprintf( "%X", -555 )]
I want the result to be FDD5 instead of FFFFFDD5.
2 bytes are enough to represent -555.But i am getting 4 bytes conversion.
Please help!
There are two problems with your approach.
It's unparsable.
For example, even if you only know you have two numbers,
Bytes 12 34 56 7816 could refer to 1216 and 34567816.
Bytes 12 34 56 7816 could refer to 123416 and 567816.
Bytes 12 34 56 7816 could refer to 12345616 and 7816.
You could use some external means of identifying the length of the encoded number, but that would nullify some or all of the savings.
It's ambiguous.
For example,
Bytes FD D516 could refer to 6498110 (Bytes 00 00 FD D516 as an int32).
Bytes FD D516 could refer to -55510 (Bytes FF FF FD D516 as an int32).
One solution is to use a length prefix (like UTF-8).
-2^13..2^13-1 2 bytes 00xx xxxx xxxx xxxx
-2^21..2^21-1 3 bytes 01xx xxxx xxxx xxxx xxxx xxxx
-2^29..2^29-1 4 bytes 10xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
-2^31..2^31-1 5 bytes 1100 0000 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
The optimal scheme will depend on the distribution of your numbers.
The packing/encoding function for the above scheme could be written as follows:
sub pack_vint32 {
my $n = shift;
my $nn = $n >= 0 ? $n : ~$n;
return substr(pack('L>', ($n & 0x3FFF ) | 0x0000 ), -2) if !($nn & ~0x1FFF);
return substr(pack('L>', ($n & 0x3FFFFF ) | 0x400000 ), -3) if !($nn & ~0x1FFFFF);
return substr(pack('L>', ($n & 0x3FFFFFFF) | 0x80000000), -4) if !($nn & ~0x1FFFFFFF);
return "\xC0".pack('L>', $n);
}
And the unpacking/decoding function for the above scheme could be written as follows:
sub unpack_vint32 {
for (shift) {
if (/^[\x00-\x3F]/) {
return if length() < 2;
my $n = unpack('L>', "\x00\x00".substr($_, 0, 2, '')) & 0x3FFF;
$n -= 0x4000 if $n & 0x2000;
return $n;
}
elsif (/^[\x40-\x7F]/) {
return if length() < 3;
my $n = unpack('L>', "\x00".substr($_, 0, 3, '')) & 0x3FFFFF;
$n -= 0x400000 if $n & 0x200000;
return $n;
}
elsif (/^[\x80-\xBF]/) {
return if length() < 4;
my $n = unpack('L>', substr($_, 0, 4, '')) & 0x3FFFFFFF;
$n -= 0x40000000 if $n & 0x20000000;
return $n;
}
elsif (/^\xC0/) {
return if length() < 5;
return unpack('xl>', substr($_, 0, 5, ''));
}
elsif (length() == 0) {
return;
}
}
croak("Bad data");
}
Test:
my $s =
join '',
map { pack_vint32($_) }
map { $_, -$_ }
130, 555, 0x12, 0x345678, 0x12345678;
say length($s);
say sprintf("%v02X", $s);
while ( my ($n) = unpack_vint32($s) ) {
say $n;
}
croak("Bad data") if length($s);
Output:
28
00.82.3F.7E.02.2B.3D.D5.00.12.3F.EE.80.34.56.78.BF.CB.A9.88.92.34.56.78.AD.CB.A9.88
----- ----- ----- ----- ----- ----- ----------- ----------- ----------- -----------
130 | | | | | | | | |
-130 ---+ | | | | | | | |
555 ----------+ | | | | | | |
-555 ---------------+ | | | | | |
18 -----------------------+ | | | | |
-18 ----------------------------+ | | | |
3430008 ---------------------------------+ | | |
-3430008 --------------------------------------------+ | |
305419896 -------------------------------------------------------+ |
-305419896 ------------------------------------------------------------------+
I think the question wants the string (ASCII) representation in hexadecimal that takes the minimum number of bytes in two's complement. I agree with comments and another answer regarding this being ambiguous, but it may be fine for "human" consumption. In this case:
sub min_bytes {
my $n = shift;
my $s = 256; # Fits in one byte
my $i = 1; # Bytes counter
while( 1 ) {
if( $n < 0 && -$n <= $s / 2 ) {
return $i;
}
elsif( $n >= 0 && $n < ($s / 2) - 1 ) {
return $i;
}
$s *= 256;
$i++;
}
}
sub to_hex {
my $n = shift;
my $l = min_bytes($n);
my $h = $n > 0 ? $n : (256 ** $l) + $n;
my $s = '';
for( my $i = 0; $i < $l; $i++ ) {
$s = unpack('H2', pack('C', $n % 256)) . $s;
$n = $n >> 8;
}
return $s;
}
# Let's try a few numbers
my #numbers = (-10, -555, -100000, -100000000, -10000000000, -10000000000000);
for my $n (#numbers) {
my $l = min_bytes($n);
my $h = to_hex($n);
print $n, " takes ", $l, " byte(s) and looks like ", uc $h, "\n";
}
I have tried not to use anything complicated. The bit unpack('H2', pack('C', $n % 256)) converts a single byte decimal number into hex.
This prints:
-10 takes 1 byte(s) and looks like F6
-555 takes 2 byte(s) and looks like FDD5
-100000 takes 3 byte(s) and looks like FE7960
-100000000 takes 4 byte(s) and looks like FA0A1F00
-10000000000 takes 5 byte(s) and looks like FDABF41C00
-10000000000000 takes 6 byte(s) and looks like F6E7B18D6000
The code uses Perl arithmetic, which may give wrong results for bigger numbers than the internal representation's precision.

switch - multiple variables

I'm trying to create a script which will work assign different IP ranges depending on the choice, currently I've done something like this:
# Get DHCP Scope Start - first IP to check - End Last IP to check
$X = 0
$Y = 0
$Z = 0
$End = 0
$DHCPServer = "DHCP"
$ScopeID = "10.0.0.0"
switch (Read-Host "Choose device to add: 1 PS3,2 PS4,3 PS4Pro,4 XboxOne,") {
1 {$z = 1 $End = 20}
2 {$z = 30 $End = 50}
3 {$z = 100 $End = 255}
4 {$y = 1 $z = 1 $end = 100}
}
But no matter how I type arguments, PowerShell always return the errors like
Unexpected token $end in expression or statement
Is there a way to fix it?
Adding some semicolons should do the trick. Alternatively, you could use new lines.
# Get DHCP Scope Start - first IP to check - End Last IP to check
$X = 0
$Y = 0
$Z = 0
$End = 0
$DHCPServer = "DHCP"
$ScopeID = "10.0.0.0"
switch (Read-Host "Choose device to add: 1 PS3,2 PS4,3 PS4Pro,4 XboxOne,") {
1 {$z = 1; $End = 20}
2 {$z = 30; $End = 50}
3 {$z = 100; $End = 255}
4 {$y = 1; $z = 1; $end = 100}
}

Swap with a consecutive line on a pattern match in unix

Can any one help me in sorting this out in sed/awk/perl
Input file
Start variable 1
End variable 2
A
Z
Next
Start variable b
End variable a
X
Y
Next
...
...
...
Start variable m
End variable n
M
N
Next
If a pattern match End found, swap with its consecutive line
Output file :
Start variable 1
A
End variable 2
Z
Next
Start variable b
X
End variable a
Y
Next
...
...
...
Start variable m
M
End variable n
N
Next
sed solution:
sed -n '/^End\s/{h;n;p;g};p' inputfile
Simple Perl solution. $n stands for "now", $b for "before", i.e. "the previous line was End".
perl -ne 'print unless $n = /^End$/; print "End\n" if $b; $b = $n'
For the updated version of your question, just add $l to remember the line to be printed:
perl -ne 'print unless $n = /^End /; $l = $_ if $n ; print $l if $b; $b = $n'
Or, equivalen but shorter:
perl -ne '$n = /^End / and $l = $_ or print; $b and print $l; $b = $n'
sed -n '/^End/{h;n;G};p' inputfile
this would do +

How does Perl decide which order to evaluate terms in an expression?

Given the code:
my $x = 1;
$x = $x * 5 * ($x += 5);
I would expect $x to be 180:
$x = $x * 5 * ($x += 5); #$x = 1
$x = $x * 5 * 6; #$x = 6
$x = 30 * 6;
$x = 180;
180;
But instead it is 30; however, if I change the ordering of the terms:
$x = ($x += 5) * $x * 5;
I do get 180. The reason I am confused is that perldoc perlop says very plainly:
A TERM has the highest precedence in Perl. They include variables,
quote and quote-like operators, any expression in parentheses, and any
function whose arguments are parenthesized.
Since ($x += 5) is in parentheses, it should be a term, and therefore executed first, regardless of the ordering of the expression.
The act of typing out the question yielded the answer to me: terms have the highest precedence. That means that the $x in the first chunk of code is evaluated and yields 1, then 5 is evaluated and yields 5, then ($x += 5) is evaluate and yields 6 (with a side-effect of setting $x to 6):
$x = $x * 5 * ($x += 5);
address of $x = $x * 5 * ($x += 5); #evaluate $x as an lvalue
address of $x = 1 * 5 * ($x += 5); #evaluate $x as an rvalue
address of $x = 1 * 5 * ($x += 5); #evaluate 5
address of $x = 1 * 5 * 6; #evaluate ($x += 5), $x is now 6
address of $x = 1 * 5 * 6; #evaluate 1 * 5
address of $x = 5 * 6; #evaluate 1 * 5
address of $x = 30; #evaluate 5 * 6
30; #evaluate address of $x = 30
Similarly, the second example reduces like this:
$x = ($x += 5) * $x * 5;
address of $x = ($x += 5) * $x * 5; #evaluate $x as an lvalue
address of $x = 6 * $x * 5; #evaluate ($x += 5), $x is now 6
address of $x = 6 * 6 * 5; #evaluate $x as an rvalue
address of $x = 6 * 6 * 5; #evaluate 5
address of $x = 36 * 5; #evaluate 6 * 6
address of $x = 180; #evaluate 36 * 5
180; #evaluate $x = 180
Whenever I have confusion about stuff like this I first pull out perldoc perlop, and then if I'm still not sure, or want to see how a particular block of code will get executed, I use B::Deparse:
perl -MO=Deparse,-p,-q,-sC
my $x = 1;
$x = $x * 5 * ($x += 5);
^D
gives:
(my $x = 1);
($x = (($x * 5) * ($x += 5)));
- syntax OK
So substituting values at each stage gives:
($x = (($x * 5) * ($x += 5)));
($x = ((1 * 5) * ($x += 5)));
($x = ((5) * (6))); # and side-effect: $x is now 6
($x = (5 * 6));
($x = (30));
($x = 30);
$x = 30;
So the fact that $x was temporarily set to 6 doesn't really affect anything, because the earlier value (1) was already substituted into the expression, and by the end of the expression it is now 30.
$x by itself is also a TERM. Since it is encountered first (in your first example), it is evaluated first.
The associativity of the * operator is leftward, so the left most term is always evaluated before the right most term. Other operators, such as ** are right associative and would have evaluated ($x += 5) before the rest of the statement.