Prefixset on codility using c# - c#

Problem Description:
Given a table A of N integers from 0 to N-1 calculate the smallest
such index P, that that {A[0],...,A[N-1]} = {A[0],...,A[P]}.
My solution
using System;
using System.Linq;
using System.Collections.Generic;
class Solution {
public int solution(int[] A) {
for (int i=A.Length-1;i>=0;i--) {
int[] Am = A.Take(i).ToArray();
int pos = Array.IndexOf(Am, A[i]);
if( pos >- 1 )
{
}
else
{
return i;
}
}
return A.Length-1;
}
}
This works but complexity is O(N**2) and times out when Array has large number of elements
If i use long in place of int, I get the cs0266 cannot implicitly convert long to int error.
Please suggest on how i can improve this. Thanks

You can just keep track of all the elements you have already observed using a set.
public Int32 Solution(Int32[] A)
{
var seenNumbers = new HashSet<Int32>();
var result = 0;
for (var index = 0; index < A.Length; index++)
{
if (seenNumbers.Add(A[index]))
{
result = index;
}
}
return result;
}
Note that HashSet<T>.Add() will return true if the element is not already in the set, false otherwise. When you discover a number for the first time you obviously have to include that number and therefore extend the prefix to the current position. This will run in O(n) and consume O(n) additional space.

Related

Linear search algorithm with generic methods

I have a problem with code.
I receive an error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'GenericMethods.search(T[], T)'. There is no implicit reference conversion from 'object' to 'System.IComparable'.
Task:
Create a console app and write a generic method, Search [ int Search( T [ ] dataArray, T searchKey) ]
that searches an array using linear search algorithm.
a) Method Search should compare the search key with each element in the array until the search key
is found or until the end of the array is reached.
b) If the search key is found, return/display its location in the array (i.e. its index value); otherwise
return -1.
c) You need to populate the array with random values. ( int values – between 10 and 49, double
values between 50 and 99, char values between a and z). The size of array as 10.
d) Test this method by passing two types of arrays to it. (an integer array and a string array) Display
the generated values so that the user knows what values he/she can search for.
[Hint: use (T: IComparable) in the where clause for method Search so that you can use method CompareTo() to
compare the search key to the elements in the array]
My code:
using System;
using System.Collections.Generic;
namespace LinearSearch
{
class GenericMethods
{
static void Main(string[] args)
{
object[] dataArray = new object[10];
Random random = new Random();
for (int i = 0; i < dataArray.Length; i++)
{
int randomType = random.Next(1, 3);
if (randomType == 1)
{
char randomChar = (char)random.Next('a', 'z');
dataArray[i] = randomChar;
}
else if (randomType == 2)
{
double randomDouble = random.Next(50, 99);
dataArray[i] = (int)randomDouble;
}
else
{
int randomInt = random.Next(10, 49);
dataArray[i] = randomInt;
}
}
Console.WriteLine("Generated array is: ");
Console.WriteLine(string.Join(" ", dataArray));
Console.WriteLine("Please, enter number from 10 to 99 or char from A to Z");
object userInput = Console.ReadLine();
Console.WriteLine(userInput);
Console.WriteLine($"Location of search value {userInput}: {search(dataArray, userInput)}");
}//end Main method
private static int search<T>(T[] dataArray, T searchKey) where T : IComparable<T>
{
// default to -1 so that we can determine the search is successful when it becomes a positive value
int arrayPosition = -1;
for (int x = 0; x < dataArray.Length; x++)
{
T arrayElement = dataArray[x];
// Console.WriteLine($"CompareTo result: {searchValue.CompareTo(arrayElement)}");
if (searchKey.CompareTo(arrayElement) == 0)
{
// value is found
arrayPosition = x;
break;
}
}
return arrayPosition;
} // end searchValue
}
}
Could you please help me to fix this problem? I am new in C#..
Instead of declaring dataArray as an object[] declare it as an IComparable[]. You wrote the type constraint limiting your generic type T to IComparable. object does not implement IComparable, so it is not a valid type
Lucky me, I always write generic searches for my code. For other search methods with Generics in C#, you can find them here.
public static int LinearSearch<T>(T[] array, T item) // O(n)
{
for (int i = 0; i < array.Length; i++)
/* array[i] == item */
if (Comparer<T>.Default.Compare(array[i], item) == 0)
return i;
return -1; // Not found
}
You must import 'System.Collections.Generic' in your file.
using System.Collections.Generic;
I found solution
string[] resultArray = Array.ConvertAll(dataArray, x => x.ToString());
After that code works

Get the biggest value of an array

I have a textbox to write the position of an array and a textbox to write the value of that position. Every time I want to add a value and a position I click the button btnStoreValue
I created a function (CompareTwoNumbers) for another exercise that compares two numbers and returns the biggest
Using that function and avoiding the use of comparison characters like > and < I'm supposed to get the biggest value of the array
public partial class Form1 : ExerciseArray
{
int[] numbers = new int[10];
private int CompareTwoNumbers(int i, int j)
{
if (i < j)
{
return j;
}
return i;
}
private void btnBiggestValue_Click(object sender, EventArgs e)
{
//int n=1;
int counter = 0;
int highestPosition = CompareTwoNumbers(0, 1);
for(int i=0; i<10; i++){
//int j = CompareTwoNumbers(numbers[i], numbers[i+1])
//n = CompareTwoNumbers(numbers[n], numbers[i+1]
counter = CompareTwoNumbers(highestPosition, i);
}
txtBiggestValuePosition.Text= n.ToString();
txtBiggestValue.Text=numbers[n].ToString();
}
I've tried multiple things, using multiple variables, I tried to write it on paper to try to understand things better and I'm stuck. I don't know how is it possible to find that value using the function I created on the previous exercise (assuming the function I created is correct)
So, the core part of your question is that you want to know how to find the biggest number in an array using your helper function CompareTwoNumbers and then figure out what the value and position of the biggest number is.
Based on my understanding above, you have the framework almost set up correctly.
First off, CompareTwoNumbers should be updated to return a bool. Doing this will let you conditionally update your variables holding the biggest number value and position.
private int CompareTwoNumbers(int i, int j)
{
if (i < j)
{
return true;
}
return false;
}
To know what the largest value in an (unsorted) array is, you will need to iterate through every value. While doing so, you need to keep track of the value and position of the biggest value, only updating it when a bigger value is found.
private void btnBiggestValue_Click(object sender, EventArgs e)
{
// Store the bigget number's index and value
// We start with the first index and corresponding
// value to give us a starting point.
int biggestNumberIndex = 0;
int biggestNumber = numbers[0];
// Iterate through the array of numbers to find
// the biggest number and its index
for(int i=0; i<10; i++)
{
// If the current number is larger than the
// currently stored biggest number...
if(CompareTwoNumbers(biggestNumber, numbers[i])
{
// ...then update the value and index with
// the new biggest number.
biggestNumber = number[i];
biggestNumberIndex = i;
}
}
// Finally, update the text fields with
// the correct biggest value and biggest
// value position.
txtBiggestValuePosition.Text= biggestNumberIndex.ToString();
txtBiggestValue.Text=numbers[biggestNumberIndex].ToString();
}
This uses a Tuple to give you both the max index and max value from the same method:
public (int, int) FindMaxValue(int[] items)
{
int maxValue = items[0];
int maxIndex = 0;
for(int i=1;i<items.Length;i++)
{
if (items[i] > maxValue)
{
maxValue = items[i];
maxIndex = i;
}
}
return (maxIndex, maxValue);
}

Nearest value from user input in an array C#

so in my application , I read some files into it and ask the user for a number , in these files there a lot of numbers and I am trying to find the nearest value when the number they enter is not in the file. So far I have as following
static int nearest(int close_num, int[] a)
{
foreach (int bob in a)
{
if ((close_num -= bob) <= 0)
return bob;
}
return -1;
}
Console.WriteLine("Enter a number to find out if is in the selected Net File: ");
int i3 = Convert.ToInt32(Console.ReadLine());
bool checker = false;
//Single nearest = 0;
//linear search#1
for (int i = 0; i < a.Length; i++)//looping through array
{
if(a[i] == i3)//checking to see the value is found in the array
{
Console.WriteLine("Value found and the position of it in the descending value of the selected Net File is: " + a[i]);
checker = true;
}
else
{
int found = nearest(i3,a);
Console.WriteLine("Cannot find this number in the Net File however here the closest number to that: " + found );
//Console.WriteLine("Cannot find this number in the Net File however here the closest number to that : " + nearest);
}
}
When a value that is in the file is entered the output is fine , but when it comes to the nearest value I cannot figure a way. I can't use this such as BinarySearchArray for this. a = the array whilst i3 is the value the user has entered. Would a binary search algorithm just be simpler for this?
Any help would be appreciated.
You need to make a pass over all the elements of the array, comparing each one in turn to find the smallest difference. At the same time, keep a note of the current nearest value.
There are many ways to do this; here's a fairly simple one:
static int nearest(int close_num, int[] a)
{
int result = -1;
long smallestDelta = long.MaxValue;
foreach (int bob in a)
{
long delta = (bob > close_num) ? (bob - close_num) : (close_num - bob);
if (delta < smallestDelta)
{
smallestDelta = delta;
result = bob;
}
}
return result;
}
Note that delta is calculated so that it is the absolute value of the difference.
Well, first we should define, what is nearest. Assuming that,
int nearest for given int number is the item of int[] a such that Math.Abs(nearest - number) is the smallest possible value
we can put it as
static int nearest(int number, int[] a)
{
long diff = -1;
int result = 0;
foreach (int item in a)
{
// actual = Math.Abs((long)item - number);
long actual = (long)item - number;
if (actual < 0)
actual = -actual;
// if item is the very first value or better than result
if (diff < 0 || actual < diff) {
result = item;
diff = actual;
}
}
return result;
}
The only tricky part is long for diff: it may appear that item - number exceeds int range (and will either have IntegerOverflow exceprion thrown or *invalid answer), e.g.
int[] a = new int[] {int.MaxValue, int.MaxValue - 1};
Console.Write(nearest(int.MinValue, a));
Note, that expected result is 2147483646, not 2147483647
what about LINQ ?
var nearestNumber = a.OrderBy(x => Math.Abs(x - i3)).First();
Just iterate through massive and find the minimal delta between close_num and array members
static int nearest(int close_num, int[] a)
{
// initialize as big number, 1000 just an example
int min_delta=1000;
int result=-1;
foreach (int bob in a)
{
if (Math.Abs(bob-close_num) <= min_delta)
{
min_delta = bob-close_num;
result = bob;
}
}
return result;
}

How to optimize a loops going through arrays?

I've been going though www.testdome.com to test my skills and opened a list of public questions. One of the practice questions was:
Implement function CountNumbers that accepts a sorted array of
integers and counts the number of array elements that are less than
the parameter lessThan.
For example, SortedSearch.CountNumbers(new int[] { 1, 3, 5, 7 }, 4)
should return 2 because there are two array elements less than 4.
And my answer was:
using System;
public class SortedSearch
{
public static int CountNumbers(int[] sortedArray, int lessThan)
{
int count = 0;
int l = sortedArray.Length;
for (int i = 0; i < l; i++) {
if (sortedArray [i] < lessThan)
count++;
}
return count;
}
public static void Main(string[] args)
{
Console.WriteLine(SortedSearch.CountNumbers(new int[] { 1, 3, 5, 7 }, 4));
}
}
It seems that I've failed on two counts:
Performance test when sortedArray contains lessThan: Time limit exceeded
and
Performance test when sortedArray doesn't contain lessThan: Time limit exceeded
To be honest I'm not sure what to optimize there? Maybe I'm using a wrong method and there is a similar way to speed up the calculation?
If someone could point out my mistake or explain what I'm going wrong, I'd really appreciate it!
Because the array is sorted, you can stop counting as soon as you reach or exceed the lessThan parameter.
else break would probably do it.
Does it have to be really a loop? You could do Lambda exp for that
public static int CountNumbers(int[] sortedArray, int lessThan)
{
return sortedArray.ToList().Where(x=>x < lessThan).Count();
}
Harold's answer and approach is spot on.
Find below another code sample in case you're practicing for technical interviews. It handles cases when the array is null or empty, when lessThan is presented in the array (including duplicates), etc.
private static int CountNumbers(int[] sortedArray, int lessThan)
{
if (sortedArray == null)
{
throw new ArgumentNullException("Sorted array cannot be null.");
}
if (sortedArray.Length == 0)
{
throw new ArgumentException("Sorted array cannot be empty.");
}
int start = 0;
int end = sortedArray.Length;
int middle = int.MinValue;
while (start < end)
{
middle = (start + end) / 2;
if (sortedArray[middle] == lessThan)
{
break; // Found the "lessThan" number in the array, we can stop and move left
}
else if (sortedArray[middle] < lessThan)
{
start = middle + 1;
}
else
{
end = middle - 1;
}
}
// Adjust the middle pointer based on the "current" and "lessThan" numbers in the sorted array
while (middle >= 0 && sortedArray[middle] >= lessThan)
{
middle--;
}
// +1 because middle is calculated through 0-based (e.g. start)
return middle + 1;
}

comparing strings, one from an array other from an entered value

Basically comparing a string that is entered, and trying to get that position from the array.
If I initialize position to 0 then it returns the position zero of the array, if I initialize to 1 then it gives me the item in slot 1, so it's skipping the compare statement.
I also tried using (custStatus == cardStatus[i])
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
int position= 0;
int discount;
for(int i = 0; i < 2; i++)
{
if (string.Equals(custStatus, cardStatus[i]))
position = i;
}
discount = pDiscount[position];
return discount;
}
With your code, there's no way to tell if position = 0 means custStatus was found in your cardStatus array or if no match was made at all and the default value is being used. I'd recommend either using a boolean matchFound variable or setting position = -1 and adding an extra if statement at the end either way. Either:
boolean matchFound = false;
...
if(matchFound)
{
discount = pDiscount[position];
}
or else
int position = -1;
...
if(position >= 0)
{
discount = pDiscount[position];
}
Give this a try:
public static int discount(string[] cardStatus, int[] pDiscount, string custStatus) {
var position = Array.IndexOf(cardStatus, custStatus);
return (position == -1) ? -1 : pDiscount[position];
}
public static int discount(string []cardStatus, int []pDiscount, string custStatus)
{
for(int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length); i++)
{
if (string.Equals(custStatus, cardStatus[i]))
{
return pDiscount[i];
}
}
return -1;
}
Don't be afraid to return directly from FOR-loop, it is old-school that teaches to have only one return point from method. You can have as many returns as it helps you to keep your code clean and easy to read.
And perhaps it would be better to use the following expression in for-loop as it will guard you from possible different lengths of arrays:
for (int i = 0; i < Math.Min(cardStatus.Length, pDiscount.Length; i++)
This looks ok, even though this is somewhat more straightforward:
for(int i = 0; i < cardStatus.Length; i++)
{
if (custStatus == cardStatus[i])
{
position = i;
break;
}
}
Given your question it appears to be the case that all cardStatus[i] match custStatus - did you check the input?
Also given your code what happens if there is no match? Currently you would return pDiscount[0] - that doesn't seem to be correct.

Categories

Resources