i'm trying to make a right aligned triangle. I am able to make a left aligned triangle easily, but can't get the number of spaces to decrease with each additional row.
output should be:
#
##
###
####
#####
let levels = 8;
let hash = '';
for (let i = 1; i <= levels; i++) {
hash += '#';
console.log(hash)
}
Instead of reusing the same string, consider generating each row with repeat() and padStart():
function rightAlignedTriangle (levels) {
for (let i = 1; i <= levels; i++) {
const row = '#'.repeat(i).padStart(levels)
console.log(row)
}
}
rightAlignedTriangle(5)
To implement this using a nested loop instead of string methods, you can manually implement the above two methods as an inner loop on a variable string declared in the outer loop:
function rightAlignedTriangle (levels) {
for (let i = 1; i <= levels; i++) {
let row = ''
for (let j = 0; j < levels; j++) {
if (j < i) { row += '#' } // repeat(i)
else { row = ' ' + row } // padStart(levels)
}
console.log(row)
}
}
rightAlignedTriangle(5)
Related
I'm trying to get N ways of solves a N rook problem. The issue I am having is currently, I seem to get n*n solutions while it needs to be N! . Below is my code, I have written it in simple loops and functions, so it's quite long. Any help would be greatly appreciated
Note: Please ignore case for n = 2. I get some duplicates which I thought I would handle via JSON.stringify
var createMatrix = function (n) {
var newMatrix = new Array(n);
// build matrix
for (var i = 0; i < n; i++) {
newMatrix[i] = new Array(n);
}
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
newMatrix[i][j] = 0;
}
}
return newMatrix;
};
var newMatrix = createMatrix(n);
// based on rook position, greying out function
var collision = function (i, j) {
var col = i;
var row = j;
while (col < n) {
// set the row (i) to all 'a'
col++;
if (col < n) {
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
while (row < n) {
// set columns (j) to all 'a'
row++;
if (row < n) {
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
if (i > 0) {
col = i;
while (col !== 0) {
col--;
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
if (j > 0) {
row = j;
while (row !== 0) {
row--;
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
};
// checks position with 0 and sets it with Rook
var emptyPositionChecker = function (matrix) {
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix.length; j++) {
if (matrix[i][j] === 0) {
matrix[i][j] = 1;
collision(i, j);
return true;
}
}
}
return false;
};
// loop for every position on the board
loop1:
for (var i = 0; i < newMatrix.length; i++) {
var row = newMatrix[i];
for (var j = 0; j < newMatrix.length; j++) {
// pick a position for rook
newMatrix[i][j] = 1;
// grey out collison zones due to the above position
collision(i, j);
var hasEmpty = true;
while (hasEmpty) {
//call empty position checker
if (emptyPositionChecker(newMatrix)) {
continue;
} else {
//else we found a complete matrix, break
hasEmpty = false;
solutionCount++;
// reinitiaze new array to start all over
newMatrix = createMatrix(n);
break;
}
}
}
}
There seem to be two underlying problems.
The first is that several copies of the same position are being found.
If we consider the case of N=3 and we visualise the positions by making the first rook placed red, the second placed green and the third to be placed blue, we get these three boards:
They are identical positions but will count as 3 separate ones in the given Javascript.
For a 3x3 board there are also 2 other positions which have duplicates. The gets the count of unique positions to 9 - 2 - 1 -1 = 5. But we are expecting N! = 6 positions.
This brings us to the second problem which is that some positions are missed. In the case of N=3 this occurs once when i===j==1 - ie the mid point of the board.
This position is reached:
This position is not reached:
So now we have the number of positions that should be found as 9 - 2 - 1 - 1 +1;
There appears to be nothing wrong with the actual Javascript in as much as it is implementing the given algorithm. What is wrong is the algorithm which is both finding and counting duplicates and is missing some positions.
A common way of solving the N Rooks problem is to use a recursive method rather than an iterative one, and indeed iteration might very soon get totally out of hand if it's trying to evaluate every single position on a board of any size.
This question is probably best taken up on one of the other stackexchange sites where algorithms are discussed.
How to extract elements of a matrix in a particular pattern using javascript?
following is the code for generating a 2d matrix of size any
var matrix = [];
for(var i=0; I<size; i++) {
matrix[i] = [];
for(var j=0; j<size; j++) {
matrix[i][j] = undefined;
}
}
so the first one is the original matrix. second one is the matrix made out by removing some elements/ cells.
// don't worry about splicing... this is just a demo.
[[3,5], [4,5], [4,2] ... ].forEach(([i,j], _, arr) => delete arr[i][j])
***** This is where you begin *****
(from the above splices matrix the following has to be done)
so what I want to achieve is that I want to separate or group cells from the above spliced matrix in the following manner. (like concentric circles/squares fashion by keeping in mind the fact that some cells are removed)
first you start at the central element [i,j], then move to the next level 3 x 3 & assign a value to all concentric cells (or separate cell address out)... then move to the next level 4 x 4 assign a value to all concentric cells (or separate cell address out) and so on...
Note that the spliced matrix is the starting point
travel in this fashion outwards (like concentric squares):
the idea is that:\
generate a matrix of size n * n.
remove some elements (that will be any)
... from here the algorithm starts...
separate cells from the above splices matrix in a concentric square fashion. --> this is where I want help (step 3 only)
In simple terms I want to separate out the cells from the matrix in the following order (one level at a time 3 x 3 first then 4 x 4 then 5 x 5 and so on.... ( from the above spliced matrix, which means that some cells will be already removed.)
keep in mind the fact that some cells are already removed (so you'll have to skip them -)
First, figure out the centroid of the square. The center is going to be at {length / 2, width / 2}. We're dealing in integer units, so floor. Using the convention that the top left of the figure is {0, 0} , then ie a 7x7 square has its center at
{floor(7/2), floor(7/2)} === {3,3}
Then, figure out a distance formula. In the pictures, the unit squares in purple are all the squares where either the x coordinate or y coordinate are N units away from the center. In other words
max(x - centerX, y-centerY) === N
I agree with #audzzy, you don't want to delete anything since that actually changes the length of an individual row, which we don't want. Instead just set it to another value.
So the idea is to:
find the center
iterate over each unit square
clear any unit squares which are N distance from the center
const clearCircle = (mat, N) => {
// find the center
const maxI = mat.length, maxJ = mat[0].length,
center = {
i: Math.floor(mat.length / 2),
j: Math.floor(mat[0].length / 2)
};
// iterate over all units
for (let i = 0; i < maxI; i++) {
for (let j = 0; j < maxJ; j++) {
// check if its N units from the center
if (Math.max(Math.abs(center.i - i), Math.abs(center.j - j)) === N) {
mat[i][j] = " ";
}
}
}
return mat;
}
Full example:
/*jshint esnext: true */
const generateMat = size => {
const mat = [];
for (let i = 0; i < size; i++) {
mat[i] = [];
for (let j = 0; j < size; j++) {
mat[i][j] = "[ ]";
}
}
return mat;
}
const mat = generateMat(9);
const logMat = mat => console.log("\n" + mat.map(row => (row).join(" ")).join("\n") + "\n");
const clearCircle = (mat, N) => {
// find the center
const maxI = mat.length, maxJ = mat[0].length,
center = {
i: Math.floor(mat.length / 2),
j: Math.floor(mat[0].length / 2)
};
// iterate over all units
for (let i = 0; i < maxI; i++) {
for (let j = 0; j < maxJ; j++) {
// check if its N units from the center
if (Math.max(Math.abs(center.i - i), Math.abs(center.j - j)) === N) {
mat[i][j] = " ";
}
}
}
return mat;
}
logMat(mat);
logMat(clearCircle(mat, 1));
logMat(clearCircle(mat, 2));
logMat(clearCircle(mat, 3));
Well... you just need exclude squares outside boundaries, after that you can just select elements which are in the most external layer of the matrix!
Something like that:
function extractElements(layer, matrix) {
const elements = []
const n = matrix.length; // matrix NxN
const frontIndex = layer -1;
const backIndex = n - layer;
if(layer <= 0 || layer > Math.ceil(n/2)) {
console.log("invalid layer");
return [];
}
for(let i = 0; i < n; ++i){
if(i < frontIndex || i > backIndex)
continue;
for(let j = 0; j < n; ++j){
if(j < frontIndex || j > backIndex)
continue;
if(i === frontIndex || i === backIndex || j === frontIndex || j === backIndex) {
if(matrix[i][j] !== undefined)
elements.push(matrix[i][j]);
}
}
}
return elements;
}
So, if you want the most external layer of a matrix 5x5, you can call extractElements(1, matrix)
Good code!
here's some basic code to do what you want (here I colored the cells, you could add them to a result array, or do whateve else you want)
notice it has very little iterations- only goes over the "wanted" cells every time- and colors the relevant lines and columns,
(for visual reasons -
'-' is a regular cell,
' ' is deleted cell,
'a' is a "purple" cell)
setMatrix is basically the interesting part that gets the interesting cells of every level..
let setMatrix = (matrix, level, value) => {
let size = matrix.length;
for(let x=Math.floor(size/2)-level;x<=Math.floor(size/2)+level;x++){
matrix[x][Math.floor(size/2)-level] = matrix[x][Math.floor(size/2)-level] == ' ' ? ' ' : value;
matrix[x][Math.floor(size/2)+level] = matrix[x][Math.floor(size/2)+level] == ' ' ? ' ' : value;
if(x!=Math.floor(size/2)-level && x!=Math.floor(size/2)+level){
matrix[Math.floor(size/2)-level][x] = matrix[Math.floor(size/2)-level][x] == ' ' ? ' ' : value;
matrix[Math.floor(size/2)+level][x] = matrix[Math.floor(size/2)+level][x] == ' ' ? ' ' : value;
}
}
}
and here's some code to call it for each level:
function doWork(){
// init
let size = 7;
var matrix = [];
for(var i=0; i<size; i++) {
matrix[i] = [];
for(var j=0; j<size; j++) {
matrix[i][j] = '-';
}
}
// delete
[[1,1], [2,3], [2,5], [5,1], [6,4]].forEach(([i,j])=> matrix[i][j] = ' ');
// go over each level
for(let i=0;i<=Math.floor(size/2);i++){
// set
setMatrix(matrix, i, 'a');
// print
for(let x=0;x<size;x++){
let line='';
for(let y=0;y<size;y++){
line+=matrix[x][y];
}
console.log(line);
}
console.log();
//reset
setMatrix(matrix, i, '-');
}
}
doWork();
I'm trying to create a system of many objects that preform an action when they collide with each other, I'm using the P5.min.js library.
I've set up an array for the grid and an array for the objects, but I can't figure out the right way to go through each grid cell and check only the objects inside that cell before moving on to the next cell.
Here's what I've got so far
let molecules = [];
const numOfMolecules = 100;
let collisions = 0;
let check = 0;
let maxR = 10; //max molecule radius
let minR = 2; //min molecule radius
let numOfCol = 5;
let numOfRow = 5;
let CellW = 600/numOfCol; //gridWidth
let CellH = 600/numOfRow; //gridHeight
let remain = numOfMolecules;
let gridArray = [];
function setup() {
createCanvas(600, 600);
background(127);
for (let i = 0; i < numOfMolecules; i++) {
molecules.push(new Molecule());
}
}
function draw() {
background(127);
molecules.forEach(molecule => {
molecule.render();
molecule.checkEdges();
molecule.step();
});
drawGrid();
splitIntoGrid();
collision();
displayFR();
}
function drawGrid() {
for (i = 0; i < numOfRow+1; i++){
for (j = 0; j < numOfCol+1; j++){
noFill();
stroke(0);
rect(CellW*(j-1), CellH*(i-1), CellW, CellH);
}
}
}
function splitIntoGrid(){
for (let i = 0; i < numOfRow; i++){
for (let j = 0; j < numOfCol; j++){
tempArray = [];
molecules.forEach(molecule => {
if (molecule.position.x > (CellW*j) &&
molecule.position.x < (CellW*(j+1)) &&
molecule.position.y > (CellH*i) &&
molecule.position.y < (CellH*(i+1))) {
tempArray.push(molecule.id);
}
});
}
}
}
How I'm checking collision between all objects:
function collision() {
for (let i=0; i < molecules.length; i++){
for (let j=0; j < molecules.length; j++){
let diff = p5.Vector.sub(molecules[j].position, molecules[i].position);
check++;
if (i != j && diff.mag() <= molecules[j].radius + molecules[i].radius){
collisions++;
molecules[j].changeColor();
}
}
}
}
As far as I can see, I need to put these for loops inside another one going through each cell in the grid, but I don't know how to limit the search to which ever tempArray(s) the object is in
If this makes any sense, this is what I'm trying to do
function collision() {
for (let k = 0; k < gridArray.length; k++){
for (let i=0; i < gridArray.tempArray.length; i++){
for (let j=0; j < gridArray.tempArray.length; j++){
let diff = p5.Vector.sub(gridArray.tempArray[j].position, gridArray.tempArray.position);
check++;
if (i != j && diff.mag() <= gridArray.tempArray[j].radius + gridArray.tempArray[i].radius){
collisions++;
gridArray.tempArray[j].changeColor();
gridArray.tempArray[i].changeColor();
}
}
}
}
}
The grid cell is represented by an array of array gridArray. You need to have a collection of molecules for each grid cell. My recommendation would be to use Sets instead of an Array since the order is irrelevant. The idea is to be able to access the set of molecules on a given grid cell (i,j) with the syntax:
gridArray[i][j]
The following code will create an array of numOfRow arrays:
const numOfRow = 5;
const gridArray = (new Array(numOfRow)).fill([]);
gridArray with look like this:
[ [], [], [], [], [] ]
Inside splitIntoGrid you are checking which molecules are in which grid cells. This is good. However, for each grid cell, you are overwriting the global variable tempArray. Therefore, at the end of the function's execution, tempArray will only hold the molecules of the last grid cell, which isn't what you want. For a given grid cell, we will add the right molecules to a Set associated with this grid cell.
The Set data structure has an #add method which appends a new element to the set:
function splitIntoGrid() {
for (let i = 0; i < numOfRow; i++) {
for (let j = 0; j < numOfCol; j++) {
gridArray[i][j] = new Set();
molecules.forEach(molecule => {
if (molecule.position.x > (CellW*j)
&& molecule.position.x < (CellW*(j+1))
&& molecule.position.y > (CellH*i)
&& molecule.position.y < (CellH*(i+1))) {
gridArray[i][j].add(molecule);
}
});
}
}
}
Now you're ready to check for collisions on each grid cells. We will have a total of four loops inside one another. Two to navigate through the grid and two to compare the molecules that are contained inside each grid cell:
function collision() {
for (let i = 0; i < numOfRow; i++) {
for (let j = 0; j < numOfCol; j++) {
gridArray[i][j].forEach(moleculeA => {
gridArray[i][j].forEach(moleculeB => {
const diff = p5.Vector.sub(moleculeA.position, moleculeB.position);
if (moleculeA != moleculeB && diff.mag() <= moleculeA.radius + moleculeB.radius) {
collisions++;
moleculeA.changeColor();
moleculeB.changeColor();
}
});
});
}
}
}
In the above code, #forEach comes in handy.
I am trying to draw a grid on screen numbered in a snake pattern in Javascript, I have a working grid but it follows the pattern of
12345
67890
And what I need is
12345
09876
I have seen this done with modulo and have tried to implement but im having trouble getting the right number sequence.
Here is my function
function createGrid(length, height) {
var ledNum = 0;
for (var rows = 0; rows < height; rows++) {
for (var columns = 0; columns < length; columns++) {
var backwards = ledNum + columns;
if (rows % 2 == 0 || rows != 0) {
$("#container").append("<div class='grid' id='" + ledNum + "'>" + //HERE IS MY PROBLEM+"</div>");
}
else if (!rows % 2 == 0) {
$("#container").append("<div class='grid' id='" + ledNum + "'>" + ledNum + "</div>");
}
ledNum++;
};
};
$(".grid").width(960 / length);
$(".grid").height(960 / height);
};
How do I work out the true modulo case to show the numbers correctly in snake pattern?
I am not well versed with 2d arrays but perhaps that might be a better way?
The best way I can think of is to use an object with arrays and exploit its inbuilt functions to ease your job...for example
function createGrid(length,height) {
var lednum = 0;
var grid = [];
for (var row = 0; row < height; row++) {
grid[row] = [];
for (var col = 0; col < length; col++) {
if ((row % 2) === 0) {
grid[row].push(lednum);
} else {
grid[row].unshift(lednum);
}
lednum++;
}
}
return grid;
}
console.log(createGrid(10, 10))
Then you can just print out above grid
Update : How to print above data. You could simply use two for loops.
var length = 10;
var height = 15;
var brNode = document.createElement('br');
var grid = createGrid(length, height));
for (var row = 0; row < height; row++) {
var rowPrint = "";
for (var col = 0; col < length; col++) {
rowPrint += String(grid[row][col]) + " ";
}
var rowNode = document.createTextNode(rowPrint)
$("#container").appendChild(rowNode);
$("#container").appendChild(brNode);
}
Note that this will create rows of textNode broken by <br/> tags. if you want it formatted in some other way..well you have the preformatted data..all you need to do is traverse through it and print it how you want.
This general idea seems to work...
// Input variables
var data = 'abcdefghijklmnopqrstuvwxyz';
var width = 5;
// The actual algorithm.
var rows = Math.ceil(data.length / width);
for (var y = 0; y < rows; y++) {
var rowText = "";
for (var x = 0; x < width; x++) {
// Basically, for every other row (y % 2 == 1),
// we count backwards within the row, as it were, while still
// outputting forward.
var offset = y * width + (y % 2 == 1 ? width - 1 - x : x);
rowText += data[offset] || " ";
}
console.log(rowText);
}
$ node so51356871.js
abcde
jihgf
klmno
tsrqp
uvwxy
z
As I mentioned in comments, there is a lot wrong with the boolean logic in your code:
The first if condition always evaluates to true, except in the first iteration
The second if condition is therefor only evaluated once, and it will be false.
I would split the functionality in two parts:
Create a 2D array with the numbers in "snake" sequence
Create the DOM elements from such a matrix, using some CSS to control the line breaks
function createSnake(width, height) {
const numbers = [...Array(width*height).keys()];
return Array.from({length:height}, (_, row) =>
numbers.splice(0, width)[row % 2 ? "reverse" : "slice"]()); // 2D array
}
function createGrid(matrix) {
$("#grid").empty().append(
[].concat(...matrix.map(row => row.map((val,i) =>
$("<div>").addClass("grid").toggleClass("newline", !i).text(val))))
);
}
// Demo generating a 3 x 3 grid
createGrid(createSnake(3,3));
.grid {
float: left;
padding: 3px;
}
.newline {
clear:left
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="grid"></div>
function makeLine(length) {
var line = "";
for (var i = 1; i <= length; i++) {
for (var j = 1; j <= i; j++) {
line += "*";
}
}
return line + "\n";
}
console.log(makeLine(2));
I am trying to print triangle, i dont know where i am doing wrong, can some please explain the logic behind printing triangle using nested loops
*
**
***
After you finish printing a line, you need to add a newline "\n" so that you move to the next line. You could do this as below :
function makeLine(length) {
// length has the number of lines the triangle should have
var line = "";
for (var i = 1; i <= length; i++) {
// Enter the first for loop for the number of lines
for(var j=1; j<=i; j++){
// Enter the second loop to figure how many *'s to print based on the current line number in i. So the 1st line will have 1 *, the second line will have 2 *s and so on.
line += "*";
}
// Add a newline after finishing printing the line and move to the next line in the outer for loop
line+="\n";
}
// Print an additional newline "\n" if desired.
return line + "\n";
}
console.log(makeLine(2));
don't forget about .repeat()
function makeLine(length) {
var line = "";
for (var i = 1; i <= length; i++) {
line+="*".repeat(i)+"\n";
}
return line;
}
console.log(makeLine(3));
The \n was at an incorrect position.
function makeLine(length) {
var line = "";
for (var i = 1; i <= length; i++) {
for (var j = 1; j <= i; j++) {
line += "*";
}
line += "\n";
}
return line;
}
console.log(makeLine(5));
function hashTriangle(length)
{
let str="";
for(let i=0;i<length;i++)
{
str+="#";
console.log(str);
}
}
hashTriangle(7);
console.log() prints a new line. So it is not necessary for nested loops and confusing newline characters to be appended to our string.
function makeLine(length) {
var line = "";
for (var i = 1; i <= length; i++) {
for (var j = 1; j <= i; j++) {
line += "*";
}
// add new line after loop is completed
line = line + "\n"
}
return line + "\n";
}
console.log(makeLine(5));
you need to add \n to line when the inner loop is completed
const printTriangle=(symbol,gapSymbol,num) =>{
// const num =25;
let gap = 1;
const Sgap = symbol+' ';
for(i= num-1;i>=0;i--){
let prefixSuffix=''
prefixSuffix = gapSymbol.repeat(i);
let line = ''
if(i == num -1){
line = gapSymbol.repeat(i)+symbol+gapSymbol.repeat(i);
}
if(i != num -1 && i !=0){
line = gapSymbol.repeat(i)+symbol+gapSymbol.repeat(gap)+symbol+gapSymbol.repeat(i);
gap = gap+2;
}
if(i<1){
line = ''+Sgap.repeat(1)+Sgap.repeat(num-2)+Sgap.repeat(1);
}
console.log(line)
}
}
printTriangle('*','.',15)
This is a JavaScript function that generates a triangle shape using the console.log method. The function takes in three parameters:
symbol: the character to be used to draw the triangle
gapSymbol: the character to be used as a gap in between the symbols
num: the size of the triangle (the number of symbols on the base)
The function starts by initializing the variable gap with the value 1 and Sgap as a string of symbol followed by a space. It then uses a for loop to iterate num number of times, starting from num - 1 down to 0.
For each iteration of the loop, the function uses a single line variable to store the string to be logged. The prefixSuffix variable is used to store the repeated gapSymbols, which are used in each iteration of the loop.
The logic for each iteration is controlled by conditional statements, which determine the shape to be drawn based on the value of i. If i is equal to num - 1, the line is constructed using a single symbol surrounded by repeated gapSymbols. If i is not equal to num - 1 and i is not equal to 0, the line is constructed using repeated gapSymbols, a symbol, a gap of repeated gapSymbols, and another symbol, all surrounded by repeated gapSymbols. If i is less than 1, the line is constructed using repeated Sgaps.
Finally, the constructed line is logged using the console.log method.
Simple solution using padStart, padEnd, repeat method for printing right and left triangle
Left triangle
const printLeftTriangle = (n) => {
let output='';
for (let i = 1; i <= n; i++) {
output +="*".repeat(i).padStart(n) + "\n";
}
return output;
}
console.log(printLeftTriangle(5));
Right triangle
const printRightTriangle = (n) => {
let output='';
for (let i = 1; i <= n; i++) {
output +="*".repeat(i).padEnd(n) + "\n";
}
return output;
}
console.log(printRightTriangle(5));
try this solution please:
const halfTriangle = N => {
for (let row = 0; row < N; row++) {
let line = "";
for (let col = 0; col <= N; col++) {
if (col <= row) {
line += '#';
} else {
line += ' '
}
}
console.log(line);
}
}
halfTriangle(4)
// creates a line of * for a given length
function makeLine(length) {
let line = "";
for (var j = 1; j <= length; j++) {
line += "* ";
}
return line + "\n";
}
// your code goes here. Make sure you call makeLine() in your own code.
function buildTriangle(length) {
// Let's build a huge string equivalent to the triangle
var triangle = "";
//Let's start from the topmost line
let lineNumber = 1;
for (lineNumber = 1; lineNumber <= length; lineNumber++) {
// We will not print one line at a time.
// Rather, we will make a huge string that will comprise the whole triangle
triangle = triangle + makeLine(lineNumber);
}
return triangle;
}
// test your code
console.log(buildTriangle(10));
Center Tringle
let line='';
for(let i=1; i<=5;i++){
line += ' '.repeat(5-i)
line += '*'.repeat(i+i-1)+'\n'
}
console.log(line);