How to process list of numbers(arrays) in C# - c#

I have a list of multiple consecutive numbers. I am trying to figure it out how to know the number of increase or decrease in relation to to past value . For example
102, 201, 198, 200
That is 2 increase (102, 201 and 198, 200) and 1 decrease (201, 198). It is a long list of number so manual is tedious. I am a beginner using C#.

There are many ways, from querying with help of Linq:
using System.Linq;
...
int[] source = new int[] { 102, 201, 198, 200 };
...
// Probably, the most generic approach
var result = source.Aggregate(
(Inc: 0, Dec: 0, prior: (int?)null),
(s, a) => (s.Inc + (s.prior < a ? 1 : 0), s.Dec + (s.prior > a ? 1 : 0), a));
Console.Write($"Increasing: {result.Inc}; decreasing: {result.Dec}");
up to good old for loop:
int Inc = 0;
int Dec = 0;
// Probably, the easiest to understand solution
for (int i = 1; i < source.Length; ++i)
if (source[i - 1] > source[i])
Dec += 1;
else if (source[i - 1] < source[i])
Inc += 1;
Console.Write($"Increasing: {Inc}; decreasing: {Dec}");
Edit: Linq Aggregate explained.
Aggregate(
(Inc: 0, Dec: 0, prior: (int?)null),
(s, a) => (s.Inc + (s.prior < a ? 1 : 0), s.Dec + (s.prior > a ? 1 : 0), a));
In order to obtain single value from a cursor, we use Aggregate.
First argument
(Inc: 0, Dec: 0, prior: (int?)null)
is the initial value (named tuple, to combine several properties in one instance). Here we have 0 increasing and decreasing and null for the previous item.
Second argument
(s, a) => (s.Inc + (s.prior < a ? 1 : 0), s.Dec + (s.prior > a ? 1 : 0), a)
Is a rule how to add a next item a to aggregated items s. We should
Increment s.Inc in case prior item is smaller than current a: s.Inc + (s.prior < a ? 1 : 0)
Increment s.Dec in case prior item is bigger than current a: s.Dec + (s.prior > a ? 1 : 0)
We should assign current item a as the next prior element.
Let's put it a bit wordy but I hope more readable:
.Aggregate(
(Inc: 0, // no increasing
Dec: 0, // no decreasing
prior: (int?)null // no prior item
),
(s, a) => ( // s - partial aggregation, a - to add item
Inc: s.Inc + (s.prior < a ? 1 : 0), // Increment Inc if required
Dec: s.Dec + (s.prior > a ? 1 : 0), // Increment Dec if required
prior: a // Set a as a prior
)
)
Hope, now it's clearer what's going under the hood of Aggregate

int[] source = new int[] { 102, 201, 198, 200 };
int Increment = 0;
int Decrement= 0;
int k;
for (k=1; k< array.length; k++)
if (array[k - 1] > array[k])
Decrement++;
else
{
if (array[k - 1] < array[k])
Increment++;
}
Console.Write("Increasing: {Increment}, decreasing: {Decrement}");
}

In this situation you can use a for loop:
for (int i = 0; i < listOfNumbers.Length; i++)
{
int currentEntry = listOfNumbers [i];
if(i > 0){
int previousEntry = listOfNumbers [i - 1];
Console.Log("Change from previous : " + (currentEntry-previousEntry));
}else{
Console.Log("No previous entry so no change can be found.");
}
}

Related

C# how to check if adjacent values are greater or smaller in an array and allocate points based on values?

I am trying to figure out how to assign points based on adjacent number values in an array. By default, each number is worth one point, and it increases in value if the adjacent numbers are lower than the current number.
For values at the start and the end of the array, the adjacent values are the end and start, so for numbers[0] adjacent values are numbers[5] && numbers[1] and for numbers[5] the values would be numbers[4] && numbers[0]. Consider it going in a circle.
As an example of numbers let's say we have int[] numbers = new int[] { 5, 6, 4, 2, 5, 6 }; after point allocation the output should be something like 1 3 2 1 2 3.
The issue I'm facing is that I don't know how to write the code in such a way that I don't get an error. And I would like to avoid using a lot of if nested functions. Managed to get it working like that but it looks horrible, so scrapped that and figured there must be a better way of doing this but I seem to be stuck...
static int[] AssignPoints (int[] numbers) {
int[] points = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++) {
points[i]++; //allocating initial point
???
}
return points;
}
static int[] AssignPoints (int[] numbers) {
int[] points = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
int prevIndex = (i-1 < 0 ? numbers.Length -1 : i-1);
int nextIndex = (i+1 >= numbers.Length ? 0 : i + 1);
if (numbers[i] > numbers[prevIndex])
points[i]++;
if (numbers[i] > numbers[nextIndex])
points[i]++;
}
return points;
}
A very explicit example:
static int[] AssignPoints (int[] numbers) {
int[] points = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++) {
var leftIndex = i == 0 ? numbers.Length - 1 : i - 1;
var rightIndex = i == numbers.Length - 1 ? 0 : i + 1;
points[i] = 1
+ (numbers[i] > numbers[leftIndex] ? 1 : 0)
+ (numbers[i] > numbers[rightIndex] ? 1 : 0);
}
return points;
}
static List<int> AssignPoints(List<int> numbers)
{
List<int> points =new List<int>(numbers.Capacity);
int i = 0, point;
foreach (int item in numbers)
{
point = 1;
if(i != 0)
if (numbers[i - 1] < numbers[i]) point++;
if(i != numbers.Capacity -1)
if (numbers[i + 1] < numbers[i]) point++;
i++;
points.Add(point);
}
return points;
}

Add Int[] array into List<int[]>

I'm having trouble with int[] arrays and adding them to a List<>. I'd like to add the values of my int[] array to something each loop but every time I do this my "something" gets the same value for every element I add. Very annoying. I understand arrays are always reference vars. However even the "new" key word doesn't seem to help. What needs to happen is to add result to some enumerated object like a List or Array or ArrayList.
Here's the codility question:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
I copied some code from others and the variable "result" does indeed load the data correctly. I just wanted to copy it back to the main program so I could see it. The only method that works is += add it into a string. Thus losing any efficiency I might have gained.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testarray
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[7];
A[0] = 3;
A[1] = 4;
A[2] = 4;
A[3] = 6;
A[4] = 1;
A[5] = 4;
A[6] = 4;
List<int[]> finish = solution(5, A);
}
public static List<int[]> solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
int iter = 0;
List<int[]> collected_result = new List<int[]>;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray<int>();
}
collected_result.Add(result);
}
// for (int i = 0; i < result.Length; i++)
//result[i] = Math.max(resetLimit, result[i]);
return collected_result;
}
}
}
This doesn't work, the collected_result ends up like:
(0,0,1,2,0)
(0,0,1,2,0)
(0,0,1,2,0)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
I know it's the line collected_result.Add(result); adding the reference each time to every instance of result in the List<>. Bother. I've tried adding "new" which is a compiler error. Finally in desperation I just added everything to a very long string. Can someone help me figure out how to properly load an object to pass back to main?
Easiest way to go:
Get a copy of your array before adding it to list:
collected_result.Add(result.ToArray());
Here is a Python solution:
def solution(A, N):
lenA = len(A)
k = 0
max_counter_value = 0
counters = [0 for x in range(0, N)]
for k in range(0, lenA):
if A[k] >= 1 and A[k] <= N:
counters[A[k] - 1] += 1
max_counter_value = max(counters)
if A[k] == N + 1:
counters = [max_counter_value for x in range(0, N)]
print counters
A = [3, 4, 4, 6, 1, 4, 4]
N = 5
solution(A, N)

Find number of ways in a maze non recursively

Given a matrix[n,n] I want to find out how many ways we can reach from [0,0] to [n,n] non recursively.
My approach is to
Create a stuct Node to store row, col and path travelled so far
Add node to a Queue
Iterate thru queue till not empty . Increment row, increment col. Add to Queue
Print the path if row=n, col=n
Question
Is there a different way of storing row,col and path
If n is very large, storing nodes in Queue can be a problem. How can we avoid this?
Please not I am not looking for recursive solution.
I see such questions in many interview forums and so want to know if this would be the right approach.
Below is the structure of Node and the function
struct Node
{
public int row;
public int col;
public string path;
public Node(int r, int c, string p)
{
this.row = r;
this.col = c;
this.path = p;
}
}
public static void NextMoveNonRecursive(int max)
{
int rowPos;
int colPos;
string prevPath = "";
Node next;
while (qu.Count > 0)
{
Node current = qu.Dequeue();
rowPos = current.row;
colPos = current.col;
prevPath = current.path;
if (rowPos + 1 == max && colPos + 1 == max)
{
Console.WriteLine("Path = ..." + prevPath);
TotalPathCounter++;
}
if (rowPos + 1 < max)
{
if (prevPath == "")
prevPath = current.path;
prevPath = prevPath + ">" + (rowPos + 1) + "" + (colPos);
next = new Node(rowPos + 1, colPos, prevPath);
qu.Enqueue(next);
prevPath = "";
}
if (colPos + 1 < max)
{
if (prevPath == "")
prevPath = current.path;
prevPath = prevPath + ">" + (rowPos) + "" + (colPos+1);
next = new Node(rowPos, colPos+1, prevPath);
qu.Enqueue(next);
prevPath = "";
}
}
}
Let dp[i, j] be the number of paths from [0, 0] to [i, j].
We have:
dp[0, i] = dp[i, 0] = 1 for all i = 0 to n
dp[i, j] = dp[i - 1, j] + come down from all paths to [i - 1, j]
dp[i, j - 1] + come down from all paths to [i, j - 1]
dp[i - 1, j - 1] come down from all paths to [i - 1, j - 1]
for i, j > 0
Remove dp[i - 1, j - 1] from the above sum if you cannot increase both the row and the column.
dp[n, n] will have your answer.
Given a matrix [n,n], how many ways we can reach from [0,0] to [n,n] by increasing either a col or a row?
(n*2-2) choose (n*2-2)/2
If you can only go down or right (i.e., increase row or col), it seems like a binary proposition -- we can think of 'down' or 'right' as '0' or '1'.
In an nxn matrix, every path following the down/right condition will be n*2-2 in length (for example, in a 3x3 square, paths are always length 4; in a 4x4 square, length 6).
The number of total combinations for 0's and 1's in binary numbers of x digits is 2^x. In this case, our 'x' is n*2-2, but we cannot use all the combinations since the number of 'down's or 'right's cannot exceed n-1. It seems we need all binary combinations that have an equal number of 0's and 1's. And the solution is ... tada:
(n*2-2) choose (n*2-2)/2
In Haskell, you could write the following non-recursive function to list the paths:
import Data.List
mazeWays n = nub $ permutations $ concat $ replicate ((n*2-2) `div` 2) "DR"
if you want the number of paths, then:
length $ mazeWays n
Javascript solutions with sample
var arr = [
[1, 1, 1, 0, 0, 1, 0],
[1, 0, 1, 1, 1, 1, 0],
[1, 0, 1, 0, 1, 0, 0],
[1, 1, 0, 0, 1, 0, 0],
[1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1]
];
function sols2(arr){
var h = arr.length,
w = arr[0].length,
i, j, current, left, top;
for(i = 0; i < h; i++){
for(j = 0; j < w; j++){
current = arr[i][j];
top = i === 0 ? 0.5 : arr[i - 1][j];
left = j === 0 ? 0.5 : arr[i][j-1];
if(left === 0 && top === 0){
arr[i][j] = 0;
} else if(current > 0 && (left > 0 || top > 0)){
arr[i][j] = (left + top) | 0;
} else {
console.log('a6');
arr[i][j] = 0;
}
}
}
return arr[h-1][w-1];
}
sols2(arr);

Finding Consecutive repetition of Elements in C# Array and Altering the element

I was given this problem
Given an int array length 3, if there is a 2 in the array immediately followed by a 3,
set the 3 element to 0.
For Example ({1, 2, 3}) → {1, 2, 0}
({2, 3, 5}) → {2, 0, 5}
({1, 2, 1}) → {1, 2, 1}
And this is my implementation.
int[] x = { 1, 2, 1 };
for (int i = 0; i < x.Length; i++)
{
if (x[i] == 2 && x[i + 1] == 3)
{
for (int j = 0; j < x.Length; j++)
{
if (x[j]==3)
{
x[j] = 0;
}
}
}
}
foreach (int i in x)
{
Console.Write(i);
}
I got zero as result. Can you help me to find where I am at mistake. I can't figure it out because the lecturer didn't gave any explanation in details.
You do not need all these loops: with the length of 3, you need to perform only two checks, like this:
if (x[0]==2 && x[1]==3) x[1] = 0;
if (x[1]==2 && x[2]==3) x[2] = 0;
For arrays of arbitrary size, you could use a single loop:
for (var i = 0 ; i < x.Length-1 ; i++) {
if (x[i]==2 && x[i+1]==3) x[i+1] = 0;
}
In your code, you have a proper check: if (x[i] == 2 && x[i + 1] == 3) However, there are 2 things you could improve on.
1) If you're going to do x[i + 1] you need to make sure that i can never be the last element of the array, because the + 1 will overflow the array. So instead of i < x.Length in the for loop, try i < x.Length - 1. It seems like duct taping, but there isn't really a better way (none I know of).
2) If the condition is true, you then have a for that will find and replace EVERY 3 in the array with a 0, regardless of if the 3 is preceded by a 2. You already know that x[i] is 2 and x[i + 1] is 3 (as determined by the if that we know at this point must be true), so the index of the 3 to be replaced is i + 1, thus: x[i + 1] = 0; No loop needed.
You can do it with one loop.
// In the test part of the for loop, use ' i < x.Length - 1'
// so you don't evaluate the last element + 1 and get an IndexOutOfRangeException
for (int i = 0; i < x.Length - 1; i++)
{
if (x[i] == 2 && x[i + 1] == 3)
x[i + 1] = 0;
}

Printing out 3 elements in array per line

I have an array with x number of elements and want to print out three elements per line (with a for-loop).
Example:
123 343 3434
342 3455 13355
3444 534 2455
I guess i could use %, but I just can't figure out how to do it.
For loop is more suitable:
var array = Enumerable.Range(0, 11).ToArray();
for (int i = 0; i < array.Length; i++)
{
Console.Write("{0,-5}", array[i]);
if (i % 3 == 2)
Console.WriteLine();
}
Outputs:
0 1 2
3 4 5
6 7 8
9 10
Loop through the array 3 at a time and use String.Format().
This should do it...
for (int i = 0; i < array.Length; i += 3)
Console.WriteLine(String.Format("{0,6} {1,6} {2,6}", array[i], array[i + 1], array[i + 2]));
But if the number of items in the array is not divisable by 3, you'll have to add some logic to make sure you don't go out of bounds on the final loop.
You perhaps need to fix the format spacing...
for(int i=0;i<array.Length;i++)
{
Console.Write(array[i] + " ");
if((i+1)%3==0)
Console.WriteLine();
}
Long... but with comments:
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int count = list.Count;
int numGroups = list.Count / 3 + ((list.Count % 3 == 0) ? 0 : 1); // A partially-filled group is still a group!
for (int i = 0; i < numGroups; i++)
{
int counterBase = i * 3;
string s = list[counterBase].ToString(); // if this a partially filled group, the first element must be here...
if (counterBase + 1 < count) // but the second...
s += list[counterBase + 1].ToString(", 0");
if (counterBase + 2 < count) // and third elements may not.
s += list[counterBase + 2].ToString(", 0");
Console.WriteLine(s);
}

Categories

Resources