Problem with going to the next item in a list - c#

The following pertains to C#
there are 4 lists:
INRHolidays list: Contains all the holidays and weekends
CashFlowDates: Containing all the dates for 10 years from today
CashFlowDatesFinal: Containing all the dates in CashFlowdates except the INRHolidays
TenorDates: Containing some specific dates i.e 6m, 9m, 12m, 1y, 2y, 3y, 4y, 5y, 7y, and 10y from now.
Now I want to check whether these specific dates in the TenorDates are Holidays or not. If not then they should be directly added to new list, HolidayAdjustedTenorDates, otherwise the next working day from CashFlowDates should be added.
20 is just a number as I didn't understand how to put the boundary condition.
var HolidayAdjustedTenorDates = new List<string>();
foreach (var a in TenorDates)
{
if (CashFlowDatesFinal.Contains(a))
{
HolidayAdjustedTenorDates.Add(a);
}
else
{
for (var i = 1; i < 20; i++)
{
if(CashFlowDatesFinal.Contains(
Convert.ToDateTime(a).AddDays(i).ToShortDateString()))
{
HolidayAdjustedTenorDates.Add(
Convert.ToDateTime(a).AddDays(i).ToShortDateString());
}
}
}
}

What is the exact problem, that you are not getting the right date or that you don't know how to write the loop, to put the boundary condition?
You may try a while loop:
int i = 1;
while(!CashFlowDatesFinal.Contains(Convert.ToDateTime(a).AddDays(i).ToShortDateString()))
{
i++;
}
HolidayAdjustedTenorDates.Add(Convert.ToDateTime(a).AddDays(i).ToShortDateString();

I cannot place a comment so sorry to post an answer but :
1-you should really improve your code. C# is a strong typed language, so avoid to use var, but use the real type instead
2-don't work directly on a, use temporarily variables.
This done, you could avoid mistakes and you can facilitate debugging.
For example, in your code, if CashFlowDatesFinal contains DateTime, you don't have to compare with string (made by ToShortDateString())

Related

Generating a variable number of random numbers to a list, then comparing those numbers to a target?

How would I go about generating a serializable variable of random numbers to a list, then comparing those generated numbers to a target number?
What I want to do is make a program that takes in a number, such as 42, and generates that number of random numbers to a list while still keeping the original variable, in this case 42, to be referenced later. Super ham-handed pseudo-code(?) example:
public class Generate {
[SerializeField]
int generate = 42;
List<int> results = new List<int>;
public void Example() {
int useGenerate = generate;
//Incoming pseudo-code (rather, code that I don't know how to do, exactly)
while (useGenerate => 1) {
results.add (random.range(0,100)); //Does this make a number between 0 and 99?
int useGenerate = useGenerate - 1;
}
}
}
I think this will do something to that effect, once I figure out how to actually code it properly (Still learning).
From there, I'd like to compare the list of results to a target number, to see how many of them pass a certain threshold, in this case greater than or equal to 50. I assume this would require a "foreach" thingamabobber, but I'm not sure how to go about doing that, really. With each "success", I'd like to increment a variable to be returned at a later point. I guess something like this:
int success = 50;
int target = 0;
foreach int in List<results> {
if (int => success) {
int target = target + 1;
}
}
If I have the right idea, please just teach me how to properly code it. If you have any suggestions on how to improve it (like the whole ++ and -- thing I see here and there but don't know how to use), please teach me that, too. I looked around the web for using foreach with lists and it seemed really complicated and people were seemingly pulling some new bit of information from the Aether to include in the operation. Thanks for reading, and thanks in advance for any advice!

Find the closest previous DateTime from a list of DateTime

Is there a faster way of obtaining the closest previous (past) DateTime from a list of DateTimes when compared to a specific time? (the list comes from a SQL database)
public DateTime GetClosestPreviousDateTime(List<DateTime> dateTimes, DateTime specificTime)
{
DateTime ret = null;
var lowestDifference = TimeSpan.MaxValue;
foreach (var date in dateTimes)
{
if (date >= specificTime)
continue;
var difference = specificTime- date;
if (difference < lowestDifference)
{
lowestDifference = difference;
ret = date;
}
}
return ret;
}
The source list will be sorted since the dates in the list come from a SQL database where they are written consecutively.
It depends what you mean by "faster". The algorithm you show is O(N) so no you won't get faster than that - if by faster you mean is there a way to not have to iterate over all dates.
But if you mean can you shave off a few microseconds with some code that doesn't emit quite as many op codes, then yes of course. But is that really the issue here?
The answer will also change based on the size of the list, how accurate you need the answer to be, whether we can make any assumptions on the data (e.g. is it already sorted).
dateTimes.Sort();
var closest = dateTimes[dateTimes.IndexOf(search) - 1];
Your problem is a classic search algorithm and binary search might suit you.
Sort list: dateTimes.Sort();
Apply Binary Search algo with similar logic as in your for statement.
dateTimes.Where(x => x < specificTime).Max()
or if you want to handle the case where none exist:
dateTimes.Where(x => x < specificTime).DefaultIfEmpty().Max()
Later edit: Now you introduce new information that the List<> is already sorted. That was not in the question before.
With a sorted List<>, your algorithm is silly since it foreaches on and on, even after having reached the point where the entries "pass" the threshold specificTime. You can use instead BinarySearch (assuming List<> is sorted in ascending order and contains no duplicates):
static DateTime GetClosestPreviousDateTime(List<DateTime> dateTimes, DateTime specificTime)
{
var search = dateTimes.BinarySearch(specificTime);
var index = (search < 0 ? ~search : search) - 1;
if (index == -1)
throw new InvalidOperationException("Not found");
return dateTimes[index];
}
If you want to do it faster, just ask the database for the value, it will know how to find the answer fast; do not fetch the entire List<> to memory first. Use SQL or LINQ to the database.

C# Sudoku puzzle solver gets stuck while trying to backtrack to avoid bad values

I'm trying to get better at understanding recursion and I'm working on a program that is supposed to solve Sudoku puzzles by iterating over each cell in the puzzle and trying a value out of a list of possible values. After it drops in a value, it checks if doing so has solved the puzzle. If not, it continues on adding values and checking if doing so has solved the puzzle. There's a problem, though - I can see in my app's GUI that it eventually gets confused or stuck and starts attempting the same value insertion over and over. For example, here's an example of some logging that shows it being stuck:
Possible values: F
Old string: 086251B7D93+++C4
New string: 086251B7D93F++C4
As you can see, it's looking to see what value could possibly go into the cell after the 3 without violating the row, column, or box constraints. The only possible value is F, so it places it in there. But then it does the same thing over and over, and randomly starts attempting to edit other cells in other lines even though there are still +'s in this first row. It'll try to edit a row a few rows down, and it'll swap between doing that and then attempting this same scenario with the F repeatedly until the app crashes because of what Visual Studio thinks is a ContextSwitchDeadlock error.
What have I missed in my algorithm? Here is my method that tries to fill in the Sudoku puzzle:
public bool SolveGrid(List<Row> rows, List<Box> boxes)
{
textBox1.Clear()
foreach (var row in rows)
{
textBox1.AppendText(row.content + "\n");
}
if (ValidatorAgent.IsGridSolved(rows, boxes))
{
textBox2.AppendText("Success!");
successGrid = rows;
return true;
}
foreach (var row in rows)
{
foreach (var cell in row.content)
{
if (cell.Equals('+'))
{
var possibleValues = availableValues.Where(v => !ValidatorAgent.AreGridConstraintsBreached(cell, v, row, rows, boxes)).ToList();
if (!possibleValues.Any())
{
return false;
}
Console.WriteLine("Possible values: ");
possibleValues.ForEach(v => Console.Write(v.ToString()));
List<char> values = new List<char>();
possibleValues.ForEach(v => values.Add(v));
foreach (var possibleValue in values)
{
var oldContent = row.content;
var stringBuilder = new StringBuilder(row.content);
var indexToChange = row.content.IndexOf(cell);
stringBuilder[indexToChange] = possibleValue;
Console.WriteLine("Old string: " + oldContent);
Console.WriteLine("New string: " + stringBuilder.ToString());
var alteredPuzzle = BuilderAgent.BuildPuzzleCopy(rows);
alteredPuzzle.Single(r => r.yCoord == row.yCoord).content = stringBuilder.ToString();
var newBoxes = BuilderAgent.BuildBoxes(alteredPuzzle);
SolveGrid(alteredPuzzle, newBoxes);
}
}
}
}
return false;
}
I am pretty confident that my IsGridSolved method works correctly because I've tested it on puzzle solutions and found that it reported whether or not a puzzle was already solved. I've also tested my AreGridConstraintsBreached method with unit tests and also by eyeballing the results of the code, so I'm fairly confident in that code. It basically checks whether or not a cell's potential value is redundant due to the relevant row, column, or box already having that value. In Sudoku, when you place a value you need to make sure that the value 1) doesn't already exist in the row 2) doesn't already exist in the column and 3) doesn't already exist in the small box surrounding the cell. I feel like I'm missing something obvious in the algorithm itself, and that it isn't backtracking properly. I've tried fiddling with the SolveGrid method so that it takes in a list of validValues that are based off of the availableValues, with some pruning so that failed values are pruned out after each recursive call to SolveGrid but that didn't do anything besides keep the puzzle from even getting as far as it currently does. Any tips would be appreciated.

Better algorithm for a date comparison task

I would like some help making this comparison faster (sample below). The sample take each value in an array, attach an hour to a comparison-variable. If no matching value, it's add the value to a second array (which are concatenated later).
if (ticks.TypeOf == Period.Hour)
while (compareAt <= endAt)
{
if (range.Where(d => d.time.AddMinutes(-d.time.Minute) == compareAt).Count() < 1)
gaps.Add(new SomeValue() {
...some dummy values.. });
compareAt = compareAt.AddTicks(ticks.Ticks);
}
This execution is too consuming when came to i.e. hours. There are 365 * 24 = 8760 values at most in this array. In future, there will also be minutes/seconds per month 60*24*31=44640, which means unusable.
If the array most often was complete (which means no gaps/empty slots), it could easily be by-passed with if (range.Count() == (hours/day * days)). Though, that day will not be today.
How would I solve it more effective?
One example: If ther are 7800 values in the array, we miss about 950, right? But can I find just the gaps-endings, and just create the missing values? That would make the o-notation depend on amount of gaps, not the amount of values..
One other welcome answer is just an more effective loop.
[Edit]
Sorry for bad english, I try my best to describe.
Your performance is low because the range lookup is not using any indexing and rechecks the entire range every time.
One way to do this a lot quicker;
if (ticks.TypeOf == Period.Hour)
{
// fill a hashset with the range's unique hourly values
var rangehs = new HashSet<DateTime>();
foreach (var r in range)
{
rangehs.Add(r.time.AddMinutes(-r.time.Minute));
}
// walk all the hours
while (compareAt <= endAt)
{
// quickly check if it's a gap
if (!rangehs.Contains(compareAt))
gaps.Add(new SomeValue() { ...some dummy values..});
compareAt = compareAt.AddTicks(ticks.Ticks);
}
}

Fastest way to check a List<T> for a date

I have a list of dates that a machine has worked on, but it doesn't include a date that machine was down. I need to create a list of days worked and not worked. I am not sure of the best way to do this. I have started by incrementing through all the days of a range and checking to see if the date is in the list by iterating through the entire list each time. I am looking for a more efficient means of finding the dates.
class machineday
{
datetime WorkingDay;
}
class machinedaycollection : List<machineday>
{
public List<TimeCatEvent> GetAllByCat(string cat)
{
_CategoryCode = cat;
List<machineday> li = this.FindAll(delegate(machinedaydummy) { return true; });
li.Sort(sortDate);
return li;
}
int sortDate(machinedayevent1, machinedayevent2)
{
int returnValue = -1;
if (event2.date < event1.date)
{
returnValue = 0;
}
else if (event2.date == event1.date)
{
//descending
returnValue = event1.date.CompareTo(event2.date);
}
return returnValue;
}
}
Sort the dates and iterate the resulting list in parallel to incrementing a counter. Whenever the counter does not match the current list element, you've found a date missing in the list.
List<DateTime> days = ...;
days.Sort();
DateTime dt = days[0].Date;
for (int i = 0; i < days.Length; dt = dt.AddDays(1))
{
if (dt == days[i].Date)
{
Console.WriteLine("Worked: {0}", dt);
i++;
}
else
{
Console.WriteLine("Not Worked: {0}", dt);
}
}
(This assumes there are no duplicate days in the list.)
Build a list of valid dates and subtract your machine day collection from it using LINQ's Enumerable.Except extension method. Something like this:
IEnumerable<DateTime> dates = get_candidate_dates();
var holidays = dates.Except(machinedays.Select(m => m.WorkingDay));
The get_candidate_dates() method could even be an iterator that generates all dates within a range on the fly, rather than a pre-stored list of all dates.
Enumerable's methods are reasonably smart and will usually do a decent job on the performance side of things, but if you want the fastest possible algorithm, it will depend on how you plan to consume the result.
Sorry dudes, but I do not pretty much like your solutions.
I think you should create a HashTable with your dates. You can do this by interating only once the working days.
Then, you interate the full range of of days and for every one you query in the hashtable if the date is there or not, by using
myHashTable.ContainsKey(day); // this is efficient
Simple, elegant and fast.
I think your solution uses an exponencial time, this one is lineal or logarithmical (which is actually a good thing).
Assuming the list is sorted and the machine was "working" most of the time, you may be able to avoid iterating through all the dates by grouping the dates by month and skipping the dates in between. Something like this (you'll need to clean up):
int chunksize = 60; // adjust depending on data
machineday currentDay = myMachinedaycollection[0];
for (int i = 0; i < myMachinedaycollection.Count; i += chunksize)
{
if (currentDay.WorkingDay.AddDays(chunksize) != myMachinedaycollection[i + chunksize].WorkingDay)
{
// write code to iterate through current chunk and get all the non-working days
}
currentDay = myMachinedaycollection[i + chunksize];
}
I doubt you want a list of days working and not working.
Your question title suggests that you want to know whether the system was up on a particular date. It also seems reasonable to calculate % uptime. Neither of these requires building a list of all time instants in the interval.
Sort the service times. For the first question, do BinarySearch for the date you care about and check whether the preceding entry was the system being taken offline of maintenance or put back into service. For % uptime, take the (down for maintenance, service restored) pair-wise, use subtraction to find the duration of maintenance, add these up. Then use subtraction to find the length of the total interval.
If your question didn't actually mean you were keeping track of maintenance intervals (or equivalently usage intervals) then you can ignore this answer.

Categories