references help

S

slash

Hi,
I need some desperate help with my references usage in the code below.
I'd appreciate the help enormously.

Following is the input in the "data" file:

quick brown fox
brown quick
brown fox jumped
fox brown quick
fox jumped over
fox resting over
jumped fox brown
jumped over lazy
over jumped fox
over lazy dog
lazy over jumped
lazy dog tripped
dog lazy over
dog tripped over
tripped dog lazy
tripped over resting
over tripped dog
over resting fox
resting tripped over
resting fox


Following is the code:

use strict;

my %C; # arrayref of children for a parent
my %P; # parent for a child

open (D, "<data") or die;
while (<D>) {
chomp;
my ($p, $c) = split /\s+/;

next if ((grep /^$p$/, @{$C{$c}}) || $p eq $c);

# add the child to the list of this parent's children
# unless we've already done so

push (@{$C{$p}}, $c) unless (grep /^$c$/, @{$C{$p}});

# record the parent for this child
$P{$c} = $p;
}
close (D);

my @T; # top levels - parents without parents :^)
foreach (keys %C) {
push (@T, $_) unless $P{$_};
}

# build the chart, starting with top levels
my $level = 0;
children($level, \@T);

sub children {
my ($level, $arrayref) = @_;

foreach (sort @$arrayref) {
# show indented
print (" " x $level);
print "$_\n";

# show the children (if any)
children($level+1, $C{$_}) if $C{$_};
}
}

---------------------------------------
And the output I seek is the following:

quick
brown
fox
brown
quick
fox
jumped
fox
brown
quick
resting
over
jumped
over
jumped
fox
brown
over
lazy
over
jumped
fox
tripped
dog
lazy
dog
resting
fox
lazy
over
jumped
dog
tripped
dog
lazy
over
tripped
over
tripped
dog
lazy
over
resting
resting
over
tripped
fox

When I run the above code, I get an infinite loop but I am not sure
where the mistake might be. I have been fiddling with this problem for
long now and any help would be greatly appreciated.

Thanks,
Slash
 
A

A. Sinan Unur

(e-mail address removed) (slash) wrote in
Hi,
I need some desperate help with my references usage in the code below.
I'd appreciate the help enormously.

Following is the input in the "data" file:

quick brown fox
....

Following is the code:

use strict;

my %C; # arrayref of children for a parent
my %P; # parent for a child

open (D, "<data") or die;
while (<D>) {
chomp;
my ($p, $c) = split /\s+/;

What happens to fox when this line encounters your code. You do not take
it into account at all, meaning you do not have chance to break some
circularities in your data. I can't tell right now if the checks below
can be done better, but you should at least do:

my ($p, @c) = split /\s+/;

the iterate over @c.
next if ((grep /^$p$/, @{$C{$c}}) || $p eq $c);

# add the child to the list of this parent's children
# unless we've already done so

push (@{$C{$p}}, $c) unless (grep /^$c$/, @{$C{$p}});

Sorry can't be of more help, but I don't have much time right now, and
that looked like the weakest link :)

Sinan.
 
S

Steve Grazzini

slash said:
I need some desperate help with my references usage in
the code below. I'd appreciate the help enormously.

Following is the input in the "data" file:

quick brown fox
brown quick

[ etc ]
Following is the code:

use strict;

my %C; # arrayref of children for a parent
my %P; # parent for a child

You might be happier using hashrefs at each level:

my $tree = {};

while (<D>) {
my $p = $tree;
$p = $p->{$_} ||= {} for split;
}

Now the leaf nodes are references to empty hashes.

use YAML;
print Dump $tree;

--- #YAML:1.0
brown:
fox:
jumped: {}
quick: {}
dog:
lazy:
over: {}
tripped:
over: {}


HTH
 
T

Tad McClellan

slash said:
I need some desperate help with my references usage in the code below.


Use the Data::Dumper module to see if your data structures
contain what you want them to contain.

Following is the input in the "data" file: [snip]
fox brown quick
fox jumped over
fox resting over

while (<D>) {
chomp;
my ($p, $c) = split /\s+/;


Your code discards data in the 3rd "column".

Is that what you want it to do?

# build the chart, starting with top levels


Before you do that, check to see if you've gotten what you wanted to get:

print Dumper \%C;
print Dumper \%P;
print Dumper \@T;

my $level = 0;
children($level, \@T);

sub children {
my ($level, $arrayref) = @_;

foreach (sort @$arrayref) {
# show indented
print (" " x $level);


Four space indent per level.

print "$_\n";

# show the children (if any)
children($level+1, $C{$_}) if $C{$_};


When are you expecting that $C{$_} will be false?

}
}

---------------------------------------
And the output I seek is the following:

quick
brown
fox


You will never get the output you seek.

You seek 1 space per level, and the code uses 4 spaces per level.

When I run the above code, I get an infinite loop but I am not sure
where the mistake might be.


Your recursion never stops because $C{$_} is never false.
 
T

Tad McClellan

slash said:
And the output I seek is the following:

[ hierarchy of the tree shown with indentation ]



The easiest way to fix your code, is to discard it and come up
with a cleaner algorithm. :)

This program makes the output you've asked for (assuming that
the order does not matter):

---------------------------------------------------------------------
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my %tree; # HoH
while (<DATA>) {
chomp;
my $href = \%tree;

foreach my $key ( split /\s+/ ) {
$href = \%{ $href->{$key} }; # autovivification creates anon hash
}
}
#print Dumper \%tree;

children( 0, \%tree );

sub children {
my($level, $href) = @_;

foreach my $key ( sort keys %$href ) { # stop recursing at an empty hash
print ' ' x $level, "$key\n";
children( $level+1, $href->{$key} );
}
}


__DATA__
quick brown fox
brown quick
brown fox jumped
fox brown quick
fox jumped over
fox resting over
jumped fox brown
jumped over lazy
over jumped fox
over lazy dog
lazy over jumped
lazy dog tripped
dog lazy over
dog tripped over
tripped dog lazy
tripped over resting
over tripped dog
over resting fox
resting tripped over
resting fox
 
S

slash

Thanks Tad!!
I have another situation (mentioned in an earlier posting.) First, I
want to know how to run this program on multiple input files. Second,
I want to output the result into a single dump file where document IDs
associated with each word in the leftmost column in the __DATA__ are
incorporated into the tree or the indented output below.
Would I need to build some sort of an inverted index? I am not sure
how that will pan out?
Again, many thanks in advance!!!

So, for the data at the end of the post, I would like something like
this:

brown
fox
jumped
DocID:fox.txt
quick
DocID:fox.txt
dog
lazy
over
DocID:fox.txt
tripped
over
DocID:fox.txt
fox
brown
quick
DocID:fox.txt
jumped
over
DocID:fox.txt
resting
over
DocID:fox.txt


slash said:
And the output I seek is the following:

[ hierarchy of the tree shown with indentation ]



The easiest way to fix your code, is to discard it and come up
with a cleaner algorithm. :)

This program makes the output you've asked for (assuming that
the order does not matter):

---------------------------------------------------------------------
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my %tree; # HoH
while (<DATA>) {
chomp;
my $href = \%tree;

foreach my $key ( split /\s+/ ) {
$href = \%{ $href->{$key} }; # autovivification creates anon hash
}
}
#print Dumper \%tree;

children( 0, \%tree );

sub children {
my($level, $href) = @_;

foreach my $key ( sort keys %$href ) { # stop recursing at an empty hash
print ' ' x $level, "$key\n";
children( $level+1, $href->{$key} );
}
}


__DATA__
quick brown fox
brown quick
brown fox jumped
fox brown quick
fox jumped over
fox resting over
jumped fox brown
jumped over lazy
over jumped fox
over lazy dog
lazy over jumped
lazy dog tripped
dog lazy over
dog tripped over
tripped dog lazy
tripped over resting
over tripped dog
over resting fox
resting tripped over
resting fox
---------------------------------------------------------------------
 
T

Tad McClellan

slash said:
Thanks Tad!!


You're welcome.

You can pay me back by learning to quote your followups properly.

Soon.


Have you seen the Posting Guidelines that are posted here frequently?

First, I
want to know how to run this program on multiple input files.
^^^^^^^^^^^^

What program?

We are here to _help_ you program, not to actually do the programming
for you.

Did you try modifying the program for multiple input files?

What part did you get stuck on?




[ snip 100 lines of TOFU ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top