when I increase window width then margin will increase and when i decrease window width margin will reduce - javascript

let getElement = document.getElementById("resize");
let width = window.innerWidth;
let arr = [];
arr.push(width);
let x = 1;
window.addEventListener("resize", () => {
arr.reduce((current, old) => {
if (current) {
getElement.style.marginTop = `${(x += 1)}px`;
} else {
getElement.style.marginTop = `${(x -= 1)}px`;
}
}, width - 1);
});
if current value margin will increase and if old value margin will reduce

Try the below code
let getElement = document.getElementById("resize");
let arr = [window.innerWidth];
let x = 1;
window.addEventListener("resize", () => {
let width = window.innerWidth;
let diff = width - arr[arr.length - 1];
if (diff > 0) {
x += 1;
} else if (diff < 0) {
x -= 1;
}
getElement.style.marginTop = `${x}px`;
arr.push(width);
});

I'm not getting what you clearly asking could you make it little elaborate and more over where you need to use this.

Related

How to solve a Box Claw mover so it spread all boxes evenly on all available stacks?

I'm trying to solve a Robotic Claw lever puzzle, which should spread all boxes across all available stacks evenly.
The problem is that when it reaches the last box, it moves LEFT and then RIGHT, looping infinitely.:
function solve(clawPos, boxes, boxInClaw) {
// Calculate a maximum number of boxes per stack
let max = (boxes.reduce((a, b) => a + b) + ~~boxInClaw) / boxes.length
// Current stack number
const current = boxes[clawPos]
// Helpers
const bigger = current > max
const lower = current < max
const equal = current === max
const last = clawPos === boxes.length - 1
// Command to return for a claw
let command = ''
// Actions for claw
const R = () => command = 'RIGHT'
const L = () => command = 'LEFT'
const U = () => command = 'PICK'
const D = () => command = 'PLACE'
// Automatically select where to move the claw
const autoDirection = () => {
const value = boxes[clawPos]
const left = boxes.slice(0, clawPos)
const right = boxes.slice(clawPos, -1)
const target = max - 1
if (boxInClaw) {
if (left.includes(target)) L()
else if (right.includes(target)) R()
} else {
R()
}
}
autoDirection()
if (boxInClaw) {
if (lower) D()
} else {
if (bigger) U()
}
return command;
}
I've tried to many different approaches to make it dynamic, is there any smarter approach to know at which direction it should go?
Here is a direct link (please, DO NOT submit): https://www.codingame.eu/evaluate/18917274?id=427696529803c1cd24e9258b89d01a98a72126e
This is my solution to that:
function createStack(length, totalBoxes) {
const boxPerStack = Math.floor(totalBoxes / length);
let newStack = new Array(length).fill(boxPerStack);
const remainder = totalBoxes % length;
if (remainder !== 0) {
for (let i = 0; i < remainder; i++) {
newStack[i]++;
}
}
return newStack;
}
function solve(clawPos, boxes, boxInClaw) {
// Write your code here
const totalBoxes = boxes.reduce((prev, acc) => prev + acc);
let targetPos;
if (boxInClaw) {
const targetStack = createStack(boxes.length, totalBoxes + 1);
// Move to place
for (let i = 0; i < boxes.length; i++) {
if (boxes[i] < targetStack[i]) {
targetPos = i;
break;
}
}
if (clawPos === targetPos) return 'PLACE';
else if (clawPos < targetPos) return 'RIGHT';
else return 'LEFT';
} else {
const targetStack = createStack(boxes.length, totalBoxes);
// Move to pick
for (let i = 0; i < boxes.length; i++) {
if (boxes[i] > targetStack[i]) {
targetPos = i;
break;
}
}
if (clawPos === targetPos) return 'PICK';
else if (clawPos < targetPos) return 'RIGHT';
else return 'LEFT';
}
return '';
}

Does my solution to the Smallest Difference algorithm problem have optimal space time complexity (O(nLog(n) + mLog(m)))?

Question:
Here is my solution:
function smallestDifference(arrayOne, arrayTwo) {
const combinedArray = [...arrayOne, ...arrayTwo];
combinedArray.sort((a, b) => a - b);
let smallestDifference = Infinity;
let arrayOneInt = null;
let arrayTwoInt = null;
for (let i = 0; i < combinedArray.length - 1; i++) {
if (Math.abs(combinedArray[i] - combinedArray[i+1]) < smallestDifference) {
if (arrayOne.includes(combinedArray[i]) && arrayTwo.includes(combinedArray[i+1])) {
smallestDifference = Math.abs(combinedArray[i] - combinedArray[i+1]);
arrayOneInt = combinedArray[i];
arrayTwoInt = combinedArray[i+1];
} else if (arrayOne.includes(combinedArray[i+1]) && arrayTwo.includes(combinedArray[i])) {
smallestDifference = Math.abs(combinedArray[i] - combinedArray[i+1]);
arrayOneInt = combinedArray[i+1];
arrayTwoInt = combinedArray[i];
}
}
}
return [arrayOneInt, arrayTwoInt];
}
Here is the given optimal solution
function smallestDifference(arrayOne, arrayTwo) {
arrayOne.sort((a, b) => a - b);
arrayTwo.sort((a, b) => a - b);
let idxOne = 0;
let idxTwo = 0;
let smallest = Infinity;
let current = Infinity;
let smallestPair = [];
while (idxOne < arrayOne.length && idxTwo < arrayTwo.length) {
let firstNum = arrayOne[idxOne];
let secondNum = arrayTwo[idxTwo];
if (firstNum < secondNum) {
current = secondNum - firstNum;
idxOne++;
} else if (secondNum < firstNum) {
current = firstNum - secondNum;
idxTwo++;
} else {
return [firstNum, secondNum]
}
if (smallest > current) {
smallest = current;
smallestPair = [firstNum, secondNum];
}
}
return smallestPair;
}
For the above given optimal solution, it says the time complexity is O(nLog(n) + mLog(m)) and space complexity is O(1). Does my solution above it also match this time complexity?
You have loop over combinedArray which has lenght N + M. Within this loop you have arrayOne.includes and arrayTwo.includes with O(N) and O(M) time complexities.
So you have at least O((N + M) ^ 2) which is bigger than O(nLog(m) + mLog(n))

Merge Sort Visualisation

// variables
// arr has elements to be sorted
var arr = []
// temp is to store the intermediate results after merging
var temp = []
// seen is for marking visited i.e. sorted half as green
var seen = []
// length of array
var len = 100
// canvas initialisations
var canvas = document.getElementById("myCanvas")
canvas.width = canvas.height = 1000
var canvaswidth = canvas.width
var canvasheight = canvas.height
var ctx = canvas.getContext("2d")
// random array
for (let i = 0; i < len; i++) {
arr.push(parseInt(Math.random() * 500))
temp.push(parseInt(0))
seen.push(parseInt(0))
}
// initial contents of array to be sorted
// console.log(arr)
// draw the bars
draw = (s, e) => {
ctx.clearRect(0, 0, 1000, 1000)
// this loop will make unvisited bars in the upper half as black
// and visited bars in the upper half as green
for (let i = 0; i < len; i++) {
ctx.fillStyle = "#000000"
ctx.fillRect(15 * i, 500 - arr[i], 10, arr[i])
if (seen[i]) {
ctx.fillStyle = "#00ff00"
ctx.fillRect(15 * i, 500 - arr[i], 10, arr[i])
}
}
// the part that was merged is made blue in the lower half
// also its equivalent in the uper half is made white
for (let i = s; i <= e; i++) {
ctx.fillStyle = "#ffffff"
ctx.fillRect(15 * i, 500 - arr[i], 10, arr[i])
ctx.fillStyle = "#0000ff"
ctx.fillRect(15 * i, 500, 10, arr[i])
seen[i] = 1
}
}
// merge
merge = (s, e) => {
let m = parseInt((s + e) / 2)
let p1 = s
let p2 = m + 1
let n1 = m
let n2 = e
let idx = s
while (p1 <= n1 && p2 <= n2) {
if (arr[p1] <= arr[p2]) {
temp[idx++] = arr[p1++]
}
else {
temp[idx++] = arr[p2++]
}
}
while (p1 <= n1) {
temp[idx++] = arr[p1++]
}
while (p2 <= n2) {
temp[idx++] = arr[p2++]
}
idx = s
while (idx <= e) {
arr[idx] = temp[idx++]
}
}
// delay
function mytimeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// mergesort
const mergesort = async (s, e) => {
if (s < e) {
let m = parseInt((s + e) / 2)
await mergesort(s, m)
await mergesort(m + 1, e)
await merge(s, e)
// await console.log(`merged ${s} to ${e} now draw...`)
await draw(s, e)
await mytimeout(500)
}
}
// calls merge sort and at last
// makes all bars become green in upper half
const performer = async () => {
await mergesort(0, len - 1)
// await console.log(arr)
await draw()
}
performer()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="myCanvas">
Your browser does not support the canvas element.
</canvas>
<script src="testmerge.js"></script>
</body>
</html>
I am trying to make a visualisation of merge sort using plain javascript with HTML canvas.
If i change the len variable to 50 or below my code works
currently i have kept the len variable at 100
the entire array after getting sorted, in the final picture, the bars in the histogram decrease in height automatically
i am not sure if there is a better/cleaner way to approach this
There is a visual glitch because the width of your canvas element is fixed to 1000 pixels, and the bars always have a width of 10 pixels with 5 pixel gaps between them. This means that the bar chart gets clipped as soon as the number of bars gets too large to fit in those 1000 pixels.
One way to fix this is to make the width of the bars (and the inter-gap) dynamically smaller as the number of bars increases.
Here is a fix, which introduces the variables bardistance, barwidth and bargap, although the latter is only there to pinpoint what the gap-value is: it is not used in the rest of the code.
// variables
// arr has elements to be sorted
var arr = [];
// temp is to store the intermediate results after merging
var temp = [];
// seen is for marking visited i.e. sorted half as green
var seen = [];
// length of array
var len = 100;
// canvas initialisations
var canvas = document.getElementById("myCanvas");
canvas.width = canvas.height = 1000;
var canvaswidth = canvas.width;
var canvasheight = canvas.height;
var ctx = canvas.getContext("2d");
var bardistance = Math.floor(canvaswidth / len);
if (!bardistance) bardistance = 1;
var barwidth = Math.floor(bardistance * 0.7);
if (!barwidth) barwidth = 1;
var bargap = bardistance - barwidth;
// random array
for (let i = 0; i < len; i++) {
arr.push(parseInt(Math.random() * 500));
temp.push(parseInt(0));
seen.push(parseInt(0));
}
// initial contents of array to be sorted
// console.log(arr)
// draw the bars
var draw = (s, e) => {
ctx.clearRect(0, 0, 1000, 1000);
// this loop will make unvisited bars in the upper half as black
// and visited bars in the upper half as green
for (let i = 0; i < len; i++) {
ctx.fillStyle = "#000000";
ctx.fillRect(bardistance * i, 500 - arr[i], barwidth, arr[i]);
if (seen[i]) {
ctx.fillStyle = "#00ff00";
ctx.fillRect(bardistance * i, 500 - arr[i], barwidth, arr[i]);
}
}
// the part that was merged is made blue in the lower half
// also its equivalent in the uper half is made white
for (let i = s; i <= e; i++) {
ctx.fillStyle = "#ffffff";
ctx.fillRect(bardistance * i, 500 - arr[i], barwidth, arr[i]);
ctx.fillStyle = "#0000ff";
ctx.fillRect(bardistance * i, 500, barwidth, arr[i]);
seen[i] = 1;
}
}
// merge
merge = (s, e) => {
let m = parseInt((s + e) / 2);
let p1 = s;
let p2 = m + 1;
let n1 = m;
let n2 = e;
let idx = s;
while (p1 <= n1 && p2 <= n2) {
if (arr[p1] <= arr[p2]) {
temp[idx++] = arr[p1++];
}
else {
temp[idx++] = arr[p2++];
}
}
while (p1 <= n1) {
temp[idx++] = arr[p1++];
}
while (p2 <= n2) {
temp[idx++] = arr[p2++];
}
idx = s;
while (idx <= e) {
arr[idx] = temp[idx++];
}
}
// delay
function mytimeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// mergesort
const mergesort = async (s, e) => {
if (s < e) {
let m = parseInt((s + e) / 2);
await mergesort(s, m);
await mergesort(m + 1, e);
await merge(s, e);
// await console.log(`merged ${s} to ${e} now draw...`)
await draw(s, e);
await mytimeout(500);
}
}
// calls merge sort and at last
// makes all bars become green in upper half
const performer = async () => {
await mergesort(0, len - 1);
// await console.log(arr)
await draw();
}
performer();
<canvas id="myCanvas"></canvas>

How to set a min/max value for variable increasing/decreasing with scrollTop?

I have a variable called yPos increasing and decreasing based on the value of $(window).scrollTop() on scroll. I would like to set a maximum and minimum value so that the yPos variable cannot be any lower than the min value and cannot be bigger than the max value, but still change depending on scrollTop. How should I go about doing this?
const max = yourMax;
const min = yourMin;
let yPos = $(window).scrollTop();
if(yPos > max) {
yPos = max;
}
else if(yPos < min) {
yPos = min;
}
$(document).ready(function(){
var scroll = 0;;
var maxvalue = 100;
var minvalue = 10;
var temp = 0;
$(document).scroll(function(){
temp = $(window).scrollTop();
if(temp > maxvalue)
{
temp = maxvalue;
}
if(temp < minvalue){
temp = minvalue;
}
scroll = temp;
console.log(scroll);
});
});
body{
height:200vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Use something like this.
var yPos= 0;
var min_value = 10;
var max_value = 100;
if($(window).scrollTop() >= min_value && $(window).scrollTop()<= max_value)
{
yPos = $(window).scrollTop();
}
note: this just a logic, please don't copy paste this to your code.

Separating Axis Theorem Implementation always returning true. What am I doing wrong?

I'm trying to implement collision detection for concave polygons in Javascript/p5.js using the Separating Axis Theorem. I've been following the following tutorial on how to use it: http://www.dyn4j.org/2010/01/sat/
However, my check is always returning true, no matter the positioning of the two polygons. Here's my code:
function SAT(shape1, shape2)
{
let axes1 = getAxes(shape1);
let axes2 = getAxes(shape2);
let colliding = true;
for (let i = 0; i < axes1.length; i++)
{
let axis = axes1[i];
let p1 = shape1.project(axis);
let p2 = shape2.project(axis);
if (!p1.overlap(p2)) colliding = false;
}
for (let i = 0; i < axes2.length; i++)
{
let axis = axes2[i];
let p1 = shape1.project(axis);
let p2 = shape2.project(axis);
if (!p1.overlap(p2)) colliding = false;
}
return colliding;
}
function getAxes(shape)
{
let axes = [];
for (let i = 0; i < shape.vertices.length; i++)
{
let p1 = shape.vertices[i];
let p2 = shape.vertices[i + 1 == shape.vertices.length ? 0 : i + 1];
let edge = p1.sub(p2);
let normal = createVector(-edge.y, edge.x);
axes[i] = normal;
}
return axes;
}
class Projection
{
constructor(min, max)
{
this.min = min;
this.max = max;
}
overlap(other)
{
if (this.max < other.min || other.max < this.min) return false;
else return true;
}
}
class PolygonCollider extends Component
{
constructor(gameObject)
{
super(gameObject);
this.untransformedVertices = [];
this.vertices = [];
...
}
setVerts(verts)
{
if (verts && verts.length > 2)
{
this.untransformedVertices = verts;
this.vertices = this.transform.getTransformedPoints(verts);
return this;
}
else return false;
}
project(axis)
{
let min = axis.dot(this.vertices[0]);
let max = min;
for (let i = 1; i < this.vertices.length; i++)
{
let p = axis.dot(this.vertices[i]);
if (p < min) min = p;
else if (p > max) max = p;
}
return new Projection(min, max);
}
update()
{
this.vertices = this.transform.getTransformedPoints(this.untransformedVertices);
}
...
}
Vertices are transformed with the following function, using a defined scale, rotation and position:
getTransformedPoints(points)
{
let transformed = [];
for (let i = 0; i < points.length; i++)
{
let rX = ((this.scale.x * points[i].x) * Math.cos(this.rotation)) - ((this.scale.y * points[i].y) * Math.sin(this.rotation));
let rY = ((this.scale.x * points[i].x) * Math.sin(this.rotation)) + ((this.scale.y * points[i].y) * Math.cos(this.rotation));
transformed[i] = createVector(rX + this.position.x, rY + this.position.y);
}
return transformed;
}
The SAT method is always returning true. I believe I'm checking for the overlap incorrectly, but I can't figure out what exactly I'm doing wrong.
So, it turns out the issue with my implementation lied with p5.js, a library I am using in this case.
In the getAxes method, I was subtracting p1 from p2 using p5's built in p5.Vector.sub function. This didn't have the desired effect. I'm not sure, but I believe the issue was that it wasn't creating a new vector that was the difference of the equation. I fixed this simply by creating the new vector myself as such: createVector(p2.x - p1.x, p2.y - p1.y);

Categories

Resources