#!/usr/bin/perl use strict; use warnings; use CGI; my $q=CGI->new; my $t1 = $q->param('t1'); my $i1 = $q->param('i1'); my $t2 = $q->param('t2'); my $i2 = $q->param('i2'); my $t3 = $q->param('t3'); my $i3 = $q->param('i3'); #my @ti = @ARGV; my @TIs = ($t1,$i1,$t2,$i2,$t3,$i3); #my @TIs = GetTIs(); print $q->header(); print "
";
print( "Input: " );
printTIs( @TIs );
validateTIs( @TIs );
@TIs = reduceTIs( @TIs );
if( isLoopFree( @TIs ) )
{
my $negativeNumerators = countNegativeNumerators( @TIs );
if( $negativeNumerators >= 2 )
{
@TIs = changeAllSigns( @TIs );
$negativeNumerators = countNegativeNumerators( @TIs );
}
if( $negativeNumerators == 1 )
{
@TIs = permuteTIsUntilAIsNegative( @TIs );
}
if( areAAndCNonNegative( @TIs ) )
{
# Theorem 3
@TIs = HandleAllPositiveCase( @TIs );
}
else
{
@TIs = handleOneNegativeNoLoopsCase( @TIs );
}
}
else # One or more loop exists in knot represented by @TIs
{
@TIs = permuteTIsSoYIsAtLeastAsBigAsXAndZ( @TIs );
( my $a, my $x, my $b, my $y, my $c, my $z ) = @TIs;
my $l = $y - $x - $z;
if( $b < 0 )
{
@TIs = changeAllSigns( @TIs );
}
my $negativeNumerators = countNegativeNumerators( @TIs );
# Page Two
if( $negativeNumerators == 0 )
{
# Theorem 4
@TIs = handleLoopsWithoutNegativesCase( @TIs, $l );
}
elsif( $negativeNumerators == 1 )
{
if( ( $a > 0 ) and ( $c < 0 ) )
{
@TIs = exchangeAXandCZ( @TIs );
}
# Theorem 5
@TIs = handleLoopsWithOneNegativeCase( @TIs, $l );
}
elsif( $negativeNumerators == 2 )
{
my $absA = abs( $a );
my $absC = abs( $c );
my $minOne = min( $absA, $x );
my $minTwo = min( $absC, $z );
if( $minOne < $minTwo )
{
@TIs = exchangeAXandCZ( @TIs );
}
# Theorem 6
@TIs = handleLoopsWithTwoNegativesCase( @TIs, $l );
}
}
@TIs = moveLargestDenominatorToMiddle( @TIs );
print( "Output: " );
printTIs( @TIs );
print "";
exit;
sub GetTIs
{
print "( [a]/[x], [b]/[y], [c]/[z] ) \n";
print "Enter six integers. \n";
print "Denominators cannot be negative. \n";
print "x + y + z must be even. \n";
print "Please enter a value for a: ";
my $line = <>;
chomp $line;
my $a = $line;
print "Please enter a value for x: ";
$line = <>;
chomp $line;
my $x = $line;
print "Please enter a value for b: ";
$line = <>;
chomp $line;
my $b = $line;
print "Please enter a value for y: ";
$line = <>;
chomp $line;
my $y = $line;
print "Please enter a value for c: ";
$line = <>;
chomp $line;
my $c = $line;
print "Please enter a value for z: ";
$line = <>;
chomp $line;
my $z = $line;
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub printTIs
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
print "( $a/$x, $b/$y, $c/$z ) \n";
return 0;
}
sub validateTIs
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
if( $a !~ /^[+-]?[0-9]+$/ )
{
print( "a is not an integer." );
exit();
}
if( $b !~ /^[+-]?[0-9]+$/ )
{
print( "b is not an integer." );
exit();
}
if( $c !~ /^[+-]?[0-9]+$/ )
{
print( "c is not an integer." );
exit();
}
if( $x !~ /^[+-]?[0-9]+$/ )
{
print( "x is not an integer." );
exit();
}
if( $y !~ /^[+-]?[0-9]+$/ )
{
print( "y is not an integer." );
exit();
}
if( $z !~ /^[+-]?[0-9]+$/ )
{
print( "z is not an integer." );
exit();
}
print "a is not an integer." if $a != int( $a );
exit() if $a != int( $a );
print "x is not an integer." if $x != int( $x );
exit() if $x != int( $x );
print "b is not an integer." if $b != int( $b );
exit() if $b != int( $b );
print "y is not an integer." if $y != int( $y );
exit() if $y != int( $y );
print "c is not an integer." if $c != int( $c );
exit() if $c != int( $c );
print "z is not an integer." if $z != int( $z );
exit() if $z != int( $z );
print "x is negative." if $x < 0;
exit() if $x < 0;
print "y is negative." if $y < 0;
exit() if $y < 0;
print "z is negative." if $z < 0;
exit() if $z < 0;
my $xyzsumeven = ( $x + $y + $z ) % 2;
print "x + y + z is not even. \n " if ( $xyzsumeven != 0 );
exit() if ( $xyzsumeven != 0 );
}
sub reduceTIs
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
$a = 0 if $x == 0;
$a = 0 if $x == 1;
$b = 0 if $y == 0;
$b = 0 if $y == 1;
$c = 0 if $z == 0;
$c = 0 if $z == 1;
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub countNegativeNumerators
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
my $negativeNumerators = 0;
$negativeNumerators++ if $a < 0;
$negativeNumerators++ if $b < 0;
$negativeNumerators++ if $c < 0;
return( $negativeNumerators );
}
sub isLoopFree
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
if ( ( $x <= $y + $z ) and
( $y <= $x + $z ) and
( $z <= $x + $y ) )
{
return 1;
}
else
{
return 0;
}
}
sub changeAllSigns
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
$a = -$a;
$b = -$b;
$c = -$c;
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub permuteTIsUntilAIsNegative
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
if ( $b < 0 )
{
( $a, $b ) = ( $b, $a );
( $x, $y ) = ( $y, $x );
}
elsif ( $c < 0 )
{
( $a, $c ) = ( $c, $a );
( $x, $z ) = ( $z, $x );
}
if ( ( $a > 0 ) or ( $b < 0 ) or ( $c < 0 ) ) {
print "Failed to permute and change signs correctly.";
exit();
}
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub areAAndCNonNegative
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
if ( ( $a >= 0 ) and ( $c >= 0 ) )
{
return 1;
}
else
{
return 0;
}
}
sub HandleAllPositiveCase # Steve Lane's program
{
# Theorem 3
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
my $a2 = ( $x + $y - $z ) / 2;
my $b2 = ( $x - $y + $z ) / 2;
my $c2 = (-$x + $y + $z ) / 2;
my $x2 = $a + $b;
my $y2 = $a + $c;
my $z2 = $b + $c;
# now need to rearrange so the largest of ($x2, $y2, $z2) is $y2
if ( $y2 < $x2 || $y2 < $z2 ) {
if ( $z2 > $x2 ) {
( $b2, $y2, $c2, $z2 ) = ( $c2, $z2, $b2, $y2 );
} else {
( $b2, $y2, $a2, $x2 ) = ( $a2, $x2, $b2, $y2 );
}
}
return( ( $a2, $x2, $b2, $y2, $c2, $z2 ) );
}
sub handleLoopsWithOneNegativeCase
{
# Theorem 4
( my $a, my $x, my $b, my $y, my $c, my $z, my $l ) = @_;
my $J = min( $l, $b );
#print "handleLoopsWithoutNegativesCase J = $J \n ";
my $aout = $x + $J;
my $xout = $a + $b;
my $bout = - $J;
my $yout = $a + $c + 2 * $l;
my $cout = $z + $J;
my $zout = $b + $c;
return( ( $aout, $xout, $bout, $yout, $cout, $zout ) );
}
sub min
{
my $currentMin = $_[ 0 ];
foreach ( @_ )
{
if ( $_ < $currentMin )
{
$currentMin = $_;
}
}
return( $currentMin );
}
sub handleOneNegativeNoLoopsCase
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
my $R1 = 0.5 * ( $x + $y - $z );
my $R2 = abs( $a );
my $R3 = $b;
my $R = min( $R1, $R2, $R3 );
#print " handleOneNegativeNoLoopsCase R = $R \n ";
my $G1 = 0.5 * ( $x - $y + $z );
my $G2 = abs( $a ) - $R;
my $G3 = $c;
my $G = min( $G1, $G2, $G3 );
#print "handleOneNegativeNoLoopsCase G = $G \n ";
my $L1 = 0;
my $L2 = 0;
my $L3 = 0;
my $L = 0;
if ( $R + $G == abs( $a ) )
{
$L1 = 0.5 * ( $x - $y + $z ) - $G;
$L2 = $R;
$L3 = $c - $G;
$L = min( $L1, $L2, $L3 );
}
else
{ # $R + $G != abs( $a )
$L = 0;
}
#print "handleOneNegativeNoLoopsCase L = $L \n ";
my $M = 0;
if ( abs( $a ) == $R ) {
$M = 1;
} else {
$M = -1;
}
#print "handleOneNegativeNoLoopsCase M = $M \n ";
my $N = 0;
if ( ( $L == $R ) and ( ( $R + $G ) == abs( $a ) ) )
{
$N = 1;
} else {
$N = -1;
}
#print "handleOneNegativeNoLoopsCase N = $N \n ";
my $outa = $M * ( ( 0.5 * ( $x + $y - $z ) ) - $R + $G );
my $outx = abs( $a ) + $b - 2 * $R;
my $outb = $N * ( ( 0.5 * ( $x - $y + $z ) ) + $R - $G - 2 * $L );
my $outy = abs( $a ) + $c - 2 * $G - 2 * $L;
my $outc = ( 0.5 * ( ( - $x ) + $y + $z ) ) + $R + $G;
my $outz = $b + $c;
return( ( $outa, $outx, $outb, $outy, $outc, $outz ) );
}
sub permuteTIsSoYIsAtLeastAsBigAsXAndZ
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
if ( $y < $x )
{
( $a, $b ) = ( $b, $a );
( $x, $y ) = ( $y, $x );
}
if ( $y < $x )
{
print "Failed to permute and have y greater than or equal to x.";
exit();
}
if ( $y < $z )
{
( $b, $c ) = ( $c, $b );
( $y, $z ) = ( $z, $y );
}
if ( ( $y < $z ) or ( $y < $x ) )
{
print "Failed to permute and have y greater than or equal to x and z.";
exit();
}
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub handleLoopsWithoutNegativesCase
{
( my $a, my $x, my $b, my $y, my $c, my $z, my $l ) = @_;
my $N = 0;
my $R = min( abs( $a ), $x, $b );
my $J = min( $l, $b - $R );
#print "handleLoopsWithoutNegativesCase R = $R \n ";
#print "handleLoopsWithoutNegativesCase J = $J \n ";
if( ( $b < abs( $a ) ) and ( $b < $x ) )
{
$N = -1;
}
else
{
$N = 1;
}
#print "handleLoopsWithoutNegativesCase N = $N \n ";
my $aout = 0;
my $xout = 0;
my $bout = 0;
my $yout = 0;
my $cout = 0;
my $zout = 0;
$aout = $N * ( $x - $R + $J );
$xout = abs( $a ) + $b - 2 * $R;
$bout = 0 - ( $R + $J );
$yout = abs( $a ) + $c + 2 * $l;
$cout = $z + $R + $J;
$zout = $b + $c;
return( $aout, $xout, $bout, $yout, $cout, $zout );
}
sub exchangeAXandCZ
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
( $a, $c ) = ( $c, $a );
( $x, $z ) = ( $z, $x );
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub handleLoopsWithTwoNegativesCase
{
( my $a, my $x, my $b, my $y, my $c, my $z, my $l ) = @_;
my $F = min( $b, abs( $c ), $z );
my $R = min( $b, abs( $a ), $x ) - $F;
my $J = min( ( $l + $F ), ( $b - $F - $R ) );
my $N = 0;
my $M = 0;
#print "handleLoopsWithTwoNegativesCase F = $F \n ";
#print "handleLoopsWithTwoNegativesCase R = $R \n ";
#print "handleLoopsWithTwoNegativesCase J = $J \n ";
if( ( ( $b < abs( $a ) ) and ( $b < $x ) ) )
{
$N = -1;
}
else
{
$N = 1;
}
#print "handleLoopsWithTwoNegativesCase N = $N \n ";
if( ( $b < abs( $c ) ) and ( $b < $z ) )
{
$M = -1;
}
else
{
$M = 1;
}
#print "handleLoopsWithTwoNegativesCase M = $M \n ";
my $aout = 0;
my $xout = 0;
my $bout = 0;
my $yout = 0;
my $cout = 0;
my $zout = 0;
$aout = $N * ( $x - $F - $R + $J );
$xout = abs( $a ) + $b - 2 * $F - 2 * $R;
$bout = -( $F + $R + $J );
$yout = abs( $a ) + abs( $c ) - 2 * $l;
$cout = $M * ( $z - $F + $R + $J );
$zout = $b + abs( $c ) - 2 * $F;
return( ( $a, $x, $b, $y, $c, $z ) );
}
sub moveLargestDenominatorToMiddle
{
( my $a, my $x, my $b, my $y, my $c, my $z ) = @_;
if( $a > $b )
{
( $a, $b ) = ( $b, $a );
( $x, $y ) = ( $y, $x );
}
if( $c > $b )
{
( $b, $c ) = ( $c, $b );
( $y, $z ) = ( $z, $y );
}
return( ( $a, $x, $b, $y, $c, $z ) );
}