Stack, I can't quite wrap my head around this oddity. I'm evaluating the positions within the array, each time. How is it that by initializing the array each time I receive different results... I would appreciate if someone can explain this.
In While Loop: Correct
0,1,0,1,1,0,0,1
0,1,1,0,0,0,0,0
0,0,0,0,1,1,1,0
0,1,1,0,0,1,0,0
0,0,0,0,0,1,0,0
0,1,1,1,0,1,0,0
0,0,1,0,1,1,0,0
0,0,1,1,0,0,0,0
Outside While Loop (Initialized Once): Incorrect
0,1,0,1,1,0,0,1
0,1,1,0,0,0,0,0
0,0,1,0,1,0,1,0
0,0,1,1,0,0,1,0
0,0,0,1,0,0,1,0
0,1,1,0,1,1,0,0
0,0,1,1,1,0,1,0
0,0,0,0,1,1,0,0
Question Details
There are 8 prison cells in a row, and each cell is either occupied or vacant.
Each day, whether the cell is occupied or vacant changes according to the following rules:
If a cell has two adjacent neighbors that are both occupied or both vacant, then the cell becomes occupied.
Otherwise, it becomes vacant.
(Note that because the prison is a row, the first and the last cells in the row can't have two adjacent neighbors.)
We describe the current state of the prison in the following way: cells[i] == 1 if the i-th cell is occupied, else cells[i] == 0.
Given the initial state of the prison, return the state of the prison after N days (and N such changes described above.)
Example 1: Expected Output
Input: cells = [0,1,0,1,1,0,0,1], N = 7
Output: [0,0,1,1,0,0,0,0]
Explanation:
The following table summarizes the state of the prison on each day:
Day 0: [0, 1, 0, 1, 1, 0, 0, 1]
Day 1: [0, 1, 1, 0, 0, 0, 0, 0]
Day 2: [0, 0, 0, 0, 1, 1, 1, 0]
Day 3: [0, 1, 1, 0, 0, 1, 0, 0]
Day 4: [0, 0, 0, 0, 0, 1, 0, 0]
Day 5: [0, 1, 1, 1, 0, 1, 0, 0]
Day 6: [0, 0, 1, 0, 1, 1, 0, 0]
Day 7: [0, 0, 1, 1, 0, 0, 0, 0]
Method
static public int[] PrisonAfterNDays(int[] cells, int N)
{
int counter = 0;
//Doesn't work if it's here
//int[] temp = new int[8];
while(counter < N)
{
Console.WriteLine(String.Join(",",cells));
//Works if it's here ?!?!?!
int[] temp = new int[8];
for(int j = 1; j < 8-1; j++)
{
if(cells[j-1] == cells[j+1])
{
temp[j] = 1;
}
else
{
temp[j] = 0;
}
}
cells = temp;
counter++;
}
return cells;
}
Remember that even though int is a value type, arrays are reference types, so int[] is a reference type. (See What is the difference between a reference type and value type in c#?)
When you execute cells = temp;, you point cells and temp at the exact same array! You can test this with the following code:
int[] a = new int[2];
int[] b = a;
b[0] = 85;
b[1] = 3;
Console.WriteLine(a[0]); // prints 85
Console.WriteLine(a[1]); // prints 3
So this means that on the second iteration of the outer loop, the following code changes both cells[j] and temp[j]:
temp[j] = 1;
Which, clearly, means you will get strange results.
For this reason, I'd argue that you should define temp within the loop.
class Solution:
def prisonAfterNDays(self, states: List[int], n: int) -> List[int]:
# Since we have 6 cells moving cells (two wil remain unchaged at anytime)
# the cycle will restart after 14 iteration
# 1- The number of days if smaller than 14 -> you brute force O(13)
# 2- The number is bigger than 14
# - You do a first round of 14 iteration
# - Than you do a second round of n%14 iteration
# ===> O(27)
if n < 14:
# iif n
for _ in range(n):
states = self.getNewStates(states)
else:
for _ in range(14):
states = self.getNewStates(states)
for _ in range(n%14):
states = self.getNewStates(states)
return states
def getNewStates(self, states: List[int]) -> List[int]:
newStates = ["0"] * len(states)
for i in range(1, len(states)):
if i != 0 and i != len(states) - 1 and states[i-1] == states[i+1]:
newStates[i] = "1"
return newStates
Related
I have read some number of implementations for example, What is the best way to find all combinations of items in an array?
What's nice about their implementation is many are Generic , not just array of int (or worse, array of positive int's only)
I cannot however find something that can take items which is array (Name array "S") of size m. Taking items from array "S", put them into another array "P" of size n (with n smaller than m, a common restriction I dont understand).
For example,
S = [-1, 1]
P[j] = [1,1,1,1], [1, -1, 1, 1], [1, -1, -1, 1], [1, -1, -1, -1], [-1, -1, -1, -1], ... [-1, 1, 1, -1], [1, -1, -1, 1], [-1, 1, -1, 1], [1, -1, 1, -1]
j = permutations = 0 ... pow(m,n), in this example pow(2, 4) = 16
Anything in C# or python please?
Also, time complexity...
References:
What is the best way to find all combinations of items in an array?
https://codereview.stackexchange.com/questions/194967/get-all-combinations-of-selecting-k-elements-from-an-n-sized-array?newreg=92ded52aec7b4f9aaf161db14d07ee7a
Would something like this work?
def f(ms, k):
stack = [[m] for m in ms]
while stack:
next = stack.pop()
if len(next) == k:
yield next
else:
stack.extend([(next[:] + [m]) for m in ms])
print([comb for comb in f([-1, 1], 4)])
Csharp version (Dont allow mixed type. Also size > 100 may crash your machine)
static IEnumerable<IEnumerable<T>> Permutations<T>(IEnumerable<T> set, int size)
{
Stack<IList<T>> stack = new Stack<IList<T>>();
foreach(var item in set)
{
var list = new List<T>() { item };
stack.Push(list);
}
while(stack.Count>0)
{
var next = stack.Pop();
if(next.Count==size)
{
yield return next;
}
else
{
foreach(var item in set)
{
var list = new List<T>();
list.AddRange(next);
list.Add(item);
stack.Push(list);
}
}
}
}
To use:
int[] possibleValues = new int[] { -1, 1 };
var permutations = Permutations(possibleValues, 4);
foreach(var permutation in permutations)
{
foreach (int x in permutation)
{
Console.Write($"{x} \t");
}
}
import itertools
size = 4
for S in list ( itertools . product ([1 , -1] , repeat = size )):
I have a set of numbers in the form of { -1, 0, +1 } which I have to iterate over using two loops, much like you would when using a 2D array.
The whole set then becomes every combination of the numbers above:
{ -1, -1 } -> { +1, +1 }, which is 9 in total.
However, the set { 0, 0 } I have to skip. Normally I would just check with an if statement, but using this inside two nested loops will make it check for this condition on every run.
Is there an efficient way to somehow do this?
UPDATE: I feel this deserves a little more detail, because there might be a completely different solution this problem than what I want to do above.
It is basicly to check adjacent cells within an array. So { 0, 0 } is cell we are checking, but I wish to check every cell adjacent to it, not including the main cell.
Imagine we had a 2D array int[,] array = new int[,] { ... };
If we then access the array at any index approximately in the middle of it (not close to any edge index; like the bottom/top row or bottom/top column), our conceptual bird's eye view of the array would look like this:
[-1, -1] [-1, 0] [-1, +1]
[0, -1] [0, 0] [0, +1]
[+1, -1] [+1, 0] [+1, +1]
[0,0] is our current element. We can access every adjacent element/cell using the above numbers for [row,column].
A typical loop to do this would look like this:
for (int i = row-1; i <= row+1; ++i) {
for (int j = col-1; j <= col+1; ++j) {
if (i == row && j == col) continue;
...
}
}
Can we avoid the if statement?
After your edit, it seems you don't need loops at all and your desired result has 8 well defined elements.
So you coud simply create a little method that gives you all adjacent cells to your main cell:
Point[] GetAdjacentPoints(Point p)
{
return new[]{
new Point { X = p.X - 1, Y = p.Y - 1 },
new Point { X = p.X, Y = p.Y - 1 },
new Point { X = p.X + 1, Y = p.Y - 1 },
new Point { X = p.X - 1, Y = p.Y },
// leave out p itself
new Point { X = p.X + 1, Y = p.Y },
new Point { X = p.X - 1, Y = p.Y + 1},
new Point { X = p.X, Y = p.Y + 1},
new Point { X = p.X + 1, Y = p.Y + 1}
};
}
(I assume Point to be something like struct Point {public int X {get;set;} public int Y {get;set;}} or any other type to hold two integers).
You can use this method like this:
foreach(Point adjacent in GetAdjacentPoints(new Point {X = 0, Y = 0})
Console.WriteLine($"X: {adjacent.X} Y: {adjacent.Y}");
Output:
X: -1 Y: -1
X: 0 Y: -1
X: 1 Y: -1
X: -1 Y: 0
X: 1 Y: 0
X: -1 Y: 1
X: 0 Y: 1
X: 1 Y: 1
Just compute every single pair and then remove the one pair you want to exclude from your final set. [well implemented] Sets are specifically designed for efficient removal (more efficient than linear anyway, O(1) for hash based sets, O(log(n)) for tree based sets), so that will be faster than checking every single value in the set, which is what you would be doing by having the check in your loop.
I suggest you measure it first and see if this is really a problem, because depending on the type of collection you're using, the Add operation may be more costly than the if statement (in my case below, it consists of creating a new list and then adding that list to another list).
For example, using a List<int> to hold the original set, and a List<List<int>> to hold the combinations, I find that using the if statement is faster than not using it (and if we don't use it then we still need to iterate over the pairs to find the ones we want to remove).
Below is the test I ran, using loops with the if and without the if, with 2001 items in the set (from -1000 to 1000), which creates a total of 4004000 sets. I ran the tests in a loop 100 times and displayed the average time in an attempt to get the most accurate result:
private static void Main()
{
var items = Enumerable.Range(-1000, 2001).ToList();
var combinations = new List<List<int>>();
var withIfCount = new List<long>();
var withoutIfCount = new List<long>();
var sw = new Stopwatch();
// Both test are run 100 times
for (int count = 0; count < 100; count++)
{
sw.Restart();
for (int outer = 0; outer < items.Count; outer++)
{
for (int inner = 0; inner < items.Count; inner++)
{
if (outer == 0 && inner == 0) continue;
combinations.Add(new List<int> {outer, inner});
}
}
sw.Stop();
withIfCount.Add(sw.ElapsedMilliseconds);
combinations.Clear();
sw.Restart();
for (int outer = 0; outer < items.Count; outer++)
{
for (int inner = 0; inner < items.Count; inner++)
{
combinations.Add(new List<int> {outer, inner});
}
}
sw.Stop();
withoutIfCount.Add(sw.ElapsedMilliseconds);
combinations.Clear();
}
// Display averages
Console.WriteLine("Average time with 'if': " + withIfCount.Average());
Console.WriteLine("Average time without 'if': " + withoutIfCount.Average());
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output
I was trying to find (using a code listed below) a simple solution for copying all the objects which are stored in first array, to second array, with changing paralelly the index of objects in second array + 1, so the object[0] in first array would be equal to object[1] in second one, and the last object[9] in the first one would be equal to the object[0] in second.
While trying to start code which I've written I've received message, which stated that "Destination array was not long enough Check destIndex and length, and the array's lower bounds", I'm just starting with arrays part at c#, so I'd be very gratefull for any quidance.
static void Main(string[] args)
{
int[] first = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
int[] second = new int[first.Length];
Array.Copy(first, 0, second, 1, 10);
foreach (int x in second)
{
Console.WriteLine("{0}", x);
}
Console.ReadKey();
}
}
Instead of Array.Copy and foreach you can do this:
for (int i = 0; i < first.Length; i++)
second[i == first.Length - 1 ? 0 : i + 1] = first[i];
It just goes from i = 0 to i = first.Length-1, copying the element at that index in first to that index plus 1 in second.
If the idea is to rotate the array one position forward, you can use a simple for:
static void Main(string[] args)
{
int[] first = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
int[] second = new int[first.Length];
for (int k = 0; k < first.Length; k++)
second[(k == (first.Length - 1))? 0: k + 1] = first[k];
foreach (int x in second)
{
Console.WriteLine("{0}", x);
}
Console.ReadKey();
}
I am looking for a way to get all combination of a list item.
what i thinking is to have a two dimention array, similary to a bit map
e.g bit[][] mybitmap;
for example if i have 4 item in my list "A, B, C, D"
i want my bitmap to be populate like this
A B C D
0, 0, 0, 1 --> D
0, 0, 1, 0 --> C
0, 0, 1, 1 --> C, D
0, 1, 0, 0 --> B
0, 1, 0, 1
0, 1, 1, 0
0, 1, 1, 1
1, 0, 0, 0
1, 0, 0, 1
1, 0, 1, 0
1, 0, 1, 1 --> A, C, D
1, 1, 0, 0
1, 1, 0, 1
1, 1, 1, 0
1, 1, 1, 1 --> A, B, C, D
but how can i write some C# code to populate my bit map?
(PS: my list might have items around 80 to 90, not 100 to 200, just confirmed)
Thanks
So... just count from 1 to 15 (=(2^n)-1), and write as binary, perhaps using shift operations.
This is sane for small numbers... but gets rather large quite quickly. For 64 items you can model in a long, but that is 18,446,744,073,709,551,615 combinations... hint: you are never, ever, ever going to loop that far.
For small cases:
int n = 4;
int max = 1 << n;
for (long val = 1; val < max; val++)
{
long mask = 1 << (n - 1);
for (int bit = 0; bit < n; bit++)
{
bool set = (val & mask) != 0;
Console.Write(set ? "1 " : "0 ");
mask >>= 1;
}
Console.WriteLine();
}
Agree with Marc Gravell. You cannot pretend to generate a list like the one you describe and then collect the elements you need.
I've been doing something similar, but I only needed a subset of all the combinations, so I was filtering my elements during the list generation process. This way, each recursive iteration (I was using F#) does not create the elements that I already know that will be discarded at the end.
With this approach I could perform variations of 200 elements and get the list of valid results (which I already knew it was going to be not so big...)
In case you are interested, the problem you are describing is a combinatory problem. There's a nice article in C# here
I believe you don't need to store all combinations in memory.
Just start from array with all zero bits (first combination). To get next combination just add 1 to last bit of previous combination (it is easily implementing operation). And so on.
Low memory usage, support of up to 2 billions of digits. :)
private void button1_Click(object sender, EventArgs e)
{
string[] items = {"A", "B", "C", "D"};
bool[] bits = new bool[items.Length];
for (int i = 0; i < bits.Length; i++)
{
bits[i] = false;
}
while (!bits.All(x => x))
{
listBox1.Items.Add(string.Join(", ", GetCombination(items, bits)));
AddBit(bits, bits.Length - 1);
}
}
public string[] GetCombination(string[] items, bool[] bits)
{
List<string> combination = new List<string>();
for (int i = 0; i < bits.Length; i++)
{
if (bits[i])
{
combination.Add(items[i]);
}
}
return combination.ToArray();
}
private void AddBit(bool[] bits, int pos)
{
if (pos < 0)
{
// overflow :)
return;
}
if (bits[pos])
{
bits[pos] = false;
AddBit(bits, pos - 1);
}
else
{
bits[pos] = true;
}
}
I am trying to write a function which iterates through an array and when it finds a certain type of value it will shift it to the right a defined number of places.
I know how to shift elements by temporarily storing a value, shifting the right side elements to the left and then writing the temporary value in the correct place.
The bit I am struggling with is if the certain character appears near the end of the array I need it to wrap around and continue from the start of the array, so is circular.
So an array shifting, for example, capital letters to the right 3 places and special characters to the left 1 place:
{ M, y, N, a, m, e, P} becomes...
{ y, M, P, a, N, m, e}
To shift an element of 8 to the right 3 places I have below, but this only works if 8 appears earlier than 3 elements from the end of the array and will not wrap around.
input array:
{0, 1, 2, 3, 4, 5, 6, 7, **8**, 9}
desired output:
{0, **8**, 1, 2, 3, 4, 5, 6, 7, 9}
int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = array.Length - 1; i >= 0; i--)
{
if (array[i] == 8)
{
int temp = array[i];
int j = 0;
for (j = i; j < i + 3; j++)
{
array[j] = array[j + 1];
}
array[j] = temp;
}
}
Just use modulo arithmetic so that instead of writing to the element at index j as you shift, instead write to the element at index j % array.Length. Thusly:
public void FindAndShift<T>(T[] array, T value, int shift) {
int index = Array.IndexOf(array, value);
int shiftsRemaining = shift;
for(int currentPosition = index; shiftsRemaining > 0; shiftsRemaining--) {
array[currentPosition % array.Length] = array[(currentPosition + 1) % array.Length];
}
array[(index + shift) % array.Length] = value;
}
I have excluded error checking.
You can do it with an if statement, check if there is room enough before the end of the array and if it isn't you have to calculate how many steps to shift in the beginning of the array aswell.
I also think that you can do it by calculating the positions modulo the length of the array when you do the shifting, I can't try it at the moment but the logic in my head says that it should work.