$" = ''; $\ = "\n"; chomp( my @edges = map /--/ ? join( '', sort /\w/g ) : (), ); my @nodes = sort { $a cmp $b } uniq( map /\w/g, @edges ); for $node ( @nodes ) { my $edge_rx = qr/$node/; my @other_nodes = map /$edge_rx/ ? grep( $_ ne $node, # ne vs gt split( //, $_ ) ) : (), @edges; use re 'eval'; my $third_edge = qr/([@other_nodes]) .* ([@other_nodes]) (??{push @TRI, join(" - ",sort($node,$1,$2))})/x; # removed the gt. Now nodes are unordered in the triangle. All triangles are visited three times, not just once. grep ! /$node/ && /$third_edge/, @edges; } print for uniq( sort @TRI ); sub uniq { my %seen; grep !$seen{$_}++, @_ } __DATA__ graph triangles { A -- B A -- C -- F -- I A -- D -- G -- J A -- E B -- C -- D -- E B -- F -- H -- J B -- I E -- G -- H -- I E -- J I -- J } #### $" = ''; $\ = "\n"; chomp( my @edges = map /--/ ? join( '', sort /\w/g ) : (), ); my @nodes = sort { $a cmp $b } uniq( map /\w/g, @edges ); for $node ( @nodes ) { my $edge_rx = qr/$node/; my @other_nodes = map /$edge_rx/ ? grep( $_ ge $node, split( //, $_ ) ) : (), @edges; use re 'eval'; my $node_rx = qr/$node/; my $third_edge_rx = qr/[@other_nodes].*[@other_nodes]/; my $last_step = qr/([@other_nodes]) .* ([@other_nodes]) (??{print "$node -- $1 -- $2"})/x; grep $_ ge $node && ! /$node_rx/ && /$last_step/, @edges; } sub uniq { my %seen; grep !$seen{$_}++, @_ } __DATA__ graph triangles { A -- B A -- C -- F -- I A -- D -- G -- J A -- E B -- C -- D -- E B -- F -- H -- J B -- I E -- G -- H -- I E -- J I -- J } #### $" = ''; $\ = "\n"; chomp( my @edges = map /--/ ? join( '', sort /\w/g ) : (), ); my @nodes = sort { $a cmp $b } uniq( map /\w/g, @edges ); for $node ( @nodes ) { my $edge_rx = qr/$node/; my @other_nodes = map /$edge_rx/ ? grep( $_ ge $node, split( //, $_ ) ) : (), @edges; my $last_step = qr/(.).*(.)(?{print "$node -- $1 -- $2"})(?!)/; my $node_rx = qr/$node/; my $third_edge_rx = qr/[@other_nodes].*[@other_nodes]/; grep $_ ge $node && ! /$node_rx/ && /$third_edge_rx/ && /$last_step/, @edges; } sub uniq { my %seen; grep !$seen{$_}++, @_ } __DATA__ graph triangles { A -- B A -- C -- F -- I A -- D -- G -- J A -- E B -- C -- D -- E B -- F -- H -- J B -- I E -- G -- H -- I E -- J I -- J } #### $" = ''; chomp( my @edges = grep /\w -- \w/, ); my @nodes = sort { $a cmp $b } uniq( map /\w/g, @edges ); for my $node ( @nodes ) { my $edge_rx = qr/$node -- (\w)/; my @other_nodes = map /$edge_rx/ ? $1 : (), @edges; my $third_edge = qr/[@other_nodes] -- [@other_nodes]/; for ( grep /$third_edge/, @edges ) { my @nodes = sort { $a cmp $b } $node, /\w/g; $triangles{"@nodes"} = undef; } } for ( sort keys %triangles ) { print join( " -- ", split // ), "\n"; } sub uniq { my %seen; grep !$seen{$_}++, @_ } __DATA__ graph triangles { A -- B A -- C A -- D A -- E B -- A B -- C B -- D B -- E B -- F B -- H B -- J B -- I C -- A C -- B C -- D C -- E C -- F C -- I D -- A D -- B D -- C D -- E D -- G D -- I E -- A E -- B E -- C E -- D E -- G E -- H E -- I E -- J F -- B F -- C F -- H F -- I F -- J G -- A G -- D G -- E G -- H G -- I G -- J H -- B H -- E H -- F H -- G H -- I H -- J I -- B I -- C I -- E I -- F I -- G I -- H I -- J J -- A J -- B J -- D J -- E J -- F J -- G J -- H J -- I }