Here's exercise 5.F.2 from 'A Book of Abstract Algebra' by Charles C Pinter:
Let
Gbe the group{e, a, b, b^2, b^3, ab, ab^2, ab^3}whose generators satisfya^2 = e,b^4 = e,ba = ab^3. Write the table ofG. (Gis called the dihedral group D4.)
Here's a little Perl 6 program which presents a solution:
sub generate(%eqs, $s)
{
my @results = ();
for %eqs.kv -> $key, $val {
if $s ~~ /$key/ { @results.push($s.subst(/$key/, $val)); }
if $s ~~ /$val/ { @results.push($s.subst(/$val/, $key)); }
}
for @results -> $result { take $result; }
my @arrs = @results.map({ gather generate(%eqs, $_) });
my $i = 0;
while (1)
{
for @arrs -> @arr { take @arr[$i]; }
$i++;
}
}
sub table(@G, %eqs)
{
printf " |"; for @G -> $y { printf "%-5s|", $y; }; say '';
printf "-----|"; for @G -> $y { printf "-----|"; }; say '';
for @G -> $x {
printf "%-5s|", $x;
for @G -> $y {
my $result = (gather generate(%eqs, "$x$y")).first(* (elem) @G);
printf "%-5s|", $result;
}
say ''
}
}
# ----------------------------------------------------------------------
# Pinter 5.F.2
my @G = <e a b bb bbb ab abb abbb>;
my %eqs = <aa e bbbb e ba abbb>; %eqs<e> = '';
table @G, %eqs;
Here's what the resulting table looks like:
Let's focus on these particular lines from generate:
my @arrs = @results.map({ gather generate(%eqs, $_) });
my $i = 0;
while (1)
{
for @arrs -> @arr { take @arr[$i]; }
$i++;
}
A recursive call to generate is made for each of the items in @results. Then we're effectively performing a manual 'zip' on the resulting sequences. However, Perl 6 has zip and the Z operator.
Instead of the above lines, I'd like to do something like this:
for ([Z] @results.map({ gather generate(%eqs, $_) })).flat -> $elt { take $elt; }
So here's the full generate using Z:
sub generate(%eqs, $s)
{
my @results = ();
for %eqs.kv -> $key, $val {
if $s ~~ /$key/ { @results.push($s.subst(/$key/, $val)); }
if $s ~~ /$val/ { @results.push($s.subst(/$val/, $key)); }
}
for @results -> $result { take $result; }
for ([Z] @results.map({ gather generate(%eqs, $_) })).flat -> $elt { take $elt; }
}
The issue with the Z version of generate is that it hangs...
So, my question is, is there a way to write generate in terms of Z?
Besides this core question, feel free to share alternative solutions to the exercise which explore and showcase Perl 6.
As another example, here's exercise 5.F.3 from the same book:
Let G be the group
{e, a, b, b^2, b^3, ab, ab^2, ab^3}whose generators satisfya^4 = e,a^2 = b^2,ba = ab^3. Write the table ofG. (G is called the quaternion group.)
And the program above displaying the table:
As an aside, this program was converted from a version in C#. Here's how generate looks there using LINQ and a version of ZipMany courtesy of Eric Lippert.
static IEnumerable<string> generate(Dictionary<string,string> eqs, string s)
{
var results = new List<string>();
foreach (var elt in eqs)
{
if (new Regex(elt.Key).IsMatch(s))
results.Add(new Regex(elt.Key).Replace(s, elt.Value, 1));
if (new Regex(elt.Value).IsMatch(s))
results.Add(new Regex(elt.Value).Replace(s, elt.Key, 1));
}
foreach (var result in results) yield return result;
foreach (var elt in ZipMany(results.Select(elt => generate(eqs, elt)), elts => elts).SelectMany(elts => elts))
yield return elt;
}
The entire C# program: link.


