'finding if a triangle is ISOSCELES in bash
How can this code could be summarized for when the triangle is ISOSCELES?
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
~
currently actually the code doesn't work:
$ ./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
Solution 1:[1]
Your code is almost correct, but there is one test more than needed on each case.
In:
[[ x -eq y ]] && [[ x -eq z ]] && [[ y -eq z ]]
If x=y and x=z it must follow that y=z. There is no need for such test.
In:
[[ x -eq z ]] && [[ x -eq y ]]
If x=z there are two sides of equal value, no need for any additional test.
Your script cleaned a little becomes:
#!/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
And furthermore, the three tests for an ISOCELES triangle could be done in one line with 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
Or even (taking advantage of [[ use):
#!/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
Please note that the variable names without a $ work only in this case of using a [[ with an arithmetic test -eq.
The usual wisdom is to use the correct names for variables, like [[ $x -eq $y ]].
To cover the other answer you wrote, here is a corrected script:
- no real need for xplusy variables
- tests could be arithmetic directly
- using arguments instead of read.
#!/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
When executed, the script will print:
./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
Solution 2:[2]
A short and simple way
case $(cat - | uniq -u | wc -l) in
0) echo "EQUILATERAL";; 1) echo "ISOSCELES";; 3) echo "SCALENE"
esac
uniq -u
To only show lines that are not repeated pass the -u option to uniq. This will output only lines that are not repeated and write the result to standard output.
wc -l
returns line count
Example: For 2 3 4, uniq -u will return 3 and hence wc -l will return 3.
Solution 3:[3]
I fixed my code to below and it works but I still would like to know why above code didn't work in the given tests:
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
Here's a more complete version of the code with checking to see if it is a triangle and also checking to see if each side is between 1 and 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
Solution 4:[4]
Below is the relevant code to help with your issue.
#!/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
Solution 5:[5]
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
Solution 6:[6]
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
Solution 7:[7]
I fixed my code to below and it works:
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
Solution 8:[8]
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
This is what worked out for me.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | jatin khattar |
| Solution 3 | |
| Solution 4 | Tyler2P |
| Solution 5 | Sumit Pandey |
| Solution 6 | Joel P Moncy |
| Solution 7 | mehrdad rafiee |
| Solution 8 | Armel |
