Pair Sum problem - c# code doesn't produce expected output-- please assist - c#

public static int FindMaxNumForMaxSum(int[] nums, int k)
{
int retVal = 0;
int N = nums.Length;
var counter = 1;
var map = new Dictionary<int, int>();
for (var i = 0; i < N; i++)
{
if (nums[i] == retVal)
{
counter++;
continue;
}
var complement = k - nums[i];
retVal = complement;
if (nums[i] == complement)
{
if (!map.ContainsKey(complement))
{
map.Add(complement, counter);
}
else
{
map[complement] = counter++;
}
}
else
{
map.Add(complement, counter);
}
}
return counter;
}
Above is my code.
Problem description below:
Given a list of n integers arr[0..(n-1)], determine the number of different pairs of elements within it which sum to k.
If an integer appears in the list multiple times, each copy is considered to be different; that is, two pairs are considered different if one pair includes at least one array index which the other doesn't, even if they include the same values.
The above solution doesn't see to produce expected output and also there is a problem of adding duplicate keys in a dictionary.
Example 1
n = 5
k = 6
arr = [1, 2, 3, 4, 3]
output = 2
The valid pairs are 2+4 and 3+3.
Example 2
n = 5
k = 6
arr = [1, 5, 3, 3, 3]
output = 4
Example 3
arr = [2, 3, 6, 7, 4, 5, 1]
output = 3

Related

My code does not check the indexes of all of the arrays (lottery program)

I am making a lottery program, it's basic and only view-able via console at the moment.
The program executes the following:
User enters 6 numbers ranging from 1 - 46.
Program generates 6 random numbers with the same range.
Program compares indexes to see which numbers the user managed to match with the program.
Program displays the same numbers which the user got right.
But, currently, there is a bug in my code and I am not sure how to proceed.
For example, my inputs are: 1 , 2 , 3 , 4 , 5 , 6
The program generated 6 numbers and I've managed to hit number 2 and 6.
But, the program only displayed number 2.
This means that my code is not comparing each and every index, and I am not sure why.
The user array is lucky, and the program generated array is numbers.
Console.WriteLine("The winning numbers are: , " );
int[] winning = new int[6];
int w = 0;
var x = 0;
var j = 0;
Console.WriteLine("The winning numbers are: , " );
int[] winning = new int[6];
int w = 0;
var x = 0;
var j = 0;
while (x< 6)
{
if (lucky[j] == numbers[x])
{
winning[w] = numbers[x];
Console.WriteLine(winning[w]);
w++;
}
j++;
if (j == 5)
{
x++;
j = 0;
}
}
There is no need to do all that looping these days. LINQ's Intersect function makes it a single function call:
var Matches = lucky.Intersect(numbers);
will return all matching numbers from the two lists in Matches.
A looping equivalent might look like this (writing off the top of my head):
List<int> winning = new List<int>();
for(int i=0; i<numbers.Length; i++)
{
if(numbers.Contains(lucky[i])
winning.Add(lucky[i]);
}
To display it on console, use a simple loop:
for(int i=0; i<winning.Length; i++)
{
Console.WriteLine(winning[i]);
}
Since you run over an array, the standard procedure would be to use a for loop.
Here are three solutions that solve the problem.
Each one is complete and can be tested on https://dotnetfiddle.net/
Linq: Use the Intersects method to find the common items between two IEnumerables.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
List<int> matches = new List<int>(numbers.Intersect(guesses));
foreach (int n in matches)
{
Console.WriteLine("Hit: " + n.ToString());
}
}
}
Using a single for loop and checking with the Contains method (Array implements the IList interface) if the other array contains the number at the current index. You could also use a foreach loop, since you don't care about the indexes.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
List<int> matches = new List<int>();
for (int i = 0; i < guesses.Length; i++)
{
if (numbers.Contains(guesses[i]))
{
Console.WriteLine("Hit: " + guesses[i].ToString());
matches.Add(guesses[i]);
}
}
}
}
Of you could use a nested for loops, one for each array, to check each number from one array against every number of the other one.
Again you could use foreach loops.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
List<int> matches = new List<int>();
for (int i = 0; i < guesses.Length; i++)
{
for (int j = 0; j < numbers.Length; j++)
{
if (guesses[i] == numbers[j])
{
Console.WriteLine("Hit: " + guesses[i].ToString());
matches.Add(guesses[i]);
break; // optional, we found the number and can leave the loop. Not optional if your lottery allows numbers to happen more than once.
}
}
}
}
}
As for the question why your code isn't working:
You set j = 0 when j == 5 just after j++, meaning you set j to 0 after checking index 4. While I do not want to encourage such unorthodox styles you could fix it by comparing j == 6. Again, this approach makes your code unreadable, please use one of the other solutions.
using System;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
int[] winning = new int[6];
int w = 0;
var x = 0;
var j = 0;
while (x < 6)
{
if (guesses[j] == numbers[x])
{
winning[w] = numbers[x];
Console.WriteLine(winning[w]);
w++;
}
j++;
if (j == 6)
{
x++;
j = 0;
}
}
}
}
I think what you are looking for is that finding common items from two arrays.
var ar1 = new int[] {1,2,3,4,5,6};
var ar2 = new int[] {2,3,4,6,7,8};
var common = ar1.Intersect(ar2);
In your case
var common = lucky.Intersect(numbers);
Using loops
// Array size is fixed here.
for (int i = 0; i < 6; i++) // OR i < lucky.Length (guessing numbers)
{
if (numbers.Contains(lucky[i]))
{
// NUMBERS DETECTED
}
}
The issue is with the checking of last index(5 in this case). It is never happening!
//say j = 4
lucky[4] == numbers[x] //false/true, whatever value of x is
You increment j
//j is now 5
if(j==5)
Yes and then you are resetting it to 0.
last index which is 5 in this case will never be checked in the next iteration
Solution-
if(j == 6)
I ended up building 2 methods that basically do what everyone here has told me.
Since I did not yet learn LinQ I couldn't understand , I didn't learn LIST as well so I couldn't use it as well.
My functions are like this:
First function: checks the indexes of a specified array
code:
static bool DoesExists(int[] a, int Value)
{
for (int i = 0; i < a.Length; i++)
{
if (Value == a[i])
{
return true;
}
}
return false;
}
second function checks how many repeated elements are in 2 arrays
code:
static int CountCorrect(int[] pc, int[] user)
{
int count = 0;
for (int i = 0; i < user.Length; i++)
{
if (DoesExists(pc, user[i]))
{
count++;
}
}
return count;
}
when using these 2 in conjunction , it solves my problem.
thanks to everyone for taking the time to give me good ideas.

Add Int[] array into List<int[]>

I'm having trouble with int[] arrays and adding them to a List<>. I'd like to add the values of my int[] array to something each loop but every time I do this my "something" gets the same value for every element I add. Very annoying. I understand arrays are always reference vars. However even the "new" key word doesn't seem to help. What needs to happen is to add result to some enumerated object like a List or Array or ArrayList.
Here's the codility question:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
I copied some code from others and the variable "result" does indeed load the data correctly. I just wanted to copy it back to the main program so I could see it. The only method that works is += add it into a string. Thus losing any efficiency I might have gained.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testarray
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[7];
A[0] = 3;
A[1] = 4;
A[2] = 4;
A[3] = 6;
A[4] = 1;
A[5] = 4;
A[6] = 4;
List<int[]> finish = solution(5, A);
}
public static List<int[]> solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
int iter = 0;
List<int[]> collected_result = new List<int[]>;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray<int>();
}
collected_result.Add(result);
}
// for (int i = 0; i < result.Length; i++)
//result[i] = Math.max(resetLimit, result[i]);
return collected_result;
}
}
}
This doesn't work, the collected_result ends up like:
(0,0,1,2,0)
(0,0,1,2,0)
(0,0,1,2,0)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
I know it's the line collected_result.Add(result); adding the reference each time to every instance of result in the List<>. Bother. I've tried adding "new" which is a compiler error. Finally in desperation I just added everything to a very long string. Can someone help me figure out how to properly load an object to pass back to main?
Easiest way to go:
Get a copy of your array before adding it to list:
collected_result.Add(result.ToArray());
Here is a Python solution:
def solution(A, N):
lenA = len(A)
k = 0
max_counter_value = 0
counters = [0 for x in range(0, N)]
for k in range(0, lenA):
if A[k] >= 1 and A[k] <= N:
counters[A[k] - 1] += 1
max_counter_value = max(counters)
if A[k] == N + 1:
counters = [max_counter_value for x in range(0, N)]
print counters
A = [3, 4, 4, 6, 1, 4, 4]
N = 5
solution(A, N)

How to find minimum number of steps to sort an integer array

I have an integer array int[] number = { 3,4,2,5,1};
The minimum number of steps to sort it should be 2. But I am getting 4.
static void Main(string[] args)
{
int[] number = { 3,4,2,5,1};
int result = get_order(number);
Console.ReadKey();
}
public static int get_order(int[] input1)
{
input1 = input1.OrderByDescending(o => o).ToArray();
bool flag = true;
int temp;
int numLength = input1.Length;
int passes = 0;
for (int i = 1; (i <= (numLength - 1)) && flag; i++)
{
flag = false;
for (int j = 0; j < (numLength - 1); j++)
{
if (input1[j + 1] > input1[j])
{
temp = input1[j];
input1[j] = input1[j + 1];
input1[j + 1] = temp;
flag = true;
}
}
passes++;
}
return passes+1;
}
What is the problem and what changes i need to do in my code?
Edit
implement #Patashu, algorithm,
public static int get_order(int[] input1)
{
var sorterArray = input1.OrderByDescending(o => o).ToArray();
var unsortedArray = input1;
int temp1;
int swap = 0;
int arrayLength = sorterArray.Length;
for (int i = 0; i < arrayLength; i++)
{
if (sorterArray[i] != unsortedArray[i])
{
temp1 = unsortedArray[i];
unsortedArray[i] = sorterArray[i];
for (int j = i + 1; j < arrayLength; j++)
{
if (unsortedArray[j] == sorterArray[i])
{
unsortedArray[j] = temp1;
swap++;
break;
}
}
}
}
return swap;
}
The problem with your algorithm is that it only attempts swapping adjacent elements.
3,4,2,5,1 is best sorted by swapping 3 with 5, which is an unadjacent swap, and then 2 with 3.
So, I suggest that you will find a better algorithm by doing the following:
1) First, sort the array into descending order using the built in sorting function of C#.
2) Now, you can use this sorted array as a comparison - iterate through the array from left to right. Every time you see an element in the unsorted array that is != to the element in the same space in the sorted array, look deeper into the unsorted array for the value the sorted array has there, and do one swap.
e.g.
3,4,2,5,1
Sort using Sort -> 5,4,3,2,1 is our sorted array
3 is != 5 - look in unsorted array for 5 - found it, swap them.
Unsorted is now 5,4,2,3,1
4 == 4
2 is != 3 - look in unsorted array for 3 - found it, swap them.
Unsorted is now 5,4,3,2,1
2 == 2
1 == 1
We're at the end of the unsorted array and we did two swaps.
EDIT: In your algorithm implementation, it looks almost right except
instead of
unsortedArray[j] = sorterArray[i];
unsortedArray[i] = temp1;
you had it backwards, you want
unsortedArray[j] = temp1;
unsortedArray[i] = sorterArray[i];
Since you're asking why you're getting 4 steps, and not how to calculate the passes, the correct way to do this is to simply step through your code. In your case the code is simple enough to step through on a piece of paper, in the debugger, or with added debug statements.
Original: 3, 4, 2, 5, 1
Pass: 1: 4, 3, 5, 2, 1
Pass: 2: 4, 5, 3, 2, 1
Pass: 3: 5, 4, 3, 2, 1
Pass: 4: 5, 4, 3, 2, 1
Basically what you see is that each iteration you sort one number into the correct position. At the end of pass one 2 is in the correct position. Then 3, 4, 5.
Ah! But this is only 3 passes you say. But you're actually incrementing passes regardless of flag, which shows you that you actually did one extra step where the array is sorted (in reverse order) but you didn't know this so you had to go through and double check (this was pass 4).
To improve performance, you do not need to start checking the array from the beginning.
Better than the last equal element.
static int MinimumSwaps(int[] arr)
{
int result = 0;
int temp;
int counter = 0;
for (int i = 0; i < arr.Length; ++i)
{
if (arr[i] - 1 == i)
{
//once all sorted then
if(counter==arr.Length)break;
counter++;
continue;
}
temp = arr[arr[i]-1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
result++;//swapped
i = counter ;//needs to start from the last equal element
}
return result;
}
At the start:
{ 3,4,2,5,1}; // passes = 0
Round 1 reuslt:
{ 4,3,2,5,1};
{ 4,3,5,2,1}; // passes = 1
Round 2 reuslt:
{ 4,5,3,2,1}; // passes = 2
Round 3 reuslt:
{ 5,4,3,2,1}; // passes = 3 and flag is set to true
Round 4 reuslt:
{ 5,4,3,2,1}; // same result and passes is incremented to be 4
You fail to mention that the array is supposed to be sorted in descending order, which is usually not the default expected behavior (at least in "C" / C++). To turn:
3, 4, 2, 5, 1
into:
1, 2, 3, 4, 5
one indeed needs 4 (non-adjacent) swaps. However, to turn it into:
5, 4, 3, 2, 1
only two swaps suffice. The following algorithm finds the number of swaps in O(m) of swap operations where m is number of swaps, which is always strictly less than the number of items in the array, n (alternately the complexity is O(m + n) of loop iterations):
int n = 5;
size_t P[] = {3, 4, 2, 5, 1};
for(int i = 0; i < n; ++ i)
-- P[i];
// need zero-based indices (yours are 1-based)
for(int i = 0; i < n; ++ i)
P[i] = 4 - P[i];
// reverse order?
size_t count = 0;
for(int i = 0; i < n; ++ i) {
for(; P[i] != i; ++ count) // could be permuted multiple times
std::swap(P[P[i]], P[i]); // look where the number at hand should be
}
// count number of permutations
This indeed finds two swaps. Note that the permutation is destroyed in the process.
The test case for this algorithm can be found here (tested with Visual Studio 2008).
Here is the solution for your question :)
static int MinimumSwaps(int[] arr)
{
int result = 0;
int temp;
int counter = 0;
for (int i = 0; i < arr.Length; ++i)
{
if (arr[i] - 1 == i)
{
//once all sorted then
if(counter==arr.Length)break;
counter++;
continue;
}
temp = arr[arr[i]-1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
result++;//swapped
i = 0;//needs to start from the beginning after every swap
counter = 0;//clearing the sorted array counter
}
return result;
}

Finding all numbers that sum to a specified target number (integer partition)

First i want to say i'm still learning so my programming skills are not very good, and i'm willing to accept any advice you have.
Second i'm still learning english so i want to say sorry for the inconvenience.
Well my problem is this, i need help improving my algorithm or any information about it, i don't know what words use for searching this.
The algorithm is supposed to find all the combinations of numbers that added is equal to a given number. Example: if i have the number 6 my results are supposed to be: [1,5],[2,4],[2,2,2],[3,3]
i have the following:
public List<List<int>> discompose(int number)
{
List<List<int>> discomposedPairs = new List<List<int>>();
if (number <= 3)
return discomposedPairs;
int[] numsForCombine = new int[number-1];
for(int i = 1; i < number;i++){
numsForCombine[i - 1] = i;
}
int ini = 0;
int end = numsForCombine.Length - 1;
while (ini <= end)
{
List<int> pair = new List<int>();
pair.Add(numsForCombine[ini++]);
pair.Add(numsForCombine[end--]);
discomposedPairs.Add(pair);
}
return discomposedPairs;
}
public List<List<int>> discomposePair(List<int> pair)
{
List<List<int>> parDisc = new List<List<int>>();
for (int i = 0; i < pair.Count; i++) {
if (pair[i] > 3)
{
List<List<int>> disc = discomposeList(discompose(pair[i]));
foreach (List<int> item in disc)
{
if (i > 0)
{
var temp = pair.GetRange(0, i);
temp.AddRange(item);
parDisc.Add(temp);
} else {
item.AddRange(pair.GetRange(i+1, pair.Count-(i+1)));
parDisc.Add(item);
}
}
}
}
return parDisc;
}
public List<List<int>> discomposeList(List<List<int>> list)
{
List<List<int>> mainDiscomposedList = new List<List<int>>();
for (int i = 0; i < list.Count; i++)
{
mainDiscomposedList.Add(list[i]);
List<List<int>> discomposedSubset = discomposePair(list[i]);
foreach(List<int> item in discomposedSubset){
mainDiscomposedList.Add(item);
}
}
return mainDiscomposedList;
}
The first method descompose the number given in pairs that added are equal the number given.
The second and the third method are the ugliest they are recursive and have bucles so they don't have any good performance. Between the two generates a List with numbers as i the problem says but there are a few inconvenients:
1) Don't have good performance
2) Gives a lot of repetitive sequences
here is the output for the number 10
[2,8,]
[2,2,6,]
[2,2,2,4,]
[2,2,2,2,2,]
[2,2,3,3,]
[2,3,5,]
[2,3,2,3,]<-------------repeated
[2,4,4,]
[2,2,2,4,]<-------------repeated
[2,4,2,2,]<-------------repeated
[3,7,]
[3,2,5,]<-------------repeated
[3,2,2,3,]<-------------repeated
[3,3,4,]
[3,3,2,2,]
[4,6,]
[2,2,6,]<-------------repeated
[4,2,4,]<-------------repeated
[4,2,2,2,]<-------------repeated
[4,3,3,]<-------------repeated
[5,5,]
[2,3,5,]<-------------repeated
[5,2,3,]<-------------repeated
Finally i want to improve the performance and have the less possible repeated items being a repeated item [1,1,3], [1,3,1], [3,1,1]
[Here is the full project link]1
Here's one approach that first builds the combinations into a tree structure, then arranges them into lists of ints:
internal class Combination
{
internal int Num;
internal IEnumerable<Combination> Combinations;
}
internal static IEnumerable<Combination> GetCombinationTrees(int num, int max)
{
return Enumerable.Range(1, num)
.Where(n => n <= max)
.Select(n =>
new Combination
{
Num = n,
Combinations = GetCombinationTrees(num - n, n)
});
}
internal static IEnumerable<IEnumerable<int>> BuildCombinations(
IEnumerable<Combination> combinations)
{
if (combinations.Count() == 0)
{
return new[] { new int[0] };
}
else
{
return combinations.SelectMany(c =>
BuildCombinations(c.Combinations)
.Select(l => new[] { c.Num }.Concat(l))
);
}
}
public static IEnumerable<IEnumerable<int>> GetCombinations(int num)
{
var combinationsList = GetCombinationTrees(num, num);
return BuildCombinations(combinationsList);
}
public static void PrintCombinations(int num)
{
var allCombinations = GetCombinations(num);
foreach (var c in allCombinations)
{
Console.WriteLine(string.Join(", ", c));
}
}
When run with the input value 6, this produces:
1, 1, 1, 1, 1, 1
2, 1, 1, 1, 1
2, 2, 1, 1
2, 2, 2
3, 1, 1, 1
3, 2, 1
3, 3
4, 1, 1
4, 2
5, 1
6

How to repeat the array elements with specific sequence according to some number?

If I have this array of integers :
int[] columns_index = { 2, 3, 4};
How can i repeat this sequence according to given number (size)?
For example :
if i give u 4 as a size then the array will be
{2,3,4,2}
if i give u 5 as a size then the array will be
{2,3,4,2,3}
if i give u 6 as a size then the array will be
{2,3,4,2,3,4}
if i give u 7 as a size then the array will be
{2,3,4,2,3,4,2}
And so on ...
Just use the modulo operator to iterate through the columns_index
int input = 7; // change this to user input of whatever it needs to be
int[] numbers = new int[ input ];
for ( int i = 0; i < input; i++ ){
int index = i % ( columns_index.length )
numbers[i] = columns_index[ index ];
}
public static class Extensions
{
public static T[] Multiply<T>(this T[] array, int length)
{
if ( array == null || array.Length == 0 || length <= array.Length )
return array;
var x = length % array.Length;
var y = length / array.Length;
return Enumerable.Range(1,y)
.SelectMany(c=>array)
.Concat(array.Take(x))
.ToArray();
}
}
One can use the Linq Repeat() and Take() functions to get the result.
private readonly static int[] Source = { 2, 3, 4 };
[TestMethod]
public void TestMethod1() {
Assert.IsTrue(new []{ 2, 3, 4, 2}.SequenceEqual(GetSequence(Source,4)));
Assert.IsTrue(new[] { 2, 3, 4, 2, 3 }.SequenceEqual(GetSequence(Source, 5)));
Assert.IsTrue(new[] { 2, 3, 4, 2, 3, 4 }.SequenceEqual(GetSequence(Source, 6)));
Assert.IsTrue(new[] { 2, 3, 4, 2, 3, 4, 2 }.SequenceEqual(GetSequence(Source, 7)));
}
private static int[] GetSequence(IEnumerable<int> src, int count) {
var srcRepeatCount = count / src.Count() + 1;
return Enumerable.Repeat(src, srcRepeatCount).SelectMany(itm => itm).Take(count).ToArray();
}
If you preferred to seperate the part where you use all in columns_index with the rest
int input = 1000001;
int[] columns_index = { 2, 3, 4 };
int[] numbers = new int[input];
// Times we can use everything in columns_index
int times = input/columns_index.Length; // 333333
List<int> numbersList = new List<int>();
for (int i = 0; i < times; i++)
{
numbersList.AddRange(columns_index);
}
// numbersInt.Count is now 999999..
// Times for the rest
int modTimes = input%(columns_index.Length); // 2
for (int j = 0; j < modTimes; j++)
{
numbersList.Add(columns_index[j]);
}
numbers = numbersList.ToArray();

Categories

Resources