creating a random (Gantt-ish) chart - c#

I'm trying to write a test for one of my audio programs, and I'm having trouble wrapping my brain around this test setup. First, I've got a table of 60 rows by 10000 columns that needs to be filled. Each cell has a value of ON, OFF, or LEFT (meaning I have the same value as my nearest ON/OFF to my left). I want a random twenty to forty rows to be on at any given time. Each has to be on for a random 6 to 200 cells. The commands to set ON or OFF have to be ordered by row then column. I'm picturing a sparse dictionary coming out with a coordinate key and on/off value. What I don't understand is how store my ON/OFF cells such that I can easily determine if my current row is ON or OFF. Help? Thanks for your time.

After further thought on this, I realized I could do it in two passes. Here's what I ended up with. Feel free to comment on this approach:
var table = new byte[60, 10000];
for(int i = 0; i < 60; i++)
{
// we want at least half the row to be blank
int j = 0;
while(j < 10000)
{
var width = rand.Next(7, 200);
j += width * 2;
var vol = (byte)rand.Next(50, 125);
for(int k = j - width; k < Math.Min(10000, j); k++)
table[i, k] = vol;
}
}
var midiEvents = new List<BASS_MIDI_EVENT>();
midiEvents.Add(new BASS_MIDI_EVENT(BASSMIDIEvent.MIDI_EVENT_PROGRAM, 0, 0, 0, 0));
for(int j = 0; j < 10000; j++)
{
for(int i = 0; i < 60; i++)
{
var cur = (int)table[i, j];
var left = j > 0 ? table[i, j - 1] : 0;
if(cur > 0 && left == 0)
{
cur <<= 8;
cur |= i + 33;
midiEvents.Add(new BASS_MIDI_EVENT(BASSMIDIEvent.MIDI_EVENT_NOTE, cur, 0, j, 0));
}
else if(cur == 0 && left > 0)
{
midiEvents.Add(new BASS_MIDI_EVENT(BASSMIDIEvent.MIDI_EVENT_NOTE, i + 33, 0, j, 0));
}
}
}

Related

Finding a minor matrix of a matrix with C# in Visual Studio

I'm developing an app will be used for calculating matrixes and I'm currently working on minor function and I need a minor matrix for that. So, I wrote the code shown below. It actually works without any error but there is an issue about 4x4 matrices. It changes the 4x1 and 4x2 values.
In this image, places of 9 and 10 are wrong. They are at each others place.
enter image description here
Note: There isn't any problem about textboxes, it's about the array (matrix).
Here is my code. I could easily solve it by rechanging them with a few lines of code but I'm trying to learn C# and Visual Studio, so I want to find the problem in my algorithm.
minorMatrix = new int[rowA.Value - 1, colA.Value - 1];
int k = 0, l = 0;
for (int i = 0; i < rowA.Value - 1; i++)
{
for (int j = 0; j < colA.Value - 1; j++)
{
if (i < row - 1)
{
k = i;
}
else
{
k = i + 1;
}
if (j < col - 1)
{
l = j;
}
else
{
l = j + 1;
}
minorMatrix[i, j] = matrixA[k, l];
}
}
Are you trying to remove the ith row and jth column? This should do it:
int[,] A = new int[3, 3]; // Original matrix
int[,] M = new int[2, 2]; // Matrix with ith row and jth column removed
int i = 2, j = 1; // 3rd row, 2nd column to remove
for (int Mi = 0; Mi < A.GetLength(0); Mi++)
for (int Mj = 0; Mj < A.GetLength(1); Mj++)
{
int Ai = Mi, Aj = Mj;
if (Mi >= i)
Ai = Mi + 1;
if (Mj >= j)
Aj = Mj + 1;
M[Mi, Mj] = A[Ai, Aj];
}

How to store the results of an array matrix into a smaller array c#

I need to add a value which would be either p1(payoff one) or p2 (payoff two) to the surrounding four neighbours of a value in a matrix that'll then be printed into a new array matrix. If it's 1 then p1 will need to be added to it's neighbours or if its 0 then p2 will be added to its neighbours. I've tried to do this approach with a nested for loop but my 'if' statement in my for loop is giving me errors and Im not sure where to go next with it.
class MainClass
{
static void Main(string[] args)
{
int m, n, i, j, p1, p2;
// rows and columns of the matrix+
m = 3;
n = 3;
//Payoff matrix
p1 = 10; //cheat payoff matrix
p2 = 5; //co-op payoff matrix
int[,] arr = new int[3, 3];
Console.Write("To enter 1 it means to co-operate" );
Console.Write("To enter 0 it means to cheat");
Console.Write("Enter elements of the Matrix: ");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
arr[i, j] = Convert.ToInt16(Console.ReadLine());
}
}
Console.WriteLine("Printing Matrix: ");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
Console.Write(arr[i, j] + "\t");
}
Console.WriteLine();
}
// how to change the values of the matrix
int[] payoffMatrix = new int[4];
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if(arr[i,j] == 1)
{
arr[i, j] = arr[i - 1, j] , arr[i + 1, j] , arr[i, j - 1] , arr[i, j + 1];
}
}
Console.WriteLine();
}
The result of the neighbouring values need to be printed into the payoff matrix aswell
If I understood correctly you need to make a copy of your array first. Because otherwise you would read e.g. "1" from a array position (i + 1) from the current iteration. That's probably not what you want.
Then you just set the desired values in your for-loop. You need some bound checking, because e.g. arrNew[i - 1] will only be accessible if i > 0
this gives you something like:
int[,] arrNew = arr.Clone() as int[,]; //creates a copy of arr
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (arr[i, j] == 1)
{
if (i > 0) //bounds checking
{
arrNew[i - 1, j] = 1;
}
if (i < m - 1) //bounds checking
{
arrNew[i + 1, j] = 1;
}
if (j > 0) //bounds checking
{
arrNew[i, j - 1] = 1;
}
if (j < n - 1) //bounds checking
{
arrNew[i, j + 1] = 1;
}
}
}
}
For a matrix:
0 0 0
0 1 0
0 0 0
the result would be
0 1 0
1 1 1
0 1 0

Efficient way to find neighboring cells in a 2d array

I have a 2d array of class Tiles. While creating the playfield I have to generate all directly neighboring cells (horizontally, vertically, diagonally). I start by generating the field filling up each cell with a new Tile, than (when that is done) I loop through the 2d array to calculate the neighbors using this piece of loop:
int dnDistance= 1; //Direct Neighbor Distance.
for (int iMapY = 0; iMapY < playfieldHeight; iMapY++)
{
for (int iMapX = 0; iMapX < playfieldWidth; iMapX++)
{
for (int yOffset = -dnDistance; yOffset <= dnDistance; yOffset++)
{
for (int xOffset = -dnDistance; xOffset <= dnDistance; xOffset++)
{
if ((iMapX + xOffset >= 0 && iMapX + xOffset < playfieldWidth) && (iMapY + yOffset >= 0 && iMapY + yOffset < playfieldHeight))
{
if (!(yOffset == 0 && xOffset == 0))
{
playfieldTiles[iMapX, iMapY].dnTiles.Add(playfieldTiles[iMapX + xOffset, iMapY + yOffset]);
}
}
}
}
}
}
Using this method, I have to loop through the entire 2d array a second time, creating a for loop, in a for loop, in a for loop, in a for loop which sometimes is quite unclear. There has to be a better way for this, right?
I found a post that looks to be similar but not quite the same, or I don't understand it properly:
When it just works then it's fine !
Here's a little optimization that makes it easier to debug:
var playfieldHeight = 5;
var playfieldWidth = 5;
var playfieldTiles = new byte[playfieldWidth + dnDistance * 2, playfieldHeight + dnDistance * 2];
var len1 = playfieldWidth * playfieldHeight;
var len2 = dnDistance * 2 + 1;
for (var i = 0; i < len1; i++)
{
var ix = i % playfieldWidth;
var iy = i / playfieldWidth;
for (var j = 0; j < len2 * len2; j++)
{
var jx = j % len2 - dnDistance;
var jy = j / len2 - dnDistance;
Console.WriteLine($"x1: {ix}, y1: {iy}, x2: {jx}, y2: {jy}");
}
}
You now have only 2 loops, the field and the neighbors.
You could further optimize it with a single for but I believe readability will decrease (inside the loop).

Calculate Nth Pi Digit

I am trying to calculate the nth digit of Pi without using Math.Pi which can be specified as a parameter.
I modified an existing algorithm, since I like to find the Nth digit without using string conversions or default classes.
This is how my algorithm currently looks like:
static int CalculatePi(int pos)
{
List<int> result = new List<int>();
int digits = 102;
int[] x = new int[digits * 3 + 2];
int[] r = new int[digits * 3 + 2];
for (int j = 0; j < x.Length; j++)
x[j] = 20;
for (int i = 0; i < digits; i++)
{
int carry = 0;
for (int j = 0; j < x.Length; j++)
{
int num = (int)(x.Length - j - 1);
int dem = num * 2 + 1;
x[j] += carry;
int q = x[j] / dem;
r[j] = x[j] % dem;
carry = q * num;
}
if (i < digits - 1)
result.Add((int)(x[x.Length - 1] / 10));
r[x.Length - 1] = x[x.Length - 1] % 10; ;
for (int j = 0; j < x.Length; j++)
x[j] = r[j] * 10;
}
return result[pos];
}
So far its working till digit 32, and then, an error occurs.
When I try to print the digits like so:
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("{0} digit of Pi is : {1}", i, CalculatePi(i));
}
Console.ReadKey();
}
This I get 10 for the 32rd digit and the 85rd digit and some others as well, which is obviously incorrect.
The original digits from 27 look like so:
...3279502884.....
but I get
...32794102884....
Whats wrong with the algorithm, how can I fix this problem?
And can the algorithm still be tweaked to improve the speed?
So far it works right up until the cursor reaches digit 32. Upon which, an exception is thrown.
Rules are as follows:
Digit 31 is incorrect, because it should be 5 not a 4.
Digit 32 should be a 0.
When you get a 10 digit result you need to carry 1 over to the previous digit to change the 10 to a 0.
The code changes below will work up to ~ digit 361 when 362 = 10.
Once the program enters the 900's then there are a lot of wrong numbers.
Inside your loop you can do this by keeping track of the previous digit, only adding it to the list after the succeeding digit has been computed.
Overflows need to be handled as they occur, as follows:
int prev = 0;
for (int i = 0; i < digits; i++)
{
int carry = 0;
for (int j = 0; j < x.Length; j++)
{
int num = (int)(x.Length - j - 1);
int dem = num * 2 + 1;
x[j] += carry;
int q = x[j] / dem;
r[j] = x[j] % dem;
carry = q * num;
}
// calculate the digit, but don't add to the list right away:
int digit = (int)(x[x.Length - 1] / 10);
// handle overflow:
if(digit >= 10)
{
digit -= 10;
prev++;
}
if (i > 0)
result.Add(prev);
// Store the digit for next time, when it will be the prev value:
prev = digit;
r[x.Length - 1] = x[x.Length - 1] % 10;
for (int j = 0; j < x.Length; j++)
x[j] = r[j] * 10;
}
Since the digits are being updated sequentially one-by-one, one whole iteration later than previously, the if (i < digits - 1) check can be removed.
However, you need to add a new one to replace it: if (i > 0), because you don't have a valid prev value on the first pass through the loop.
The happy coincidence of computing only the first 100 digits means the above will work.
However, what do you suppose will happen when a 10 digit result follows a 9 digit one? Not good news I'm afraid, because the 1 with need carrying over to the 9 (the previous value), which will make it 10.
A more robust solution is to finish your calculation, then do a loop over your list going backwards, carrying any 10s you encounter over to the previous digits, and propagating any carries.
Consider the following:
for (int pos = digits - 2; pos >= 1; pos--)
{
if(result[pos] >= 10)
{
result[pos] -= 10;
result[pos - 1] += 1;
}
}

find diagonal in 2 dimensional array

I have a 2-dimensional array with user-entered values. I need to find sum of the even elements in the diagonal of the array.
I know how to declare the array and get it filled by the user, but I'm not sure what even elements in the main diagonal really means.
I know I can find out if a number is even by saying:
if n / 2 == 0
Once I've reported the sum of the even elements in the diagonal, I would like to replace all 0 values in the array with ones.
Diagonal means all places where x and y cordinates are the same
Do if your array contains:
1 3 8 5
3 3 9 7
4 4 5 7
5 1 7 4
Then the diagonal are in bold.
Assuming the array is a square:
int sum = 0;
for(int i = 0; i < numOfArrayRows; i++)
{
//Use the mod operator to find if the value is even.
if(array[i][i] % 2 == 0)
sum += array[i][i];
//Change 0's to ones
for(int j = 0; j < numOfArrayCols; j++)
if(array[i][j] == 0)
array[i][j] = 1;
}
Also, next time add the "Homework" tag if you have a homework question :P
With a two-dimensional array it's really easy, since you don't need any index magic:
int a[N][N] = ...;
int sum = 0;
for(int i=0; i<N; ++i)
if(a[i][i] % 2 == 0) //or a[i] & 1, if you like, just check if it's dividable by 2
sum += a[i][i];
This C++ code shouldn't be that different in C or C#, but you should get the point. Likewise the second question would be as simple as:
int a[M][N] = ...;
for(i=0; i<M; ++i)
for(j=0; j<N; ++j)
if(a[i][j] == 0)
a[i][j] = 1;
And I suspec that the main diagonal is the one that begins with coordinates 0,0.
To replace 0 elements with 1 you would do something like:
if (array[i,j] == 0) array[i,j] == 1;
This sounds like homework - however I will help out :)
So if you have an 2D array, and in order to find the sum of the diagonal values, you will know that the indices of both of the values would match in order to provide you with each of the diagonal values.
To iterate through these you could use a simple loop that would sum up every diagonal value, as shown:
//Your Sum
int sum = 0;
//This will iterate and grab all of the diagonals
//You don't need to iterate through every element as you only need
//the diagonals.
for(int i = 0; i < sizeOfArray; i++)
{
//This will add the value of the first, second, ... diagonal value to your sum
sum += array[i,i];
}
To set each of the values that is 0 to 1, you could iterate through each element of the array and check if the value is 0, then set that value to 1, for example:
for(int i = 0; i < sizeOfArray; i++)
{
for(int j = 0; j < sizeOfArray; j++)
{
//Check if this value is 0;
//If it is 0, set it to 1, otherwise continue
}
}
int[,] array = new int[,] {{1,2,3},
{4,5,6},
{7,8,9}};
//Suppose you want to find 2,5,8
for(int row = 0; row < 3; row++)
{
for(int column = 0; column < 3; column++)
{
if((row == 0 && column == 1) || (row == 1 && column == 1) || (row == 2 && column == 1))
{
Console.WriteLine("Row: {0} Column: {1} Value: {2}",row + 1, column + 1, array[row, column]);
}
}
}
Here is the code you need, not much explain:
//Read the size of the array, you can get it from .Count() if you wish
int n = Convert.ToInt32(Console.ReadLine());
int[][] a = new int[n][];
//Reading all the values and preparing the array (a)
for (int a_i = 0; a_i < n; a_i++)
{
string[] a_temp = Console.ReadLine().Split(' ');
a[a_i] = Array.ConvertAll(a_temp, Int32.Parse);
}
//performing the operation (google what diagonal matrix means)
int PrimarySum = 0, SecondarySum = 0;
for (int i = 0; i < n; i++)
{
//The If condition is to skip the odd numbers
if (a[i][i] % 2 == 0) { PrimarySum += a[i][i]; }
//For the reverse order
int lastelement = a[i].Count() - 1 - i;
if (a[i][lastelement] % 2 == 0) { SecondarySum += a[i][lastelement]; }
}
//Get the absolute value
Console.WriteLine(Math.Abs(PrimarySum - SecondarySum).ToString());
Console.ReadKey();

Categories