by BoulderBuff64 (Novice)
 on Jun 15, 2011 at 15:55 UTC Need Help??
BoulderBuff64 has asked for the wisdom of the Perl Monks concerning the following question:

Oh Wise and Mighty Perl Monks,

Bit of a n00b here.

I have a binary input and would like to use that input to reference a block of information. A mock example: 1111 = ABCD. If given 0101 it would return B, D. If given 1001 it would return A, D.

I thought I could have the script go bit by bit: x1xx => print B. But I don't know the best way to do that.

Thanks!

Replies are listed 'Best First'.
by duelafn (Vicar) on Jun 15, 2011 at 16:30 UTC

You can use vec for this

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

my @letter = 'A'..'Z';
my \$bits = pack "b*", "1001";

for (0..8*length(\$bits)-1) {
print \$letter[\$_] if vec(\$bits,\$_,1);
}
print "\n";

Good Day,
Dean

This is the method I ended up using. Thanks!
by toolic (Bishop) on Jun 15, 2011 at 16:18 UTC
One way to move through all characters in a string is with substr:
```use warnings;
use strict;

my \$str = 'ABCD';
while (my \$mask = <DATA>) {
for my \$i (0 .. length(\$mask)-1) {
print substr(\$str, \$i, 1) if substr(\$mask, \$i, 1) eq '1';
}
print "\n";
}

__DATA__
1001
1110
0101
0001
I think the OP is asking about binary data, not character data that contains '0' and '1'?
by oxone (Friar) on Jun 15, 2011 at 16:18 UTC
Not a complete solution, but a hint to point you in the right direction:
```use strict;
use warnings;

my \$byte = 'X';

my \$binary = unpack('b*', \$byte);

print \$binary;    # prints 00011010
by TomDLux (Vicar) on Jun 15, 2011 at 16:38 UTC

Given some input string representing a binary number, \$bin, verify it only contains 1 & 0, to protect little Bobby Tables, then convert to an ordinary number. You only have 15 values to deal with, so you can hardcode an array. If it's 10 to 20 bits, you can precompute the array; if it's more, probably better to stick with calculating things as you need them, possibly with memoizing.

```my @block = qw( D C CD B BD BC BCD A AD AC ACD AB ABD ABC ABCD );
unshift @block, '';   # empty string for 0

\$bin =~ m{([01]+)};     # untaint input
my \$idx = eval "0b\$1";

my \$result = \$block[\$idx];

As Occam said: Entia non sunt multiplicanda praeter necessitatem.

```\$bin =~ m{([01]+)};     # untaint input
my \$idx = eval "0b\$1";

1. You shouldn't use the results of a regular expression unless you verify that it matched correctly.
2. Why use string eval when oct is less dangerous and provides the same result.

by AnomalousMonk (Chancellor) on Jun 15, 2011 at 20:35 UTC

The comment in the  extract() function below says it works for a binary mask in the range 0 .. 255 (i.e., an 8-bit mask, and it does), but I think it will work with up to a 31-bit mask (but this is untested). The test suite is not complete; add your own examples.

by Marshall (Abbot) on Jun 16, 2011 at 09:05 UTC
Another way to shift through the ascii bit pattern is with split. A split on //, separates a string into individual characters.
```#!/usr/bin/perl -w
use strict;

my @ltrs = qw (A B C D);
my \$num = "0101";

print "\$num=>";
my \$i =0;
foreach my \$bit (split(//,\$num))
{
print \$ltrs[\$i] if \$bit;
\$i++;
}
print "\n";

# prints: 0101=>BD
I did not get the impression that the OP was interested in doing actual binary to decimal conversion although jwkrahn's suggestion of: \$decimal = oct( "0b\$input" ); looks like a "winner" to me in the case of ASCII strings.

I would like to hear more about the application if these bits or combinations of bits represent something other than just a number. I probably would have some suggestions in that event, but want to hear more before running off on a tangent.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://909797]
Approved by BrowserUk
help
Chatterbox?
 [Corion]: Discipulus: Notepad++, or Perl ;) [marto]: xubuntu or lubuntu [Corion]: :-D [marto]: my desktop is a core2 duo, 120GB SSD, 4GB RAM, boots to (GUI) login in less than 10 seconds from cold start [Discipulus]: mah, winbuntu 10... [marto]: whent he boys start school I'll build myself as new machine, ryzen based [Corion]: marto: That's cool! I think my (home) desktop spends 30 seconds in the BIOS... [Corion]: marto: Heh - currently they seem promising, but I think I'll stay with nVidia+Intel for the time being, as I've been bitten too often by bad AMD drivers Discipulus is (still?) not a big fan of notepad++

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2017-07-27 08:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I came, I saw, I ...

Results (407 votes). Check out past polls.