在 bash 中判断三角形是否等腰

问题描述 投票:0回答:9

当三角形为等腰三角形时,如何总结这段代码?

  1 #!/bin/bash
  2 
  3 read x y z
  4 
  5 if [[ x -eq z ]] && [[ x -eq y ]] && [[ y -eq z ]]; then
  6   echo EQUILATERAL
  7 elif [[ x -eq z ]] && [[ x -eq y ]]
  8 then
  9   echo ISOSCELES
 10 elif [[ y -eq z ]] && [[ y -eq x ]]
 11 then
 12   echo ISOSCELES
 13 elif [[ z -eq x ]] && [[ z -eq y ]]
 14 then
 15   echo ISOSCELES
 16 else
 17   echo SCALENE
 18 fi
~  

目前实际上代码不起作用:

$ ./triangle.sh 
4 4 6
SCALENE
$ ./triangle.sh 
4 5 5
SCALENE
$ ./triangle.sh 
4 5 3
SCALENE
$ ./triangle.sh 
4 4 4 
EQUILATERAL
$ ./triangle.sh 
2 9 1
SCALENE
$ ./triangle.sh 
2 3 2
SCALENE
bash shell if-statement sh
9个回答
5
投票

您的代码几乎是正确的,但每种情况下都需要进行一次测试。

在:

[[ x -eq y ]] && [[ x -eq z ]] && [[ y -eq z ]] 

如果

x=y
x=z
,则必须遵循
y=z
。不需要这样的测试。

在:

[[ x -eq z ]] && [[ x -eq y ]]

如果

x=z
有两侧值相等,则不需要任何额外的测试。

你的脚本清理了一下就变成了:

#!/bin/bash

read x y z

if   [[ x -eq y ]] && [[ x -eq z ]]; then echo EQUILATERAL
elif [[ x -eq y ]]                 ; then echo ISOSCELES
elif [[ x -eq z ]]                 ; then echo ISOSCELES
elif [[ y -eq z ]]                 ; then echo ISOSCELES
else                                      echo SCALENE
fi

此外,等腰三角形的三个测试可以使用 OR (

||
) 在一行中完成:

#!/bin/bash

read x y z

if   [[ x -eq y ]] && [[ x -eq z ]]                 ; then echo EQUILATERAL
elif [[ x -eq y ]] || [[ x -eq z ]] || [[ y -eq z ]]; then echo ISOSCELES
else                                                       echo SCALENE
fi

甚至(利用

[[
使用):

#!/bin/bash

read x y z

if   [[ x -eq y && x -eq z ]]           ; then echo EQUILATERAL
elif [[ x -eq y || x -eq z || y -eq z ]]; then echo ISOSCELES
else                                           echo SCALENE
fi

请注意,不带

$
的变量名称仅在使用
[[
进行算术测试
-eq
的情况下才有效。
通常的智慧是为变量使用正确的名称,例如
[[ $x -eq $y ]]


为了涵盖您写的其他答案,这里是一个更正的脚本:

  • 真正需要 xplusy 变量
  • 测试可以直接算术
  • 使用参数而不是读取。

#!/bin/bash

triangle(){
    x=$1 y=$2 z=$3
    for i in $x $y $z; do
        if (( i < 1 ||  i > 1000 )); then
            printf '%4d %4d %4d %s\n' "$x" "$y" "$z" "side out of range"
            return 1
        fi
    done

    if (( ! ( x+y > z && y+z > x && z+x > y )  )); then
        printf '%4d %4d %4d %s\n' "$x" "$y" "$z" "not a triangle"
        return 1
    fi

    if   (( x != z && x != y && y != z )); then printf '%4d %4d %4d %s\n' "$x" "$y" "$z" SCALENE
    elif (( x == y && x == z ))          ; then printf '%4d %4d %4d %s\n' "$x" "$y" "$z" EQUILATERAL
    else                                        printf '%4d %4d %4d %s\n' "$x" "$y" "$z" ISOSCELES
    fi
}

triangle 4    4  6
triangle 4    5  5
triangle 4    5  3
triangle 4    4  4
triangle 2    9  1
triangle 2    3  2
triangle 100  3  3
triangle 1    2  1000
triangle 1003 3  3

执行时,脚本会打印:

./script.sh
   4    4    6 ISOSCELES
   4    5    5 ISOSCELES
   4    5    3 SCALENE
   4    4    4 EQUILATERAL
   2    9    1 not a triangle
   2    3    2 ISOSCELES
 100    3    3 not a triangle
   1    2 1000 not a triangle
1003    3    3 side out of range

1
投票

一个简短而简单的方法

case $(cat - | uniq -u | wc -l) in
0) echo "EQUILATERAL";; 1) echo "ISOSCELES";; 3) echo "SCALENE"
esac

uniq-u

要仅显示不重复的行,请将 -u 选项传递给 uniq。这将仅输出不重复的行并将结果写入标准输出。

wc-l

返回行数

示例:对于 2 3 4, uniq -u 将返回 3,因此 wc -l 将返回 3。


0
投票

我将代码修复到下面并且它可以工作,但我仍然想知道为什么上面的代码在给定的测试中不起作用:

 1 #!/bin/bash
  2 
  3 read x y z
  4 
  5 if [[ x -ne z ]] && [[ x -ne y ]] && [[ y -ne z ]]; then
  6   echo SCALENE
  7 elif [[ x -eq z ]] && [[ x -eq y ]] && [[ y -eq z ]]; then
  8   echo EQUILATERAL
  9 else
 10   echo ISOSCELES
 11 fi

这是代码的更完整版本,其中检查它是否是三角形,并检查每条边是否在 1 到 1000 之间。

1 #!/bin/bash
  2 
  3 read x y z
  4 #for i in x y z
  5 #do
  6 #  (( i >= 1 )) && (( i <= 1000 )) || echo error
  7 #done
  8 xplusy=$x+$y
  9 yplusz=$y+$z
 10 zplusx=$z+$x
 11 if [[ $x -ge 1 ]] && [[ $x -le 1000 ]] &&
 12    [[ $y -ge 1 ]] && [[ $y -le 1000 ]] &&
 13    [[ $z -ge 1 ]] && [[ $z -le 1000 ]]; then
 14 if [[ $xplusy -gt $z ]] && [[ $yplusz -gt $x ]] && [[ $zplusx -gt $y ]]; then
 15 if [[ $x -ne $z ]] && [[ $x -ne $y ]] && [[ $y -ne $z ]]; then
 16   echo SCALENE
 17 elif [[ $x -eq $z ]] && [[ $x -eq $y ]] && [[ $y -eq $z ]]; then
 18   echo EQUILATERAL
 19 else
 20   echo ISOSCELES
 21 fi
 22 fi
 23 fi

0
投票

以下是帮助解决您的问题的相关代码。

#!/bin/bash

read x;
read y;
read z;
if [ $x -eq $y ] && [ $y -eq $z ]
then
echo "EQUILATERAL"
elif [ $x -ne $y ] && [ $x -ne $z ] && [ $y -ne $z ]
then
echo "SCALENE"
else
echo "ISOSCELES"
fi

0
投票
read x
read y
read z

if [[ $x -eq $y ]] && [[ $y -eq $z ]]; then
  echo EQUILATERAL
elif [[ $x != $y ]] && [[ $y != $z ]] && [[ $x != $z ]]; then
  echo SCALENE
else
    echo ISOSCELES
fi

0
投票

我将代码修复到下面并且它有效:

read X
read Y
read Z

if (("$X","$Y","$Z" > "1000")) || (("$X","$Y","$Z" < "1"));then
  exit

else
  if (("$X"=="$Y")) && (("$Y"=="$Z")) && (("$X"=="$Z"));then
    echo "EQUILATERAL"
  elif  (("$X"=="$Y")) || (("$Y"=="$Z")) || (("$X"=="$Z"));then
    echo "ISOSCELES"
  else
    echo "SCALENE"
  fi
fi

0
投票
read a
read b
read c
if [ $a == $b ] && [ $a == $c ] && [ $b == $c ]
then
    echo "EQUILATERAL"
elif [ $a == $b ]
then
    echo "ISOSCELES"
elif [ $c == $a ] 
then 
    echo "ISOSCELES"
elif [ $b == $c ] 
then
    echo "ISOSCELES"
else
    echo "SCALENE"
fi

-1
投票
read x 
read y 
read z
if [[ x -ne z ]] && [[ x -ne y ]] && [[ y -ne z ]]; then
echo "SCALENE"
elif [[ x -ne z ]]
then
echo "ISOSCELES"
elif [[ y -ne z ]]
then
echo "ISOSCELES"
elif [[ z -ne x ]]
then
echo "ISOSCELES"
else
echo "EQUILATERAL"
fi

这对我来说很有效。


-3
投票

这尚未经过测试,但总体思路如下:

#!/bin/bash

read x y z

if [ $x -eq $z ] && [ $x -eq $y ]; then
  # You can't test x==y==z directly, so do it in two parts
  echo EQUILATERAL
elif [ $x -eq $z ] || [ $x -eq $y ] || [ $y -eq $z ]; then
    # isosceles == any pair of sides are the same
    echo ISOSCELES
else
    echo SCALENE
fi

至于“原来的问题出了什么问题”......让我们只进行一个应该是等腰三角形的测试

elif [[ x -eq z ]] && [[ x -eq y ]]
你可以看到如何满足所有三个边必须相等。所有检查都有类似的问题。

© www.soinside.com 2019 - 2024. All rights reserved.