dimmesdale has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to create a circuit from a text file. The format is that wire is represented as a '.' and a capacitor is represented by a number (0-9). (So far this is all that is supported.) The first element must be a battery, and the positive lead goes to the right, the negative goes down. In reading in the file, I transfer it to an array. However, when I later try to access the array via $Circ->[$i][$j], I cannot test this for equality -- I print out the value of @{$Circ->[$i][$j]} and it is '.', but when I ask if @{$Circ->[$i][$j]} eq '.' (or == '.' or =~ /\./) I get a negative. Here is a snippet.
# read in file, make circuit ... use Data::Dumper; # 012345678901 <--(i)--> # 0 B+.....1.... # | 1 - . # (j) 2 . . # | 3 . . # 4 .........2.. # ======================= # C1:5 (for 5 uF) # C2:6 open (CIRC, "circ.txt"); $i = 0; $j = 0; while (<CIRC>) { # put elements of circuit into m-d array last if $_ =~ /=+/; chomp; $i = 0; for $char (split //, $_) { push @{$Circ->[$i++][$j]}, $char } $j++; } $i = 1; $j = 0; while (1) { # count caps, make sure > 1 $on_i = $i; $on_j = $j; # make conditions for going up, dwn, lft, rt... if ($j-1 > 0) { LookAt ($i,$j-1) } # look up if ($j+1 < scalar @{$Circ->[$i]}-1) { LookAt ($i,$j+1) } # look down if ($i-1 > 0) { LookAt ($i-1,$j) } # look left if ($i+1 < scalar @$Circ-1) { LookAt ($i+1,$j) } # look up } sub LookAt { $l_i = $_[0]; $l_j = $_[1]; if (@{$Circ->[$l_i][$l_j]} eq '.') { print "i'm here" } }

Replies are listed 'Best First'.
Re: Array equality woes
by MarkM (Curate) on Oct 12, 2003 at 15:16 UTC

    The use of the 'eq' operator, or the '=~', will force the lvalue into scalar context. Your array, as a scalar, is interpretted to be the length of the array at the time of reference. You are comparing "1" to ".".

    You likely intend one of the following:

    @{$Circ->[$i][$j]} == 1 && $Circ->[$i][$j][0] eq '.'

    or,

    "@{$Circ->[$i][$j]}" eq '.'

    Note, in the latter case, that the array is being interpolated within a string. This code is equivalent to:

    join($,, @{$Circ->[$i][$j]}) eq '.'

    For simplicitly, I would choose to use a temporary variable:

    my $cell = $Circ->[$i][$j]; ... @$cell == 0 && $cell->[0] eq '.' ...

    Cheers,
    mark

Re: Array equality woes
by pg (Canon) on Oct 12, 2003 at 17:24 UTC

    Update1:

    Come back with some code (only breifly tested):
    $a = [[[1,2],[2,3]], [[3,4],[4,5]], [[4,5],[5,6]]]; $b = [[[1,2],[2,3]], [[3,4],[4,5]], [[4,5],[5,6]]]; print is_array_equal($a, $b); sub is_array_equal { my ($array1, $array2) = @_; if ($#array1 != $#array2) { return 0; } else { print "here\n"; for (my $i = 0; $i <= $#{$array1}; $i ++) { print "there\n"; if ((ref($array1->[$i]) eq "ARRAY") && (ref($array2->[$i]) + eq "ARRAY")) { if (!is_array_equal($array1->[$i], $array2->[$i])) { return 0; } } elsif (!ref($array1->[$i]) && !ref($array2->[$i])) { print "compare $array1->[$i] and $array2->[$i]\n"; if ($array1->[$i] != $array2->[$i]) { return 0; } } else { return 0; } } } return 1; }

    Original:

    Looks like you are comparing three dimentional arrays.

    What you can do is to write a function that calls itself recursively:
    • First it compares number of elements, if not equal, then the two arrays are not equal, so return false;
    • If number of elements are the same, then iterate thru all elements, for each pair:
      • If both elements are atomic, simply compare their values
      • If one is atomic , one is collection, no need to continue, return false
      • If both are collection, call this func recursively)
    This would not only work for your three dimentional array, but array at any depth.
Re: Array equality woes
by thens (Scribe) on Oct 12, 2003 at 15:44 UTC

    You are trying to roll your own format and parser for representation of the circuit network. You can take advantage of the plethora of the Graph modules available in CPAN. They might actually help you in finding the connectivity of nodes and other stuff. This is of course if you are building a production worthy system out of this. If this is only for academic learning purposes you can stay with your own format and parser.

    Hope this helps.

    -T

    use perl; use strict;

      It's just a small little thing I need to write for a class (academic learning purposes, you could say). But thanks for the help.
        Pity you don't need to take it further - a general-purpose circuit simulator in perl would be really nifty :-)