It's consecutive doubling and adding from left to right
- the first tr doubles every digit mod 10 1->2, ... 5->0, 6->2,...
- the second tr adds a carry bit for every 5-9 -> 1
- since the next bit is appended, the carry bit is shifted to the left
- the | does a bitwise or which adds the bits ²
for example if $n == "08" and the next bit is "1", you'll get "06" | "11" == "17" and so on.
tybalt loves constructing¹ regex-automatons on strings
¹) cryptic
²) this part is a bit (sic ;) voodoo for me | [reply] [d/l] [select] |
Hmm... That's amazing. But i tried to break it down into more easily understandable parts for me, and I think I broke it! Can you please show me why it no longer works? EDIT: I think I know what I did wrong. I accidentally doubled the "|" character. I can't even type. X_X
sub binary2decimal
{
defined $_[0] or return 0;
my $B = $_[0];
$B =~ tr|01||cd; # Remove illegal chars
$B =~ s/^0+//; # Remove preceding zeros
my @BITS = split(//, $B);
my $n = 0;
my $copy1;
my $copy2;
my $copy3;
foreach (@BITS)
{
$copy1 = $n;
$copy2 = $n;
$copy1 =~ tr/1-9/246802468/;
$copy2 =~ tr/1-9/00001/;
$n = (0 . $copy1 || $copy2 . $_); # This should be | not ||
$n =~ s/^0+(?=.)//;
}
return $n;
}
| [reply] [d/l] |
Not my code, and far too tricky to maintain in my opinion.
Relying on the idiosyncracies of | is nothing I recommend.
I even have problems to reproduce my own explanation in the debugger.
The original code works tho when tested. 🤷🏻♀️
| [reply] [d/l] |
shift in a sub shifts @_, the array that holds the sub's arguments.
| [reply] [d/l] [select] |
Oh oh, I see!! So, you get the value of $_[0] using shift, then you split the incoming string into individual characters, then you iterate through each character one by one performing this Chinese transform on each digit:
$n = (0 . $n =~ tr/1-9/246802468/r | $n =~ tr/1-9/00001/r . $_) =~
s/^0+(?=.)//r
I have no idea what I'm looking at, but I think, if I can ever come up with code like this, I will have become a Perl hacker. Haha for example, I don't understand how transforming digits from 1-9 into 246802468 is going to end up as a decimal in the end. So, I don't understand any of this. But I find it fascinating/amazing.
I'm Harangzsolt33, but somehow I got logged out. | [reply] |
The first tr/// converts each digit to the least significant digit you get when you multiply that digit by 2.
The second tr/// produces the carry bit for each digit product.
The bitwise 'or' adds the carry to the next higher digit (because of the concatenation of the new bit).
It's sort of like how you were doing the multiply by 2, but with a better handling of the carry. Because we are only multiplying
by 2 there never will be a chained carry (where a carry causes another carry, similar to 4999+1).
| [reply] |
| [reply] |