P5 - load data from a matrix - javascript

I'm attempting to create a game with the p5.play.js library and I've run into some problems. I want the GUI of the game to comprise x amount of squares (sprites) on board, pulled from a text file sitting in an assets folder. They have to be sprites because I want to interact with them with mouse events and other sprites. The text file is currently an 8 x 8 matrix, but I want to use any sized matrix - from 8 x8 to 24 x 24.
I've used the splitTokens function to convert each line of 8 into 8 separate strings...so far, so good! However, the conditional logic that I have used isn't interpreting the 1, 2 and 3's contained in the text file into red, green and blue. I'm not sure whether I should convert the string to an integer - I've tried that, but it didn't work...funny that!
I've only been coding for 2 months, so I'm pushing the envelope of my limited knowledge!
My code thus far:
let fileContent;
let tiles;
let spr;
function preload(){
fileContent = loadStrings('assets/game.txt');
}
function setup() {
createCanvas(500, 500);
gui = new Array(fileContent.length);
for (let i = 0; i < gui.length; i++) {
let tiles = splitTokens(fileContent[i]);
console.log(tiles);
for (let j = 0; j < gui.length; j++) {
for (let k = 0; k < gui.length; k++) {
spr = createSprite(j * 50 + 75, k * 50 + 75, 50, 50);
if (tiles[i] == "1") {
spr.shapeColor = color('red');
}
if (tiles[i] == "2") {
spr.shapeColor = color('green');
}
if (tiles[i] == "3") {
spr.shapeColor = color('blue');
}
}
}
}
}
function draw() {
background(0);
drawSprites()
}
I'm not sure where to upload any external assets here, so the current text file is as follows:
1 2 3 2 1 3 1 2
2 3 1 1 2 1 3 1
2 3 1 2 2 1 3 1
1 3 1 1 2 1 3 1
2 3 1 1 2 1 3 1
1 2 1 1 2 2 3 1
2 3 2 3 2 1 3 1
2 1 2 2 2 1 3 1
As you can see from the code, it resides in an "assets" folder.

You are triply nesting here when not necessary on a 2d matrix. Rather than iterating 64 times, you are instead iterating 512 times (with the incorrect index as well on tiles[i], changing it to the nested iterators also "works"). However I suggest you remove the j loop and rename the outer i to j. I tried to recreate based on the info you gave here, with the change in mind.

Related

How would I fix my approach to this Manhattan Skyline/Stone Wall and where did I go wrong? Javascript

I just came across this problem and thought I would give it a try, but now I'm stuck and need help if possible.
The problem I keep facing is my return is usually off by 1 or 2 but I can't figure out why not. I have traced my code back but still can't figure it out
The problem :
You are to write a program to assist an architect in drawing the skyline of a city. Building are rectangular in shape, the height of each building is represented by an element in a given array.
The above skyline above is represented like
[1,3,2,1,2,1,5,3,3,4,2]
SO FAR HERE IS WHAT I AM WORKING WITH:
const skyline =(H)=> {
let stack = [];
let count = 0;
let height = 0;
const addBlock = (value) => {
if (value > height) {
stack.push(value - height);
height = value;
count += 1;
}
}
const pop = (value) => {
while (value < height) {
height -= stack.pop();
}
if (value > height) {
addBlock(value)
}
}
for (let i = 0; i < H.length; i += 1) {
let value = H[i];
if (value < height) {
pop(value)
} else if (value > height) {
addBlock(value)
}
}
return count
}
skyline([1,3,2,1,2,1,5,3,3,4,2]) //Expect 9
// Test CASES:
let strokes = [1,3,2,1,2,1,5,3,3,4,2] // Expect 9
// let strokes = [5,8] // Expect 8
// let strokes = [1,1,1,1] // Expect 1
skyline(strokes)
Is this the basic algorithm?
* Big eats small (and equal-sized)
* Small reduces big to small
adding the difference
* Count last one standing
Examples:
[5,8]
-> 8 eats 5, count 8
[1,1,1,1]
-> 1 eats 1 eats 1 eats 1
-> count 1
[1,3,2,1,2,1,5,3,3,4,2]
-> 3 eats 1
-> 2 reduces 3 to 2 and adds 3-2
-> 1 reduces 2 to 1 and adds 2-1
-> 2 eats 1
-> 1 reduces 2 to 1 and adds 2-1
-> 5 eats 1
-> 3 reduces 5 to 3 and adds 5-3
-> 3 eats 3
-> 4 eats 3
-> 2 reduces 4 to 2 and adds 4-2
-> count 2
Total: 1 + 1 + 1 + 2 + 2 + 2 = 9
JavaScript code:
function f(A){
let result = 0;
for (let i=1; i<A.length; i++)
result += Math.max(0, A[i-1] - A[i]);
return result + A[A.length-1];
}
console.log(f([1,3,2,1,2,1,5,3,3,4,2]));
console.log(f([5,8]));
console.log(f([1,1,1,1]));
One liner :)
function f(A){
return [0].concat(A).reduce((a,b,i,A) => a + Math.max(0, A[i-1] - b)) + A[A.length-1];
}
the current answer seems to solve the problem presented, additionally I would like to point that a way to tackle this kind of problems is to solve it by hand and take notes on which steps you took to solve it.
In this case, they ask you to draw horizontal lines without picking up the pencil and one way to do that by hand is to do all the posible strokes on the same row before passing on to the next, until there are no rows left to check.
On every row, you will surely check if the current spot (array element) is greater than 0, which means that it is part of the stroke.
Now in more concise words:
While there are rowsLeft I will traverse the array. on every
traversal I will:
check if the current position is greater than 0 which means there is a
newStroke, it also means there are rowsLeft and since you want to keep
moving forward you would like to decrease the current element by one.
then, if there is a newStroke and the current element is 0 (end of the
stroke) or if it is the end of the array, I would add 1 to my numOfStrokes
count and also state that since I have just finished the stroke then there is
no newStroke at the moment.
Well that's what I did to solve the case you posted, I believe you can code it from there and I hope it helps you, then again, bruce's answer seems to be right, I just wanted to add how you could came up with the solution, there are surely many ways f doing it.
function minimalNumberOfSkylinesIn(array) {
if(array.length == 0)
return 0;
let result = array[0];
for(let i=1; i<array.length; ++i) {
let differnce = array[i] - array[i-1];
result += difference > 0 ? difference : 0;
}
return result;
}

21 counting game (like nim game)

I'd like to develop a bot that is able to win the 21 - counting game/NIM - game every time.
Rules: Here are the rules for the game:
In a game players take it in turns to say up to 3 numbers (starting at 1 and working their way up).
Who every say's the number 21 is eliminated.
Strategie: Winning the game ever time is possible if you know the right strategy How to win?
Continuing on, if you say 12 you win
if you say 9, you win,
if you say 6, you win,
if you say 3, you win
So, if you go second, you can guarantee that you will say 3, and win every time.
My question: I'd like to create a bot using javascript that is able to beat the user.
let _ = function(call, int) {
setTimeout(call, int)
}
class game {
constructor() {
this.number = 1;
}
user(val) {
console.log(`Userinput: +${val}`)
for (let i=0; i<val; i++)
console.log(`number: ${this.number++}`)
this.checkWin("bot")
console.log("\n\n\n")
this.bot()
}
bot() {
let val = (this.number === 3) ? 3 : parseInt(Math.random()*2)+1
console.log(`Botinput: +${val}`)
for (let i=0; i<val; i++)
console.log(`number: ${this.number++}`)
this.checkWin("user")
console.log("\n\n\n")
}
checkWin(looser) {
if (this.number >= 21) {
console.log(`${looser} lost the game.`);
}
}
}
let instance = new game()
_(function() {
instance.user(3)
},0)
_(function() {
instance.user(2)
},100)
_(function() {
instance.user(3)
},200)
_(function() {
instance.user(3)
},300)
_(function() {
instance.user(1)
},400)
Note: I did not finished the development but obviously there are some issues. I would really appreciate if somebody is able to help me finding/fixing them.
To solve a nim game we calculate the nimbers:
the losing state has nimber 0
the rest of the nimbers is calculated by looking at all the reachable states and taking the mex (minimal exclusive) which is the smallest missing number in the sequence of 0, 1, 2, 3, ...
nimber(21) = 0
nimber(20) = 1, only 0 can be reached, so 1 is the mex
nimber(19) = 2, 0 and 1 can be reached within one move, so mex is 2
nimber(18) = 3
nimber(17) = 0, because we can reach 1 to 3, so 0 is the smallest missing number
and so on...
It is easy to see, that it is repeating. So we can calculate the nimber like this (n is the current state): 3 - (n + 2) % 4. Or generalized if we can count up to x numbers and the losing number is y: we want to add z to y, so that (y + z) % (x + 1) = x and then the formula is x - (n + z) % (x + 1). We could also say that y % (x + 1) + z = x (to find the smallest non-negative z, the other formula has an infinite amount of solutions for z), so z = x - y % (x + 1).
So if the nimber of a state is not 0, the winning move is the one going to the next losing state with nimber 0. As it turns out the winning move (how many numbers to count) is exactly equal to the nimber.
It is important to note, that 21 denotes the state when 20 was said, 21 itself wasn't said yet.
It gets interesting when we play with several instances, like having cards numbered from 1 to 21 in several stacks where you can draw 1 to 3 of the lowest cards in a stack. The one taking the very last card loses. Here we can just xor the nimbers of all stacks, if it is 0 we are in a losing state, otherwise there is a winning move.

Sum of Array of Odd numbers - JS

Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
// Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:
rowSumOddNumbers(1); // 1
rowSumOddNumbers(2); // 3 + 5 = 8
I tried to solve this using for loops:
function rowSumOddNumbers(n){
let result = [];
// generate the arrays of odd numbers
for(let i = 0; i < 30; i++){
// generate sub arrays by using another for loop
// and only pushing if the length is equal to current j
let sub = [];
for(let j = 1; j <= n; j++){
// if length === j (from 1 - n) keep pushing
if(sub[j - 1].length <= j){
// and if i is odd
if(i % 2 !== 0){
// push the i to sub (per length)
sub.push(i);
}
}
}
// push everything to the main array
result.push(sub);
}
// return sum of n
return result[n + 1].reduce(function(total, item){
return total += item;
});
}
My code above is not working. Basically I was planning to 1st generate an array of odd numbers less than 30. Next I need to create a sub array base on the length of iteration (j) that would from 1 - n (passed). Then finally push it to the main array. And then use reduce to get the sum of all the values in that index + 1 (since the index starts at 1).
Any idea what am I missing and how to make this work?
Most code problems involve some analysis first in order to spot patterns which you can then convert into code. Looking at the triangle, you'll see the sum of each row follows a pattern:
1: 1 === 1 ^ 3
2: 3 + 5 = 8 === 2 ^ 3
3: 7 + 9 + 11 = 27 === 3 ^ 3
... etc
So from the analysis above you can see that your code could probably be simplified slightly - I won't post an answer, but think about using Math.pow.
No need for any loops.
function rowSumOddNumbers(n) {
// how many numbers are there in the rows above n?
// sum of arithmetic sequence...
let numbers_before_n_count = (n - 1) * n / 2;
let first_number_in_nth_row = numbers_before_n_count * 2 + 1;
let last_number_in_nth_row = first_number_in_nth_row + 2 * (n - 1);
// sum of arithmetic sequence again...
return n * (first_number_in_nth_row + last_number_in_nth_row) / 2;
}

Understanding the modulus operator

I have some code that loops through a collection of list elements and a collection of colours. It makes sure each list element is designated to a colour.
I understand everything about this apart from the modulus operator. I get that it finds and uses the remaining number, but I cannot for the life of me understand what it is doing here?
var li = document.getElementsByTagName('li');
var colors = ["salmon", "teal", "orange", "grey", "blue"];
var colorsCount = colors.length;
for ( var i = 0; i < li.length; i++ ) {
li[i].style.backgroundColor = colors[ i % colorsCount ]; // why does this work?
}
Since there is (potentially) a larger number of items in the li array, this prevents i from being outside the bounds of the colors array, since i % colorsCount can never be over colorsCount.
For example, if we had 10 elements in li, and 5 colors, i % colorsCount would be:
i i % colorsCount Color
-------------------------------
0 0 salmon
1 1 teal
2 2 orange
3 3 grey
4 4 blue
5 0 salmon
6 1 teal
7 2 orange
8 3 grey
9 4 blue
More Information on Modulo Operations.
i % colorsCount will set the bound of the index to be between 0 and colorsCount-1, thus ensuring you never index past the end of the array.
Since mod is the remainder, the remainder can never be greater than the divisor (which in this case, is the length of the array).
Perhaps this snippet may help you understand:
var s = ''
for (var i = 0; i < 20; i ++) {
s += (i % 5) + ', '
}
console.log(s)
The result is:
0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
Note how the number resets to 0 every time it reaches 5. The % colors.length just makes sure the index never goes above the array's length.
A more descriptive way of understanding:
0 % 5: 0/5 = 0, remainder 0
1 % 5: 1/5 = 1/5, remainder 1
...
5 % 5: 5/5 = 1, remainder 0
6 % 5: 6/5 = 1 1/5, remainder 1
7 % 5: 7/5 = 1 2/5, remainder 2
...
It's cycling your colours. Because you only have a limited number of colours, and any number of possible list items, it makes sure that i will not overflow the bounds of your colors array.
The modulus operator returns the remainder of division. It allows you to loop through and reuse the colors array even though there are potentially less colors in the array than there are elements in your list to color.
If length is say 8,
5 % 1 == (5 / 1) = 0 remainder 1
5 % 2 == (5 / 2) = 0 remainder 2
5 % 3 == (5 / 3) = 0 remainder 3
5 % 4 == (5 / 4) = 0 remainder 4
5 % 5 == (5 / 5) = 1 remainder 0
5 % 6 == (5 / 6) = 1 remainder 1
5 % 8 == (5 / 7) = 1 remainder 2
5 % 7 == (5 / 8) = 1 remainder 3
As you can see, the remainders are what's returned by the mod operator, and they're always less than the length of the colors array.
why does i % colorsCount work?
What it does
This code cycles through colors. It does so using the modulus operator to ensure you're always within the bounds of the array.
How it does it
Modulus operation finds the remainder of division of one number by another.
In your case by taking i modulus the colorsCount:
0 % 5; // 0
1 % 5; // 1
1 % 5; // 2
3 % 5; // 3
4 % 5; // 4
5 % 5; // 0
8 % 5; // 3
The result of a modulus operation is the remainder after division of the left operand by the right operand.
So the line of code in question will always return some number between 0 and colorsCount-1.
You iterate from 0 until how many li elements you have. For this example, say 10.
You then look at the colors array and find the element for that iteration (i) and modulus by how many items are in the colors array.
In short, this is what's happening:
var colorsCount = 10;
1 % 10 = 1 // ... Access colors[1]; (teal)
2 % 10 = 2 // .... Access colors[2]; (orange)
3 % 10 = 3 // .... Access colors[3]; (grey)
4 % 10 = 4 // .... Access colors[4]; (blue)
5 % 10 = 5 // .... Access colors[5];
etc
If you are wondering why it will never access an element outside of the array, the answer is because as i becomes greater, the result becomes smaller.
For example, take iteration 8:
8 % 5 = 3
(Iteration 8, 5 elements in the array)
Therefore you are accessing colors[3];

Why does this code loops 16 times instead of 8?

var tops = 5;
while (tops > 0) {
for (var spins = 0; spins < 3; spins++) {
alert("Top is spinning!");
}
tops = tops - 1;
}
Doesn't the var = spins loops 2 times each time the var = tops decreases by one until it gets to the value of 1? Wouldn't that code alert 8 times? I don't know why I get the alert 16 times.
You should get the alert 15 times, not 8 or 16.
The values of tops are 5, 4, 3, 2, 1. For each of these values, spins will be set to 0, 1 and 2.
5 (values for tops) X 3 (values for spins) = 15
You can just print to the screen the values of your variables(tops, spins).
Then you'll see that it loops 15 times and you'll see why.
Here is the jsFiddle for you:
http://jsfiddle.net/66UuT/
you spins loops for 3 times not 2 times as you are starting it from 0

Categories