tags:

views:

158

answers:

7

Hi all,

I want to generate a truth table for the given input.Suppose if i give input 2 the output will be

10 01 11 00 

if the input is 3 the output will be

111 000 110 101 011 100 001 010

i have a code snippet

#!/usr/bin/perl

#print "a|b|c\n";

for $a (1, 0){
    for $b (1, 0){
      for  $c (1,0) {
        for $d ( 1,0) 
        {        
          print "$a $b $c $d";
          #print $x = ($a & $b & $c);
          print "\n";
        }
     }
   }
}

print "\n";

above code is for 4.

i don't know how to do this without writing multiple for loops. Here for value 2 i need to write two for loops and so on.

can any body tell me how to tweak this code for several input values.

Any help would be great appreciated

+4  A: 

Hi

I don't know Perl so this may not work:

-- loop from 0 to (2^n)-1, where n is the number of digits in your cases;

-- convert each number to its n-digit binary representation;

Regards

Mark

High Performance Mark
You don't know Perl but you want to answer Perl questions?
Kinopiko
Actually, the question is not only perl, but also algorithmic. And this answer provides a contribution to the latter part.
mouviciel
+5  A: 

I'm no Perl expert, so you might need to clean this up, but if forced to use Perl I'd probably do something like this:

#!/usr/bin/perl

my ($n) = @ARGV;

printf("%0*b\n", $n, $_) for 0 .. (1 << $n) - 1;
Mark Byers
+6  A: 

Recursion

Here is a simple solution using recursion:

#!/usr/bin/perl -w                                                              
my $variables=$ARGV[0]||0;
show_combinations($variables);                                                           

sub show_combinations { my($n,@prefix)=@_;                                      
  if($n > 0) {                                                                  
    show_combinations( $n-1, @prefix, 0);                                       
    show_combinations( $n-1, @prefix, 1);                                       
  } else {                                                                      
    print "@prefix\n";                                                          
  }                                                                             
}

Here are some sample cases:

> script.pl 1
0
1
> script.pl 2
0 0
0 1
1 0
1 1
> script.pl 3
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Yaakov Belch
Very nice solution!
Ether
+4  A: 

Here is a generalization of my previous solution using Math::BigInt. This is an iterative solution:

#!/usr/bin/perl

use strict;
use warnings;

use Math::BigInt try => 'GMP';

my $n_bits = $ARGV[0] || 0;

my $it = make_it($n_bits);

while ( defined(my $bits = $it->()) ) {
    print "$bits\n";
}

sub make_it {
    my ($n_bits) = @_;

    my $limit = Math::BigInt->new('2');
    $limit->blsft($n_bits - 1);

    my $next = Math::BigInt->new('-1');

    return sub {
        $next->binc;
        return unless $next->bcmp($limit) < 0;
        my $bits = $next->as_bin;
        $bits =~ s/^0b//;
        if ( (my $x = length $bits) < $n_bits ) {
            $bits = '0' x ($n_bits - $x) . $bits;
        }
        return $bits;
    }
}

You can use the %b format specifier for printf:

use strict;
use warnings;

my ($count) = @ARGV;

my $fmt = "%0${count}b";
my $n = 2**$count - 1;

for my $c (0 .. $n) {
    my @bits = split //, sprintf $fmt, $c;
    print "@bits\n";
}

This will only work for $count values less than 32.

Output:

C:\Temp> y 3
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Sinan Ünür
+5  A: 

This is simple one line Perl code using module Math::Cartesian::Product.

use Math::Cartesian::Product;

cartesian {print "@_\n"} ([0..1]) x $ARGV[0];

Output

    
./sample.pl 2

0 0
0 1
1 0
1 1

./sample.pl 3

0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
somukirankumar
+1 I keep forgetting about `Math::Cartesian::Product`. I haven't tried this but what happens if `$ARGV[0]` is large?
Sinan Ünür
A: 

Based on "High-Performance Mark's answer" ( should be a comment)


my $n = shift;
printf("%0${n}b\n",$_) for  0..2**$n-1;

aartist
It looks like you missed http://stackoverflow.com/users/61974/mark-byers
Sinan Ünür
+4  A: 

I am surprised no one has mentioned glob as a solution here:

perl -e 'print join "\n", glob("{0,1}" x shift || 1 )' -- 3

This prints:

000
001
010
011
100
101
110
111

glob is very handy for computing string permutations.

Here is the above, in a cleaner, non-one-liner form:

use strict;
use warnings;

my $symbol_count = shift || 1;

my @permutations = glob( '{0,1}' x $symbol_count );

print join "\n", @permutations;
daotoad