How to solve an array number count and dividing problem?

Viewed 491

I am have been trying to do some problem-solving practice using C# and also new to C#. So here is the problem, given the array arr= [1,1,0,-1,-1] there are 5 elements, two positive, two negative and one zero digits. Their ratios would be 2/5=0.400000 for two positive digit numbers, 2/5 = 0.400000 for two negative numbers and 1/5 = 0.200000 for 1 zero. It should be printed as

0.400000
0.400000
0.200000

What I am trying to do actually is, count all negative number from an array and divide it by the total number of elements in that array. Same case for positive and zeros in that array. And finally, it would print out the 3 results. Here is what I have tried. I am not getting the desired output.

using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Text;
using System;

class Solution {

    // Complete the plusMinus function below.
    static void plusMinus(int[] arr) {
        int[] positiveArray = new int[arr.Length];
        int[] negativeArray = new int[arr.Length];
        int[] zeroArray = new int[arr.Length];

        for(int i=0; i <arr.Length; i++){
            if(arr[i]>0){

                arr[i]=positiveArray[i];

            }else if(arr[i]<0){
                arr[i] = negativeArray[i];
            }else if(arr[i] == 0){
                arr[i] = zeroArray[i];
            }
        }
        float postive = (float)positiveArray.Length/arr.Length;
        float negative = (float)negativeArray.Length/arr.Length;
        float zero = (float)zeroArray.Length/arr.Length;

        Console.WriteLine(postive);
        Console.WriteLine(negative);
        Console.WriteLine(zero);

    }

    static void Main(string[] args) {
        int n = Convert.ToInt32(Console.ReadLine());

        int[] arr = Array.ConvertAll(Console.ReadLine().Split(' '), arrTemp => Convert.ToInt32(arrTemp))
        ;
        plusMinus(arr);
    }
}

Output example:

enter image description here

4 Answers

Since this is c# you can go for some fancy LINQ

Console.WriteLine((float)arr.Count(n => n  > 0)/(float)arr.Length);
Console.WriteLine((float)arr.Count(n => n  < 0)/(float)arr.Length);
Console.WriteLine((float)arr.Count(n => n == 0)/(float)arr.Length);

There are a couple of issues here. Let me see if I can help you decide how to tackle them.

Your assignments are inverted.

In the part where you want to classify the elements into the corresponding array, you're assigning the item in the wrong way. Instead of this:

for(int i=0; i <arr.Length; i++){
    if(arr[i]>0){
        arr[i]=positiveArray[i];
    }else if(arr[i]<0){
        arr[i] = negativeArray[i];
    }else if(arr[i] == 0){
        arr[i] = zeroArray[i];
    }
}

Try this:

for(int i=0; i <arr.Length; i++){
    if(arr[i]>0){
        positiveArray[i] = arr[i];
    }else if(arr[i]<0){
        negativeArray[i] = arr[i];
    }else if(arr[i] == 0){
        zeroArray[i] = arr[i];
    }
}

Now, I think I get the idea of your algorithm but now we have a bigger problem.

The size of the 3 arrays is always the same and equal to the total items in the original array.

Here's the problem. Before you start your counting loop, you create the arrays where you'll save the items depending on their category (positive, negative, zero) but the thing is that in C# we must reserve the size of the array we want to use beforehand and so you're always allocating the length of the original array to each of created ones. So all your arrays are of the same size and hence you're always getting 1 as the result.

Possible solution:

Tip 1: For this kind of problem you don't need to actually store the array values but only count them. So one possible way to solve this is create counters instead of arrays, increment the proper counter each time and then use those counters to compute the final result.

UPDATE

Now that you solved this using Lists, I'll give you some more advice. Even when you solved the problem, you should think about whether you solved it efficiently or not. And how could you improve it. (Hint: In this case using lists you're wasting a lot of space)

I recommend you to read more about runtime/space algorithm analysis. It'll teach you how to write better code. There's a lot of material available out there. This is one I just found through a quick Google search: https://www.cs.cmu.edu/~adamchik/15-121/lectures/Algorithmic%20Complexity/complexity.html

I'll leave you this fiddle with a possible solution not using List just in case you want to give it a try.

https://dotnetfiddle.net/01R09n

Hope this helps!

Okay, now with the example i can assume your problem is that you are already specifying your arrays lengths on this lines:

    int[] positiveArray = new int[arr.Length];
    int[] negativeArray = new int[arr.Length];
    int[] zeroArray = new int[arr.Length];

So when you divide you are getting always 1 as all arrays have the same length that the original one. One solution is removing the initialization of array lengths, but if you do this you will encounter another problem when inserting on positive, negative and zero arrays and you will have to fix it by changing the way you insert into them.

I would probably suggest you to change arrays for List<T> as this post recommends.

Cheers!

The reason you got 1 for every calculation is that you are dividing the same numbers, the length of the new int[arr.Length] is the same as arr.Length.

However you can count the occurence of the different numbers like:

var positiveCount = 0;
// with the negative numbers and zeros also

for(int i=0; i <arr.Length; i++){
    if(arr[i]>0){
        positiveCount++;
    }
    // and so on...
}

//then divide with the length:
var positive = (float)positiveCount/arr.Length;
Related