HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Calculate pairs in a Set ("Sherlock and Pairs" HackerRank challenge)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
challengesherlockcalculatehackerrankandpairsset

Problem

I have started reading clean code and want to improve my coding practices. Here is my attempt at solving an online puzzle. Please review the code and let me know how could I have written it better in terms of logic, coding practices or any other advice you might have.

Problem Statement


Sherlock is given an array of N integers (\$A_0, A_1 \ldots A_{N-1}\$) by Watson. Now Watson asks Sherlock how many different pairs of indices \$i\$ and \$j\$ exist such that \$i\$ is not equal to \$j\$ but \$A_i\$ is equal to \$A_j\$.


That is, Sherlock has to count the total number of pairs of indices \$(i,j)\$ where \$A_i =Aj\$ AND \$i≠j\$.


Input Format


The first line contains \$T\$, the number of test cases. \$T\$ test cases follow.
Each test case consists of two lines; the first line contains an integer \$N\$, the size of array, while the next line contains N space separated integers.


Output Format


For each test case, print the required answer on a different line.


Constraints


\$1≤T≤10\$


\$1≤N≤10^5\$


\$1≤A[i]≤10^6\$

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NoOfPairsInASet
{
class Solution
{
static Dictionary CountOfElements = new Dictionary();
static Int64 Sum = 0;
static Int64[] data;
static void Main(string[] args)
{
int TestCases = Convert.ToInt32(Console.ReadLine());
//int TestCases = 1;
for (int t = 0; t item in CountOfElements)
{
if (item.Value > 1)
{
Sum += CalculatePermutationOfValue(item.Value, 2);
}
}
}

private static Int64 CalculatePermutationOfValue(Int64 n, Int64 r)
{
//Int64 P = factorial(n) / factorial(n - r); // with r = 2, this simplifies to n*n-1
Int64 P = n * (n - 1);
return P;

Solution

Dead code

Kill it. If you have some commented out code that you aren't using just delete it. It adds noise to the reader and doesn't add anything to the code. Not to mention factorial is an incredibly simple thing to add back in:

public int Factorial(int number)
{
    return number == 0 ? 1 : Enumerable.Range(1, number).Aggregate((i, j) => i * j);
}


Note from the above that, like you, I prefer non-recursive solutions where possible.

You also have dead code here:

private static Int64 CalculatePermutationOfValue(Int64 n, Int64 r)
{
    //Int64 P = factorial(n) / factorial(n - r); // with r = 2, this simplifies to n*n-1
    Int64 P = n * (n - 1);
    return P;
}


Remove the r parameter and delete the commented code. Also, don't bother with P = ... just return n * (n - 1);.

Naming

You've used a sensible name for namespace and class - kudos!

Prefer long to Int64 - it looks nicer and is more standard.

All local variables should be named in camelCase P -> p.

Quite a few of your names are quite good - but can be tightened up in places: try to be as descriptive as you can.

Other stuff

Everything is static - not necessarily a problem but some people get upset about that sort of thing.

This function can be massively simplified (I think):

private static void IncrementCounter(Int64 i)
{
    Int64 count = CountOfElements[(data[i])];
    count++;
    CountOfElements[(data[i])] = count;
}


To

CountOfElements[(data[i])]++;


You should rely on fields less and pass things through parameters. Side effects suck when you're trying to follow execution. E.g.

private static void GenerateDictionary()


It returns void but it generates a dictionary? Now I have to dig into the code to find where my dictionary has been generated.

You should write instructions out the Console. Users don't like spamming the keyboard hoping to do the right thing(TM).

Never trust a user to input a sensible value:

int TestCases = Convert.ToInt32(Console.ReadLine());


Should be more along the lines of:

var numberOfTestCases = 0;
// This only works if MinimumNumberOfTestCases >= 1
while (numberOfTestCases  MaximumNumberOfTestCases)
{
    Console.WriteLine(UserMessages.PromptForNumberOfTestCases);
    int.TryParse(Console.ReadLine(), out numberOfTestCases);
}


Note that I've pretended that you have a class called UserMessages with a property/field containing the text to prompt to a user. I've also assumed that you have created well named constants for the min/max number of test cases.

Linq

You should defintely learn some LINQ (Language integrated query). For example, your ConvertStringToInt becomes redundant. I didn't mention it earlier but that's also a poorly named function. It converts the items of a string array to ints - that isn't clear from the name.

Anyway, with LINQ:

ArrayOfElements.Select(item => int.Parse(item)).ToArray();


Notice that I'm just doing a straight forward parse - if the item isn't a valid integer we can't continue so might as well fail quickly.

Code Snippets

public int Factorial(int number)
{
    return number == 0 ? 1 : Enumerable.Range(1, number).Aggregate((i, j) => i * j);
}
private static Int64 CalculatePermutationOfValue(Int64 n, Int64 r)
{
    //Int64 P = factorial(n) / factorial(n - r); // with r = 2, this simplifies to n*n-1
    Int64 P = n * (n - 1);
    return P;
}
private static void IncrementCounter(Int64 i)
{
    Int64 count = CountOfElements[(data[i])];
    count++;
    CountOfElements[(data[i])] = count;
}
CountOfElements[(data[i])]++;
private static void GenerateDictionary()

Context

StackExchange Code Review Q#98557, answer score: 5

Revisions (0)

No revisions yet.