#!/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 ) ); }