Edit: I put a JavaScript snippet at the bottom.
I've made two versions of the same celluar automata in JavaScript and Python.
The Python version works perfectly as expected, whereas the JavaScript doesn't...
The problem is the third generation.
How it looks in Python:
How it looks in JavaScript:
Two cells (C and D) should change from defectors back to cooperators (blue cell). This is because these cells have a cooperator in their neighbourhood that scores a 6 (6 > 5.7). On the other hand, cells A and B change rightfully back to cooperators. My confusion is that this automata is perfectly symmetrical. Why is A and B working, but not C and D when they are, in theory, existing under the exact same conditions?
Some where in the update function I suspected the cells C and D have a neighbor whose score in generation= 3 is 6 (a cooperator. Only a cooperator could score this. See picture of generation = 2 below to see what I mean) but this neighbor's actual strategy is for some reason being written as a defector, when is should be a cooperator.
this.updateCell = function(row, col) {
let player = this.active_array[row][col];
let best_strat = 0;
let highest_score = 0;
player.neighbours.forEach(coords => {
let x_coord = coords[0];
let y_coord = coords[1];
let neighbour = this.active_array[x_coord][y_coord];
if (neighbour.score > highest_score) {
highest_score = neighbour.score;
best_strat = neighbour.strat;
}
});
if (player.score < highest_score) {
return best_strat;
}
if (player.score >= highest_score) {
return player.strat;
}
}
I ran some console logs in the third generation and it seems to be the case. When cells C and D update, highest_score is returning a 6 (hence, a cooperator) but best_strategy is returning a 1 (meaning a defector). Meaning, cells C and D must have a neighbor whose strategy should be a cooperator but it's actually a defector (even though the scores are correct). If I'm right, I'm not sure how to fix this.
What's equally annoying is that I've tried basically copying the logic from the working Python version in JavaScript exactly, but no matter what I change, nothing seems to fix it. I can't find any difference between the two! :<
Again, the first two generations of the JavaScript version work perfectly.
For reference, the working Python code (JavaScript snippet below):
from calendar import c
from random import choices, sample, shuffle
import numpy as np
import pandas as pd
import copy
import matplotlib.pyplot as plt
from collections import Counter
v = 1.96
generations = 100
width = 100
height = 100
# cooperate = 0, defect = 1
strategies = ['0', '1']
next_cells = {}
temp = [0.2, 0.8]
payoffs = np.array([[1, 0], [1 + v, 0]])
rpm = pd.DataFrame(payoffs, columns=['0', '1'])
rpm.index = ['0', '1']
cpm = rpm.T
output2 = []
for x in range(width):
for y in range(height):
if (x == width/2) and (y == height/2):
strat = '1'
else:
strat = '0'
next_cells[(x, y)] = {
'strategy': strat,
'prev_strat': None,
'score': 0,
'neighbours': [((x + 1) % width, y), ((x - 1) % width, y), (x, (y - 1) % height), (x, (y + 1) % height),
((x + 1) % width, (y - 1) % height), ((x + 1) % width, (y + 1) % height), ((x - 1) % width, (y - 1) % height), ((x - 1) % width, (y + 1) % height)
]
}
for gen in range(generations):
output = np.zeros(shape=(width, height))
cells = copy.deepcopy(next_cells)
for coord, cell in cells.items():
score = 0
if cell['strategy'] == '0':
score += 1
for neighbour in cell['neighbours']:
if cell['strategy'] == '0' and cells[neighbour]['strategy'] == '0':
score += 1
if cell['strategy'] == '1' and cells[neighbour]['strategy'] == '0':
score += v
cell['score'] = score
for coord, cell in cells.items():
highest_score = 0
best_strat = None
for neighbour in cell['neighbours']:
if cells[neighbour]['score'] > highest_score:
highest_score = cells[neighbour]['score']
best_strat = cells[neighbour]['strategy']
if cell['score'] < highest_score:
next_cells[coord]['strategy'] = best_strat
next_cells[coord]['prev_strat'] = cell['strategy']
if cell['score'] >= highest_score:
next_cells[coord]['strategy'] = cell['strategy']
next_cells[coord]['prev_strat'] = cell['strategy']
x, y = coord[0], coord[1]
if next_cells[coord]['strategy'] == '0' and next_cells[coord]['prev_strat'] == '1':
output[x][y] = 2
elif next_cells[coord]['strategy'] == '1' and next_cells[coord]['prev_strat'] == '0':
output[x][y] = 3
else:
output[x][y] = int(next_cells[coord]['strategy'])
plt.imshow(output, interpolation='nearest')
plt.colorbar()
plt.pause(0.01)
plt.savefig(f"images/foo{gen}.png")
plt.close("all")
plt.show()
class Cell4 {
constructor() {
this.score = 0;
this.neighbours;
this.strat;
this.prev_strat;
this.initNeighbours = function(row, col) {
let array = [];
array.push(
[(((row - 1) % rows) + rows) % rows, (((col - 1) % cols) + cols) % cols],
[(((row + 1) % rows) + rows) % rows, (((col + 1) % cols) + cols) % cols],
[(((row - 1) % rows) + rows) % rows, (((col + 1) % cols) + cols) % cols],
[(((row + 1) % rows) + rows) % rows, (((col - 1) % cols) + cols) % cols],
[(((row - 1) % rows) + rows) % rows, col],
[(((row + 1) % rows) + rows) % rows, col],
[row, (((col - 1) % cols) + cols) % cols],
[row, (((col + 1) % cols) + cols) % cols],
)
this.neighbours = array;
};
}
}
class FractalPD {
constructor() {
this.u = 1.96;
this.cooperator_color = 'blue';
this.defect_color = 'red';
this.was_defect_color = 'cyan';
this.was_coop_color = 'yellow';
this.active_array = [];
this.inactive_array = [];
this.makeGrid = function() {
for (let i = 0; i < rows; i++) {
this.active_array[i] = [];
for (let j = 0; j < cols; j++) {
this.active_array[i][j] = 0;
}
}
this.inactive_array = this.active_array;
};
this.randomizeGrid = function() {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
const cell = new Cell4();
cell.strat = 0;
cell.prev_strat = 0;
cell.initNeighbours(i, j);
this.active_array[i][j] = cell;
if (i === parseInt(rows/2) && j === parseInt(cols/2)) {
this.active_array[i][j].strat = 1;
this.active_array[i][j].prev_strat = 1;
}
}
}
};
this.fillGrid = function() {
// cooperate = 0 defect = 1
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (this.active_array[i][j].strat === 0 && this.active_array[i][j].prev_strat === 0) {
ctx.fillStyle = this.cooperator_color;
}
if (this.active_array[i][j].strat === 1 && this.active_array[i][j].prev_strat === 1) {
ctx.fillStyle = this.defect_color;
}
if (this.active_array[i][j].strat === 1 && this.active_array[i][j].prev_strat === 0) {
ctx.fillStyle = this.was_coop_color;
}
if (this.active_array[i][j].strat === 0 && this.active_array[i][j].prev_strat === 1) {
ctx.fillStyle = this.was_defect_color;
}
ctx.fillRect(j * cell_size, i * cell_size, cell_size - 1, cell_size - 1);
ctx.textAlign="center";
ctx.textBaseline = "middle";
ctx.fillStyle = "black";
ctx.fillText(`${this.active_array[i][j].score.toFixed(1)}`, (j * cell_size) + cell_size/2 , (i * cell_size) + cell_size/2)
}
}
};
this.playRound = function(row, col) {
const player = this.active_array[row][col];
const neighbours = player.neighbours;
let score = 0;
if (player.strat === 0) {
score += 1;
}
neighbours.forEach(coords => {
let x_coord = coords[0];
let y_coord = coords[1];
let neighbour = this.active_array[x_coord][y_coord];
if (player.strat === 0 && neighbour.strat === 0) {
score += 1;
}
if (player.strat === 1 && neighbour.strat === 0) {
score += this.u;
}
});
player.score = score;
};
this.updateCell = function(row, col) {
let player = this.active_array[row][col];
let best_strat = 0;
let highest_score = 0;
player.neighbours.forEach(coords => {
let x_coord = coords[0];
let y_coord = coords[1];
let neighbour = this.active_array[x_coord][y_coord];
if (neighbour.score > highest_score) {
highest_score = neighbour.score;
best_strat = neighbour.strat;
}
});
if (player.score < highest_score) {
return best_strat;
}
if (player.score >= highest_score) {
return player.strat;
}
}
this.updateGrid = function() {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
this.playRound(i, j);
}
}
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
let old_state = this.active_array[i][j].strat;
let new_state = this.updateCell(i, j);
this.inactive_array[i][j].strat = new_state;
this.inactive_array[i][j].prev_strat = old_state;
}
}
this.active_array = this.inactive_array;
};
this.gameSetUp = () => {
this.makeGrid();
};
this.runGame = () => {
this.updateGrid();
this.fillGrid();
};
}
}
const canvas = document.querySelector("#gamefield");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
let PD = new FractalPD();
let cell_size = 19;
let cols = Math.floor(canvas.width / cell_size);
let rows = Math.floor(canvas.height / cell_size);
PD.gameSetUp();
PD.randomizeGrid();
PD.fillGrid();
setInterval(function() {
PD.runGame();
}, 3000)
body {
font-family: 'Poppins', sans-serif;
background: #1d1d1d;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="content">
<canvas id="gamefield" width="1500" height="1000"></canvas>
</div>
<script src="fractalPD.js"></script>
</body>
</html>
At a glance, I would guess the problem is this line in your makeGrid method:
this.inactive_array = this.active_array;
This a reference assignment, not a deep copy, so you don't actually have two arrays, but just two references to the same array. When you try to update inactive_array in updateGrid, you're actually also updating active_array, since they're the same array.
To fix this issue, you could make a deep copy of the array with structuredClone(). Or just have a method that creates a single array and returns it, and call it twice to get two independent arrays.
I am currently trying to solve the xmas tree problem, with internal tree-like shape.
issue is with internal spacing, it supposed to be like: 1, 5, 7, 9. Instead it is 1, 3, 4, 5. I do not know, how to increment s loop by 2 in each loop turn.
/*
*********
**** ****
*** ***
** **
* *
*********
*/
function drawTree(h) {
let n = h + 3;
for (var i = 1; i <= 1; i++) {
var temp = "";
for (var j = 1; j <= n; j++) {
temp = temp + "*";
}
console.log(temp);
}
for (var i = 0; i < h - 2; i++) {
var tree = '';
console.log("\n");
for (var k = 3; k <= h - i; k++) {
tree += "*";
};
tree += "s";
for (var k = 1; k <= i; k++) {
for (var k = 1; k <= i; k++) {
tree += "s";
};
tree += "s";
};
for (var k = 3; k <= h - i; k++) {
tree += "*";
};
console.log(tree);
};
console.log("\n");
let g = h + 3;
for (var i = 1; i <= 1; i++) {
var temp = "";
for (var j = 1; j <= g; j++) {
temp = temp + "*";
}
console.log(temp);
}
};
drawTree(6);
function drawTree(stars, rowLength) {
for (let row = 0; row < rowLength; row++) {
if (row === 0) {
console.log("*".repeat(stars));
} else if(row === rowLength - 1) {
console.log("*".repeat(stars));
} else {
let spaces = 2 * row - 1;
if (spaces > stars) {
spaces = stars;
}
let numStarsInRow = "*".repeat((stars - spaces) / 2);
console.log(numStarsInRow + " ".repeat(spaces) + numStarsInRow);
}
}
}
drawTree(9, 5)
You can implement this by nesting loops over the height and the width of the tree, noting that the output is a * whenever:
it's the first or last row; or
the current x position is less than or equal to the halfway point minus the row number; or
the current x position is greater than or equal to the halfway point plus the row number
For all other cases the output is a space. For example:
function drawTree(height) {
// compute the width of the tree from the height
let width = height % 2 ? height + 2 : height + 3;
// find the halfway point
let half = (width - 1) / 2;
for (let i = 0; i < height; i++) {
let l = '';
for (let j = 0; j < width; j++) {
if (i == 0 || // first row
i == height - 1 || // last row
j <= (half - i) || // left side
j >= (half + i) // right side
) {
l += '*';
}
else {
l += ' ';
}
}
console.log(l);
}
}
drawTree(6);
drawTree(5);
Hi Everyone I am New Here Basically i want to generate a array with the help of nodejs means i want to generate an array which keeps on generating alphabets like this
array = ["A","B","C"..."Z","AA","BB",..."ZZ","AAA","BBB",..."ZZZ"]
After googling i came across this one
function columnToLetter(column)
{
var temp, letter = '';
while (column > 0)
{
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
}
But can't understand it still new to the language
I think my method can meet your requirements
function columnToLetter(column) {
var letter = [],
newLetter = [],
merchant = Math.floor(column / 26),
remainder = column % 26;
if (merchant === 0) {
for (let i = 0; i < remainder; i++) {
newLetter.push(String.fromCharCode(i + 65));
}
return newLetter;
} else if (merchant > 0) {
for (let j = 0; j < 26; j++) {
let str = String.fromCharCode(j + 65);
letter.push(str)
}
for (let i = 1; i <= merchant; i++) {
newLetter.push(...letter);
letter = letter.map(item => item + item.split('')[0])
}
newLetter.push(...letter.slice(0, remainder));
return newLetter;
}
}
console.log(columnToLetter(28));
Hello everyone i have a problem with my code and i'm not sure how to do this , i need to write code that draw this in console:
Draw '*' in every even number
For that i need to use nested loops.
So far i have only this:
var n = 5;
var stars = '';
for (var i = 1; i <= n; i++) {
var starsline = '';
for (var j = 1; j <= n; j++) {
console.log(i + j);
}
if ( i % 2 === 0){
starsline += '2';
} else {
starsline += '1'
}
stars += starsline;
}
console.log(stars);
This numbers 2 and 1 are only to check if the number is even or odd.
Just a few things:
1) you got some weird bracket here:
/*}*/ if ( i % 2 === 0){
which causes a syntax error later on.
2) you actually log the right thing:
console.log(i + j)
but you dont use it. Just put that into your condition:
if((i + j) % 2 === 0)
and you are done :)
let size = 5, stars = "";
for (var row = 1; row <= size; row++) {
var starsline = "";
for (var col = 1; col <= size; col++){
if ((row + col) % 2 === 0){
starsline += '*';
} else {
starsline += ' ';
}
stars += starsline + "\n";
}
console.log(stars);
I think what you tried to do is something like this:
var n = 5;
var stars = '';
for (var i = 1; i <= n; i++) {
var starsline = '';
for (var j = 1; j <= n; j++){
if ( (i + j) % 2 === 0){
// used three spaces for consistency in the drawing
starsline += ' ';
} else {
starsline += ' * '
}
}
stars += starsline + '\n';
}
console.log(stars);
Try this:
var n = 5;
var stars = '';
for (var i = 1; i <= n; i++)
{
var starsline = '';//<-- reset the value of line
if ( i % 2 === 0)//<--this identifies which line will the stars be created
{
starsline += '* * *';//<--creating the stars on each line
}
else
{
starsline += ' * * ';//<--creating the stars on each line
}
stars += starsline+'\n';//<-- '\n' add line breaks for each lines
}
console.log(stars);//<-- print the stars
Guys I need your assistance I should accomplish several tasks given by supervisor to make triangle using for loop. But I can't get the exact one. Please help me with that!
Here is an illustration how the final output should look like:
Task 2
input
N (example: N = 5)
output
*
**
***
****
*****
Task 3
input
N (example: N = 5)
output
* * *
* *
* * *
* *
* * *
Task 4
input
N (example: N = 5)
output
*****
* *
* *
* *
*****
and this is my code:
function mixedTriangle (n) {
for (var i = 0; i < n; i++) {
for (var j = 0; j <= i; j++) {
document.write('*');
}
document.write('<br>');
}
}
mixedTriangle(5);
this is my take on it (scaling width with n):
first one you want to walk backwards on the columns so we start at the right side.
for the second function the we switch the pattern for each row other than that it's just using modulus to switch for each column
last one you just need the border which basically means minimum column or row or maximum column or row
<script type="text/javascript">
var fullSign = '*';
var emptySign = ' ';
var newRowSign = '<br>';
function mixedTriangle (n) {
for (var row = 1; row <= n; row++) {
for (var col = n; col > 0; col--) {
if(col <= row)
document.write(fullSign);
else
document.write(emptySign);
}
document.write('<br>');
}
}
function mixedTriangle2(n) {
for (var row = 0; row < n; row++) {
for (var col = 0; col < n; col++) {
if(row % 2 == 0) {
if(col % 2 == 0)
document.write(fullSign);
else
document.write(emptySign);
}
else {
if(col % 2 == 1)
document.write(fullSign);
else
document.write(emptySign);
}
}
document.write(newRowSign);
}
}
function mixedTriangle3(n) {
for (var row = 1; row <= n; row++) {
for (var col = 1; col <= n; col++) {
if(row == 1 || col == 1 || col == n || row == n)
document.write(fullSign);
else
document.write(emptySign);
}
document.write(newRowSign);
}
}
// mixedTriangle(5);
// mixedTriangle2(5);
mixedTriangle3(5);
</script>
//create function
function makeDownwardStairs(height) {
//initialize an empty array inside function.
let pyr = [];
//initialize loop and run a number of times
for (let i = 1; i <= height; i++) {
//update array w/ variable value.
pyr += '#'
//Prints the array to the console
console.log(pyr)
}
}
// calls the function
makeDownwardStairs(5);