#!/usr/bin/env perl

use strict;
use warnings;
use Math::DifferenceSet::Planar 1.000;

use constant PDS => Math::DifferenceSet::Planar::;

$| = 1;

my $USAGE = "usage: pds_planes [-l|-g|-z] [-D database] (p n|order|-)\n";

my $type = 1;
my $db   = undef;
my $read = 0;
while (@ARGV && $ARGV[0] =~ /^-(.+)/s) {
    my $opt = $1;
    shift @ARGV;
    last                       if '-' eq $opt;
    $type = 1,            next if 'l' eq $opt;
    $type = 2,            next if 'g' eq $opt;
    $type = 0,            next if 'z' eq $opt;
    $db   = shift(@ARGV), next if 'D' eq $opt && @ARGV;
    $db   = $1,           next if $opt =~ /^D(.+)s/;
    die $USAGE;
}
if (@ARGV == 1 && $ARGV[0] eq '-') {
    $read = 1;
}
elsif (@ARGV < 1 || 2 < @ARGV  || grep {!/^[1-9][0-9]*\z/} @ARGV) {
    die $USAGE;
}

Math::DifferenceSet::Planar->set_database($db) if defined $db;

if ($read) {
    while (<STDIN>) {
        s/^\s+//;
        my @e = split /\s+/;

        die "integer numbers separated by whitespace expected\n"
            if !@e || grep { !/^(?:0|[1-9][0-9]*)\z/ } @e;

        my $s0 = Math::DifferenceSet::Planar->from_elements(@e);
        process($s0);
    }
}
else {
    my $s0 = PDS->new(@ARGV);
    process($s0);
}

sub process {
    my ($s0) = @_;

    my $it = $type? $s0->iterate_planes: $s0->iterate_planes_zc;
    while (my $s = $it->()) {
        my $t = $type == 2? $s->gap_canonize: $s;
        my @e = $t->elements_sorted;
        print "@e\n";
    }
}

__END__

=head1 NAME

pds_planes - enumerate planar difference set planes of a same order

=head1 SYNOPSIS

  pds_planes [-l|-g|-z] [-D database] p n
  pds_planes [-l|-g|-z] [-D database] order
  pds_planes [-l|-g|-z] [-D database] -

=head1 DESCRIPTION

This example program writes planar difference sets of a given order
to standard output.  The order can be specified as a prime number and
an exponent, or as a prime power.  The output will be lines with one
representative difference set per line, for all planes of the given order.

A single dash argument instead of an order makes the tool read planar
difference sets from standard input and generate all planes of their
respective order.

Option C<-l> specifies canonical (i.e. lexically smallest) sets as
plane representatives.  This is the default.

Option C<-g> specifies gap-canonical (i.e. lexically smallest when large
take priority over small elements) sets as plane representatives.

Option C<-z> specifies zeta-canonical sets as plane representatives.

Parameter C<-D> specifies an alternate sample database.

=head1 BUGS AND LIMITATIONS

If an order is specified, possible orders are limited to those of sample
sets in the database.

If no order is specified and input is not planar difference sets, errors
will likely be reported, but behaviour is undefined.

=head1 AUTHOR

Martin Becker, E<lt>becker-cpan-mp I<at> cozap.comE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (c) 2019-2023 by Martin Becker, Blaubeuren.

This library is free software; you can distribute it and/or modify it
under the terms of the Artistic License 2.0 (see the LICENSE file).

=head1 DISCLAIMER OF WARRANTY

This library is distributed in the hope that it will be useful, but
without any warranty; without even the implied warranty of merchantability
or fitness for a particular purpose.

=cut
