Triangle Type Program

Posted on

Problem

Is there any way to simplify it further?

import java.util.*;

class Triangle {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        int c = sc.nextInt();


        if(a==b && b==c)
            System.out.println("Equilateral");

        else if(a >= (b+c) || c >= (b+a) || b >= (a+c) )
            System.out.println("Not a triangle");

        else if ((a==b && b!=c ) || (a!=b && c==a) || (c==b && c!=a))
            System.out.println("Isosceles");

        else if(a!=b && b!=c && c!=a)
            System.out.println("Scalene");
    }
}

Solution

Is there any way to simplify it further?

Sure, but what’s more important: Create some useful methods. Your class is single shot only: read data, classify, output. This is a bad start, a method should do one thing only. So you need three methods.

You classify into 4 categories and this is a clear case for an enum:

enum TriangleType {
    EQUILATERAL, INVALID, ISOSCELES, SCALENE
}

This is the only interesting method:

static TriangleType classify(int a, int b, int c) {
    if (a <= 0 || b <= 0 || c <= 0) return INVALID; // added test
    if (a == b && b == c) return EQUILATERAL;
    if (a >= b+c || c >= b+a || b >= a+c) return INVALID;
    if (b==c || a==b || c==a)) return ISOSCELES;
    return SCALENE;
}

Note that I’m violating the “braces everywhere” rule. I can’t help myself.

In case of ISOSCELES, there’s no need for checks like a==b && b!=c as we already know that not all sites are equal.

In case of SCALENE, there’s no need for any test, as we know that there are no two equals sides.


You’re using a bit too many parentheses, but feel free to keep them if you feel you need them.

Be consequent with your spacing, there are rules for it, which help to make it more readable:

  • single space between “if” and “(“
  • (but no space between a method name and “(“)
  • no space after “(“
  • no space before “)”

The addition is subject to overflow as Ryan noted, but let’s ignore it for now. You should know about it and do a corresponding test if needed, but in general, overflow is impossible to check for everywhere.

Here it’s trivial, just replace a >= b+c by a >= (long) b+c. The latter means a >= ((long) b) + c, which is equivalent to ((long) a) >= ((long) b) + ((long) c).

as an addition to all already mentioned points:

import java.util.*;

This is dumb!

The Java Util-Package contains a large amount of classes, interfaces and exceptions. With that single line, you make Eclipse / Netbeans “Do what I want Button” ™ – also known as “completion suggestion” – load ALL THE CLASSES:

how not to do it

What exactly do you use of that? right, the Scanner.
Aside from being hugely inconvenient, it clutters your namespace and can lead to naming conflicts.

Instead do this:

import java.util.Scanner;

Additional “nitpicks:”

  • Place braces around if and else blocks…
  • Make your variable names more speaking than a, b, c, even though it’s hard with triangle-sides
  • Improve User Experience (UX). If someone executes this, what are they supposed to enter??

There’s a lot of redundancy due to symmetry, since a, b, and c are interchangeable. Whenever you have a group of variables that should be treated the same way as each other, you should consider using an array instead.

Once you sort the sides by length, the problem becomes easier. Need to check for a negative length (which you didn’t do)? Just check the smallest number. Need to detect an equilateral triangle? Just check the “shortest” and “longest” sides for equality.

In one of the comments, @Ryan pointed out that adding two sides could result in overflow. Therefore, subtracting is safer.

int[] s = new int[3];   // Lengths of the sides
try (Scanner sc = new Scanner(System.in)) {
    for (int i = 0; i < s.length; i++) {
        s[i] = sc.nextInt();
    }
    Arrays.sort(s);

    if (s[0] <= 0) {
        throw new IllegalArgumentException("Side with non-positive length");
    }

    System.out.println( (s[0] == s[2]) ? "Equilateral"
                      : (s[2] - s[1] >= s[0]) ? "Not a triangle" 
                      : (s[1] == s[0] || s[1] == s[2]) ? "Isosceles"
                      : "Scalene");
}

If you’re looking for strictly fewer lines, this is what I submitted to a competition with that problem. It really only reduces it by a couple lines, and it’s not quite as simple as if else statements, but I think it might work better for larger input.

import java.util.*;
public class triangle {
public static void main(String[] args) {
    in = new Scanner(System.in);
    Integer[] sides = {in.nextInt(), in.nextInt(), in.nextInt()};
    Arrays.sort(sides);
    if(sides[0] + sides[1] < sides[2])
        System.out.println("NOT A TRIANGLE");
    HashMap<Integer, Integer> occurences = new HashMap<>();
    for(Integer i : sides)
        occurences.put(i, occurences.get(i) == null ? 1 : occurences.get(i) + 1);
    int size = occurences.size();
    System.out.println(size == 3 ? "Scalene" : (size == 2 ? "Isocoles" : "Equilateral"));
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *