Given a matrix print the given triangle - c#

Given 2 dimensional:
int[,] arr2d = new int[3,3]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Objective: Print the 2d array in the given triangle pattern so it appears as below:

I thought this is print along its main diagonal.
.
In the example case, we list the indices of arr2d:
(0, 2)
(0, 1), (1, 2)
(0, 0), (1, 1), (2, 2)
(1, 0), (2, 1)
(2, 0)
See the regular pattern?
In the first 3 lines, the x of first element on each line remains 0, and the y decreases.
In the last 3 lines, the y of first element on each line remains 0, and the x increases.
In each line, next element relative to previous is (x++, y++), until either x or y ≥3.
For more general way, a n dimensional matrix has 2n-1 line of trangle.
In the first n lines, the x of first element remains to 0, the y decreases.
In the last n lines, the y of first element remains to 0, the x increases.
For each line, print (x++, y++) until either x or y ≥3.
Here's the code:
static void Main(string[] args) {
int[,] arr2d = new int[3,3]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int dimension = 3;
int x = 0, y = dimension - 1
while(y >= 0) {
WriteDiagalNumbers(arr2d, x, y, dimension);
y--;
// or shorten as
// WriteDiagalNumbers(arr2d, x, y--, dimension);
}
x = 1;
y = 0;
while(x < dimension) {
WriteDiagalNumbers(arr2d, x, y, dimension);
x++;
// or shorten as
// WriteDiagalNumbers(arr2d, x++, y, dimension);
}
}
static void WriteDiagalNumbers(int[,] arr, int x, int y, int dimension) {
List<int> nums = new List<int>();
while(x < dimension && y < dimension) {
nums.Add(arr[x, y]);
x++;
y++;
// or shorten as
// nums.Add(arr[x++, y++]);
}
Console.WriteLine(string.Join(", ", nums));
}
Gives the output:
3
2, 6
1, 5, 9
4, 8
7

I like Sheey's answer, though it bothers me that the array dimensions are hard-coded in that solution. So here's a generic approach using GetUpperBound() to determine the number of rows/columns.
Calling GetUpperBound(0) would tell you how many ROWS, while GetUpperBound(1) would give the number of COLUMNS.
We can get the coordinates of all the diagonal starting positions by starting in the upper right corner of the array and moving left. Once we hit the left side we travel down the array. From each of those starting positions we get the diagonal values by incrementing both of the starting x/y positions while they are within the bounds of the array. This is one of those rare occasions where a for loop with multiple variables can be used.
The code also pads the output based on the largest value so that the triangle can handle any size integers.
Note that when accessing a 2D array, the x and y parameters are reversed:
arr[y, x]
You list the y value as the first parameter, and the x value as the second parameter.
So with this array:
int[,] arr2d = new int[,]
{
{85, 86, 87, 88},
{89, 90, 91, 92},
{93, 94, 95, 96},
{97, 98, 99, 100}
}
The 88 value, using zero based notation, would be normally thought of as at coordinates (2, 0), but would be accessed with arr2d[0, 2].
Similarly, the 97 value would be normally thought of as at coordinates (0, 2), but would be accessed with arr2d[2, 0].
I felt this approach was different enough to warrant an additional answer to the question:
static void Main(string[] args)
{
int[,] arr2d = new int[,]
{
{85, 86, 87, 88},
{89, 90, 91, 92},
{93, 94, 95, 96},
{97, 98, 99, 100}
};
printTriangle(arr2d);
Console.Write("Press Enter to quit...");
Console.ReadLine();
}
static void printTriangle(int[,] arr)
{
// Get all the starting positions for "diagonals":
// Start in the top right of the array,
// then move all the way left,
// followed by all the way down.
int y = 0;
int x = arr.GetUpperBound(1);
bool travelLeft = true;
bool triangleComplete = false;
List<string> diagonalValues = new List<string>();
int pad = arr.Cast<int>().Max().ToString().Length;
while (!triangleComplete)
{
diagonalValues.Clear();
for(int yTemp = y, xTemp = x;
xTemp <= arr.GetUpperBound(1) && yTemp <= arr.GetUpperBound(0);
xTemp++, yTemp++)
{
diagonalValues.Add(arr[yTemp, xTemp].ToString().PadLeft(pad));
}
Console.WriteLine(String.Join(", ", diagonalValues));
if (travelLeft)
{
x--; // move left
travelLeft = (x > 0);
}
else
{
y++; // move down
triangleComplete = (y > arr.GetUpperBound(1));
}
}
}
Output:
88
87, 92
86, 91, 96
85, 90, 95, 100
89, 94, 99
93, 98
97
Press Enter to quit...

Related

Custom sorting array - smaller values between larger values

I have an array A with values: {10, 12, 6, 14, 7} and I have an array B with values: {1, 8, 2}
I have sorted the array B in an ascending order and then combined both the arrays in a new array C as shown in the following code -
static void Main()
{
int A[] = {10, 12, 6, 14, 7};
int B[] = {1, 8, 2};
Array.Sort(B);
var myList = new List<int>();
myList.AddRange(A);
myList.AddRange(B);
int[] C = myList.ToArray();
//need values in this order: 10, 1, 12, 2, 8, 6, 14, 7
}
Now I wanna sort the array C this way: 10, 1, 12, 2, 8, 6, 14, 7
The smaller values should be between the larger values, for ex: 1 is between 10 and 12, 2 is between 12 and 8, 6 is between 8 and 14, so on and so forth.
How can I do this in C#?
If recursion is needed, how can I add it to the code?
What I understood from your example is that you are trying to alternate between large and small values such that the small value is always smaller than the number to the left and the right. I wrote an algorithm below to do that however it does not yield the exact same results you requested. However I believe it does meet the requirement.
The straggling 7 is considered the next smallest number in the sequence but there is no number that follows it. Based on your example it appears that is allowed.
To Invoke
int[] A = { 10, 12, 6, 14, 7 };
int[] B = { 1, 8, 2 };
var result = Sort(A, B);
Sort Method
public static int[] Sort(int[] A, int[] B)
{
var result = new int[A.Length + B.Length];
var resultIndex = 0;
Array.Sort(A);
Array.Sort(B);
//'Pointer' for lower index, higher index
var aLeft = 0;
var aRight = A.Length-1;
var bLeft = 0;
var bRight = B.Length - 1;
//When Items remain in both arrays
while (aRight >= aLeft && bRight >= bLeft)
{
//Add smallest
if (resultIndex % 2 > 0)
{
if (A[aLeft] < B[bLeft])
result[resultIndex++] = A[aLeft++];
else
result[resultIndex++] = B[bLeft++];
}
//Add largest
else
{
if (A[aRight] > B[bRight])
result[resultIndex++] = A[aRight--];
else
result[resultIndex++] = B[bRight--];
}
}
//When items only in array A
while (aRight >= aLeft)
{
//Add smallest
if (resultIndex % 2 > 0)
result[resultIndex++] = A[aLeft++];
//Add largest
else
result[resultIndex++] = A[aRight--];
}
//When items remain only in B
while (bRight >= bLeft)
{
//Add smallest
if (resultIndex % 2 > 0)
result[resultIndex++] = B[bLeft++];
//Add largest
else
result[resultIndex++] = B[bRight--];
}
return result;
}
Result
[14, 1, 12, 2, 10, 6, 8, 7]

C# percentile rank algorithm

I'm trying to reverse engineer a calculation that was done on an old program but can't quite get it. I need a count of how many values are in the top 27%, middle 46%, and bottom 27%.
I have the following data sets with eleven values in each and what the program yields in regards to the percentages and the number of values that fall into those percentiles.
Upper 27%: 4, Middle 46%: 4, Lower 27%: 3
values: 8,9,10,11,11,11,11,12,12,12,13
Upper 27%: 5, Middle 46%: 4, Lower 27%: 2
values: 2,3,4,4,4,4,5,5,5,5,5
Upper 27%: 2, Middle 46%: 8, Lower 27%: 1
values: 2,4,4,4,4,4,4,4,4,5,5
Upper 27%: 2, Middle 46%: 6, Lower 27%: 3
values: 13,17,17,18,19,19,19,21,21,23,24
I have found formulas such as (n * p) where n is the number of values and p is the percentile but it doesn't seem to work across all of these data sets to give the same results. I'm a little lost and haven't found anything that produces the results here.
I have tested code that I have found on the internet but none have worked on the different data sets.
Code sample that I tried:
internal static double percentile(double[] sortedData, double p)
{
if (p >= 100.0d) return sortedData[sortedData.Length - 1];
double position = (double)(sortedData.Length + 1) * p / 100.0;
double leftNumber = 0.0d, rightNumber = 0.0d;
double n = p / 100.0d * (sortedData.Length - 1) + 1.0d;
if (position >= 1)
{
leftNumber = sortedData[(int)System.Math.Floor(n) - 1];
rightNumber = sortedData[(int)System.Math.Floor(n)];
}
else
{
leftNumber = sortedData[0]; // first data
rightNumber = sortedData[1]; // first data
}
if (leftNumber == rightNumber)
return leftNumber;
else
{
double part = n - System.Math.Floor(n);
return leftNumber + part * (rightNumber - leftNumber);
}
}
Is there a formula or a name for what I am trying to do? Am I on the right track with percentile ranks?
You're on the right path. This is indeed the percentile rank formula. My initial thought was to get the value at the 27th percentile (which looking at your code it looks like you started down this path as well) and figure out how many values were greater than or less than; but the values you provided don't support these numbers very well.
Therefore the approach I took was to calculate the percentile rank of each number and put it into a count if they matched the percentile you have above. This seems to be the approach they took.
Formula (check out this website for more info):
PR% = L + ( 0.5 x S ) / N
Where,
L = Number of below rank,
S = Number of same rank,
N = Total numbers.
Code:
var lower = 0;
var middle = 0;
var upper = 0;
// var values = new int[] { 8, 9, 10, 11, 11, 11, 11, 12, 12, 12, 13 };
// var values = new int[] { 2, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
// var values = new int[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5 };
var values = new int[] { 13, 17, 17, 18, 19, 19, 19, 21, 21, 23, 24 };
var n = values.Length;
foreach(var i in values)
{
var pr = ((values.Count(v => v < i) + (.5 * values.Count(v => v == i))) / n);
if (pr < .27)
lower += 1;
else if (pr > .73)
upper += 1;
else
middle += 1;
}
Console.WriteLine("Upper: " + upper);
Console.WriteLine("Middle: " + middle);
Console.WriteLine("Lower: " + lower);

cannot convert type System.Collections.Generic.Icollection<int> to int

I want to obtain all the possible ways to make a certain price using four basic denominations (1,5,10,25). I have the following code. I know it generates the results in a collection but I don’t know how to extract the integers at runtime. Can someone help?
void CoinCalculator()
{
//function that checks how many coins and of what denomation the player needs
//get a copy of the purse contents
priceChecker = ApplicationManager.am_keyPrice; //hold key Price
List<ICollection<int>> coins = new List<ICollection<int>> ();
coins.Add(CoinChange1.GetCoinSets(priceChecker)[0]);
}
public class CoinChange1
{
private int[] cs = new [] {25, 10, 5, 1};
private List<ICollection<int>> solutions = new List<ICollection<int>> ();
public static IList<ICollection<int>> GetCoinSets(int total) {
// Handle corner case outside of recursive solution
if (total == 0)
return new List<ICollection<int>> ();
// Get all possible sets
CoinChange1 cc = new CoinChange1 ();
cc.GetCoinSets (total, 0, new Stack<int>());
return cc.solutions;
}
private void GetCoinSets(int n, int csi, Stack<int> combo) {
// Find largest allowable coin (exploiting that cs is ordered descendingly)
while (cs[csi] > n)
csi++;
int c = cs [csi];
combo.Push (c); // Track coin selection
if (n == c)
solutions.Add(combo.ToArray()); // Base case
else
GetCoinSets (n - c, csi, combo); // Recursion 1: with a selected coin
combo.Pop ();
// Recurse for all other possibilities beyond this point with a combo of smaller coin units
if(csi < (cs.Length - 1))
GetCoinSets (n, csi + 1, combo);
}
}
you have a list of collections so to output them to the console for example:
foreach(ICollection<int> coll in solutions)(
{
foreach(int item in coll)
{
Console.WriteLine(item);
}
}
Because you have alist of collections you must iterate the list and for each item in the list iterate the collection to get to your int.
You can just iterate over the result and "print" them or do whatever you want. For instance.
var result = GetCoinSets(priceChecker );
// display result
for (int i = 0; i < result.Count; i++) {
string valuesSeparatedByComma = string.Join(", ", result[i]);
Debug.WriteLine($"Combinaison #{i + 1}: {valuesSeparatedByComma}");
}
would display if you enter 15:
Combinaison #1: 5, 10
Combinaison #2: 1, 1, 1, 1, 1, 10
Combinaison #3: 5, 5, 5
Combinaison #4: 1, 1, 1, 1, 1, 5, 5
Combinaison #5: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5
Combinaison #6: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1

Get all groups on n from array of length k

I am looking for the best way to get all possible int arrays of length n from int array of length k, including an option for n-1 items to be null.
for example I have the array with 5 elements (k=5) and I want all combinations of 3 (n=3)
int[] numbers = new int[5] {1, 2, 3, 4, 5};
and the possible sub arrays of length 3:
{1,null,null},{1,null,2},{1,2,null}..... and so on.
What would be the best way to do it?
Matan
You could include null in your numbers array.
This code produces all possible permutations except of {null, null, null}.
var numbers = new int?[]{null, 1, 2, 3, 4, 5};
var result = new List<int?[]>();
foreach (int? x in numbers)
{
foreach (int? y in numbers)
{
foreach (int? z in numbers)
{
if (x == null && y == null && z == null)
continue;
result.Add(new int?[] { x, y, z });
Console.WriteLine("x: {0} - y: {1} - z: {2}", x, y, z);
}
}
}

c# - How can I add a value to a multi array?

I have this array here:
float[, ,] vectors;
int pos = 0;
void Start() {
vectors = new float[,,] { {
{ 0, 1, 1 },
{ 0, 2, 2 } }
};
}
This works. I fill the array with numbers.
Now I want to add some values again to a given position. But how?
This are not working:
vectors[pos] = new float[,,] { { { 33, 44, 55 } } };
or
vectors[pos] = { { { 33, 44, 55 } } };
I searched, but not found the right answer.
EDIT:
I want something like this:
[0]+
[0] {1, 2, 3},
[1] {4, 5, 6}
[1]+
[0] {11, 22, 33},
[1] {44, 55, 66},
[2] {77, 88, 99}
...
etc.
Now, e.g. I want add values {10,10,10} to pos = 0. But how?
If you want to add values I suggest using generic lists instead of arrays. And you should create your own Vector class or find one that is suitable to your needs like this.
public class Vector
{
public float X { get; private set; }
public float Y { get; private set; }
public float Z { get; private set; }
public Vector(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
Then you can do the following
var vectors = new List<List<Vector>>
{
new List<Vector>{
new Vector(0, 1, 1),
new Vector(0, 2, 2)
}
};
vectors[0].Add(new Vector(33,44,55));
And your vectors will contain
[0]
[0] {0, 1, 1}
[1] {0, 2, 2}
[2] {33, 44, 55}
Note that if you need to add to the first dimention you have to do this.
vectors.Add(new List<Vector>());
vectors[1].Add(new Vector(1, 2, 3));
And now you have
[0]
[0] {0, 1, 1}
[1] {0, 2, 2}
[2] {33, 44, 55}
[1]
[0] {1, 2, 3}
You should determine the other positions within the array, you are just specifying one. If your problem cannot be solved within lists
you can try array of arrays as follows
float [][][] x = new float [n][m][];
// initialize the third dimension until m is reached
x[0] = new float {1,2,3,4,5}; // specify whatever value you want
x[1] = new float {3,2,4};
x[2] = new float [3];
// etc until m is reached
// do the same for the n dimension
This will work for you, the array is assigned, you cannot change it you must expand the array as is.
float[, ,] vectors;
int pos = 0;
vectors = new float[,,]
{
{
{ 0, 1, 2 }, { 0, 3, 4 }
}
};
vectors = new float[,,]
{
{
{vectors[0,0,0], vectors[0,0,1], vectors[0,0,2]}, { vectors[0,1,0], vectors[0,1,1], vectors[0,1,2] }, { 33,44,55}
}
};

Categories

Resources