#!/usr/bin/perl
use warnings;
use diagnostics;
use strict;

# sort_invert.pl
#
# Please send corrections, suggestions for improvement, comments etc. to
# chandra@ee.uwa.edu.au
# 
# This program illustrates both not-in-place and in-place
# sorting of an array and inverting of a hash
# using references.

my (@halogens, %capitals, $out_aref, $out_href);
@halogens = qw{fluorine chlorine bromine iodine astatine};
%capitals = qw(UK London France Paris Australia Canberra Iceland Reykjavik);

print "Original array\n";
print_array(\@halogens);
($out_aref) = sort_array(\@halogens);
print "Sorted array\n";
print_array($out_aref);

print "Original hash\n";
print_hash(\%capitals);
($out_href) = invert_hash(\%capitals);
print "Inverted hash\n";
print_hash($out_href);

print "\n**** Sorting and Inverting in Place **** \n";
print "Original array\n";
print_array(\@halogens);
print "Original hash\n";
print_hash(\%capitals);
($out_aref, $out_href) = sort_invert_in_place(\@halogens, \%capitals);
print "Sorted array\n";
print_array($out_aref);
print "Inverted hash\n";
print_hash($out_href);

sub sort_array
    {
    my ($aref) = @_; # called with an array reference as the argument
    my @array = sort(@$aref);
    return (\@array); # return a new array reference
    }

sub sort_array_in_place
    {
    my ($aref) = @_; # called with an array reference as the argument
    @$aref = sort(@$aref); # sort original array and return it into itself
    return ($aref); # return original input array reference
    }

sub invert_hash
    {
    my ($href) = @_; # called with a hash reference as the argument
    my %hash = reverse %$href;
    return (\%hash); # return a new hash reference
    }

sub invert_hash_in_place
    {
    my ($href) = @_; # called with a hash reference as the argument
    %$href = reverse %$href; # reverse original hash; assign it into itself
    return ($href); # return original input hash reference
    }

sub sort_invert
    {
    my ($aref, $href) = @_;
    return (sort_array($aref), invert_hash($href));
    }

sub sort_invert_in_place
    {
    my ($aref, $href) = @_;
    return (sort_array_in_place($aref), invert_hash_in_place($href));
    }

sub print_array
    {
    my $count = 0;
    while (my $aref = shift)
        {
        $count++;
        print "arg $count: array reference --> $aref\n";
        print "arg $count: array values -->  @$aref\n";
        }
    }

sub print_hash
    {
    my $count = 0;
    my ($key, $value); # do not forget parentheses!
    while (my $href = shift)
        {
        $count++;
        print "arg $count hash reference --> $href\n";
        while (($key, $value) = each %$href)
            {
            print "arg $count hash key-value pair --> ",
                "$key => $value\n";
            }
        }
    }
