shellsort.pl


#!/usr/bin/env perl
#
# $Id:$

use 5.036_003;
use strict;
use warnings;


# ***=====================================================================
# **    
# **      Author: David Billsbrough <billsbrough@gmail.com>
# **     Created: Sunday, November 10, 2024 at 15:49:49 PM (EST)
# **     License: GNU General Public License - version 2
# **     Version: $Revision:$
# **    Warranty: None
# **    
# **     Purpose: ShellSort demo in Perl
# **    
# ***=====================================================================

#####################
###  Subroutines  ###
#####################

sub process_line($handle2)
{
	my $index = 0;
	my $count = 0;

	my $line = readline($handle2);

	chomp($line);							# frag the newline
	if (($line cmp "") == 0) { CORE::break };
	### @list[$index] = $line;
	printf "Adding %s to array\n", $line;
	$count = $index + 1;
	
	return ($count);
}

## -------------------------------------------------------------

sub SwapElements($a, $b)
{
	my $j = $a;
	my $i = $b;
	return ($i, $j);
}

## -------------------------------------------------------------

sub CalcListSize(@c_array)
{
	my $count = @c_array;
	return $count;
}


sub StatusReport(@list)
{
	my $count = &CalcListSize(@list);

	printf "\n\nThe list has %s elements.\n", $count;
	return $count;
}


sub DisplayTitle($param)
{
	my $Title = $param;

	print("\n");
	printf "  %s\n", $Title;
	print("--------------------\n");
}


sub DisplayList(@list2)
{
	my $NumberOfItems = CalcListSize(@list2);

	for (my $n = 0; $n < $NumberOfItems; $n++) {
		printf " %s\n", $list2[$n];
	}
	print "\n";
}

sub DisplayNumbers(@list2)
{
	my $NumberOfItems = CalcListSize(@list2);

	for (my $n = 0; $n < $NumberOfItems; $n++) {
		printf " %5d\n", $list2[$n];
	}
	print "\n";
}

## -------------------------------------------------------------

# Shell-Metzner Sort
# Adapted from Programming in Pascal, P. Grogono, Addison-Wesley, 1980
# From Borland Pascal Programs for Scientists and Engineers
# by Alan R. Miller, Copyright C 1993, SYBEX Inc

sub ShellSort(@list)
{
	my @a = ();
	my $n = CalcListSize(@list);
	my $done = 0;

	@a = @list;

	#printf "number of interations = %d\n", $n;
	#foreach (@a) { printf "%s, ", $_; } print "\n";

	my $jump = $n - 1;
	while ($jump > 1) {
		$jump = int($jump / 2);
		do {
			$done = 1;
			for (my $j = 0; $j < $n - $jump; $j++) {
				my $i = $j + $jump;
				if ($a[$j] gt $a[$i]) {
					($a[$i], $a[$j]) = SwapElements($a[$i], $a[$j]);
					## print "swapped: $a[$i] $a[$j]\n";
					$done = 0;
				}
			}
		} until ($done == 1);
	}
	return @a
}

## -------------------------------------------------------------

# Shell-Metzner Sort for Numbers
# Adapted from Programming in Pascal, P. Grogono, Addison-Wesley, 1980
# From Borland Pascal Programs for Scientists and Engineers
# by Alan R. Miller, Copyright C 1993, SYBEX Inc

sub ShellSortNums(@list)
{
	my @a = ();
	my $n = CalcListSize(@list);
	my $done = 0;

	@a = @list;

	#printf "number of interations = %d\n", $n;
	#foreach (@a) { printf "%s, ", $_; } print "\n";

	my $jump = $n - 1;
	while ($jump > 1) {
		$jump = int($jump / 2);
		do {
			$done = 1;
			for (my $j = 0; $j < $n - $jump; $j++) {
				my $i = $j + $jump;
				if ($a[$j] > $a[$i]) {
					($a[$i], $a[$j]) = SwapElements($a[$i], $a[$j]);
					## print "swapped: $a[$i] $a[$j]\n";
					$done = 0;
				}
			}
		} until ($done == 1);
	}
	return @a
}


######################
###  Main program  ###
######################


my @arr1 = qw//;
my @array = qw/ 1 2 3 4 5 6 7 8 9 10 11 12 /;
my @numarray = qw/ 12 11 10 9 8 7 6 5 4 3 2 1 /;
my @arr2 = qw//;
my @line = qw//;
my @list = qw//;
my @nums = qw//;

my $handle;
my $handle2;
my $NumberOfItems = 0;
my $path_to_file = "alpha.txt";
my $TextFile = "bravo.txt";

print "\n";
print "Shellsort Demo\n";
print "\n";

unless (open $handle, "<:encoding(ascii)", $path_to_file) {
	print STDERR "Could not open file '$path_to_file'.\n";
	die "No reason to continue : $!\n";
	#return undef
}

chomp(my @lines = <$handle>);
@arr1 = @lines;

unless (close $handle) {
	# what does it mean if close yields an error and you are just reading?
	print STDERR "Don't care error while closing - '$path_to_file'.\n";
	warn "contining - $!\n";
}

unless (open $handle2, "<:encoding(ascii)", $TextFile) {
	print STDERR "Could not open file '$TextFile' : $!\n";
	die "Can't read input text file '$TextFile' for list data.\n$!\n";
}

### ($NumberOfItems, @list) = &process_line($handle2) until eof($handle2);
chomp(my @list = <$handle2>);

@arr2 = @list;

close $handle2;

#
#
#
$NumberOfItems = &StatusReport(@arr1);

DisplayTitle("Unsorted list");
DisplayList(@arr1);
@line = &ShellSort(@arr1);
### @line = sort(@arr1);
DisplayTitle("Sorted list");
DisplayList(@line);

print "\n";

#
#
#
$NumberOfItems = &StatusReport(@arr2);

DisplayTitle("Unsorted list");
DisplayList(@arr2);
@list = &ShellSort(@arr2);
### @list = sort(@arr2);
DisplayTitle("Sorted list");
DisplayList(@list);

print "\n";

#
#
#
$NumberOfItems = &StatusReport(@numarray);

DisplayTitle("Unsorted list");
DisplayNumbers(@numarray);
### @nums = &ShellSortNums(@numarray);
@nums = sort {$a <=> $b} (@numarray);
DisplayTitle("Sorted list");
DisplayNumbers(@nums);

print "\n";
print "Finished.\n";

# End of Script