Construct the following pattern in a X by X grid(Multidimensional array) X should be an odd number
ooxoo
oxxxo
xxxxx
oxxxo
ooxoo
Example :
Input X = 5 should return
[["o","o","x","o","o"],
["o","x","x","x","o"],
["x","x","x","x","x"],
["o","x","x","x","o"],
["o","o","x","o","o"]]
Return type should be a object.
So far I have written this code but it does not correctly provide the result I am looking for.
function drawPattern(X) {
// Create an empty grid
var grid = [];
// Calculate the middle of the grid
var middle = Math.floor(X / 2);
// Loop through each row of the grid
for (var i = 0; i < X; i ) {
// Create an empty row
var row = [];
// Loop through each column of the row
for (var j = 0; j < X; j ) {
// Check if the current position is on the edge of the grid
if (i == 0 || i == X - 1 || j == 0 || j == X - 1) {
// If the current position is on the edge, add an "o" to the row
row.push("o");
} else {
// If the current position is not on the edge, check if it is in the middle of the grid
if (i == middle && j == middle) {
// If the current position is in the middle, add an "x" to the row
row.push("x");
} else {
// If the current position is not in the middle, add an "o" to the row
row.push("o");
}
}
}
// Add the row to the grid
grid.push(row);
}
// Return the grid
return grid;
}
console.log(drawPattern(5).join("\n"))
CodePudding user response:
The idea here is to calculate the distance from the middle (where distance doesn't allow diagonals) and then fill in x if it's close enough or o if it's not.
To put it another way, the outer edge of the 'x's should always be the same number of moves (excluding diagonals) from the center of the square so if the point you're at is at that distance or closer it should be an x otherwise an o.
// the distance from one point to another, assuming we can only move
// left or right and up or down
const distance = (point_a, point_b) =>
// distance left and right
Math.abs(point_a[0] - point_b[0])
// distance up and down
Math.abs(point_a[1] - point_b[1]);
const make_pattern = (side_length) => {
const halfish_length = Math.floor(side_length / 2);
const middle = [halfish_length, halfish_length];
return Array.from(
{ length: side_length },
(_, row_i) => Array.from(
{ length: side_length },
(_, col_i) => distance(middle, [col_i, row_i]) > halfish_length ? 'o' : 'x'
)
);
};
const draw_pattern = (side_length) =>
make_pattern(side_length)
.map((row) => row.join(''))
.join("\n");
console.log(draw_pattern(5));
console.log(draw_pattern(7));
For loop version:
const distance = (point_a, point_b) =>
Math.abs(point_a[0] - point_b[0]) Math.abs(point_a[1] - point_b[1]);
const make_pattern = (side_length) => {
const halfish_length = Math.floor(side_length / 2);
const middle = [halfish_length, halfish_length];
let rows = [];
for(let row_i = 0; row_i < side_length; row_i ) {
let cols = [];
for(let col_i = 0; col_i < side_length; col_i )
cols.push( distance(middle, [col_i, row_i]) > halfish_length ? 'o' : 'x' );
rows.push(cols);
}
return rows;
};
const draw_pattern = (side_length) =>
make_pattern(side_length)
.map((row) => row.join(''))
.join("\n");
console.log(draw_pattern(5));
console.log(draw_pattern(7));
References:
CodePudding user response:
If you do it one line at a time and fluctuate the sides:
function drawPattern(X) {
// Create an empty grid
const grid = [];
// Calculate the middle of the grid
let middle = left = right = Math.floor(X / 2); // works because arrays are 0 based
// Loop through each row of the grid
for (let i = 0; i < X; i ) {
// Create an empty row
const row = [];
// Loop through each column of the row
let j = 0;
for (; j < left; j ) row.push("o"); // from 0 to left
for (; j <= right; j ) row.push("x"); // from where we are now to right
for (; j < X; j ) row.push("o"); // from where we are now to end
// Add the row to the grid
grid.push(row.join('')); // join the items
// count up or down
left = i<middle ? -1 : 1; // how far down? if less than the middle move left
right = i<middle ? 1 : -1; // how far down? if less than the middle move right
}
// Return the grid
return grid.join('\n'); // join the rows
}
console.log(drawPattern(5))
console.log(drawPattern(7))
Using spread and Array.from and mirror the Os
const drawPattern = X => {
// Calculate the middle of the grid
let middle = oLen = Math.floor(X / 2); // works because arrays are 0 based
// Loop through each row of the grid using Array.from and map
return Array.from({ length: X }).map((_, i) => {
const o = Array.from({length:oLen}).fill("o"); // fill from start
const x = Array.from({length:X-(oLen*2)}).fill("x"); // fill from last o
oLen = i < middle ? -1 : 1;
return [...o,...x,...o] // spread to get copy - last o is repeat of first o
.join(''); // join items
}).join('\n'); // join rows
};
console.log(drawPattern(5))
console.log(drawPattern(7))
CodePudding user response:
I have broken up the code into manageable pieces. The key into solving this type of problem is to break it into subproblems.
// Generate a single row
function getRow(c1, n, c2, m) {
const row = [];
// Generate left side consisting of n characters
for (let i=0; i<n; i )
row.push(c1);
// Generate middle consisting of m characters
for (let i=0; i<m; i )
row.push(c2);
// Generate right side consisting of n characters
for (let i=0; i<n; i )
row.push(c1);
return row;
}
// Generate grid data
function getGrid(c1, c2, p) {
let grid = [];
// Generate rows starting with 1 character in the middle
// until p characters in the middle.
for (let i=1; i<=p; i =2) {
let m = i;
let n = (p - i) / 2;
let row = getRow(c1, n, c2, m);
grid.push(row);
}
// Generate the second part of the grid's rows starting
// at p-2 characters to avoid repeating the middle row
// until 1 single character is left in the middle row.
for (let i=p-2; i>=1; i-=2) {
let m = i;
let n = (p - i) / 2;
let row = getRow(c1, n, c2, m);
grid.push(row);
}
return grid;
}
function prettyPrint(grid) {
for (const row of grid)
console.log(row.join(''));
}
console.log('Printing patterns:');
prettyPrint(getGrid('o', 'x', 5));
console.log('');
prettyPrint(getGrid('o', 'x', 7));
console.log('Printing raw data:');
console.log(getGrid('o', 'x', 5));
console.log('');
console.log(getGrid('o', 'x', 7));
CodePudding user response:
I came up with this code (a very simplify version to play with)
Hope this demonstration educates you to solve future problems! Main guidelines:
- when having an information (direction, how many characters to draw, etc.) - use variables
- try to make a long and inefficient code that solves the problem
- test the edges (for instance: what happens if size = 1) and refine your code
- consider make it better in terms of performance
Happy coding
const matrix = []
const size = 5 // control the size of the matrix
let start = parseInt(size / 2) // control the start point - in your case the middle
let count = 1 // control how many `x`s are we going to draw
let direction = -1 // control the direction of drawing
for (let i = 0; i < size; i ) {
const row = []
for (let j = 0; j < size; j ) {
// as long as j is inside the drawing range - draw `x`
row.push(j >= start && j < start count ? 'x' : 'o')
}
start = direction // update start position for next line
if (start < 0) { // if we need to change direction
direction *= -1
start = 2
}
count = count - direction * 2
matrix.push(row)
}
console.log(matrix.join('\n')) // you should use a better printing method if you want a nice draw of the matrix