Find missed elements in array of numbers - c#

I have array with numbers 1...31 (days at month)
On my side I would like to find all missed numbers.
This my solution but I not sure that is a good way.
var result = new List<int>();
int[] days = GetSelectedDays(); //I recive array with 1..31 with some missing elements sometimes (without "5" as example it depends if user has selected this number)
for (int i=0; i <30; i++)
{
if (!days.Contains(i))
result.Add(i);
}

You can use LINQ Except:
var result = Enumerable.Range(1, 31).Except(days);

Looks like you are currently checking numbers in the range 0..29 as opposed to 1..31. The only suggestion I have is to change the for loop to:
for (int i=1; i <= 31; i++)

First off, when you're adding days of a month its probably easier to loop through a loop of DateTimes, i.e.
var missedDateDictionary = new Dictionary<DateTime, bool>(); // or other value
var date = new DateTime(2016, 01, 01);
for (int i = 0 ; i < 32 ; i++)
{
var newDate = date.AddDays(i);
//do something with adding / not adding date
if (notDoneSomething)
missedDateDictionary.Add(newDate, true)
}
The premise here is that each DateTime you're adding is unique.
If you cant guarantee that, your solution is pretty efficient but could use some optimization.
Initialize arary with max value: int[31] days = GetSelectedDays();
A month can have 31 days: for (int i = 1; i <32; i++)
If at all possible, fill result in the loop you're filling GetSelecteDays()

Related

Lowest date from list after remove below DateTime.Now?

Hey I want to find the lowest date after DateTime.Now from my saved times. My Idea was to add them all to a list then delete all 'DateTimes' from the list which are lower than the actual time to then find the lowest date in the list.
The way I approached it doesnt work and I dont really understand why..
Here's my code:
List<DateTime> list = new List<DateTime>() {
Convert.ToDateTime(search.ReadConfig("somedate1")),
Convert.ToDateTime(search.ReadConfig("somedate2")),
Convert.ToDateTime(search.ReadConfig("somedate3")),
Convert.ToDateTime(search.ReadConfig("somedate5"))};
DateTime dtnow = DateTime.Now;
for(int kk = 0; kk < list.Count; kk++){
if(list[kk] < dtnow){ list.RemoveAt(kk); }
}
DateTime smallestDate = list.Min();
label2.Text = smallestDate.ToString();
It doesnt remove the times older than now and I wasnt able to find something which fits my problem over google.
I would appreciate any help!
Try Where() clause,
Filters a sequence of values based on a predicate.
//Here you have to use Greater than equal operator.
var minDate = list.Where(x => x >= DateTime.Now).Min().ToString();
Console.WriteLine(minDate);

How to make a one dimensional array to display multiples of seven

I am attempting to code a one dimensional array to display code allowing me to display multiples of seven, I'm not sure how to go through with this, thank you.
I hope I understood your question. You can use generate multiples of 7 using Linq as follows.
var result = Enumerable.Range(1, 100).Select(x => x * 7).ToArray();
Enumerable.Range allows you to generate a sequence of values in specified range (First parameter is the first number in sequence, the second parameter is number of items), while the Select statement (x=>x*7, multiply each value in generated sequence with 7) ensures you get the multiples of 7.
Complete Code:
var result = Enumerable.Range(1, 100).Select(x => x * 7).ToArray();
foreach (var item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
Due to the vagueness of the question, my answer may not be applicable, but I will attempt to answer based on my assumption of what you are asking.
If you have an array of int and you want to multiply the values of the individual array objects, you would do something like this:
int[] myArray= { 3,5,8};
for (int i = 0; i < myArray.Length; i++)
{
Console.WriteLine(myArray[i]*7);
}
//outputs 21,35,56
If you want to multiply based on the index of the array object, you would do it like this:
int[] myArray= { 3,5,8};
for (int i = 0; i < myArray.Length; i++)
{
Console.WriteLine(i*7);
}
//outputs 0,7,14
//or if you need to start with an index of 1 instead of 0
int[] myArray= { 3,5,8};
for (int i = 0; i < myArray.Length; i++)
{
Console.WriteLine((i+1)*7);
}
//outputs 7,14,21
Anu Viswan also has a good answer, but depending on what it is you are trying to do, it may be better to rely on loops. Hope my answer helps.

How to get count of numbers in int and how to split a number without making a string

I have a number like 601511616
If all number's length is multiple of 3, how can a split the number into an array without making a string
Also, how can I count numbers in the int without making a string?
Edit: Is there a way to simply split the number, knowing it's always in a multiple of 3... good output should look like this: {616,511,601}
You can use i % 10 in order to get the last digit of integer.
Then, you can use division by 10 for removing the last digit.
1234567 % 10 = 7
1234567 / 10 = 123456
Here is the code sample:
int value = 601511616;
List<int> digits = new List<int>();
while (value > 0)
{
digits.Add(value % 10);
value /= 10;
}
// digits is [6,1,6,1,1,5,1,0,6] now
digits.Reverse(); // Values has been inserted from least significant to the most
// digits is [6,0,1,5,1,1,6,1,6] now
Console.WriteLine("Count of digits: {0}", digits.Count); // Outputs "9"
for (int i = 0; i < digits.Count; i++) // Outputs "601,511,616"
{
Console.Write("{0}", digits[i]);
if (i > 0 && i % 3 == 0) Console.Write(","); // Insert comma after every 3 digits
}
IDEOne working demonstration of List and division approach.
Actually, if you don't need to split it up but only need to output in 3-digit groups, then there is a very convenient and proper way to do this with formatting.
It will work as well :)
int value = 601511616;
Console.WriteLine("{0:N0}", value); // 601,511,616
Console.WriteLine("{0:N2}", value); // 601,511,616.00
IDEOne working demonstration of formatting approach.
I can't understand your question regarding how to split a number into an array without making a string - sorry. But I can understand the question about getting the count of numbers in an int.
Here's your answer to that question.
Math.Floor(Math.Log10(601511616) + 1) = 9
Edit:
Here's the answer to your first question..
var n = 601511616;
var nArray = new int[3];
for (int i = 0, numMod = n; i < 3; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Please keep in mind there's no safety in this operation.
Edit#3
Still not perfect, but a better example.
var n = 601511616;
var nLength = (int)Math.Floor(Math.Log10(n) + 1)/ 3;
var nArray = new int[nLength];
for (int i = 0, numMod = n; i < nLength; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Edit#3:
IDEOne example http://ideone.com/SSz3Ni
the output is exactly as the edit approved by the poster suggested.
{ 616, 511, 601 }
Using Log10 to calculate the number of digits is easy, but it involves floating-point operations which is very slow and sometimes incorrect due to rounding errors. You can use this way without calculating the value size first. It doesn't care if the number of digits is a multiple of 3 or not.
int value = 601511616;
List<int> list = new List<int>();
while (value > 0) // main part to split the number
{
int t = value % 1000;
value /= 1000;
list.Add(t);
}
// Convert back to an array only if it's necessary, otherwise use List<T> directly
int[] splitted = list.ToArray();
This will store the splitted numbers in reverse order, i.e. 601511616 will become {616, 511, 601}. If you want the numbers in original order, simply iterate the array backwards. Alternatively use Array.Reverse or a Stack
Since you already know they are in multiples of 3, you can just use the extracting each digit method but use 1000 instead of 10. Here is the example
a = 601511616
b = []
while(a):
b.append(a%1000)
a = a//1000
print(b)
#[616, 511, 601]

How to improve my FindDuplicate classic algorithm

I have classic find duplicate algorithm like this:
int n = int.Parse(Console.ReadLine());
Console.WriteLine();
List<int> tempArr = new List<int>();
List<int> array = new List<int>();
for (int i = 0; i < n; i++)
{
Console.Write("input number {0}: ", i + 1);
tempArr.Add(int.Parse(Console.ReadLine()));
}
tempArr.Sort();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
if (tempArr[i] == tempArr[j])
{
array.Add(tempArr[i]);
}
}
}
Everything work's okay, but if i have just two duplicate numbers like (1,2,2,3,4,5) how can i add them both to List<int> **array** with one clean shot at the loop ?
Instead of lists you could use some kind of data structure that have a better search capability (hash tables or binary trees, for example). Even if you have just one duplicate, the problem is that you need to check if you have already added the element in the list, so the key operation in your algorithm is the search. The faster you perform the search, the faster the algorithm will be. Using binary search, which is the fastest way to search, you get O(nlogn) (you perform n searches of O(logn)).
An even better way to do this is to have some kind of array that has the same size as your input range and "tick" each value that you already have. This search runs in constant time, but gets inefficient if you have a large range of input.
You can use distinct:
array = tempArr.Distinct().ToList();
Distinct isn't in linear time, if that's what you're looking for ("one clean shot"). If you know more about the input you might be able to find a way to do this in linear time. For example, if you know if the integers you take are in a certain range.
To extract all the duplicates you can use Linq:
List<int> tempList = new List<int>() { 1, 2, 2, 3, 4, 5 };
// array == [2, 2]
List<int> array = tempList
.GroupBy(x => x)
.Where(x => x.Count() > 1)
.SelectMany(x => Enumerable.Repeat(x.Key, x.Count()))
.ToList();

Calculate number of hours filtered by jobNum

I'm creating a string[] array from an xml file that lists every job number assigned to a time keeping application. I can successfully return string[] from the xml files. I'm trying to match the array for time with the array position for job num and I'm having difficulty. I'm hoping someone here has the paitience to help and/or direct a NEWB to good information already displayed somewhere.
Here is what I have so far. I just can't seem to sew them together. Get Max occurrences of a job number.
public static string totalHoursbyJob()
{
int count = 0;
if (jobNum.Length > count)
{
var items = jobNum.Distinct();
count = items.Count();
foreach (string value in items)
{
string[,] itemArr = new string[count, Convert.ToInt32(jobNum)];
}
}
}
This gets the time component and calculates the values, but it does not filter by job number. It accurately calculates the values found in the .innerText of the nodes in the xml file.
for (i = 0; i < ticks.Length; i++)
{
ticksInt = double.Parse(ticks[i]);
if (ticksInt > 1)
{
double small = ((((ticksInt / 10000) / 1000) / 60) / 60);
sum2 += small;
}
}
Can somebody please point me to what I'm doing wrong here? Thank you in advance. I really appreciate you stopping by to look and help. :-D Have a Great Day
EDIT1 Cleared an error!! Yay
EDIT2 Thank you user910683. I removed the code that does nothing at the moment and modified the code that creates the comparative array. Please see next.
if (jobNum.Length > count)
{
string[] items = jobNum.Distinct().ToArray();//This change made to clear
//error at items.length below
count = items.Count();
//itemArr.Join(++items);
foreach (string value in items)
{
string[,] itemArr = new string[count, items.Length];
}
}
for (jn = 0; jn < jobNum.Length; jn++)
{
string test = jobNum.ToString();
}
You seem to have a logic error here. You're not using jn within the loop, so each time the loop is executed you're setting test to jobNum.ToString(). You're doing the same thing over and over again, and you're not using the 'test' string for anything. Is this what you want?
Also, consider this line from the previous block:
string[,] itemArr = new string[count, Convert.ToInt32(jobNum)];
You have removed the exception here by converting jobNum to an Int32, but is this what you want? I would guess that you actually want the number of strings in jobNum, in which case you should use jobNum.Length.
UPDATE
I think I have a better sense of what you want now. Do you want a multidimensional array matching a job number string to the amount of time spent on that job? If so, change:
foreach (string value in items)
{
string[,] itemArr = new string[count, Convert.ToInt32(jobNum)];
}
to something like:
string[,] itemArr = new string[count, 2];
var items = jobNum.Distinct();
for(int x=0; x<items.Count, x++)
{
itemArr[x][0] = items[x];
}
}
Then with the ticks, change the ticks conversion from this:
double small = ((((ticksInt / 10000) / 1000) / 60) / 60);
sum2 += small;
to something like:
sum2 += TimeSpan.FromTicks(ticks[i]).TotalHours;
I'd have to see the declaration and initialisation of jobNum and ticks to explain how to put sum2 into your job/time array.
You might consider using something like XmlSerializer instead, it seems like you're doing a lot of manual work with your XML-derived data, you might be able to simplify it for yourself.

Categories