> For the complete documentation index, see [llms.txt](https://trizen.gitbook.io/perl6-rosettacode/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://trizen.gitbook.io/perl6-rosettacode/programming_tasks/f/faces_from_a_mesh.md).

# Faces from a mesh

```perl
sub check-equivalence ($a, $b) { so $a.Bag eqv $b.Bag }

sub edge-to-periphery (@a is copy) {
    return Nil unless @a.List.Bag.values.all == 2;
    my @b = @a.shift.flat;
    while @a > 1 {
        for @a.kv -> $k, $v {
            if $v[0] == @b.tail {
                @b.push: $v[1];
                @a.splice($k,1);
                last
            }
            elsif $v[1] == @b.tail {
                @b.push: $v[0];
                @a.splice($k,1);
                last
            }
        }
    }
    @b
}

say 'Perimeter format equality checks:';

for (8, 1, 3), (1, 3, 8),
    (18, 8, 14, 10, 12, 17, 19), (8, 14, 10, 12, 17, 19, 18)
  -> $a, $b {
     say "({$a.join: ', '})  equivalent to  ({$b.join: ', '})? ",
         check-equivalence($a, $b)
}

say "\nEdge to perimeter format translations:";

for ((1, 11), (7, 11), (1, 7)),
    ((11, 23), (1, 17), (17, 23), (1, 11)),
    ((8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)),
    ((1, 3), (9, 11), (3, 11), (1, 11))
  {
    .gist.print;
    say "  ==>  ({.&edge-to-periphery || 'Invalid edge format'})";
}
```

#### Output:

```
Perimeter format equality checks:
(8, 1, 3)  equivalent to  (1, 3, 8)? True
(18, 8, 14, 10, 12, 17, 19)  equivalent to  (8, 14, 10, 12, 17, 19, 18)? True

Edge to perimeter format translations:
((1 11) (7 11) (1 7))  ==>  (1 11 7)
((11 23) (1 17) (17 23) (1 11))  ==>  (11 23 17 1)
((8 14) (17 19) (10 12) (10 14) (12 17) (8 18) (18 19))  ==>  (8 14 10 12 17 19 18)
((1 3) (9 11) (3 11) (1 11))  ==>  (Invalid edge format)
```
