Print all points in an infinite grid of n dimensions - c#

I can not have infinite points stored in the computer, but what I mean by that is the max value of Int64 (long).
I could use a nested loop, but that would take an eternity to go to the next line, so I found another way.
All the points whose x and y values add upto n are on a diagonal.
(0,0) - 0
(1,0),(0,1) - 1
(2,0),(1,1),(0,2) - 2
(all of these are diagonals)
So we could iterate through all values of n, from 0 to max value of long, that would give us all the points on all the diagonals.
So I wrote the code to do this.
public void Main()
{
for(long i = 0; i < Int64.MaxValue; i++)
{
long[] a = new long[(i + 1)];
long[] b = new long[(i + 1)];
for(long j = 0; j <= i; j++)
{
a[j] = j;
b[j] = (i - a[j]);
}
f(a,b);
}
}
public void f(long[] a, long[] b)
{
string toPrint = "";
for(int i = 0; i < a.Length; i++)
{
toPrint += "(" + a[i] + "," + b[i] + "),";
}
Console.Write(toPrint + "\n\n");
}
It does the job for a grid of 2 dimensions, but I want it to work for n dimensions, the same idea applies

Related

Rotate array of k position performance c#

I'm solving problems on LeetCode, and referring to this problem: 189. Rotate Array
Given an array, rotate the array to the right by k steps, where k is non-negative.
Example 1:
Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]
I gave my solution as:
public void Rotate(int[] nums, int k) {
if (k <= 0)
return;
int t = 0;
for (int i = 0; i < k; i++) {
t = nums[nums.Length - 1];
for (int j = nums.Length - 1; j > 0; j--) {
nums[j] = nums[j - 1];
}
nums[0] = t;
}
}
My question is not about the solution, but is about its performance.
Can I improve my solution to be faster? Or is wrong my approach?
Cause it pass all the test cases, but it fail the last one cause is a big array with big numbers, and it fail on being fast enough, it gives me
"Time Limit Exceeded"
You could run it in a single while loop. I don't have leetcode so I can't test it, I just ran it locally but if you run this what do you get? Also, it doesn't do the in place movement so if there is a memory test it might fail that.
public static int[] Rotate(int[] nums, int k) {
if (k <= 0) return nums;
var n = new int[nums.Length];
var stopAt = nums.Length - k;
while(stopAt < 0) {
stopAt = nums.Length - Math.Abs(stopAt);
}
var i = stopAt;
var y = 0;
while (true) {
n[y] = nums[i];
y++;
i++;
if (i >= nums.Length) {
i = 0;
}
if (i == stopAt) break;
}
return n;
}
There's a trick to performing this in place that involves a transformation over two steps. O(n) time, O(1) space.
Example, k = 3:
1234567
First reverse in place each of the two sections delineated by n-k:
4321 765
Now revese the whole array:
5671234
Reversing sections in place left as an exercise to the reader.
If you are looking for performance you can get rid of nested loops to have O(n) time complexity vs. O(n * n):
Compute what each item of the result array should be
Copy result array into initial one
Code:
public void Rotate(int[] nums, int k) {
int[] result = new int[nums.Length];
for (int i = 0; i < nums.Length; ++i) {
int index = (i + k % nums.Length + nums.Length) % nums.Length;
result[index] = nums[i];
}
Array.Copy(result, nums, nums.Length);
}
Note, that in general case we have a quite complex formula for index:
int index = (i + k % nums.Length + nums.Length) % nums.Length;
we should be ready for negative k (while index must not be negative) and huge k (possible integer overflow). If k >= 0 and k <= 1e5 as Leet Code claims we can simplify index into
int index = (i + k) % nums.Length;
and have compact solution as
public void Rotate(int[] nums, int k) {
int[] result = new int[nums.Length];
for (int i = 0; i < nums.Length; ++i)
result[(i + k) % nums.Length] = nums[i];
Array.Copy(result, nums, nums.Length);
}
Edit: Why % (remainder) appears in index formula?
Let's have a look on what's going on. When i + k is less than nums.Length we should write the value just at i + k index. When i + k == nums.Length we should write at index == 0, when i + k == nums.Length + 1 we should write at index == 1, ..., when i + k == nums.Length + r then we should write at index == r, note that r == (i + k) % nums.Length == (nums.Length + r) % nums.Length == 0 + r == r

Is it possible to move around in an array for new location?

I am messing around and making a text based game, I am using an array as my layout for a map and I have a random starting point, and from that point I want to be able to move up down left and right but I am not sure how to proceed
int[,] dungeon = new int[5, 5] { {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}};
shuffleArray(dungeon);
int startingPoint;
// i think this has to be in the actual game loop for a new random spot?
for(int i = 0; i<1; i++)
{
for(int j = 0; j < 1; j++)
{
startingPoint = dungeon[i,j];
Console.WriteLine(startingPoint);
}
}
void shuffleArray(int[,] arr)
{
int n = arr.GetLength(0);
int m = arr.GetLength(1);
Random rand = new Random();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
swap(arr, i + rand.Next(n - i), j + rand.Next(m - j), i, j);
}
}
}
void swap(int[,] arr, int changed, int changedB, int a, int b)
{
int temp = arr[a, b];
arr[a, b] = arr[changed, changedB];
arr[changed, changedB] = temp;
}
Given a starting point (I'm calling it "position"), you can find the value in the shuffled array with this method:
// position is NOT zero-based! In a 5x5 matrix 1 is the first position
// and 25 is the last position
int getValueAtPosition(int position)
{
//assuming non-jagged board!
var w = dungeon.GetLength(0);
int row = position % w == 0 ? (position / w) : (position / w) + 1;
int col = position % w == 0 ? w : position - ((row - 1) * w);
int location = dungeon[row - 1, col - 1];
return location;
}
Now, if you move left you subtract one from the current position and pass it into this method. Likewise, add 1 to move right.
To move up or down subtract or add 5.
Be sure to check bounds so you don't move out of the matrix when adding or subtracting.

How would you create n nested loops for math?

So, I am trying to wrap my head around understanding how you can use a variable to denote how many times a loop is nested.
Here is an example I write up to simulate the output of dimensions = 4:
static void Main(string[] args)
{
int dimensions = 4; // e.g. for (1, 2, 3, 4), dimensions = 4
Console.WriteLine($"{addNumbers(dimensions)}");
Console.ReadKey();
}
static long addNumbers(int dimensions)
{
long number = 0;
// hard coded to be dimensions = 4
for (int h = 0; h <= dimensions; h++)
for (int i = 0; i <= dimensions; i++)
for (int j = 0; j <= dimensions; j++)
for (int k = 0; k <= dimensions; k++)
number += h + i + j + k; // just some random math
return number;
}
This will present the expected output of:
5000
So to readdress the problem, how can I code to allow this for n dimensions? Thanks for your help!
For arbitrary n dimensions you can loop with a help of array int[] address which represents n dimensions:
static long addNumbers(int dimensions) {
int[] address = new int[dimensions];
// size of each dimension; not necessary equals to dimensions
// + 1 : in your code, int the loops you have i <= dimensions, j <= dimensions etc.
int size = dimensions + 1;
long number = 0;
do {
//TODO: some math here
// i == address[0]; j = address[1]; ... etc.
number += address.Sum();
// next address: adding 1 to array
for (int i = 0; i < address.Length; ++i) {
if (address[i] >= size - 1)
address[i] = 0;
else {
address[i] += 1;
break;
}
}
}
while (!address.All(index => index == 0)); // all 0 address - items're exhausted
return number;
}
Finally, let's add some Linq to look at the results:
int upTo = 5;
string report = string.Join(Environment.NewLine, Enumerable
.Range(1, upTo)
.Select(i => $"{i} -> {addNumbers(i),6}"));
Console.Write(report);
Outcome:
1 -> 1
2 -> 18
3 -> 288
4 -> 5000 // <- We've got it: 5000 for 4 dimensions
5 -> 97200

Strand sort in c# using arrays only

i have a homework using strand sort and i must take the growing sequence of numbers from the initial array and merge them together in the array that represents our result (C#)
Like this one http://imgur.com/nQFzJw7
So far i did something like that
public static int[] Str(int[] a)
{
int i, j, x ,temp,k=0,count=1;
int size = a.Length;
int len = a.Length;
Strand = new int[size];
Merged = new int[size];
for (i = k; i < size; i++)
{
x = a[i];
Strand[0] = x;
for (i = k; i < size; i++) //checking if there's a bigger int than the first one
{
if (a[i] > x)
{
x = a[i];
}
}
for (i = k; i < len; i++)
{
if (a[i] == x) // checking if the max appears more than 1 time
{
temp = a[i];
a[i] = a[len];
a[len] = temp;
len--; //swaps the max numbers to the last position
Strand[count] = x;
count++;
}
}
for (i = 0; i < count; i++) // cant find a way to put in the final merged and sorted array
{
}
count = 1;
k++;
}
Any suggestions?
You always need to extract the first element into strand
strand[0] = a[0]
count = 1
Then you need to extract suitable elements into strand, shifting the rest of array
for i = 1 to size - 1
if a[i] >= strand[count - 1]
strand[count++] = a[i]
else
a[i - count] = a[i]
size = size - count
Then you need merge current strand and merged - look for Merge procedure from MergeSort
Repeat these steps until size becomes 0

Multiknapsack algorithm - out of collection while trying to remove object

I've encountered the problem while working on my multiknapsack solver.
The program is working well on one knapsack but when it comes to multiple knaps there are some problems.
Problem: The items aren't removed from collection. I know that I need to do this, because for the second knapsack its iterating again through the same objects - so the maximized val is the same...
private void Knapsack()
{
List<Plecak> descendingKanps = _plecakList.OrderByDescending(o => o.W).ToList(); // List of configured Kanpsacks in descending order
List<Produkt> descendingProducts = _produktList.OrderByDescending(o => o.cena).ToList(); // List of products to pack in descending order
int N = descendingProducts.Count; //number of items in product list
double maxVal = 0; // accumulated value of one knapsack
foreach (Plecak p in descendingKanps) // for every knapsack...
{
double[,] V = new double[N + 1, (int)p.W + 1]; //array that stores best option (the value of item)
for (int c = 0; c <= p.W; c++) //since its a 0-1 MKP problem so initialize whole array with zeroes
{
V[0, c] = 0;
}
for (int r = 0; r <= N; r++)
{
V[r, 0] = 0;
}
for (int i = 1; i <= N; i++) // constraint of items count
{
for (int wt = 1; wt <= p.W; wt++) //the constraint of weight
{
if (descendingProducts[i - 1].waga < wt + 1) // if weight of the product is less than constraint, so it can be added...
V[i, wt] = Math.Max(descendingProducts[i - 1].cena + V[i - 1, wt - descendingProducts[i - 1].waga], V[i - 1, wt]); // find best solution and add the value to the Value array, comapre the value with the value form previous row
else
V[i, wt] = V[i - 1, wt]; // keep 0, or last best solution
maxVal = V[i, wt]; // assign to variable
}
}
summary.Items.Add("maximum val for knapsack: " + p.nazwa + " is: " + maxVal); // print out the value of knapsack
}
}
This will hopefully turn into an answer, but for now it is a question.
In your code you have this:
for (int c = 0; c <= p.W; c++) //since its a 0-1 MKP problem so initialize whole array with zeroes
{
V[0, c] = 0;
}
for (int r = 0; r <= N; r++)
{
V[r, 0] = 0;
}
You say that you "initialize whole array with zeroes". The above code will do this to an array:
0 0 0 0 0
0 1 1 1 1
0 1 1 1 1
0 1 1 1 1
You'll only ever reach the first column and the top row. If all places in the array should be changed to 0, then this is the correct approach:
for (int r = 0; r <= N; r++)
{
for (int c = 0; c <= p.W; c++)
{
V[r, c] = 0;
}
}
I hope this input can be of help.

Categories

Resources