#!perl

use 5.014;
use strict;
use warnings;

use Getopt::Long;
use POSIX qw(ceil);

my %Opts = (
    num => undef,
    separator => "\t",
);

Getopt::Long::Configure("gnu_getopt", "no_ignore_case", "pass_through");
GetOptions(
    "num|n=s" => \$Opts{num},
    "separator|s=s" => \$Opts{separator},
    "help|h" => sub {
        print <<TEXT;
Usage:
  % partition-zip [options] [input ...]
  % partition-zip --help (or -h)
  % partition-zip --version (or -v)
Options:
  --num=s, -n          Number of partition, required
  --separator=s, -s    Separator string to use, default is tab character
TEXT
    },
    'version|v' => sub {
        no warnings 'once';
        print "partition-zip version ", ($main::VERSION || "dev"),
            ($main::DATE ? " ($main::DATE)" : ""), "\n";
        exit 0;
    },
) or do { warn "partition-zip: error in command-line options, bailing out\n"; exit 99 };

defined $Opts{num} or do { warn "partition-zip: --num (-n) is required\n"; exit 99 };
$Opts{num} >= 1 or do { warn "partition-zip: Please supply a positive --num (-n)\n"; exit 99 };

my @input;
while (<>) { chomp; push @input, $_ }

my $num_lines = @input;
exit 0 unless $num_lines;
$Opts{num} = $num_lines if $Opts{num} > $num_lines;

my @partitions = map { [] } 1 .. $Opts{num}; # [line 1 for partition 1, ...], [line 1 for partition 2, ...], ...
my @indexes = map { int( ($_-1)*($num_lines/$Opts{num}) ) } 1 .. $Opts{num};

for my $i (0 .. ceil($num_lines/$Opts{num})-1) {
    for my $j (0 .. $Opts{num}-1) {
        my $index = $indexes[$j] + $i;
        next if ($j == $Opts{num}-1 && $index > @input);
        next if ($j <  $Opts{num}-1 && $index >= $indexes[$j+1]);
        push @{ $partitions[$j] }, $input[$index];
    }
}

for my $i (0 .. ceil($num_lines/$Opts{num})-1) {
    my @output = grep { defined } map { $partitions[$_][$i] } 0 .. $#partitions;
    say join($Opts{separator}, @output);
}

# ABSTRACT: Partition input into N partitions, then zip
# PODNAME: partition-zip

__END__

=pod

=encoding UTF-8

=head1 NAME

partition-zip - Partition input into N partitions, then zip

=head1 VERSION

This document describes version 0.001 of partition-zip (from Perl distribution App-PartitionUtils), released on 2026-08-25.

=head1 SYNOPSIS

 % partition-zip [options] [input ...]

Examples:

Given this input:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12

This:

 % partition-zip -n2 < INPUT

will give:

 1      7
 2      8
 3      9
 4      10
 5      11
 6      12

which can also be done using something like:

 % paste <(head -n 6 INPUT) <(tail -n 6 INPUT)

while this:

 % partition-zip -n3 -s'|' < INPUT

will give:

 1|5|9
 2|6|10
 3|7|11
 4|8|12

and this:

 % partition-zip -n5 -s, < INPUT

will give:

 1|4|7|9|11
 2|5|8|10|12
 3|6

=head1 DESCRIPTION

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-PartitionUtils>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-PartitionUtils>.

=head1 SEE ALSO

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 CONTRIBUTING


To contribute, you can send patches by email/via RT, or send pull requests on
GitHub.

Most of the time, you don't need to build the distribution yourself. You can
simply modify the code, then test via:

 % prove -l

If you want to build the distribution (e.g. to try to install it locally on your
system), you can install L<Dist::Zilla>,
L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
that are considered a bug and can be reported to me.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by perlancar <perlancar@cpan.org>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-PartitionUtils>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=cut
