Rotate a 2D NxN matrix in Concentric Circles - arrays

Given a 2D NxN matrix, visualize it as concentric circles. You have to find the rotated matrix where each element in the circle is rotated by 1 position layer by layer in an alternate clockwise and anticlockwise direction. All rotations should be in-place.
2 3 4 5
1 6 7 8
4 2 1 9
5 3 2 4
should get transformed to
1 2 3 4
4 7 1 5
5 6 2 8
3 2 4 9
I thought about the solution
1> For clockwise circle rotation, read elements in the order
i -> 0 to n-1 and j = 0
j -> 0 to n-1 and i = n-1
i -> n-1 to 0 and j = n-1
j -> n-1 to 0 and i = 0
2> For anti-clockwise circle rotation, read elements in the order
j -> 0 to n-1 and i = 0
i -> 0 to n-1 and j = n-1
j -> n-1 to 0 and i = n-1
i -> n-1 to 0 and j = 0
Code
for(int cnt = 0; cnt < n/2; cnt++)
{
if(cnt%2 == 0) // Clockwise
{
i = cnt; j = cnt;
// while loops for each case
}
else // anti-clockwise
{
i = cnt; j = cnt;
// while loops for each case
}
}
Is there any better approach to solve this problem in O(n2) or better ?

As your array is of size N*N and the desired computation demands each element to be visited atleast once, there cannot be a solution better than O(n^2) which uses 2 dimensional arrays.
I think that your solution will be fine if the operation has to be done single time on the same array.
If you have to do this operation multiple times on the same input array, better create circles from the input array. The data structure of circle should be a CLL (circular linked list). So doing the operation multiple times will be piece of cake as you have to change the root element of the CLL storing the circle info depending on the direction.

I think that this can be solved easily in-place in O(n) time.
(NOTE: O(N) where N is the total number of matrix elements)
The following solution doesn't use four consecutive loops, but uses a small table of [X, Y] deltas that describe the difference between the current coordinate and the next one, when the next coordinate is invalid (i.e outside of the current window) the index to the table itself is advanced and the look-up repeated. The algorithm starts with full window and decreases it by one element from each side every time the nested loop finishes. The whole process repeats until the window defined as [minX, minY, maxX, maxY] is valid (i.e. contains at least 2x2 elements).
This solution doesn't implement swapping cw and ccw, but this is the easiest part to add.
function pad(s, n) {
while(s.length < n)
s = " " + s;
return s;
}
// Create a matrix of [WxH] size.
function Matrix(w, h, data) {
if (Array.isArray(data)) {
if (data.length !== w * h)
throw new Error("Data.length has to match the size " + (w * h) + ".");
}
else {
var n = typeof data === "number" ? data : 0.0;
data = [];
for (var i = 0; i < w*h; i++) data.push(n);
}
this.w = w;
this.h = h;
this.data = data;
}
// Get value at [x, y]
Matrix.prototype.get = function(x, y) {
if (x < 0 || x >= this.w || y < 0 || y >= this.h)
throw new Error("Index [" + x + ", " + y + "] out of bounds");
return this.data[y * this.w + x];
}
// Set value at [x, y] and return the previous value.
Matrix.prototype.set = function(x, y, value) {
if (x < 0 || x >= this.w || y < 0 || y >= this.h)
throw new Error("Index [" + x + ", " + y + "] out of bounds");
var i = y * this.w + x;
var prev = this.data[i];
this.data[i] = value;
return prev;
}
// Log the matrix data.
Matrix.prototype.dump = function() {
var s = "["
var i = 0;
for (var y = 0; y < this.h; y++) {
for (var x = 0; x < this.w; x++, i++) {
s += pad("" + this.data[i], 2);
if (x !== this.w - 1)
s += ","
}
if (y !== this.h - 1)
s += ",\n ";
}
s += "]";
console.log(s);
}
// Shift, `dir` can be "cw" or "ccw".
Matrix.prototype.shift = function(dir) {
var instructions = {
cw : [1, 0, 0, 1,-1, 0, 0,-1],
ccw: [0, 1, 1, 0, 0,-1,-1, 0]
};
var inst = instructions[dir];
// A window, shrink by one from each side after the nested loop is done.
var minX = 0;
var minY = 0;
var maxX = this.w - 1;
var maxY = this.h - 1;
while (minX < maxX && minY < maxY) {
// Always start at the top-left corner and iterate.
var x0 = minX;
var y0 = minY;
var v0 = this.get(x0, y0);
var n = 0;
for (;;) {
var x1 = x0 + inst[n + 0];
var y1 = y0 + inst[n + 1];
if (x1 < minX || x1 > maxX || y1 < minY || y1 > maxY) {
n += 2;
x1 = x0 + inst[n + 0];
y1 = y0 + inst[n + 1];
}
v0 = this.set(x1, y1, v0);
// Last one.
if (x1 === minX && y1 === minY)
break;
x0 = x1;
y0 = y1;
}
minX++;
minY++;
maxX--;
maxY--;
}
}
var a = new Matrix(3, 3, [
1,2,3,
4,5,6,
7,8,9,
]);
a.dump();
a.shift("cw");
a.dump();
var b = new Matrix(4, 4, [
1 ,2 ,3 ,4 ,
5 ,6 ,7 ,8 ,
9 ,10,11,12,
13,14,15,16
]);
b.dump();
b.shift("ccw");
b.dump();

I faced this problem recently in a job interview and I failed to solve it in under one hour.
Then I got home and produced the code below in java. It is recursive and I believe it has O(n^2) complexity. You can also see the code here: https://github.com/lotif/rotateMatrix
You will have first to input the dimension of the (square) matrix and then the numbers of the matrix itself separated by spaces, line by line. For instance:
3
1 2 3
4 5 6
7 8 9
It will return you the matrix rotated clockwise in concentric circles.
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class RotateMatrix {
public static void main(String args[] ) throws Exception {
Scanner s = new Scanner(System.in);
int d = s.nextInt();
int[][] matrix = new int[d][d];
for(int i = 0; i < d; i++) {
for(int j = 0; j < d; j++) {
matrix[i][j] = Integer.parseInt(s.next());
}
}
matrix = rotate(matrix);
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix.length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
s.close();
}
public static int[][] rotate(int[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix.length == 1) {
return matrix;
}
List<Integer> outerCircle = getOuterCircle(matrix);
matrix = removeOuterCircle(matrix);
//rotating outer circle
outerCircle.add(0, outerCircle.remove(outerCircle.size() - 1));
matrix = rotate(matrix);
matrix = addOuterCircle(outerCircle, matrix);
return matrix;
}
private static int[][] addOuterCircle(List<Integer> outerCircle, int[][] matrix) {
int d = matrix.length + 2;
int[][] newMatrix = new int[d][d];
//Adding the outer circle to the matrix
for(int j = 0; j < d; j++) {
newMatrix[0][j] = outerCircle.remove(0);
}
for(int i = 1; i < d; i++) {
newMatrix[i][d-1] = outerCircle.remove(0);
}
for(int j = d-2; j >= 0; j--) {
newMatrix[d-1][j] = outerCircle.remove(0);
}
for(int i = d-2; i >= 1; i--) {
newMatrix[i][0] = outerCircle.remove(0);
}
//Adding the inner matrix
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[i].length; j++) {
newMatrix[i + 1][j + 1] = matrix[i][j];
}
}
return newMatrix;
}
private static List<Integer> getOuterCircle(int[][] matrix) {
int d = matrix.length;
List<Integer> outerCircle = new ArrayList<Integer>();
for(int j = 0; j < d; j++) {
outerCircle.add(matrix[0][j]);
}
for(int i = 1; i < d; i++) {
outerCircle.add(matrix[i][d-1]);
}
for(int j = d-2; j >= 0; j--) {
outerCircle.add(matrix[d-1][j]);
}
for(int i = d-2; i >= 1; i--) {
outerCircle.add(matrix[i][0]);
}
return outerCircle;
}
private static int[][] removeOuterCircle(int[][] matrix) {
int d = matrix.length;
int[][] newMatrix = new int[d-2][d-2];
for(int i = 1; i < d-1; i++) {
for(int j = 1; j < d-1; j++) {
newMatrix[i-1][j-1] = matrix[i][j];
}
}
return newMatrix;
}
}

public class ShiftArray {
static void shiftArray(int[][]a, int index, int n) {
if ((n%2 == 0) && (index >= n/2))
return;
if ((n%2 != 0) && (index > n/2))
return;
int tempRowTopLast = a[index][n-1-index];
int tempColRightLast = a[n-1-index][n-1-index];
int tempRowBottomLast = a[n-1-index][index];
int tempColLeftLast = a[index][index];
int temp, temp2;
temp = tempColLeftLast;
for (int k = index + 1; k < n-index; k++) {
temp2 = a[index][k];
a[index][k] = temp;
temp = temp2;
}
temp = tempRowTopLast;
for (int k = index + 1; k < n-index; k++) {
temp2 = a[k][n-1-index];
a[k][n-1-index] = temp;
temp = temp2;
}
temp = tempColRightLast;
for (int k = n-2-index; k >=index; k--) {
temp2 = a[n-1-index][k];
a[n-1-index][k] = temp;
temp = temp2;
}
temp = tempRowBottomLast;
for (int k = n-2-index; k >=index; k--) {
temp2 = a[k][index];
a[k][index] = temp;
temp = temp2;
}
shiftArray(a, index+1, n);
}
public static void main(String[] args) {
int a[][] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
shiftArray(a, 0, 3);
System.out.println("Rotated array...");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(a[i][j] + ",");
}
System.out.println();
}
}
}

import java.util.Scanner;
public class RotateMatrix
{
static int rows = 0;
static int cols = 0;
public static void main(String[] args)
{
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
rows = scan.nextInt();
cols = scan.nextInt();
int rots = scan.nextInt();
int[][] matrix = new int[rows][cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
matrix[i][j] = scan.nextInt();
}
}
for (int i = 0; i < rots; i++)
rotate(matrix, 0, rows - 1, 0, cols - 1);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
scan.close();
}
public static int[][] rotate(int[][] arr, int rowStart, int rowEnd, int colStart, int colEnd)
{
if (rowStart == rowEnd && colStart == colEnd)
{
return arr;
}
if (rowStart > rowEnd || colStart > colEnd)
{
return arr;
}
int temp = arr[rowStart][colStart];
for (int j = colStart; j < colEnd; j++)
{
arr[colStart][j] = arr[colStart][j + 1];
}
for (int i = rowStart; i < rowEnd; i++)
{
arr[i][colEnd] = arr[i + 1][colEnd];
}
for (int i = colEnd; i > colStart; i--)
{
arr[rowEnd][i] = arr[rowEnd][i - 1];
}
for (int i = rowEnd; i > rowStart; i--)
{
arr[i][colStart] = arr[i - 1][colStart];
}
if (rows == 1)
{
arr[colEnd][rowStart] = temp;
}
else
arr[rowStart + 1][colStart] = temp;
System.out.println("-----------------------------------------\n");
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
System.out.println("-----------------------------------------\n");
rotate(arr, rowStart + 1, rowEnd - 1, colStart + 1, colEnd - 1);
return arr;
}
}

Clockwise rotation by 90 degrees. O(n^2) time and O(1) memory in Python3:
# #param A : list of list of integers
# #return the same list modified
def rotate(A):
for row in range(len(A) // 2):
for col in range(row, len(A)-1 - row): # First col already takes care of last.
r = row
c = col
tmp1 = A[r][c]
while True:
next_r = c
next_c = len(A) - 1 - r
tmp2 = A[next_r][next_c]
A[next_r][next_c] = tmp1
if next_r == row and next_c == col:
break
tmp1 = tmp2
r = next_r
c = next_c
return A

Related

Matrix multiplication by divide and conquer method

This is implementation of matrix multiplication by divide and conquer.
But this code works on only N <= 4.
when N is 8, segmentation fault occurs and i don't know why.
when debugging, i found that matrix index becomes minus but it's ridiculous that it works properly on N == 4. But why N not on N is 8?
Is it because of stack overflow?
Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 8
struct _matrix {
int row_st;
int row_en;
int col_st;
int col_en;
int mat[N][N];
};
typedef struct _matrix matrix;
void print_mat(matrix m) {
for (int i = m.row_st; i <= m.row_en; i++) {
for (int j = m.col_st; j <= m.col_en; j++) {
printf("%d ", m.mat[i][j]);
}
printf("\n");
}
printf("\n");
return;
}
matrix add(matrix a, matrix b) {
int n = a.row_en - a.row_st;
//set result matrix
matrix c;
c.row_st = 0; c.row_en = n; c.col_st = 0; c.col_en = n;
//create submatrices from original matrix by indexing caculation
int arow, acol, brow, bcol, crow, ccol;
for (arow = a.row_st, brow = b.row_st, crow = 0;
arow <= a.row_en; arow++, brow++, crow++) {
for (acol = a.col_st, bcol = b.col_st, ccol = 0;
acol <= a.col_en; acol++, bcol++, ccol++) {
c.mat[crow][ccol] = a.mat[arow][acol] + b.mat[brow][bcol];
}
}
return c;
}
matrix sub(matrix a, matrix b) {
int n = a.row_en - a.row_st;
//set result matrix
matrix c;
c.row_st = 0; c.row_en = n; c.col_st = 0; c.col_en = n;
//create submatrices from original matrix by indexing caculation
int arow, acol, brow, bcol, crow, ccol;
for (arow = a.row_st, brow = b.row_st, crow = 0;
arow <= a.row_en; arow++, brow++, crow++) {
for (acol = a.col_st, bcol = b.col_st, ccol = 0;
acol <= a.col_en; acol++, bcol++, ccol++) {
c.mat[crow][ccol] = a.mat[arow][acol] - b.mat[brow][bcol];
}
}
return c;
}
matrix dc(matrix input1, matrix input2) {
int n = input1.row_en - input1.row_st + 1;
if (n == 2) {
int a, b, c, d, e, f, g, h;
a = input1.mat[input1.row_st][input1.col_st];
b = input1.mat[input1.row_st][input1.col_st+1];
c = input1.mat[input1.row_st+1][input1.col_st];
d = input1.mat[input1.row_st+1][input1.col_st+1];
e = input2.mat[input2.row_st][input2.col_st];
f = input2.mat[input2.row_st][input2.col_st+1];
g = input2.mat[input2.row_st+1][input2.col_st];
h = input2.mat[input2.row_st+1][input2.col_st+1];
matrix output = input1;
output.mat[output.row_st][output.col_st] = a*e + b*g;
output.mat[output.row_st][output.col_st+1] = a*f + b*h;
output.mat[output.row_st+1][output.col_st] = c*e + d*g;
output.mat[output.row_st+1][output.col_st+1] = c*f + d*h;
print_mat(output);
return output;
}
//divide into submatrices using index calculation
matrix a11 = input1;
matrix a12 = input1;
matrix a21 = input1;
matrix a22 = input1;
matrix b11 = input2;
matrix b12 = input2;
matrix b21 = input2;
matrix b22 = input2;
a11.row_st = input1.row_st;
a11.row_en = input1.row_en/2;
a11.col_st = input1.col_st;
a11.col_en = input1.col_en/2;
a12.row_st = input1.row_st;
a12.row_en = input1.row_en/2;
a12.col_st = input1.col_en/2 + 1;
a12.col_en = input1.col_en;
a21.row_st = input1.row_en/2 + 1;
a21.row_en = input1.row_en;
a21.col_st = input1.col_st;
a21.col_en = input1.col_en/2;
a22.row_st = input1.row_en/2 + 1;
a22.row_en = input1.row_en;
a22.col_st = input1.col_en/2 + 1;
a22.col_en = input1.col_en;
b11.row_st = input2.row_st;
b11.row_en = input2.row_en/2;
b11.col_st = input2.col_st;
b11.col_en = input2.col_en/2;
b12.row_st = input2.row_st;
b12.row_en = input2.row_en/2;
b12.col_st = input2.col_en/2 + 1;
b12.col_en = input2.col_en;
b21.row_st = input2.row_en/2 + 1;
b21.row_en = input2.row_en;
b21.col_st = input2.col_st;
b21.col_en = input2.col_en/2;
b22.row_st = input2.row_en/2 + 1;
b22.row_en = input2.row_en;
b22.col_st = input2.col_en/2 + 1;
b22.col_en = input2.col_en;
matrix c;
c.row_st = 0;
c.row_en = n-1;
c.col_st = 0;
c.col_en = n-1;
matrix c11 = c;
matrix c12 = c;
matrix c21 = c;
matrix c22 = c;
c11.row_st = c.row_st;
c11.row_en = c.row_en/2;
c11.col_st = c.col_st;
c11.col_en = c.col_en/2;
c12.row_st = c.row_st;
c12.row_en = c.row_en/2;
c12.col_st = c.col_en/2 + 1;
c12.col_en = c.col_en;
c21.row_st = c.row_en/2 + 1;
c21.row_en = c.row_en;
c21.col_st = c.col_st;
c21.col_en = c.col_en/2;
c22.row_st = c.row_en/2 + 1;
c22.row_en = c.row_en;
c22.col_st = c.col_en/2 + 1;
c22.col_en = c.col_en;
c11 = add(dc(a11, b11), dc(a12, b21));
c12 = add(dc(a11, b12), dc(a12, b22));
c21 = add(dc(a21, b11), dc(a22, b21));
c22 = add(dc(a21, b12), dc(a22, b22));
int tmprow, tmpcol, row, col;
for (tmprow = c11.row_st, row = 0; tmprow <= c11.row_en; tmprow++, row++) {
for (tmpcol = c11.col_st, col = 0; tmpcol <= c11.col_en; tmpcol++, col++) {
c.mat[row][col] = c11.mat[tmprow][tmpcol];
}
}
for (tmprow = c12.row_st, row = 0; tmprow <= c12.row_en; tmprow++, row++) {
for (tmpcol = c12.col_st, col = n/2; tmpcol <= c12.col_en; tmpcol++, col++) {
c.mat[row][col] = c12.mat[tmprow][tmpcol];
}
}
for (tmprow = c21.row_st, row = n/2; tmprow <= c21.row_en; tmprow++, row++) {
for (tmpcol = c21.col_st, col = 0; tmpcol <= c21.col_en; tmpcol++, col++) {
c.mat[row][col] = c21.mat[tmprow][tmpcol];
}
}
for (tmprow = c22.row_st, row = n/2; tmprow <= c22.row_en; tmprow++, row++) {
for (tmpcol = c22.col_st, col = n/2; tmpcol <= c22.col_en; tmpcol++, col++) {
c.mat[row][col] = c22.mat[tmprow][tmpcol];
}
}
print_mat(c);
return c;
}

CS50x Blur Function

I am currently working on the blur function in PSET4 for filter-more, and I am struggling to find the bug in my code. The blur function seems to correctly filter the middle pixel and I would assume other pixels that are not on the edges, but is incorrectly filtering those on the corners and edges. Any nudges in the right direction would be greatly appreciated.
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// Copy to store filtered image into
RGBTRIPLE temp[height][width];
int red_total = 0, blue_total = 0, green_total = 0;
int red_average = 0, blue_average = 0, green_average = 0;
// Goes through each pixel [i][j]
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// Loops through surrounding 3x3 grid and records the average of all of them
for (int h = -1; h < 2; h++)
{
// Checks if the current row is within the image array
if (i + h >= 0 && i + h < height)
{
for (int k = -1; k < 2; k++)
{
// Checks if current column is within image array
if (j + k >= 0 && j + k < width)
{
red_total = red_total + image[i + h][j + k].rgbtRed;
blue_total = blue_total + image[i + h][j + k].rgbtBlue;
green_total = green_total + image[i + h][j + k].rgbtGreen;
}
else continue;
}
}
else continue;
}
// Averages and reassigns pixel value
red_average = round(red_total / 9.0);
blue_average = round(blue_total / 9.0);
green_average = round(green_total / 9.0);
temp[i][j].rgbtBlue = blue_average;
temp[i][j].rgbtRed = red_average;
temp[i][j].rgbtGreen = green_average;
// Resets counter variables
red_total = green_total = blue_total = 0;
red_average = blue_average = green_average = 0;
}
}
// Makes image (original) array equal to the filtered image
for (int x = 0; x < height; x++)
{
for(int y = 0; y < width; y++)
{
image[x][y] = temp[x][y];
}
}
return;
}

Reverse an Array without using reverse Function and other array the same array to be reverse all elements in the same array. size fix

// I am tring but cant do it
int[] arr = {1,3,4,2,5,6};
int n = arr.length,x = 0;
for (int i = 0 ; i < n; i++ ) {
x++;
System.out.println(arr[i]);
}
//try this:
public class reverseArray {
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[] = new int[] { 1,3,4,2,5,6 };
System.out.print("Original array: ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
// method #1: by using extra array
System.out.println();
System.out.print("Reversed array method 1: ");
int j = 0;
int revArr[] = new int[] { arr.length };
for (int i = arr.length - 1; i >= 0; i--) {
revArr[j] = arr[i];
System.out.print(revArr[j] + " ");
}
// method #2: without using extra array
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
System.out.println();
System.out.print("Reversed array method 2: ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}

C Program numbers not sorting array correctly

I have an array of structs for products that I am trying to sort by name, type, price, and quantity. Name and type work, but price and quantity aren't working.
My code is:
else if (sort == sortByPrice)
{
for (int i = 0; i < numProducts; i++)
{
int smallPosition = i;
for (int x = i + 1; x < numProducts; x++)
{
if (list[i].price > list[x].price)
{
smallPosition = x;
}
}
temp = list[i];
list[i] = list[smallPosition];
list[smallPosition] = temp;
}
}
else if (sort == sortByQty)
{
for (int i = 0; i < numProducts; i++)
{
int smallPosition = i;
for (int x = i + 1; x < numProducts; x++)
{
if (list[i].qty > list[x].qty)
{
smallPosition = x;
}
}
temp = list[i];
list[i] = list[smallPosition];
list[smallPosition] = temp;
}
}
Can anyone tell me why it doesn't work/how to fix it?
Following up on Lee Daniel Crocker's comment, you should dynamically compare with the value at smallPosition instead of i so that it will always point to the smallest remaining item:
int smallPosition = i;
for (int x = i + 1; x < numProducts; x++)
{
if (list[smallPosition].price > list[x].price)
{
smallPosition = x;
}
}
You should move the swap code inside the if statement:
for (int i = 0; i < numProducts; i++)
{
for (int x = i + 1; x < numProducts; x++)
{
if (list[i].price > list[x].price)
{
temp = list[i];
list[i] = list[X];
list[X] = temp;
}
}
}
Just use bubble sort.
In the bubble sort you swap the values of the current value is bigger than the next one, if you do this action until you get to the end of the array then the array will be sorted.

Cell Compete Problems

Here is my assignment:
There is a colony of 8 cells arranged in a straight line where each day every cell competes with its adjacent cells(neighbour). Each day, for each cell, if its neighbours are both active or both inactive, the cell becomes inactive the next day,. otherwise itbecomes active the next day.
Assumptions: The two cells on the ends have single adjacent cell, so
the other adjacent cell can be assumsed to be always inactive. Even
after updating the cell state. consider its pervious state for
updating the state of other cells. Update the cell informationof
allcells simultaneously.
Write a fuction cellCompete which takes takes one 8 element array of
integers cells representing the current state of 8 cells and one
integer days representing te number of days to simulate. An integer
value of 1 represents an active cell and value of 0 represents an
inactive cell.
Program:
int* cellCompete(int* cells,int days)
{
//write your code here
}
//function signature ends
Test Case 1:
INPUT:
[1,0,0,0,0,1,0,0],1
EXPECTED RETURN VALUE:
[0,1,0,0,1,0,1,0]
Test Case 2:
INPUT:
[1,1,1,0,1,1,1,1,],2
EXPECTED RETURN VALUE:
[0,0,0,0,0,1,1,0]
This is the problem statement given above for the problem. The code which I have written for this problem is given below. But the output is coming same as the input.
#include<iostream>
using namespace std;
// signature function to solve the problem
int *cells(int *cells,int days)
{ int previous=0;
for(int i=0;i<days;i++)
{
if(i==0)
{
if(cells[i+1]==0)
{
previous=cells[i];
cells[i]=0;
}
else
{
cells[i]=0;
}
if(i==days-1)
{
if(cells[days-2]==0)
{
previous=cells[days-1];
cells[days-1]=0;
}
else
{
cells[days-1]=1;
}
}
if(previous==cells[i+1])
{
previous=cells[i];
cells[i]=0;
}
else
{
previous=cells[i];
cells[i]=1;
}
}
}
return cells;
}
int main()
{
int array[]={1,0,0,0,0,1,0,0};
int *result=cells(array,8);
for(int i=0;i<8;i++)
cout<<result[i];
}
I am not able to get the error and I think my logic is wrong. Can we apply dynamic programming here If we can then how?
private List<Integer> finalStates = new ArrayList<>();
public static void main(String[] args) {
// int arr[] = { 1, 0, 0, 0, 0, 1, 0, 0 };
// int days = 1;
EightHousePuzzle eightHousePuzzle = new EightHousePuzzle();
int arr[] = { 1, 1, 1, 0, 1, 1, 1, 1 };
int days = 2;
eightHousePuzzle.cellCompete(arr, days);
}
public List<Integer> cellCompete(int[] states, int days) {
List<Integer> currentCellStates = Arrays.stream(states).boxed().collect(Collectors.toList());
return getCellStateAfterNDays(currentCellStates, days);
}
private List<Integer> getCellStateAfterNDays(List<Integer> currentCellStates, int days) {
List<Integer> changedCellStates = new ArrayList<>();
int stateUnoccupied = 0;
if (days != 0) {
for (int i1 = 0; i1 < currentCellStates.size(); i1++) {
if (i1 == 0) {
changedCellStates.add(calculateCellState(stateUnoccupied, currentCellStates.get(i1 + 1)));
} else if (i1 == 7) {
changedCellStates.add(calculateCellState(currentCellStates.get(i1 - 1), stateUnoccupied));
} else {
changedCellStates
.add(calculateCellState(currentCellStates.get(i1 - 1), currentCellStates.get(i1 + 1)));
}
}
if (days == 1) {
System.out.println("days ==1 hit");
finalStates = new ArrayList<>(changedCellStates);
return finalStates;
}
days = days - 1;
System.out.println("Starting recurssion");
getCellStateAfterNDays(changedCellStates, days);
}
return finalStates;
}
private int calculateCellState(int previousLeft, int previousRight) {
if ((previousLeft == 0 && previousRight == 0) || (previousLeft == 1 && previousRight == 1)) {
// the state gets now changed to 0
return 0;
}
// the state gets now changed to 0
return 1;
}
Here is my solution in Java:
public class Colony
{
public static int[] cellCompete(int[] cells, int days)
{
int oldCell[]=new int[cells.length];
for (Integer i = 0; i < cells.length ; i++ ){
oldCell[i] = cells[i];
}
for (Integer k = 0; k < days ; k++ ){
for (Integer j = 1; j < oldCell.length - 1 ; j++ ){
if ((oldCell[j-1] == 1 && oldCell[j+1] == 1) || (oldCell[j-1] == 0 && oldCell[j+1] == 0)){
cells[j] = 0;
} else{
cells[j] = 1;
}
}
if (oldCell[1] == 0){
cells[0] = 0;
} else{
cells[0] = 1;
}
if (oldCell[6] == 0){
cells[7] = 0;
} else{
cells[7] = 1;
}
for (Integer i = 0; i < cells.length ; i++ ){
oldCell[i] = cells[i];
}
}
return cells;
}
}
Your program does not distinguish between the number of days to simulate and the number of cells.
#include <bits/stdc++.h>
using namespace std;
int* cellCompete(int* cells,int days)
{
for(int j=0; j<days; j++)
{
int copy_cells[10];
for(int i=1; i<9; i++)
copy_cells[i]=cells[i-1];
copy_cells[0]=0;copy_cells[9]=0;
for(int i=0; i<8; i++)
cells[i]=copy_cells[i]==copy_cells[i+2]?0:1;
}
return cells;
}
int main()
{
int arr[8]={1,1,1,0,1,1,1,1};
int arr2[8]={1,0,0,0,0,1,0,0};
cellCompete(arr2,1);
for(int i=0; i<8; i++)
{
cout<<arr2[i]<<" ";
}
}
Here's some sweet little python code:
def cell(arr, days):
new = arr[:] #get a copy of the array
n = len(arr)
if n == 1: print [0] #when only 1 node, return [0]
for _ in range(days):
new[0] = arr[1] #determine the edge nodes first
new[n - 1] = arr[n - 2]
for i in range(1, n-1):
new[i] = 1 - (arr[i-1] == arr[i+1]) #logic for the rest nodes
arr = new[:] #update the list for the next day
return new
arr = [1, 1, 1, 0, 1, 1, 1, 1]
days = 2
print cell(arr, days)
You can easily do this in Javascript with few lines of code
let cells = [1,1,1,0,1,1,1,1];
let numOfDays = 2;
let changeState = (cellarr)=> cellarr.map((cur, idx, arr)=> (arr[idx-1] ||0) + (arr[idx+1] || 0)===1?1:0);
let newCells =cells;
for (let i = 0 ; i <numOfDays; i++) newCells = changeState(newCells);
console.log(newCells);
This is a C# version of a possible answer. I really struggled with this for a while for some reason!
I also incorporated some of Janardan's stuff above as it helped spur me in the right direction. (cheers!)
The tricky part of the question was dealing with the fact that you had to persist the state of the cell to figure out the next cell competition which I had originally tried with a second array which was messy.
Note: I chose to use the Array.Copy method as I believe it is slightly more efficient and a lot more readable than copying arrays with a for loop when reading through.
Hopefully this helps someone out in the future!
public int[] cellCompete(int[] cell, int day)
{
//First create an array with an extra 2 cells (these represent the empty cells on either end)
int[] inputArray = new int[cell.Length + 2];
//Copy the cell array into the new input array leaving the value of the first and last indexes as zero (empty cells)
Array.Copy(cell, 0, inputArray, 1, cell.Length);
//This is cool I stole this from the guy above! (cheers mate), this decrements the day count while checking that we are still above zero.
while (day-- > 0)
{
int oldCellValue = 0;
//In this section we loop through the array starting at the first real cell and going to the last real cell
//(we are not including the empty cells at the ends which are always inactive/0)
for (int i = 1; i < inputArray.Length - 1; i++)
{
//if the cells below and above our current index are the same == then the target cell will be inactive/0
//otherwise if they are different then the target cell will be set to active/1
//NOTE: before we change the index value to active/inactive state we are saving the cells oldvalue to a variable so that
//we can use that to do the next "cell competition" comparison (this fulfills the requirement to update the values at the same time)
if (oldCellValue == inputArray[i + 1])
{
oldCellValue = inputArray[i];
inputArray[i] = 0;
}
else
{
oldCellValue = inputArray[i];
inputArray[i] = 1;
}
}
}
//Finally we create a new output array that doesn't include the empty cells on each end
//copy the input array to the output array and Bob's yer uncle ;)...(comments are lies)
int[] outputArray = new int[cell.Length];
Array.Copy(inputArray, 1, outputArray, 0, outputArray.Length);
return outputArray;
}
With C#
public static int[] cellCompete(int[] states, int days)
{
if (days == 0) return states;
int leftValue = 0;
int rigthValue = 0;
for (int i = 0; i < states.Length; i++)
{
if (i == states.Length - 1)
rigthValue = 0;
else
rigthValue = states[i + 1];
if (leftValue == rigthValue){
leftValue = states[i];
states[i] = 0;
}
else{
leftValue = states[i];
states[i] = 1;
}
}
cellCompete(states, days - 1);
return states;
}
I think some of the answers above could be more readable (in addition to being more efficient). Use an additional array and alternate updates between them depending on the number of days. You can return the most recently updated array, which will always be the correct one. Like this:
function cellCompete(states, days) {
const newStates = [];
let originalStates = true;
while (days--) {
changeStates(
originalStates ? states : newStates,
originalStates ? newStates : states,
states.length
);
originalStates = !originalStates;
}
return originalStates ? states : newStates;
}
function changeStates(states, newStates, len) {
newStates[0] = !states[1] ? 0 : 1;
newStates[len-1] = !states[len-2] ? 0 : 1;
for (let i = 1; i < len - 1; i++) {
newStates[i] = states[i-1] === states[i+1] ? 0 : 1;
}
}
Here is my solution in c++ using bitwise operators :
#include <iostream>
using namespace std;
void cellCompete( int *arr, int days )
{
int num = 0;
for( int i = 0; i < 8; i++ )
{
num = ( num << 1 ) | arr[i];
}
for( int i = 0; i < days; i++ )
{
num = num << 1;
num = ( ( ( num << 1 ) ^ ( num >> 1 ) ) >> 1 ) & 0xFF;
}
for( int i = 0; i < 8; i++ )
{
arr[i] = ( num >> 7 - i ) & 0x01;
}
}
int main()
{
int arr[8] = { 1, 0, 0, 0, 0, 1, 0, 0};
cellCompete( arr, 1 );
for(int i = 0; i < 8; i++)
{
cout << arr[i] << " ";
}
}
#include <stdio.h>
int main() {
int days,ind,arr[8],outer;
for(ind=0;ind<8;scanf("%d ",&arr[ind]),ind++); //Reading the array
scanf("%d",&days);
int dupArr[8];
for(outer=0;outer<days;outer++){ //Number of days to simulate
for(ind=0;ind<8;ind++){ //Traverse the whole array
//cells on the ends have single adjacent cell, so the other adjacent cell can be assumsed to be always inactive
if(ind==0){
if(arr[ind+1]==0)
dupArr[ind]=0;
else
dupArr[ind]=1;
}
else if(ind==7){
if(arr[ind-1]==0)
dupArr[ind]=0;
else
dupArr[ind]=1;
}
else{
if((arr[ind-1]==0&&arr[ind+1]==0) || (arr[ind-1]==1&&arr[ind+1]==1)){// if its neighbours are both active or both inactive, the cell becomes inactive the next day
dupArr[ind]=0;
}
else //otherwise it becomes active the next day
dupArr[ind]=1;
}
}
for(ind=0;ind<8;ind++){
arr[ind]=dupArr[ind]; //Copying the altered array to original array, so that we can alter it n number of times.
}
}
for(ind=0;ind<8;ind++)
printf("%d ",arr[ind]);//Displaying output
return 0;
}
Here is my code which i had created some months ago,
You want to create two different arrays, because altering same array element will gives you different results.
func competeCell(cell []uint, days uint) []uint{
n := len(cell)
temp := make([]uint, n)
for i :=0; i < n; i ++ {
temp[i] = cell[i]
}
for days > 0 {
temp[0] = 0 ^ cell[1]
temp[n-1] = 0 ^ cell[n-2]
for i := 1; i < n-2 +1; i++ {
temp[i] = cell[i-1] ^ cell[i +1]
}
for i:=0; i < n; i++ {
cell[i] = temp[i]
}
days -= 1
}
return cell
}
Using c++
#include <list>
#include <iterator>
#include <vector>
using namespace std;
vector<int> cellCompete(int* states, int days)
{
vector<int> result1;
int size=8;
int list[size];
int counter=1;
int i=0;
int temp;
for(int i=0;i<days;i++)//computes upto days
{
vector<int> result;
if(states[counter]==0)
{
temp=0;
list[i]=temp;
//states[i]=0;
result.push_back(temp);
}
else
{
temp=1;
list[i]=temp;
result.push_back(temp);
}
for(int j=1;j<size;j++)
{
if(j==size)
{
if(states[j-1]==0)
{
temp=0;
list[j]=temp;
//states[i]=1;
result.push_back(temp);
}
else
{
temp=1;
list[i]=temp;
//states[i]=1;
result.push_back(temp);
}
}
else if(states[j-1]==states[j+1])
{
temp=0;
list[j]=temp;
//states[i]=1;
result.push_back(temp);
}
else
{
temp=1;
list[j]=temp;
//states[i]=1;
result.push_back(temp);
}
}
result1=result;
for(int i=0;i<size;i++)
{
states[i]=list[i];
}
}
return result1;
}
Java solution
This is solution is Java, which will work any number of Cells and any number of days .
public class Solution
{
public List<Integer> cellCompete(int[] states, int days)
{
List<Integer> inputList = new ArrayList<Integer>();
List<Integer> finalList = new ArrayList<Integer>();
// Covert integer array as list
for (int i :states)
{
inputList.add(i);
}
// for loop for finding status after number of days.
for(int i=1; i<= days; i++)
{
if(i==1)
{
finalList = nextDayStatus(inputList);
}
else
{
finalList = nextDayStatus(finalList);
}
}
return finalList;
}
// find out status of next day, get return as list
public List<Integer> nextDayStatus(List<Integer> input)
{
List<Integer> output = new ArrayList<Integer>();
input.add(0,0);
input.add(0);
for(int i=0; i < input.size()-2; i++)
{
if (input.get(i) == input.get(i+2))
{
output.add(0);
}
else
{
output.add(1);
}
}
return output;
}
}
I know this has been answered, but I gave it a go in Java and am pretty sure it will work for any size states array along with number of days:
public class CellCompete {
public static List<Integer> cellCompete(int[] states, int days) {
List<Integer> resultList = new ArrayList<>();
int active = 1, inactive = 0;
int dayCount = 1;
// Execute for the given number of days
while (days > 0) {
int[] temp = new int[states.length];
System.out.print("Day " + dayCount + ": ");
// Iterate through the states array
for (int i = 0; i < states.length; i++) {
// Logic for first end cell
if (i == 0) {
temp[i] = states[i + 1] == active ? active : inactive;
resultList.add(temp[i]);
System.out.print(temp[i] + ", ");
}
// Logic for last end cell
if (i == states.length - 1) {
temp[i] = states[i - 1] == active ? active : inactive;
resultList.add(temp[i]);
System.out.println(temp[i]);
}
// Logic for the in between cells
if (i > 0 && i < states.length - 1) {
if ((states[i - 1] == active && states[i + 1] == active) || (states[i - 1] == inactive && states[i + 1] == inactive)) {
temp[i] = inactive;
} else {
temp[i] = active;
}
resultList.add(temp[i]);
System.out.print(temp[i] + ", ");
}
}
dayCount++;
days--;
// Reset the states array with the temp array
states = temp;
}
return resultList;
}
public static void main(String[] args) {
int[] states = {1, 1, 0, 1, 0, 1, 0, 0};
int days = 5;
// Total of 40
System.out.println(cellCompete(states, days) );
}
}
Where did the people who wanted optimized solutions go?
def Solution(states, days):
for i in range(days):
for j in range(len(states)):
if (j == 0):
states[i] = states[1]
elif (j == len(states)-1):
states[i] = states[-2]
else:
states[i] = abs(states[i-1] - states[i+1])
return states
By definition, all the cells, including non-existent ones, are in fact booleans:
var cellUpdate = (cells, days) => {
let result = [];
// update states
for(let i = 0; i < cells.length; i++) result.push((!Boolean(cells[i-1]) === !Boolean(cells[i+1])) ? 0 : 1) ;
// repeat for each day
if (days > 1) result = cellUpdate(result, days - 1);
return result;
Here is the best python Solution
value=input()
n=int(input())
lst=[]
for i in value:
if "1"in i:
lst.append(1)
elif "0" in i:
lst.append(0)
for _ in range(n):
store = []
for i in range(8):
if i==0:
store.append(lst[i+1])
elif i==7:
store.append(lst[i-1])
elif lst[i-1]==lst[i+1]:
store.append(0)
else:
store.append(1)
lst=store
print(store)
Scala solution:
def cellDayCompete(cells: Seq[Int]): Seq[Int] = {
val addEdges = 0 +: cells :+ 0
(addEdges.dropRight(2) zip addEdges.drop(2)).map {
case (left, right) =>
(left - right).abs
}
}
def cellCompete(cells: Seq[Int], days: Int): Seq[Int] = {
if (days == 0) {
cells
} else {
cellCompete(cellDayCompete(cells), days - 1)
}
}
A code run with the example above can be found at Scastie
Just answered this question today and here was my solution in python3
def cellCompete(states, days):
for i in range(0, days):
#this is where we will hold all the flipped states
newStates = []
'''
Algo: if neigbors are the same, append 0 to newStates
if they are different append 1 to newStates
'''
for currState in range(len(states)):
#left and right ptr's
left = currState - 1
right = currState + 1
#if at beginning of states, left is automatically inactive
if left < 0:
if states[right] == 1:
newStates.append(1)
else:
newStates.append(0)
#if at end of states, right is automatically inactive
elif right > 7: #we know there is always only 8 elems in the states list
if states[left] == 1:
newStates.append(1)
else
newStates.append(0)
#check to see if neighbors are same or different
elif states[left] != states[right]:
newStates.append(1)
else:
newStates.append(0)
#Set the states equal to the new flipped states and have it loop N times to get final output.
states = newStates
return states
def cellCompete(states, days):
d = 0
l = len(states)
while d < days:
new_states = [0] * l
for i in range(l):
if i == 0 and states[i+1] == 0 or i == l - 1 and states[i-1] == 0:
new_states[i] = 0
elif i == 0 and states[i+1] == 1 or i == l - 1 and states[i-1] == 1:
new_states[i] = 1
elif states[i+1] == states[i-1]:
new_states[i] = 0
else:
new_states[i] = 1
states = new_states
d = d + 1
return states
static int[] CellCompete(int[] states, int days)
{
int e = states.Length;
int[] newStates = new int[(e+2)];
newStates[0] = 0;
newStates[e+1] = 0;
Array.Copy(states, 0, newStates, 1, e);
for (int d = 0; d < days; d++)
{
states = Enumerable.Range(1, e).Select(x => newStates[x - 1] ^ newStates[x + 1]).ToArray();
newStates[0] = 0;
newStates[e + 1] = 0;
Array.Copy(states, 0, newStates, 1, e);
}
return states;
}
//Here is a working solution for this problem in C#
public class HousesinSeq
{
private string _result;
public string Result
{
get { return _result; }
}
public void HousesActivation(string houses, int noOfDays)
{
string[] housesArr = houses.Split(' ');
string[] resultArr = new string[housesArr.Length];
for (int i = 0; i < noOfDays; i++)
{
for (int j = 0; j < housesArr.Length; j++)
{
if (j == 0)
{
if (housesArr[j + 1] == "0")
{
resultArr[j] = "0";
}
else
{
resultArr[j] = "1";
}
}
else if (j == housesArr.Length - 1)
{
if (housesArr[j - 1] == "0")
{
resultArr[j] = "0";
}
else
{
resultArr[j] = "1";
}
}
else
{
if (housesArr[j + 1] == housesArr[j - 1])
{
resultArr[j] = "0";
}
else
{
resultArr[j] = "1";
}
}
}
resultArr.CopyTo(housesArr, 0);
}
foreach (var item in resultArr)
{
//Console.Write($"{item} ");
_result += item + " ";
}
_result = _result.Trim();
}
}
public class Colony {
public static int[] cellCompete(int[] cell, int day) {
int[] ar = new int[10];
for(int i=1; i<9; i++) {
ar[i] = cell[i-1];
}
while(day-- >0) {
int temp = 0;
for(int i=1; i<9; i++) {
if(Math.abs(temp-ar[i+1])==1) {
temp = ar[i];
ar[i] = 1;
}
else {
temp = ar[i];
ar[i] = 0;
}
}
}
return ar;
}
public static void main(String[] args) {
int[] cell = {1,0,1,1,0,1,0,1};
int day = 1;
cell = cellCompete(cell, day);
for(int i=1; i<9; i++) {
System.out.print(cell[i]+" ");
}
}
}

Resources