This was fun :)

First part is basically the same as Re^3: Sub set where all are connected and finds all the cliques.

Last part looks for duplicated nodes, removes one of them from a clique such that the score is higher.

#!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11109069 # clique use warnings; use List::Util qw( uniq sum ); my $edges = <<END =~ s/.*Relationship.*\n//gr; Person-1 Person-2 Relationship-strength A B 92 A C 7 B C 2 C D 88 END $edges =~ s/^(\w+)\s+(\w+)\b/join ' ', sort $1, $2/gem; # fix order print "$edges\n"; my %edges = map +( $_ => qr/(*FAIL)/ ), map s/\s+/,/r, $edges =~ /^\w+\s+\w+/gm; my %cliques; my %seen; find( uniq sort $edges =~ /^(\w+)\s+(\w+)\b/gm ); # start with ever +y node sub find { $seen{ my $set = "@_" }++ and return; if( my @out = $set =~ /\b(\w+)\b.+\b(\w+)\b(??{ $edges{"$1,$2"} || " +" })/ ) { for my $node ( @out ) # pair of unconnected nodes, try without eac +h one { @_ > 1 and find( grep $_ ne $node, @_ ); } } else { $cliques{ $set }++; # it is fully con +nected } } my $uniquecliques = ''; for ( sort { length $b <=> length $a } sort +uniq # ignore subsets keys %cliques, map tr/,/ /r, keys %edges ) { my $pattern = " $_ " =~ s/\w+/\\b$&\\b/gr =~ s/ /.*?/gr; $uniquecliques =~ /^$pattern$/m or $uniquecliques .= "$_\n"; } print "cliques:\n\n$uniquecliques"; my %scorecache; sub scoreclique { $scorecache{ $_[0] } //= do { my $score = 0; "$_[0]:\n$edges" =~ /\b(\w+)\b.*\b(\w+)\b.*:.*^\1\s+\2\s+(\d+)\b(? +{ $score += $3 })(*FAIL)/ms; $score; } } my @cliques = split /\n/, $uniquecliques; my %count; $count{$_}++ for split ' ', $uniquecliques; for my $node ( map +($_) x --$count{$_}, keys %count ) # for all dups { my ($from, $to) = grep $cliques[$_] =~ /\b$node\b/, 0 .. $#cliques; my $fromscore = scoreclique($cliques[$from]) + scoreclique($cliques[$to] =~ s/\b$node\b//r); my $toscore = scoreclique($cliques[$to]) + scoreclique($cliques[$from] =~ s/\b$node\b//r); my $mod = $fromscore < $toscore ? $from : $to; # favor highest score $cliques[$mod] = join ' ', grep $_ ne $node, split ' ', $cliques[$mo +d]; } my $total = sum map scoreclique($_), @cliques; print "\nanswer($total):\n\n"; print "$_\n" for sort grep length, @cliques; __END__

Outputs:

A B 92 A C 7 B C 2 C D 88 cliques: A B C C D answer(180): A B C D

It passes all the test cases that have been provided :)


In reply to Re: Cliques solution pertinent to my use case by tybalt89
in thread Cliques solution pertinent to my use case by Sanjay

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.