#!/usr/bin/env perl

# Given sample planar difference sets, find lex, gap, or zeta-canonical
# reference sets of their respective spaces, without using precomputed sets.

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

$| = 1;

my $USAGE = "usage: pds_find_any_ref [-l|-g|-z] [file]...\n";

my $type = 1;
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;
    die $USAGE;
}

while(<<>>) {
    s/^\s+//;
    my @list = split /\s+/;
    next if !@list;
    die "integer numbers separated by whitespace expected\n"
        if grep { !/^(?:0|[1-9][0-9]*)\z/ } @list;
    my $s1 = Math::DifferenceSet::Planar->from_elements_fast(@list);
    my $it = $type == 1? $s1->iterate_planes: $s1->iterate_planes_zc;
    my $cmp = $s1->can($type == 2? 'compare_topdown': 'compare');
    my $best = $it->();
    $best = $best->gap_canonize if $type == 2;
    while (my $s = $it->()) {
        $s = $s->gap_canonize if $type == 2;
        $best = $s if $best->$cmp($s) > 0;
    }
    my @e = $best->elements_sorted;
    print "@e\n";
}

__END__

=encoding utf8

=head1 NAME

pds_find_any_ref - find reference planar difference sets

=head1 SYNOPSIS

  pds_find_any_ref [-l|-g|-z] [file]...

=head1 DESCRIPTION

This example program reads planar difference sets, one per line,
as integer numbers separated by whitespace, finds from each of their
respective spaces the reference set of a specified type, and prints the
results.  It can be used to get standard reference sets from arbitrary
sample sets without using pre-computed data.

Currently, there are three types of supported reference sets.
Option B<-l> (the default) finds lexically lowest sets when compared
from smallest to largest element.  Option B<-g> finds lexically lowest
sets when compared from largest to smallest element.  Option B<-z> finds
the lexically lowest zeta-canonical set when compared from smallest to
largest element.  Note that in any case all rotations of the sets in the
input are considered, which takes I<O(nE<179>)> or more modular integer
operations for sets of order I<n>.  For zeta-canonical and lex-canonical
references, faster algorithms are implemented in other example programs.
This generic algorithm might be useful for counter-checking.

=head1 AUTHOR

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

=head1 COPYRIGHT AND LICENSE

Copyright (c) 2019-2025 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).

The license grants freedom for related software development but does
not cover incorporating code or documentation into AI training material.
Please contact the copyright holder if you want to use the library whole
or in part for other purposes than stated in the license.

=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
