0

I'm taking each element as "sum", "first" and "sec". If (first + sec < sum) I'll make a hashset(tmp) of these 3 and put this hashset into a larger hashset(triangle) containing all tmp hashsets. This removes duplicate combinations of 3 numbers. Here's my code. It works but is there any better solution?

public void findTriangle(int[] a){

    HashSet<HashSet<Integer>> triangle = new HashSet<HashSet<Integer>>();
    HashSet<Integer> tmp;
    for(int i=0;i<a.length;i++){
        int sum=a[i];
        for(int j=0;j<a.length;j++){
            int first = a[j];
            if(first!=sum){
                for(int k=0;k<a.length;k++){
                    int sec = a[k];
                    if(sec!=first && sec!=sum && (first + sec < sum)){
                        tmp = new HashSet<Integer>();
                        tmp.add(first);
                        tmp.add(sec);
                        tmp.add(sum);
                        triangle.add(tmp);
                    }
                }       
            }
        }

    }

    for(HashSet<Integer> hs : triangle)
        System.out.println(hs);
}
Punit
  • 69
  • 1
  • 7
  • If it's already working it might be better suited for CodeReview. One improvement is to not print to stdout from inside your method. Return the HashSet. – ChiefTwoPencils Mar 15 '15 at 04:11
  • link: http://codereview.stackexchange.com/ – mk. Mar 15 '15 at 04:12
  • @ChiefTwoPencils It works but with 3 for loops complexity is not convincing. What's wrong if I print it from the method itself? – Punit Mar 15 '15 at 04:15
  • 1
    It's bad practice in general. The most obvious reason is you're binding the use of the method to System.out. If output is necessary in a method it's better to pass in the stream; it's more flexible. It may not matter to you for this case though. – ChiefTwoPencils Mar 15 '15 at 04:18
  • 1
    It's just a bit cleaner if you don't print it there, because then the method is responsible for one thing: crunching numbers. Something else can be responsible for printing them. It'd take a while to explain exactly why, but if you try to make everything do as little as possible, things turn out better. – mk. Mar 15 '15 at 04:18
  • 1
    I'm a bit confused. If you have three numbers A, B, C, and A + B < C, doesn't that mean you *cannot* make a triangle with those sides? (P.S. And it's not going to work just to change it to `>`. You have to ensure that A + B > C where C is the largest of the three.) – ajb Mar 15 '15 at 04:29
  • 1
    Also, it appears that your code expects all the `a[i]` to be different. If any of them are the same, your code will miss all the isosceles and equilateral triangles. – ajb Mar 15 '15 at 04:31
  • You're right @ajb Do you have a solution for this problem? – Punit Mar 15 '15 at 05:42
  • What if I add 2 more conditions in the && clause of the innermost loop - && (sec + sum > first) && (first + sum > sec)? – Punit Mar 15 '15 at 06:04
  • @Punit I think that would solve the first problem. To allow isosceles and equilateral triangles: you should be comparing the indexes for equality, not the values. That is, `i != j`, `i != k`, and so on. That prevents you from using the same number from the same array element twice, but lets you use the same number from different array elements. Even better would be to say `for j = i + 1; ...` and `for k = j + 1`, instead of staring at 0. When you start `j` over at 0, it will lead you to look at the same numbers you've already looked at, which is wasteful. – ajb Mar 15 '15 at 07:09
  • As for what's the best solution: I don't know, but I'd start by sorting the array. If your elements are in order, there are ways you can optimize. For instance, you can look at each combination of two numbers; if they're A and B, then you can do a binary search over the rest of the array to find where A+B would be. Then A+B (if it's in the array) and everything to the right of it will not form a triangle; everything to the left (and to the right of the elements you're examining) will form a triangle with A and B. – ajb Mar 15 '15 at 07:12

2 Answers2

0

Sort the array and add the triplets to a list -

public static ArrayList<ArrayList<Integer>> get(int[] input) {
    ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    if (input.length < 3) {
      return result;
    }
    Arrays.sort(input);
    for (int i = 0; i < input.length - 2; i++) {
      int k = i + 2;
      for (int j = i + 1; j < input.length; j++) {
        while (k < input.length && input[i] + input[j] > input[k]) {
          ArrayList<Integer> inner = new ArrayList<Integer>();
          inner.add(input[i]);
          inner.add(input[j]);
          inner.add(input[k]);
          result.add(inner);
          k++;
        }
      }
    }
    return result;
  }
Onkar Deshpande
  • 301
  • 4
  • 15
0

Not so optimal works yet. I tried testing the above two solutions and they seemed to not work. May be i was missing something. Hence decided to post my tested solution here. It does not check for duplicates. Condition to find a triangle: http://www.wikihow.com/Determine-if-Three-Side-Lengths-Are-a-Triangle

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;

class Triangle {
    int a;
    int b;
    int c;

    public Triangle(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    @Override
    public String toString() {
        return this.a + " " + this.b + " " + this.c;
    }
}

public class FindTriangle {

    public List<Triangle> findTriangle(List<Integer> points) {
        List<Triangle> result = new ArrayList<Triangle>();
        System.out.println("Entered");

        for (int i = 0; i < points.size(); i++) {
            int pt0 = points.get(i);
            System.out.println("Entered i:" + i);

            for (int j = i + 1; j < points.size() - 2; j++) {
                int pt1 = points.get(j);
                int pt2 = points.get(j + 1);
                Boolean isTri = isTriangle(pt0, pt1, pt2);
                if (isTri.equals(Boolean.TRUE)) {
                    Triangle t = new Triangle(pt0, pt1, pt2);
                    result.add(t);
                }
            }
            for (int j = 0; j < (i - 1) && j > 0; j++) {
                int pt1 = points.get(j);
                int pt2 = points.get(j + 1);
                Boolean isTri = isTriangle(pt0, pt1, pt2);
                if (isTri.equals(Boolean.TRUE)) {
                    Triangle t = new Triangle(pt0, pt1, pt2);
                    result.add(t);
                }
            }

            // final
            int pt1, pt2;
            if (i == 0) {
                pt1 = points.get(i + 1);
                pt2 = points.get(points.size() - 1);
            } else if (i == points.size() - 1) {
                pt1 = points.get(0);
                pt2 = points.get(i - 1);
            } else {
                pt1 = points.get(i + 1);
                pt2 = points.get(i - 1);
            }

            Boolean isTri = isTriangle(pt0, pt1, pt2);
            if (isTri.equals(Boolean.TRUE)) {
                Triangle t = new Triangle(pt0, pt1, pt2);
                result.add(t);
            }
        }
        return result;
    }

    public Boolean isTriangle(Integer pt1, Integer pt2, Integer pt3) {
        System.out.println("Pt1, Pt2, Pt3: " + pt1 + ":" + pt2 + ":" + pt3);

        if ((pt1 + pt2) > pt3 && (pt1 + pt3) > pt2 && (pt2 + pt3) > pt1) {
            System.out.println("This is triangle");
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public ArrayList<ArrayList<Integer>> getTri(int[] input) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        if (input.length < 3) {
            return result;
        }
        Arrays.sort(input);
        for (int i = 0; i < input.length - 2; i++) {
            int k = i + 2;
            for (int j = i + 1; j < input.length; j++) {
                while (k < input.length && input[i] + input[j] > input[k]) {
                    ArrayList<Integer> inner = new ArrayList<Integer>();
                    inner.add(input[i]);
                    inner.add(input[j]);
                    inner.add(input[k]);
                    result.add(inner);
                    k++;
                }
            }
        }
        return result;
    }

    public void findTriangleW(int[] a) {

        HashSet<HashSet<Integer>> triangle = new HashSet<HashSet<Integer>>();
        HashSet<Integer> tmp;
        for (int i = 0; i < a.length; i++) {
            int sum = a[i];
            for (int j = 0; j < a.length; j++) {
                int first = a[j];
                if (first != sum) {
                    for (int k = 0; k < a.length; k++) {
                        int sec = a[k];
                        if (sec != first && sec != sum && (first + sec < sum)) {
                            tmp = new HashSet<Integer>();
                            tmp.add(first);
                            tmp.add(sec);
                            tmp.add(sum);
                            triangle.add(tmp);
                        }
                    }
                }
            }

        }

        for (HashSet<Integer> hs : triangle)
            System.out.println(hs);
    }

    public static void main(String[] args) {
        FindTriangle f = new FindTriangle();
        List<Integer> points = new ArrayList<Integer>();
        points.add(1);
        points.add(5);
        points.add(10);
        points.add(7);

        System.out.println("Printing final results");
        List<Triangle> result = f.findTriangle(points);
        for (int i = 0; i < result.size(); i++) {
            System.out.println(result.get(i).toString());
        }
    }
}
Community
  • 1
  • 1