How to assign a variable using 3 arrays in C# - c#

I am trying to write an add-in for a finite element geology piece of software.
I have three arrays which are essentially a coordinate system. I want to assign a value to a variable depending on its position in the grid system. Basically I want to say if my node is within an x range and a y range, then my aquifer thickness at this node is this value. So far I have this.
//create an array of xcoords of data points:
double[] xcoord = new double[11] {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
//create an array of ycoords of data points:
double[] ycoord = new double[11] {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
//create an array of aquifer thickness
double[] aquiferThicknessPoints = new double[121]
{
10, 10, 12, 13, 12, 15, 14, 15, 14, 13, 13,
10, 10, 13, 15, 16, 14, 13, 15, 16, 12, 13,
12, 14, 15, 18, 19, 17, 14, 15, 18, 14, 14,
13, 14, 15, 18, 20, 17, 15, 17, 18, 15, 15,
14, 15, 17, 18, 21, 17, 18, 18, 19, 17, 16,
15, 15, 17, 17, 20, 21, 21, 19, 19, 18, 18,
15, 15, 17, 20, 20, 21, 22, 21, 19, 19, 19,
16, 17, 19, 20, 22, 23, 22, 21, 20, 20, 20,
17, 18, 20, 22, 23, 24, 24, 23, 22, 20, 21,
18, 19, 21, 22, 24, 25, 24, 23, 22, 22, 22,
19, 19, 22, 22, 24, 25, 25, 23, 23, 22, 23,
};
dataPointSpacingHalf = dataPointSpacing / 2;
for (int i = 0; i < xcoord.Length; i++)
{
for (int j = 0; j < ycoord.Length; j++)
{
if (nodeX >= (xcoord[i] - dataPointSpacingHalf) && (nodeX < (xcoord[i] + dataPointSpacingHalf)) && (nodeY >= (ycoord[j] - dataPointSpacingHalf) && (nodeY < (ycoord[j] + dataPointSpacingHalf))))
{
aquiferThickness = aquiferThicknessPoints[?];
}
}
}
I can see how the nested for loops will loop through 110 times, but i don't know how to assign my aquifer thickness from my array to each loop.
I open to any way of solving this problem as I'm very new new to programming and am still not sure which is the best way to achieve things.

Just use i * xcoord.Length + j insted of ?
Here is the code:
for (int i = 0; i < xcoord.Length; i++)
{
for (int j = 0; j < ycoord.Length; j++)
{
//Here is the magic!
//without considering coordinates
//aquiferThickness[i, j] = aquiferThicknessPoints[i * xcoord.Length + j];
//considering coordinates
aquiferThickness[i, j] =
aquiferThicknessPoints[
CoordToIndex(xNode,indexedCoords) * xcoord.Length +
CoordToIndex(yNode,indexedCoords)];
}
}
Also to consider the xNode, yNode coordinate, you can take this approach
Dictionary<int, double> indexedCoords = new Dictionary<int, double> { { 0, 0 }, { 1, 5 }, { 2, 10 }, .... };
int CoordToIndex(double node, Dictionary<int, double> indexedCoords)
{
return indexedCoords.First(i => i.Value > node).Key;
}

You want to use a two-dimensional array for your aquiferThicknessPoints:
double[,] aquiferThicknessPoints = new double[,]
{
{10, 10, 12, 13, 12, 15, 14, 15, 14, 13, 13},
{10, 10, 13, 15, 16, 14, 13, 15, 16, 12, 13},
{12, 14, 15, 18, 19, 17, 14, 15, 18, 14, 14},
{13, 14, 15, 18, 20, 17, 15, 17, 18, 15, 15},
// the rest
};
You can then address the data using the two coordinates:
aquiferThickness = aquiferThicknessPoints[j, i];
(or i, j, it's not obvious how your data is organized)

Related

Search missing numbers in sequence

Suppose I have the following array (my sequences are all sorted in ascending order, and contain positive integers)
var tabSequence = new[] { 1, 2, 3, 7, 8, 9, 12, 15, 16, 17, 22, 23, 32 };
I made a code using LINQ and a loop to search missing numbers like that :
List<Int32> lstSearch = new List<int>();
var lstGroup = tabSequence
.Select((val, ind) => new { val, group = val - ind })
.GroupBy(v => v.group, v => v.val)
.Select(group => new{ GroupNumber = group.Key, Min = group.Min(), Max = group.Max() }).ToList();
for (int number = 0; number < lstGroup.Count; number++)
{
if (number < lstGroup.Count-1)
{
for (int missingNumber = lstGroup[number].Max+1; missingNumber < lstGroup[number+1].Min; missingNumber++)
lstSearch.Add(missingNumber);
}
}
var tabSequence2 = lstSearch.ToArray();
// Same result as var tabSequence2 = new[] {4, 5, 6, 10, 11, 13, 14, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, 31 };
This code works but i'd like to know if there a better way to do the same thing only with linq.
Maybe I am just not understanding the problem. Your code seems very complicated, you could make this a lot simpler:
int[] tabSequence = new[] { 1, 2, 3, 7, 8, 9, 12, 15, 16, 17, 22, 23, 32 };
var results = Enumerable.Range(1, tabSequence.Max()).Except(tabSequence);
//results is: 4, 5, 6, 10, 11, 13, 14, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, 31
I made a fiddle here
You can use IEnumerable.Aggregate to your advantage. The overload I choose uses an accumulator seed (empty List<IEnumerable<int>>) and proceeds to iterate over each item in your array.
The first time I set an lastNR defined before using the aggregate to the firsst number we iterate over. We compare the nexts iterations actual nr against this lastNr.
If we are in sequence we just increment the lastNr.
If not, we generate the missing numbers via Enumerable.Range(a,count) between lastNr
and the actual nr and add them to our accumulator-List. Then we set the lastNr to nr to continue.
public static List<IEnumerable<int>> GetMissingSeq(int[] seq)
{
var lastNr = int.MinValue;
var missing = seq.Aggregate(
new List<IEnumerable<int>>(),
(acc, nr) =>
{
if (lastNr == int.MinValue || lastNr == nr - 1)
{
lastNr = nr; // first ever or in sequence
return acc; // noting to do
}
// not in sequence, add the missing into our ac'umulator list
acc.Add(Enumerable.Range(lastNr + 1, nr - lastNr - 1));
lastNr = nr; //thats the new lastNR to compare against in the next iteration
return acc;
}
);
return missing;
}
Tested by:
public static void Main(string[] args)
{
var tabSequence = new[] { 1, 2, 3, 7, 8, 9, 12, 15, 16, 17, 22, 23, 32 };
var lastNr = int.MinValue;
var missing = tabSequence.Aggregate(
new List<IEnumerable<int>>(),
(acc, nr) =>
{
if (lastNr == int.MinValue || lastNr == nr - 1)
{
lastNr = nr; // first ever or in sequence
return acc; // noting to do
}
acc.Add(Enumerable.Range(lastNr + 1, nr - lastNr - 1));
return acc;
}
);
Console.WriteLine(string.Join(", ", tabSequence));
foreach (var inner in GetMissingSeq(tabSequence))
Console.WriteLine(string.Join(", ", inner));
Console.ReadLine();
}
Output:
1, 2, 3, 7, 8, 9, 12, 15, 16, 17, 22, 23, 32 // original followed by missing sequences
4, 5, 6
10, 11
13, 14
18, 19, 20, 21
24, 25, 26, 27, 28, 29, 30, 31
If you are not interested in the subsequences you can use GetMissingSeq(tabSequence).SelectMany(i => i) to flatten them into one IEnumerable.

Getting a list of date ranges that occur between the ranges of two lists of date ranges

Given I have a list of KeyValuePair<DateTime,DateTime> (which represent date ranges available), and I have another list of same type (which represent date ranges not available), then I need to end up with a list of date ranges that are within the first list's ranges, but with ranges in first list being sliced by ranges in the second list. It may be that second list only has one entry, but it covers the entire available range, in which case the result should be empty.
To illustrate:
available: |~| |~~~~| |~~| |~~~~~~~~~~~~~~~~~~~~~|
unavailab: |~~~~~~~~~| |~| |~~~~~~| |~~~~~~~~|
expected : |~| |~| |~~~~~~~| |~~|
Or, in code, if you prefer (not same as illustration):
IList<KeyValuePair<DateTime, DateTime>> scheduleDates = new List<KeyValuePair<DateTime, DateTime>>()
{
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 9, 0, 0), new DateTime(2016, 11, 15, 12, 0, 0)),
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 15, 0, 0), new DateTime(2016, 11, 15, 21, 0, 0))
};
IList<KeyValuePair<DateTime, DateTime>> holidayDates = new List<KeyValuePair<DateTime, DateTime>>()
{
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 11, 0, 0), new DateTime(2016, 11, 15, 16, 0, 0)),
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 17, 0, 0), new DateTime(2016, 11, 15, 18, 0, 0)),
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 20, 0, 0), new DateTime(2016, 11, 15, 24, 0, 0)),
};
IList<KeyValuePair<DateTime, DateTime>> availability = new List<KeyValuePair<DateTime, DateTime>>()
{
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 9, 0, 0), new DateTime(2016, 11, 15, 11, 0, 0)),
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 16, 0, 0), new DateTime(2016, 11, 15, 17, 0, 0)),
new KeyValuePair<DateTime, DateTime>(new DateTime(2016, 11, 15, 18, 0, 0), new DateTime(2016, 11, 15, 20, 0, 0))
};
What would be the most efficient method of doing this? I can only think of a brute force, and surely that's not the way to go. Note that both input lists and/or the output list could be empty.

C# datetime array

I have two arrays, array1 has datetime data count by minute from 8am to 2pm and array2 has datetime data count by hour from same date 8am to 1pm.
I want to output the index number of two array that has same datetime.hour. and it should matchup the last available index number of array2 for all of the datetime data from array1 that later than array2.
for example if I have two datetime array like this:
DateTime[] dateTimes1 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 15, 0),
new DateTime(2010, 10, 1, 8, 30, 1),
new DateTime(2010, 10, 1, 8, 45, 2),
new DateTime(2010, 10, 1, 9, 15, 3),
new DateTime(2010, 10, 1, 9, 30, 4),
new DateTime(2010, 10, 1, 9, 45, 5),
new DateTime(2010, 10, 1, 10, 15, 6),
new DateTime(2010, 10, 1, 10, 30, 7),
new DateTime(2010, 10, 1, 10, 45, 8),
new DateTime(2010, 10, 1, 11, 15, 9),
new DateTime(2010, 10, 1, 11, 30, 10),
new DateTime(2010, 10, 1, 11, 45, 11),
new DateTime(2010, 10, 1, 12, 15, 12),
new DateTime(2010, 10, 1, 12, 30, 13),
new DateTime(2010, 10, 1, 12, 45, 14),
new DateTime(2010, 10, 1, 13, 15, 15),
new DateTime(2010, 10, 1, 13, 30, 16),
new DateTime(2010, 10, 1, 13, 45, 17),
new DateTime(2010, 10, 1, 14, 15, 18),
new DateTime(2010, 10, 1, 14, 30, 19),
new DateTime(2010, 10, 1, 14, 45, 20),
};
DateTime[] dateTimes2 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 0, 0),
new DateTime(2010, 10, 1, 9, 0, 1),
new DateTime(2010, 10, 1, 10, 0, 2),
new DateTime(2010, 10, 1, 11, 0, 3),
new DateTime(2010, 10, 1, 12, 0, 4),
new DateTime(2010, 10, 1, 13, 0, 5),
};
it should gives me the output:
0, 0
1, 0
2, 0
3, 1
4, 1
5, 1
6, 2
7, 2
8, 2
9, 3
10, 3
11, 3
12, 4
13, 4
14, 4
15, 5
16, 5
17, 5
18, 5
19, 5
20, 5
This is what I have tried:
int i = 0;
int j = 0;
while (i < dateTimes1.Length && j < dateTimes2.Length)
{
if (dateTimes1[i].Date == dateTimes2[j].Date && dateTimes1[i].Hour == dateTimes2[j].Hour)
{
list.Add(i);
list2.Add(j);
i++;
}
else if (dateTimes1[i] < dateTimes2[j])
{
i++;
}
else if (dateTimes1[i] > dateTimes2[j])
{
j++;
}
}
for (int k = 0; k < list.Count; k++)
{
Console.WriteLine(list[k] + " , " + list2[k];
}
but it won't output the index number after 1pm.
Your two lists are not the same length. In your while statement you are trying to iterate two different length lists at the same time.
If I understand your requirements properly you should be doing something like this by using an inner loop:
DateTime[] dateTimes1 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 15, 0),
new DateTime(2010, 10, 1, 8, 30, 1),
new DateTime(2010, 10, 1, 8, 45, 2),
new DateTime(2010, 10, 1, 9, 15, 3),
new DateTime(2010, 10, 1, 9, 30, 4),
new DateTime(2010, 10, 1, 9, 45, 5),
new DateTime(2010, 10, 1, 10, 15, 6),
new DateTime(2010, 10, 1, 10, 30, 7),
new DateTime(2010, 10, 1, 10, 45, 8),
new DateTime(2010, 10, 1, 11, 15, 9),
new DateTime(2010, 10, 1, 11, 30, 10),
new DateTime(2010, 10, 1, 11, 45, 11),
new DateTime(2010, 10, 1, 12, 15, 12),
new DateTime(2010, 10, 1, 12, 30, 13),
new DateTime(2010, 10, 1, 12, 45, 14),
new DateTime(2010, 10, 1, 13, 15, 15),
new DateTime(2010, 10, 1, 13, 30, 16),
new DateTime(2010, 10, 1, 13, 45, 17),
new DateTime(2010, 10, 1, 14, 15, 18),
new DateTime(2010, 10, 1, 14, 30, 19),
new DateTime(2010, 10, 1, 14, 45, 20),
};
DateTime[] dateTimes2 = new DateTime[]
{
new DateTime(2010, 10, 1, 8, 0, 0),
new DateTime(2010, 10, 1, 9, 0, 1),
new DateTime(2010, 10, 1, 10, 0, 2),
new DateTime(2010, 10, 1, 11, 0, 3),
new DateTime(2010, 10, 1, 12, 0, 4),
new DateTime(2010, 10, 1, 13, 0, 5),
};
int i = 0;
while (i < dateTimes1.Length)
{
int j = 0;
while (j < dateTimes2.Length))
{
if (dateTimes1[i].Date == dateTimes2[j].Date && dateTimes1[i].Hour == dateTimes2[j].Hour)
{
list.Add(i);
list2.Add(j);
i++;
}
else if (dateTimes1[i] < dateTimes2[j])
{
i++;
}
else if (dateTimes1[i] > dateTimes2[j])
{
j++;
}
}
}
for (int k = 0; k < list.Count; k++)
{
Console.WriteLine(list[k] + " , " + list2[k];
}
Here's a pretty basic method using Array.FindIndex and foreach:
EDIT: Updated this answer to handle the "matchup the last available index number of array2 for all of the datetime data from array1 that later than array2." issue.
foreach (DateTime dt in dateTimes1)
{
int currentHour = dt.Hour;
int lastHour = dateTimes2[dateTimes2.GetUpperBound(0)].Hour; //GetUpperBound(0) is the last index
int dt1index = Array.FindIndex(dateTimes1, a => a == dt); //get the index of the current item in dateTimes1
int dt2index = Array.FindIndex(dateTimes2, x => x.Hour == currentHour); //get the index of the item in dateTimes2 matching dateTimes1 hour field
if (currentHour > lastHour)
{
Console.WriteLine("{0}, {1}", dt1index, dateTimes2.GetUpperBound(0));
}
else
{
Console.WriteLine("{0}, {1}", dt1index, dt2index);
}
}
This simply looks at each of the values in dateTimes1 and dateTimes2 and returns the first match it finds (very similar to your loop).
To determine dt1index, we look through dateTimes1 and return the first match where a => a == dt (a is just the predicate, representing the "current" value in dateTimes1 - think of i = 0,1,2,etc in a regular loop ).
Similarly, to determine dt2index, we look for the first match on x => x.Hour == dt.Hour -- that is, where the "current" dt's hour field matches the hour field in dateTimes2.
In both cases, the first match is returned - if no matches are found, -1 is returned.
When we go to write to the console, we check if currentHour is greater than the last hour in dateTimes2 if so, we just write the current index of dateTimes1 and the last index of dateTimes2. Otherwise, we write the current index of dateTimes1 and the index where the hour matches on dateTimes2.
Using Linq:
var hour = new TimeSpan(1, 0, 0);
var dt2MaxValue = dateTimes2.Max();
for (int i = 0; i < dateTimes1.Length; i++)
{
var output = string.Format("{0}, {1}",
i,
dateTimes2
.Select((o, index) => new { index = index, value = o })
.Where(dt2 => (dateTimes1[i] - dt2.value) < hour
|| dt2.value == dt2MaxValue)
.Select(dt2 => dt2.index)
.FirstOrDefault());
Console.WriteLine(output);
}
What the above Linq statement does:
The first Select uses that method's overload which also passes the index of the item. This simply allows that info to cascade through. It uses an anonymous object with both index and the collection item being the index and value properties, respectively.
The Where clause queries the collection of these anonymous objects and compares their value with dateTime1[i]. It gets the one where value is less than dateTime1[i] but not by more than 1 hour, OR if it is the maximum value in the whole collection.
The second Select simply gets the indexes of the items that Where filtered through.
And FirstOrDefault returns just that (ie, the first or default, which is the index of the item selected or 0 if no item was selected).

Windows Phone - quick blur effect use on bitmap image in background

I have cover image for artist that I am using in center of page with 200x200 resolution. I want to repeat this image to background too but change it so user can recognize colors and some shapes that are big. I am not sure which name has this effect in english. I think something as blug, smoothing and something like that.
I found that this block of code do what I want:
coverBitmap.ImageOpened += (s, args) =>
{
var wb = new WriteableBitmap((BitmapImage)s);
var newHeight = 800;
wb = wb.Resize(newHeight, newHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
wb = wb.Crop(new Rect(160, 0, 480, 800));
wb = wb.Convolute(WriteableBitmapExtensions.KernelGaussianBlur5x5);
var brush = new ImageBrush {ImageSource = wb};
LayoutRoot.Background = brush;
};
Problem is that with KernelGaussianBlur5x5 it's still too much sharp (precise). I create my own matrix for 19x19:
var array = new[,]
{
{16, 17, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 17, 16},
{17, 19, 20, 22, 23, 24, 25, 26, 26, 26, 26, 26, 25, 24, 23, 22, 20, 19, 17},
{19, 20, 22, 24, 25, 26, 27, 28, 28, 28, 28, 28, 27, 26, 25, 24, 22, 20, 19},
{20, 22, 24, 25, 27, 28, 29, 30, 30, 30, 30, 30, 29, 28, 27, 25, 24, 22, 20},
{21, 23, 25, 27, 28, 29, 31, 31, 32, 32, 32, 31, 31, 29, 28, 27, 25, 23, 21},
{22, 24, 26, 28, 29, 31, 32, 33, 33, 33, 33, 33, 32, 31, 29, 28, 26, 24, 22},
{23, 25, 27, 29, 31, 32, 33, 34, 34, 35, 34, 34, 33, 32, 31, 29, 27, 25, 23},
{24, 26, 28, 30, 31, 33, 34, 35, 35, 36, 35, 35, 34, 33, 31, 30, 28, 26, 24},
{24, 26, 28, 30, 32, 33, 34, 35, 36, 36, 36, 35, 34, 33, 32, 30, 28, 26, 24},
{24, 26, 28, 30, 32, 33, 35, 36, 36, 36, 36, 36, 35, 33, 32, 30, 28, 26, 24},
{24, 26, 28, 30, 32, 33, 34, 35, 36, 36, 36, 35, 34, 33, 32, 30, 28, 26, 24},
{24, 26, 28, 30, 31, 33, 34, 35, 35, 36, 35, 35, 34, 33, 31, 30, 28, 26, 24},
{23, 25, 27, 29, 31, 32, 33, 34, 34, 35, 34, 34, 33, 32, 31, 29, 27, 25, 23},
{22, 24, 26, 28, 29, 31, 32, 33, 33, 33, 33, 33, 32, 31, 29, 28, 26, 24, 22},
{21, 23, 25, 27, 28, 29, 31, 31, 32, 32, 32, 31, 31, 29, 28, 27, 25, 23, 21},
{20, 22, 24, 25, 27, 28, 29, 30, 30, 30, 30, 30, 29, 28, 27, 25, 24, 22, 20},
{19, 20, 22, 24, 25, 26, 27, 28, 28, 28, 28, 28, 27, 26, 25, 24, 22, 20, 19},
{17, 19, 20, 22, 23, 24, 25, 26, 26, 26, 26, 26, 25, 24, 23, 22, 20, 19, 17},
{16, 17, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 17, 16}
};
I am not sure if I created it right. I found example from Microsoft samples from WinForm app and it results double[,] so I multiply by 10000 a then save it to int[,]. But when I apply this to my code it takes several seconds to create new image and I still want it more blur.
So is there a way how can I fast resize (expand) and crop image and then blur (smudge, smooth) it? Thanks

Convert IObservable<byte[]> with irregular length byte arrays to IObservable<byte[]> with regular length arrays

I have an IObservable<byte[]> that gives me an uncertain amount of bytes in the byte array. I want to know how I go from that, to returning an IObservable<byte[]> with a set amount of bytes in each byte array. Let's assume we want 10 bytes at a time.
That is to say, if I get the following input if I were to subscribe:
{1, 2, 3, 4}
{5, 6}
{7, 8, 9}
{10}
{11, 12, 13, 14, 15}
{16}
{17, 18}
{19, 20}
Bytes.Subscribe(b => Console.WriteLine(b.Length));
The output would be
3
2
3
1
5
1
2
2
What I would like is to convert the input above into this:
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
Bytes.<WhateverItTakesToDoThat>.Subscribe(b => Console.WriteLine(b.Length));
The output would be
10
10
It must also work if an amount of bytes come in that are larger than a single output packet, i.e.:
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
{33, 34, 35, 36, 37, 38, 39, 40, 41}
{42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52}
Should be turned into
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
{31, 32, 33, 34, 35, 36, 37, 38, 39, 40}
{41, 42, 43, 44, 45, 46, 47, 48, 49, 50}
(and be holding on to {51, 52}, waiting for more input to come along)
It's easy. Try this:
Bytes
.SelectMany(b => b)
.Buffer(10)
.Select(bs => bs.ToArray());
I came up with one solution after a bit of thinking and tinkering. The following code does what I want:
Bytes.Select( b => b.ToObservable() ) // Convert input to IObservable<IObservable<byte>>
.Merge( 1 ) // Merges the IObservable<IObservable<byte>> to an IObservable<byte>
// with the bytes in the right order
.Buffer( 4 ) // Wait until we have 4 bytes ready
.Select( bl => bl.ToArray() ) // Take these 4 bytes and turn them back into an array
.Subscribe( b => Console.WriteLine( b.Length ) );
This is probably inefficient, and I'm almost certain it's not he most efficient way of doing this, so if somebody out there can come up with a better, more efficient solution, I'm all ears!

Categories