This has been bugging me for a few hours so I was wondering if anyone could help me out as I might be thinking about this the wrong way.
I want to be able to get a boolean value from a set of x and y coordinates on an grid with an infinite width and height. There are also other constraints, along the x axis there needs to be at least n places between two true values, I would also need to know the number of true values in the area from 0,0 to x,y.
The width and height of the area given to getTrueCoordinatesInArea is equal to x and y as its the area is created from 0,0 to x,y
If that makes sense..
So for example:
value = coordinateContainsTrue( x, y );//return true or false.
total = getTrueCoordinatesInArea( x , y );//Returns the total true values inside the area.
Edit: This would work off a seed.
I don't understand exacly what you need but I thought it sounded like a good and fun exercise. I hoped it's what you wanted. =) It's not coded exactly how I wanted. Would rather have used a bool[,] array but don't know how to make that one dynamic and didn't want to code my own class for this, but maybe I should have.
However, this solution should work.
private List<List<bool>> grid = new List<List<bool>>();
private int N = 4;
Random randomNumberGenerator = new Random();
private bool getRandomBoolean()
{
return this.randomNumberGenerator.Next(0, 2) == 1;
}
private void testProgram()
{
var containsTrue = coordinateContainsTrue(0, 10);
var total = getTrueCoordinatesInArea(14, 2);
var isTrue = coordinateIsTrue(15, 11);
}
private bool coordinateIsTrue(int x, int y)
{
expandGridOfNeeded(x, y);
return grid[x][y];
}
private bool coordinateContainsTrue(int x, int y)
{
expandGridOfNeeded(x, y);
for (int xTemp = 0; xTemp < x; xTemp++) // Loop columns
{
for (int yTemp = 0; yTemp < y; yTemp++) // Loop rows
{
if (grid[xTemp][yTemp])
return true; // Return true if any true was found
}
}
return false;
}
private int getTrueCoordinatesInArea(int x, int y)
{
expandGridOfNeeded(x, y);
var total = 0;
for (int xTemp = 0; xTemp < x; xTemp++) // Loop columns
{
for (int yTemp = 0; yTemp < y; yTemp++) // Loop rows
{
if (grid[xTemp][yTemp])
total++; // Increase count if true was found
}
}
return total;
}
private void expandGridOfNeeded(int x, int y)
{
if (x < 0 || y < 0)
return;
// Add needed columns
while (grid.Count <= x)
{
var column = new List<bool>();
// Only add rows if the others have rows
if (grid.Count > 0)
{
while (column.Count < grid[0].Count)
{
// Check if legal to add a true value, if it is then add random else add false
bool forceFalseValue = false;
for (int i = grid.Count - 1; i > grid.Count + N && forceFalseValue == false; i--)
{
forceFalseValue = grid[i][column.Count - 1];
}
column.Add(forceFalseValue ? false : getRandomBoolean());
}
}
grid.Add(column);
}
// Add needed rows
while (grid[0].Count <= y)
{
var counter = N;
foreach (var column in grid)
{
// Check if legal to add a true value, if it is then add random else add false
if (counter < N)
{
column.Add(false);
counter++;
}
else
{
var randomValue = getRandomBoolean();
if (randomValue)
counter = 0;
else
counter++;
column.Add(randomValue);
}
}
}
}
Related
I'm currently working for a distribution center with ~500 shelves with items for sale and ready to be shipped out to customers. I have decided to create a ranking for each aisle, where the best selling products will be stored at the front and the worst selling products will be stored at the back. I assumed that this would automatically improve efficience in my warehouse. However, after implementing this (see here). After using BFS to simulate a warehouse worker's route it's turned out that this new layout is actually taking more steps for a worker to complete than a regular non-optimized layout..
This is my code for BFS, however I think my problem lies in the way I decide where high demand items go, not in my BFS.
List<String> findPathBFS(magazijnObject[,] grid, bool[,] vis,
string start, string goal)
{
List<string> path = new List<string>();
// Stores indices of the matrix cells
Queue<pair> q = new Queue<pair>();
int row = 0; int col = 0;
// Mark the starting cell as visited
// and push it into the queue
for (int x = 0; x < grid.GetLength(0); x++)
for (int y = 0; y < grid.GetLength(1); y++)
{
if (grid[x, y].Locatie == start)
{
row = x; col = y;
x = grid.GetLength(0); y = grid.GetLength(1);
break;
}
}
q.Enqueue(new pair(row, col, null));
vis[row, col] = true;
// Iterate while the queue
// is not empty
while (q.Count != 0)
{
pair cell = q.Peek();
int x = cell.first;
int y = cell.second;
if (grid[x, y].Locatie == goal)
{
//Console.WriteLine(cell.parent.first + " " + cell.parent.second);
findPath(cell, path);
return path;
}
q.Dequeue();
// Go to the adjacent cells
for (int i = 0; i < 4; i++)
{
int adjx = x + dRow[i];
int adjy = y + dCol[i];
if (isValid(vis, adjx, adjy, grid))
{
if (grid[adjx, adjy].Loopbaar || grid[adjx, adjy].Locatie == goal)
#Locatie = Location of item in aisle, Loopbaar = whether or not a worker can walk here.
{
q.Enqueue(new pair(adjx, adjy, cell));
vis[adjx, adjy] = true;
}
}
}
}
return path;
}
And this is my pair Class which defines a cell and it's parent
class pair
{
public int first, second;
public pair parent;
public pair(int first, int second, pair parent)
{
this.first = first;
this.second = second;
this.parent = parent;
}
public String toString()
{
return (first + " " + second);
}
}
static int[] dRow = { -1, 0, 1, 0 };
static int[] dCol = { 0, 1, 0, -1 };
static bool isValid(bool[,] vis,
int row, int col, magazijnObject[,] test)
{
// If cell lies out of bounds
if (row < 0 || col < 0 ||
row >= test.GetLength(0) || col >= test.GetLength(1))
return false;
// If cell is already visited
if (vis[row, col])
return false;
// Otherwise
return true;
}
private static void findPath(pair node, List<String> path)
{
if (node != null)
{
findPath(node.parent, path);
path.Add(node.toString());
}
}
I'm curious to see whether you have any ideas on how to improve this layout in a way. As this obviously is not an improvement.
Kind regards,
D.
I am using this backtracking soduku solving algorithm which is really good and efficient
private void solve()
{
for (var y = 8; y >= 0; y--)
{
for (var x = 8; x >= 0; x--)
{
var a = grid[y, x];
if (a == 0)
{
for (var n = 1; n <= 9; n++)
{
if (possible(y, x, n))
{
grid[y, x] = n;
solve();
grid[y, x] = 0;
}
}
return;
}
}
}
print();
}
The thing is i want to add a little change which I haven't been able to do and it is that instead of trying numbers 1 to 9 in order i want it to choose a random number from 1 to 9, and then set it in the grid, without repetition of course.
public static class MyRandomGenerator
{
private static Random random = new Random();
public static int[] Generate(int inclusiveMinValue, int exclusiveMaxValue)
{
if (exclusiveMaxValue <= inclusiveMinValue)
throw new ArgumentException(nameof(exclusiveMaxValue));
var capacity = exclusiveMaxValue - inclusiveMinValue;
var result = new HashSet<int>(capacity);
while (result.Count < capacity)
{
result.Add(random.Next(inclusiveMinValue, exclusiveMaxValue));
}
return result.ToArray();
}
}
I'm very new to programming and have yet to understand methods & return values. I've created the following method. (As my assignment requires) I'm supposed to return a value, but I am unsure what type of value. I've tried returning the matrix I created, but I'll get an error
Cannot implicitly convert type 'int' to 'Opdracht2.Position'
Sorry if this is a bad question but I don't know how or where else to ask. The method is used to find the position of a specific number in the 2-dimensional array/matrix.
class Position
{
Position FindNumber(int[,] matrix, int findNumber)
{
Console.WriteLine("Give the number to be searched: ");
findNumber = int.Parse(Console.ReadLine());
int row = matrix.GetLength(0);
int col = matrix.GetLength(1);
int y, x;
for(y = 0; y < col; y++)
{
for(x = 0; x < row; x++)
{
if (findNumber == matrix[y, x])
{
return matrix[x, y];
}
}
}
}
}
The return type is the first thing in the function definition line:
// +--- This is the return type
// |
// v
Position FindNumber(int[,] matrix, int findNumber)
The return type is Position which isn't defined in the code you posted. This is a custom type; it can be a struct or a class. It sounds like part of your assignment is to create this custom type, instantiate it in your function, populate it, then return it.
You can return a tuple (int xPos, int yPos)
public (int xPos, int yPos) FindNumber(int[,] matrix, int findNumber)
{
Console.WriteLine("Give the number to be searched: ");
findNumber = int.Parse(Console.ReadLine());
int row = matrix.GetLength(0);
int col = matrix.GetLength(1);
int y, x;
for (y = 0; y < col; y++)
{
for (x = 0; x < row; x++)
{
if (findNumber == matrix[y, x])
{
return (x, y);
}
}
}
return (-1, -1);
}
Or if you MUST use Position class instead of
return (x, y)
you can do
return new Position { xPosition = x, yPosition = y };
Assuming that you name 2 properties as (x/yPosition)
I have a 2D array of boolean[30,10]. those are all set to false. I only want to check if the Rows are filled. so example. if the rows of the 0th column are all true. Then I debug returning say: "First row are all true". Same goes for all other columns. If the 5th column and his rows are also all true. Then I return say: "Fifth row of booleans are all true"
private bool[,] grid = new bool[30,10];
for( int y = 0; x < grid.GetLength(0); y++ )
{
for( int x = 0; x < grid.GetLength(1); x++ )
{
if ( grid[y,x] == true )
{
Debug.Log(y + "th rows are filled!");
}
}
}
There are just my pseudo codes. they don't work i know. but does someone know how to?
first of, a very small issue, in your first for loop you, you wrote
for (int y = 0; **x** < grid.GetLength(0); y++)
instead you should write:
for (int y = 0; **y** < grid.GetLength(0); y++) ;
but unfortunately it's not the problem :(
In your code you are going through every element in a row and checking if it is true, and here is the problem, this if statement:
if(grid[y,x] == true){
Debug.Log(y + "th rows are filled!");
is checking if the first element is true, if it is, it will print out that the whole
row is filled with true variables. Instead I offer this solution:
bool[,] grid = new bool[2,2];
bool isRowTrue = true;
for (int y = 0; y < grid.GetLength(0); y++)
{
for (int x = 0; x < grid.GetLength(1); x++)
{
if (grid[y, x] == false)
{
isRowTrue = false;
break;
}
}
if (isRowTrue == true)
{
Debug.Log(y + "th are all true!");
}
else {
isRowTrue = true;
}
}
I hope I've understood your problem correctly, if not, my apologies, tell me and I will try to understand and help.
To loop through check if an array of values is all true do this:
private bool[,] grid = new bool[30,10];
for(int y = 0; x < grid.GetLength(0); y++){
bool row = true;
for(int x = 0; x < grid.GetLength(1); x++)
row &&= grid[y,x]; // row stays true until it encounters a false
if (row) Debug.Log(y + " row is filled");
}
Try this:
int rows = 30;
int cols = 10;
bool[,] grid = new bool[rows,cols];
InitializeGrid(grid);
for (int row = 0 ; row < rows ; ++row )
{
bool isAllTrue = true;
for( int col = 0 ; col < cols ; ++col {
if ( !grid[row,col] )
{
isAllTrue = false;
break;
}
}
if (isAllTrue)
{
Console.WriteLine($"Row {row} is all true");
}
}
You can do it in a single foreach loop like
private bool[,] grid = new bool[30,10];
bool allAreTrue = true;
foreach(var b in grid)
{
if(!b)
{
allAreTrue = false;
// No need to check others anymore
break;
}
}
Or you could use Linq All after converting the multi dimensional array to an enumerable using Linq OfType
using System.Linq;
...
private bool[,] grid = new bool[30,10];
var allAreTrue = grid.OfType<bool>().All(b => !b);
I don't understand why the messagebox keeps displaying 0. For each sequence there is a direction. The purpose of the random function is to find the best point to start a new sequence. There seems to be a problem with my howfree function, I can't understand what the problem is, please help me.
public int howfree(int x, int y)
{
int freenum = 0;
int counter = 0;
foreach (GameForm.direction dirs in (GameForm.direction[]) Enum.GetValues(typeof(GameForm.direction)))
{
for (int j = 0; j < 5; j++)
{
y += Directions[(int)dirs, 0];
x += Directions[(int)dirs, 1];
if ( InBoard(y, x) && cells[y,x].cellType == Type.EMPTY)
{
counter++;
}
else
break;
}
if (counter == 5)
{
freenum++;
}
counter = 0;
}
return freenum;
}
///////////////////////////////////////////////////////////////////////////////
public Cell Randomize()
{
int row=0;
int col=0;
Random random = new Random();
int rand = 0;
//bool Found = false;
int max = 0;
int fff=0;
List<Cell> Options = new List<Cell>();
foreach (Cell CCC in cells)
{
fff=howfree(CCC.row,CCC.col);
if (fff > max)
max = fff;
}
foreach (Cell c in cells)
{
if (howfree(c.row, c.col) == max)
{
Options.Add(new Cell(c.row, c.col));
}
}
// while (!Found)
// {
rand = (int)random.NextDouble() * (Options.Count - 1);
//row = random.Next() * (Settings.Rows);
//col = random.Next() * (Settings.Cols);
MessageBox.Show(rand.ToString());
row = Options[rand].row;
col = Options[rand].col;
//}
return new Cell(row, col);
}
Why not use the overload that's designed for integers?
rand = random.Next(Options.Count);
From the MSDN documentation:
Returns a nonnegative random integer that is less than the specified maximum.
You're doing it wrong.
rand = (int)random.NextDouble() * (Options.Count - 1);
Random.NextDouble() will produce number between 0 and less than 1.0.
That means it can get up to 0.999 (You get my point) but will never be 1.
When you use explicit int cast on a fraction less bigger than 0 and less than 1 you will always get 0.
You should have done it like this:
rand = (int)(random.NextDouble() * (Options.Count - 1));
So now it will int cast after the count of options.