# call_a_gcm_lcm.pl
# サブルーチンのテスト(3)
  
@ax = (85, 323) ;                         # この2数の値を求める
require "mysub/gcm_lcm.pl" ;              # サブルーチンを呼ぶ
@glx = &gcm_lcm(@ax) ;                   # 計算結果を保存する
  
print <<EOF ;
\n A = 85 , B = 323                       # 与えられた2数の表示
\n G.C.M. = @glx[0] , L.C.M. = @glx[1]    # G.C.M.とL.C.M.の表示
EOF


# gcm_lcm.pl
# G.C.M. L.C.M. を求めるサブルーチン
  
# ユークリッドの互除法により与えられた2数の
# 最大公約数及び最小公倍数を求める
  
sub gcm_lcm
   {
    my ($a, $b) = @_;
    ($ra, $rb) = ($a, $b) ;
  
  # 大小関係の入れ換え
    if ($ra < $rb) {($ra, $rb) = ($rb, $ra)}
  
  # ユークリッドの互除法の計算
    while (1)
         {
          unless ($ra %= $rb) {$gcm = $rb ; last}
          unless ($rb %= $ra) {$gcm = $ra ; last}
         }
  
  # 最小公倍数の計算
    $lcm = $a * $b / $gcm ;
  
  # 最終的な戻し引数のセット
    @gx = ($gcm, $lcm)
   }
1 ;


# fraction.pl
# 分数の計算
  
# 入力方法の説明
  print "\n" ; print " *" x 17 ;
print <<EOF;
\n 内 容 : 分数の足し算(約分)
入 力 : a/b の値を a,b の形で入力
実 行 : Enter Key
EOF
  print " *" x 17 ; print "\n" ;
  
# 使用するサブルーチンの宣言
  require "mysub/gcm_lcm.pl" ;
  
# 入力部分のループ開始
  while (1)
{
# 分数要素の入力
  print "\n a,b = " ;
  $ax = <STDIN> ;
  if ($ax eq "\n") {last}
  chomp $ax ;
  ($a, $b) = split /,/, $ax ;
  
# 分数要素の追加及び現在の分数の個数
  push @frac1, $a ;
  push @frac2, $b ;
  $num = @frac1 ;
  
# 現在の入力状況の表示
  print "\n" ;
  if ($num == 1) {print " $a/$b = "}
  else
    {
     for $i (0..$num-2)
        {print " $frac1[$i]/$frac2[$i] +" }
     print " $frac1[$num-1]/$frac2[$num-1] = "
    }
  print "\n"
}
# 入力部分のループ終了
  
# 分数が1つの場合(約分のみ)
  if ($num == 1)
    {  
     print "\n $frac1[0]/$frac2[0] = " ;
     ($G, $L) = &gcm_lcm($frac1[0], $frac2[0]) ;
     map $_ /= $G, ($frac1[0], $frac2[0]) ;
     print "$frac1[0]/$frac2[0] \n"
    }
  
# 分数が2つ以上の場合(足し算及び約分)
  else
    {
     for $i (0..$num-2)
    {
   # 足し算する前に約分できるものは約分しておく
     for $j ($i..$i+1)
    {
     ($G, $L) = &gcm_lcm(abs $frac1[$j], $frac2[$j]) ;
     unless ($G == 1) {map $_ /= $G, ($frac1[$j], $frac2[$j])}
    }
  
   # 通分後の分子
     ($G1, $L1) = &gcm_lcm($frac2[$i], $frac2[$i+1]) ;
     $a1 = $frac1[$i]*($L1/$frac2[$i]) ;
     $a2 = $frac1[$i+1]*($L1/$frac2[$i+1]) ;
     $c1 = $a1 + $a2 ;
  
  # 左から2つ分の足し算の表示
     print "\n $frac1[$i]/$frac2[$i] + $frac1[$i+1]/$frac2[$i+1]
= $a1/$L1 + $a2/$L1 = $c1/$L1" ;
  
   # 約分できる場合はそれを追加して示す
     ($G2, $L2) = &gcm_lcm(abs $c1, $L1) ;
     unless ($G2 == 1)
           {$c1 /= $G2 ; $L1 /= $G2 ; print "= $c1/$L1"}
     print "\n" ;
  
  # 計算した結果を次の分数の初期値に設定
     ($frac1[$i+1], $frac2[$i+1]) =  ($c1, $L1)
    }  
    }  
  
print "\n お疲れさま! \(^o^)/\n"