Related
I have a fixed list of
List<int> values = new List<int>() {0, 1, 2, 3, 4, 5, 6};
I can give 2 input named startValue and endValue and it will return a List<int>.
Examples:
#1
startValue = 0
endValue = 4
returned List: {0, 1, 2, 3, 4}
#2
startValue = 1
endValue = 6
returned List: {1, 2, 3, 4, 5, 6}
#3
startValue = 6
endValue = 4
returned List: {6, 0, 1, 2, 3, 4}
I have implemented in linq.
List<int> days = new List<int> { 0, 1, 2, 3, 4, 5, 6 };
List<int> excpt = new List<int> { startDay, endDay };
List<int> fDays = new List<int>();
fDays = days.Except(excpt).ToList();
My idea would be to use LinkedList collection like that:
List<int> days = new List<int> { 0, 1, 2, 3, 4, 5, 6 };
var startDay = 6;
var endDay = 4;
var linked = new LinkedList<int>(days);
var result = new List<int>();
var current = linked.Find(startDay);
result.Add(current.Value);
var finished = false;
while (!finished){
current = current.Next ?? current.List.First;
result.Add(current.Value);
if (current.Value == endDay)
{
finished = true;
}
}
Obviously you would have to implement all the protection against null values etc. But concept would work as you like
I would use this simple method using Enumerable.Range and Prepend:
public static IEnumerable<int> GetRange(int startValue, int endValue, int zero = 0)
{
if (startValue < endValue)
{
return Enumerable.Range(startValue, endValue - startValue + 1);
}
return Enumerable.Range(zeroValue, endValue - zero + 1).Prepend(startValue);
}
int startValue = 6;
int endValue = 4;
List<int> resultList = GetRange(startValue, endValue).ToList();
If values is a list with arbitrary values, you can return all items twice i.e.
{0, 1, 2, 3, 4, 5, 6} -> 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6
| <- [6..4] -> |
And then use good old Linq:
List<int> values = new List<int> { 0, 1, 2, 3, 4, 5, 6 };
int startDay = 6;
int endDay = 4;
...
var result = values
.Concat(days) // <- Repeats days twice
.SkipWhile(day => day != startDay)
.TakeWhile(day => day != endDay)
.Append(endDay)
.ToList();
If you want to generate consequent numbers mod week (week == 7 in your case), you don't need values list at all:
int startDay = 6;
int endDay = 4;
const int week = 7;
var result = Enumerable
.Range(startDay, (endDay - startDay + week + 1) % week)
.Select(day => day % week)
.ToList();
I was hoping someone could assist with an issue I'm having with a subset sum problem. I took the below code from another thread. What I'd like to do, ideally, is have a function that returns the first array that meets this condition: " if (s == target && partial.ToArray().Length == 7)".
Is that possible with the code I'm using below? In other words, I don't want ALL of the combinations, just the first one that meets that condition. I've tried a few things, but I'm not experienced enough at C# to really understand how to break out of the recursion or return the array to a calling function. Any help would be greatly appreciated.
private void button1_Click(object sender, EventArgs e)
{
List<int> numbers = new List<int>() { 2, 6, 6, 5, 8, 1, 3, 3, 9, 3, 6, 1, 3, 9, 1, 7, 8, 6, 8, 1, 1, 4, 4, 2, 8, 4, 5, 4, 6, 10, 1, 4, 3, 1, 2, 8, 4, 5, 9, 2, 2, 4 };
int target = 27;
sum_up(numbers, target);
}
private static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers, target, new List<int>());
}
private static void sum_up_recursive(List<int> numbers, int target, List<int> partial)
{
int s = 0;
foreach (int x in partial) s += x;
if (s == target && partial.ToArray().Length == 7)
Console.WriteLine("sum(" + string.Join(",", partial.ToArray()) + ")=" + target);
if (s >= target)
return;
for (int i = 0; i < numbers.Count; i++)
{
List<int> remaining = new List<int>();
int n = numbers[i];
for (int j = i + 1; j < numbers.Count; j++) remaining.Add(numbers[j]);
List<int> partial_rec = new List<int>(partial);
partial_rec.Add(n);
sum_up_recursive(remaining, target, partial_rec);
}
}
}
I'm sure there are easier ways of doing this, but to use your code, I believe this is one way you could do it:
using System.Linq;
using System.Collections.Generic;
private void button1_Click(object sender, EventArgs e)
{
List<int> numbers = new List<int>
{
2, 6, 6, 5, 8, 1, 3, 3, 9, 3, 6, 1, 3, 9, 1, 7, 8, 6, 8, 1, 1,
4, 4, 2, 8, 4, 5, 4, 6, 10, 1, 4, 3, 1, 2, 8, 4, 5, 9, 2, 2, 4
};
int target = 27;
sum_up(numbers, target);
}
private static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers, target, new List<int>(), 0);
}
private static void sum_up_recursive
(List<int> numbers, int target, List<int> #partial, int index)
{
int s = #partial.Sum();
if (s >= target && #partial.Count == 7)
{
Console.WriteLine("sum(" + string.Join(",", partial.ToArray()) + ")=" + target);
}
else if (s < target)
{
if( index + 7 > numbers.Count )
{
return;
}
else
{
List<int> partial_rec = numbers.GetRange(index, index + 7);
sum_up_recursive(numbers, target, partial_rec, ++index);
}
}
}
For an example if I want to iterate test and perfrorm operations on elements from that array but they have to be formatted in a particular way.
Essentially I am trying to loop over a 2d array using a 2d array.
double[,] test = {
{9, 8, 7, 6, 5, 4, 3, 2},
{8, 7, 6, 5, 4, 3, 2, 1},
{7, 6, 5, 4, 3, 2, 1, 0},
{6, 5, 4, 3, 2, 1, 0, 0},
{5, 4, 3, 2, 1, 0, 0, 0},
{4, 3, 2, 1, 0, 0, 0, 0},
{3, 2, 1, 0, 0, 0, 0, 0},
{2, 1, 0, 0, 0, 0, 0, 0},
};
double[,] subset = new double[2,2]; //used in math
What I would like to be able to do is to iterate over any size matrix (assuming that they are even sized and square) with each iteration looking like this:
Iteration 1:
subset[0,0] = test[0,0];
subset[0,1] = test[0,1];
subset[1,0] = test[1,0];
subset[1,1] = test[1,1];
So basically it selected a square same size as subset out of the large matrix.
Iteration 2:
subset[0,2] = test[0,2];
subset[1,2] = test[1,2];
subset[0,3] = test[0,3];
subset[1,3] = test[1,3];
You can do this via an extension method. A few things worth mentioning:
Using Array.Copy as opposed to manually assigning the elements should yield better performance.
Like Tom A mentioned in a comment, you should use yield return to create an IEnumerable. You can then iterate over it using a foreach loop, or perform other operations.
Implementation:
static class MatrixExtensions
{
public static IEnumerable<T[,]> ChunkMatrix<T>(this T[,] inputMatrix, int chunkWidth, int chunkHeight)
{
int inputWidth = inputMatrix.GetLength(0);
int inputHeight = inputMatrix.GetLength(1);
for(int i = 0; i < inputWidth; i += chunkWidth)
{
for(int j = 0; j < inputHeight; j += chunkHeight)
{
T[,] chunk = new T[chunkWidth, chunkHeight];
for(int k = 0; k < chunkWidth; k++)
{
int sourceIndex = i*inputWidth + k* inputWidth + j;
var destinationIndex = k* chunkHeight;
Array.Copy(inputMatrix, sourceIndex, chunk, destinationIndex, chunkHeight);
}
yield return chunk;
}
}
}
}
Usage:
double[,] test = {
{1, 2, 3, 4, 5, 6, 7, 8},
{9, 10, 11, 12, 13, 14, 15, 16},
{17, 18, 19, 20, 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, 53, 54, 55, 56},
{57, 58, 59, 60, 61, 62, 63, 64},
};
foreach(double[,] chunk in test.ChunkMatrix(2, 2))
{
// First iteration:
// 1 2
// 9 10
//
// Second iteration:
// 3 4
// 11 12
//
// ...
}
I changed your test data to not include duplicate values, as to better illustrate the effect.
It should be noted that my implementation will not work correctly on matrices with dimensions that are not multiples of the chunks' dimensions, as it was mentioned in a comment that this will never be the case. If needed, modifying it to account for this scenario shouldn't be too hard.
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
const int COLUMNS = 8;
const int ROWS = 8;
const int SIZE = 2;
static void Main(string[] args)
{
double[,] test = {
{9, 8, 7, 6, 5, 4, 3, 2},
{8, 7, 6, 5, 4, 3, 2, 1},
{7, 6, 5, 4, 3, 2, 1, 0},
{6, 5, 4, 3, 2, 1, 0, 0},
{5, 4, 3, 2, 1, 0, 0, 0},
{4, 3, 2, 1, 0, 0, 0, 0},
{3, 2, 1, 0, 0, 0, 0, 0},
{2, 1, 0, 0, 0, 0, 0, 0},
};
for (int i = 0; i < COLUMNS; i += SIZE)
{
for (int j = 0; j < ROWS; j += SIZE)
{
for (int k = j; k < j + SIZE; k++)
{
for (int l = i; l < i + SIZE; l++)
{
Console.WriteLine("test[{0}, {1}] = {2}", k, l, test[k, l]);
}
}
}
}
Console.ReadLine();
}
}
}
I am not saying this is the best solution but while I look at the yield statement I managed to get it working using this method.
public static double[,] GetMapSection(Rectangle area, double[,] map) {
double[,] result = new double[area.Width, area.Height];
for (Int32 y = 0; y < area.Height; ++y) {
for (Int32 x = 0; x < area.Width; ++x) {
result[x, y] = map[x + area.X, y + area.Y];
}
}
return result;
}
I call it via:
List<double[,]> testChannel = new List<double[,]>();
for (int i = 0; i < Math.Sqrt(large_mapdata.Length); i+=8) {
for (int j = 0; j < Math.Sqrt(large_mapdata.Length); j+=8) {
testChannel.Add(GetMapSection(new Rectangle(i, j, 8, 8), large_mapdata));
}
}
In this example I am creating 8x8 chunks out of an array that is 32x32 in size.
I can confirm that this worked for me and is cleaner than what I had before.
Note: the array and total of columns should be appear as below figure (numbers should not be
the same as figure below, numbers should be random)
5 1 1 1 1 1 1 1 1 1
2 2 4 5 6 7 8 8 9 9
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3 3
5 5 5 5 5 5 5 5 5 5
4 4 4 4 4 4 4 4 4 4
7 7 7 7 7 7 7 7 7 7
3 3 3 3 3 3 3 3 3 3
1 1 1 1 1 1 1 11 1 1
The total of each column
33 29 31 32 33 34 35 45 36 36
`enter coddouble[,] a = new double[10, 10];
Random x = new Random();
string s = "";
for (int r = 0; r < 10; r++)
{
for (int c = 0; c < 10; c++)
{
a[r, c] = x.Next(1, 21);
s = s + a[r, c].ToString() + "\t";
}
}
textBox1.Text = s;e here`
this is how to print the arry now how to find the sum of each column
It is very basic in array implementation.
There are many ways to achieve this.One of my preferred way by iterating over the array structure using simple loop like this.
static int array[10][10];
//or like
int[,] array = new int[,]
{
<declare array structure>
};
int i, j, rowlength=10, columnlength=10, sum = 0; //assuming your order 10 as given example .To make it dynamic use array.Length
sum = 0;
for (j = 0; j < columnlength; ++j)
{
for (i = 0; i < rowlength; ++i)
{
sum = sum + array[i][j];
}
Console.WriteLine(String.Format("Summation of {0}th column is {1}", j,sum));
sum=0;
}
var arr2d = new int[5];
arr2d[0] = {1,2,3,4,5};
// etc...
var arr = new int[arr2d.length];
for(int i=0; i<arr2d.length; i++) {
var item = arr2d[i];
for(int j=0; j<item.length; j++) {
arr[i] += item[j];
}
}
you can try the below code. It generic code and can work on any number of column, you don't need to hardcode number of column. columnSum List contain the sum of individual column
var array2D = Get2DArray(); //some function to populate, you can have your own way to populate your 2D array
List<int> columnSum = new List<int>();
for (int j = 0; j < array2D.length ; ++j)
{
int sum = 0;
for (int i = 0; i < array2D[j].length; ++i)
{
sum = sum + array2D[i][j];
}
columnSum.Add(sum); // columnSum List contain the sum of individual column
}
Try this using your code.
What I did was sum the column you add the number to the array. This is assuming c is column and r is row.
double[,] a = new double[10, 10];
Random x = new Random();
string s = "";
var colsum = new List<int>();
for (int r = 0; r < 10; r++)
{
var col = 0;
for (int c = 0; c < 10; c++)
{
col += x.Next(1, 21);
a[r, c] = col;
s = s + a[r, c].ToString() + "\t";
}
colsum.Add(col);
}
foreach(var col in colsum){
Console.WriteLine(colsum.ToString());
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[,] data = new int[,] {
{5, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{2 ,2, 4, 5, 6, 7, 8, 8, 9, 9},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
{5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{7, 7, 7, 7, 7, 7, 7, 7, 7, 7},
{3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
{1, 1, 1, 1, 1, 1, 1, 11, 1, 1}
};
int[] sum = new int[10];
for (int row = 0; row < 10; row++)
{
for (int col = 0; col < 10; col++)
{
if (row == 0)
{
sum[col] = data[row, col];
}
else
{
sum[col] += data[row, col];
}
}
}
List<List<int>> data2 = new List<List<int>>() {
new List<int>() {5, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
new List<int>() {2 ,2, 4, 5, 6, 7, 8, 8, 9, 9},
new List<int>() {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
new List<int>() {2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
new List<int>() {3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
new List<int>() {5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
new List<int>() {4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
new List<int>() {7, 7, 7, 7, 7, 7, 7, 7, 7, 7},
new List<int>() {3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
new List<int>() {1, 1, 1, 1, 1, 1, 1, 11, 1, 1}
};
//using linq
int[] sum2 = data2.Select(s => s.Select((t, i) => new { num = t, col = i })).SelectMany(u => u).GroupBy(v => v.col).ToList().Select(w => w.Select(x => x.num).Sum()).ToArray();
}
}
}
It's pretty simple - just 2 nested for loops like this
static double[] SumColumns(double[,] source)
{
int rowCount = source.GetLength(0);
int colCount = source.GetLength(1);
var colSums = new double[colCount];
for (int row = 0; row < rowCount; row++)
for (int col = 0; col < colCount; col++)
colSums[col] += source[row, col];
return colSums;
}
Sample usage with your code:
int rows = 10, cols = 10;
var a = new double[rows, cols];
var x = new Random();
var sb = new StringBuilder();
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
a[r, c] = x.Next(1, 21);
if (c > 0) sb.Append("\t");
sb.Append(a[r, c]);
}
sb.AppendLine();
}
var colsSums = SumColumns(a);
for (int c = 0; c < cols; c++)
{
if (c > 0) sb.Append("\t");
sb.Append(colsSums[c]);
}
var s = sb.ToString();
textBox1.Text = s;
I know this is an old post but you can have it by the following single line,
var result = Enumerable.Range(0, sample.GetLength(1)).Select(c => Enumerable.Range(0, sample.GetLength(0)).Select(r => sample[r, c]).Sum()).ToArray();
Test with sample data
var sample = new int[10, 10]
{
{ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 2, 2, 4, 5, 6, 7, 8, 8, 9, 9 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
{ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
{ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
{ 1, 1, 1, 1, 1, 1, 1, 11, 1, 1 }
};
var row = sample.GetLength(0);
var column = sample.GetLength(1);
var result = Enumerable.Range(0, column).Select(c => Enumerable.Range(0, row).Select(r => sample[r, c]).Sum()).ToArray();
Gets sum of each column in an array with; 33, 29, 31, 32, 33, 34, 35, 45, 36, 36
My code is as follows but it took 3 minute to give an output is there a faster technique to find cycles in an undirected graph:
When the inputs are less as follows
{1, 2}, {1, 3}, {1, 4}, {2, 3},
{3, 4}, {2, 6}, {4, 6}, {7, 8},
{8, 9}, {9, 7}
it works fast otherwise when it has too many inputs then it is too slow
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CycleDetection
{
class Program
{
// Graph modelled as list of edges
static int[,] graph =
{
{1, 2}, {1, 3}, {1, 4}, {2, 3},
{3, 4}, {2, 6}, {4, 6}, {7, 8},
{8, 9}, {9, 7}, {2, 3}, {1, 5}, {2, 4}, {4, 6},
{7, 4}, {3, 5}, {4, 5}, {2, 8},
{8, 1}, {9, 1}, {14,1}, {2,14}, {5, 1}, {7, 3}, {6, 2}, {10,1},
{10, 4}, {10, 6}, {10, 3}, {10,2},
{8, 3}, {1, 7}
};
static List<int[]> cycles = new List<int[]>();
static void Main(string[] args)
{
for (int i = 0; i < graph.GetLength(0); i++)
for (int j = 0; j < graph.GetLength(1); j++)
{
findNewCycles(new int[] { graph[i, j] });
}
foreach (int[] cy in cycles)
{
string s = "" + cy[0];
for (int i = 1; i < cy.Length; i++)
s += "," + cy[i];
Console.WriteLine(s);
}
Console.ReadLine();
}
static void findNewCycles(int[] path)
{
int n = path[0];
int x;
int[] sub = new int[path.Length + 1];
for (int i = 0; i < graph.GetLength(0); i++)
for (int y = 0; y <= 1; y++)
if (graph[i, y] == n)
// edge referes to our current node
{
x = graph[i, (y + 1) % 2];
if (!visited(x, path))
// neighbor node not on path yet
{
sub[0] = x;
Array.Copy(path, 0, sub, 1, path.Length);
// explore extended path
findNewCycles(sub);
}
else if ((path.Length > 2) && (x == path[path.Length - 1]))
// cycle found
{
int[] p = normalize(path);
int[] inv = invert(p);
if (isNew(p) && isNew(inv))
cycles.Add(p);
}
}
}
static bool equals(int[] a, int[] b)
{
bool ret = (a[0] == b[0]) && (a.Length == b.Length);
for (int i = 1; ret && (i < a.Length); i++)
if (a[i] != b[i])
{
ret = false;
}
return ret;
}
static int[] invert(int[] path)
{
int[] p = new int[path.Length];
for (int i = 0; i < path.Length; i++)
p[i] = path[path.Length - 1 - i];
return normalize(p);
}
// rotate cycle path such that it begins with the smallest node
static int[] normalize(int[] path)
{
int[] p = new int[path.Length];
int x = smallest(path);
int n;
Array.Copy(path, 0, p, 0, path.Length);
while (p[0] != x)
{
n = p[0];
Array.Copy(p, 1, p, 0, p.Length - 1);
p[p.Length - 1] = n;
}
return p;
}
static bool isNew(int[] path)
{
bool ret = true;
foreach (int[] p in cycles)
if (equals(p, path))
{
ret = false;
break;
}
return ret;
}
static int smallest(int[] path)
{
int min = path[0];
foreach (int p in path)
if (p < min)
min = p;
return min;
}
static bool visited(int n, int[] path)
{
bool ret = false;
foreach (int p in path)
if (p == n)
{
ret = true;
break;
}
return ret;
}
}
}
Output:-list of cycles
I used visual studio 2010 to run this
How about something like this?
int[,] graph =
{
{1, 2}, {1, 3}, {1, 4}, {2, 3},
{3, 4}, {2, 6}, {4, 6}, {7, 8},
{8, 9}, {9, 7}, {2, 3}, {1, 5}, {2, 4}, {4, 6},
{7, 4}, {3, 5}, {4, 5}, {2, 8},
{8, 1}, {9, 1}, {14,1}, {2,14}, {5, 1}, {7, 3}, {6, 2}, {10,1},
{10, 4}, {10, 6}, {10, 3}, {10,2},
{8, 3}, {1, 7}
};
var g = graph.Cast<int>().ToArray();
var edges = Enumerable.Range(0, g.Length / 2)
.Select(i => Tuple.Create(g[i * 2], g[i * 2 + 1]));
var edgeLookup = edges.ToLookup(x => x.Item1);
var stack = new Stack<Tuple<int, int>>(edgeLookup.First());
var visited = new HashSet<Tuple<int, int>>();
while(stack.Count > 0)
{
var current = stack.Pop();
if(!visited.Add(current)) throw new Exception("cycle!!!");
var newNodes = edgeLookup[current.Item2];
foreach(var newNode in newNodes)
{
stack.Push(newNode);
}
}