aboutsummaryrefslogtreecommitdiff
path: root/challenge-209/e-choroba/perl/ch-2.pl
blob: cf74d143caff1a596a5f852af4318a9d5d86917b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#! /usr/bin/perl
use warnings;
use strict;

use Test2::V0;

use experimental qw( signatures );

use Graph::Undirected;

sub merge_account(@accounts) {
    my %seen;
    for my $idx (0 .. $#accounts) {
        my $account = $accounts[$idx];
        my ($name, @addresses) = @$account;
        undef $seen{$_}{$name}{$idx} for @addresses;
    }

    my $g = 'Graph::Undirected'->new(unionfind => 1);
    for my $address (keys %seen) {
        for my $name (keys %{ $seen{$address} }) {
            my @indices = keys %{ $seen{$address}{$name} };
            for my $i (0 .. $#indices - 1) {
                for my $j ($i + 1 .. $#indices) {
                    $g->add_edge(@indices[$i, $j]);
                }
            }
        }
    }

    for my $component ($g->connected_components) {
        my $first = shift @$component;
        my %emails;
        @emails{ @{ $accounts[$first] }[1 .. $#{ $accounts[$first] }] } = ();
        for my $next (@$component) {
            @emails{ @{ $accounts[$next] }[1 .. $#{ $accounts[$next] }] } = ();
            undef $accounts[$next];
        }
        $accounts[$first] = [$accounts[$first][0], keys %emails];
    }
    return [grep defined, @accounts]
}

plan 8;
sub verify($got, $expected, $name) {
    is $got, bag {
        for my $account (@$expected) {
            item bag {
                item $_ for @$account;
                end();
            }
        }
        end();
    }, $name;

    is $got, bag {
        item array {
            item $_->[0];
            etc();
        } for @$expected;
        end();
    }, "$name: name goes first";
}

verify(merge_account(['A', 'a1@a.com', 'a2@a.com'],
                     ['B', 'b1@b.com'],
                     ['A', 'a3@a.com', 'a1@a.com']),
       [['A', 'a1@a.com', 'a2@a.com', 'a3@a.com'],
        ['B', 'b1@b.com']],
       'Example 1');

verify(merge_account(['A', 'a1@a.com', 'a2@a.com'],
                     ['B', 'b1@b.com'],
                     ['A', 'a3@a.com'],
                     ['B', 'b2@b.com', 'b1@b.com']),
       [['A', 'a1@a.com', 'a2@a.com'],
        ['A', 'a3@a.com'],
        ['B', 'b1@b.com', 'b2@b.com']],
       'Example 2');

verify(merge_account(['A', 'a1@a.com', 'a2@a.com'],
                     ['A', 'b1@b.com', 'a1@a.com'],
                     ['A', 'a3@a.com', 'b1@b.com']),
       [['A', 'a1@a.com', 'a2@a.com', 'a3@a.com', 'b1@b.com']],
       'Merge 3');

verify(merge_account(['A', 'a1@a.com', 'a2@a.com'],
                     ['A', 'b1@b.com', 'a1@a.com'],
                     ['A', 'a3@a.com', 'b1@b.com'],
                     ['A', 'a3@a.com', 'b2@b.com']),
       [['A', 'a1@a.com', 'a2@a.com', 'a3@a.com', 'b1@b.com', 'b2@b.com']],
       'Merge 4');