0

I wrote this method. It's supposed to return all triplets [a, b, c] from an array of integers for which a ^ 2 + b ^ 2 = c ^ 2.

public static List<int[]> AllTripletsThatFulfilla2b2c2Equality(int[] n)
    {
        var combinations = from i in n
                           from j in n
                           from p in n
                           select new int[][] {new int[]{ i, j, p }, new int[] {p, j, i}, new int[] {i, p, j}};
        
        return combinations.Where(x => x.Length == x.Distinct().Count() && Math.Pow(x[0], 2) + Math.Pow(x[1], 2) == Math.Pow(x[2], 2)).Distinct().ToList();
    }

Distinct doesn't work.

I've tried several other ways to write this, including

public static List<int[]> AllTripletsThatFulfilla2b2c2Equality(int[] n)
    {
        var combinations = from i in n
                           from j in n
                           from p in n
                           select new[] { i, j, p };
        combinations = combinations.ToList();
        Func<int[], List<int[]>> combo = x =>
        {
            List<int[]> list = new List<int[]>();
            list.Add(x);
            if (!combinations.Contains(new [] { x[0], x[2], x[1] }))
            {
                list.Add(new[] { x[0], x[2], x[1] });
            }


            if (!combinations.Contains(new[] { x[2], x[1], x[0] }))
            {
                list.Add(new[] { x[2], x[1], x[0] });
            }
            list.Add(new [] { x[0], x[2], x[1] });
            list.Add(new [] { x[2], x[1], x[0] });
            return list;
        };

        return combinations.SelectMany(combo).Distinct().Where(x => x.Length == x.Distinct().Count() && Math.Pow(x[0], 2) + Math.Pow(x[1], 2) == Math.Pow(x[2], 2)).ToList();
    }

and even added a comparer for Distinct:

        public class TripletComparer : IEqualityComparer<int[]>
    {
        public bool Equals(int[] x, int[] y)
        {
            return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
        }

        public int GetHashCode(int[] obj)
        {
            return obj.GetHashCode();
        }
    }

Same result when tested, this one:

Assert.Equal() Failure
Expected: List<Int32[]> [[3, 4, 5], [4, 3, 5]]
Actual:   List<Int32[]> [[3, 4, 5], [3, 4, 5], [4, 3, 5], [4, 3, 5], [4, 3, 5], ...]

Somehow, it doesn't see that there are items that repeat themselves. Does anyone have any idea why, and how to fix it?

  • 3
    because there is no overloaded comparsion and default check only if it's the same object (same point in the memory) – Selvin Jun 30 '20 at 10:10
  • @Selvin okay, do you have any idea how to fix it? –  Jun 30 '20 at 10:11
  • 2
    I mean you need to use `Distinct(IEnumerable, IEqualityComparer)` and pass `IEqualityComparer` to point what do you mean when you are saying that `int[]` is equal to another `int[]` – Selvin Jun 30 '20 at 10:12
  • Look into the duplicate, in particular this answer, if you can´t (or dont want to) change the class: https://stackoverflow.com/a/1365761/2528063 – MakePeaceGreatAgain Jun 30 '20 at 10:16
  • and additional resource https://stackoverflow.com/questions/3232744/easiest-way-to-compare-arrays-in-c-sharp – Selvin Jun 30 '20 at 10:17
  • @Selvin How does this link help? OP needs to provide some means for equality anyway, no matter if he´s using `Distinct` or `SequenceEquals`. – MakePeaceGreatAgain Jun 30 '20 at 10:19
  • I can´t see where you provide an instance of the equality-comparer to `Distinct`. – MakePeaceGreatAgain Jun 30 '20 at 10:21
  • @HimBromBeere with *provide some means for equality* for `int[]` – Selvin Jun 30 '20 at 10:21
  • 2
    your `GetHashCode`-implementation seems odd. Usually you compute a hashcode based on the exact same members you use within the actual `Equals`-check. – MakePeaceGreatAgain Jun 30 '20 at 10:23
  • @HimBromBeere fixed GetHashCode, it worked, thank you so much –  Jun 30 '20 at 10:30

1 Answers1

0

Your GetHashCode-implementation seems odd. Usually you compute a hashcode based on the exact same members you use within the actual Equals-check. Otherwise Distinct will probably not even call into your Equals-method.

public bool Equals(int[] x, int[] y)
{
    return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
}

public int GetHashCode(int[] obj)
{
    int hash = 17;
    // Suitable nullity checks etc, of course :)
    hash = hash * 23 + obj[0].GetHashCode();
    hash = hash * 23 + obj[1].GetHashCode();
    hash = hash * 23 + obj[2].GetHashCode();
    return hash;
}

Disclaimer: the hashcode-code is adapted from https://stackoverflow.com/a/263416/2528063.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111