Middle element in stack - javascript

I read the article on stack implementation in javascript and python on geeksforgeeks website. I implemented the code to delete the middle element in the stack in javascript exactly as given for python in the same website. But I get wrong answer. Why is it so? what is the difference between the two languages in this case? How can I get the correct answer in javascript? Below is the code in Javascript.
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length === 0) {
return "Underflow";
} else {
return this.items.pop();
}
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length == 0;
}
print() {
console.log(this.items);
}
}
function deleteMid(stack, curr) {
// If stack is empty or all items
// are traversed
if (stack.isEmpty() || curr == stack.items.length) {
return;
}
// Remove last item
x = stack.peek();
stack.pop();
// Remove other items
deleteMid(stack, curr + 1);
console.log("length value: ", stack.items.length);
// Put all items back except middle
if (curr != Math.floor(stack.length / 2)) {
stack.push(x);
}
}
var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack, 0);
stack.print();

There are some parts of the Python implementation that your implementation misses:
You have an implicitly global x variable - unlike Python, in Javascript, variables declared without var / let / const are assigned to the global object, so once the recursive deleteMids have completed, there's only been one variable named x (rather than one for each iteration) which you've reassigned every time. Use const x instead, to ensure that every call of deleteMid has its own binding of x.
Your stack does not have a length property, so your curr != Math.floor(stack.length/2) test results in curr != NaN - which isn't what you want. Although you could give your stack a length getter property:
get length() {
return this.items.length;
}
this still does not conform to the Python implementation, which continually recursively passes the initial length, as another argument: if you want to imitate the Python implementation, do this too, with an n variable:
function deleteMid(stack, n, curr) {
// ...
// Remove other items
deleteMid(stack, n, curr + 1);
// Put all items back except middle
if (curr != Math.floor(n / 2)) {
// ...
// Call with:
deleteMid(stack, stack.items.length, 0);
The problem with checking the length property is that it will change while you're iterating, which will make things much more difficult to work with.
For the same reason, so that even sized stacks work, we also need to change your JS test here:
if (stack.isEmpty() || curr == stack.items.length) {
to correspond to the Python code:
if (st.isEmpty() or curr == n) :
Working code:
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length === 0) {
return "Underflow";
} else {
return this.items.pop();
}
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length == 0;
}
print() {
console.log(this.items);
}
get length() {
return this.items.length;
}
}
function deleteMid(stack, n, curr) {
// If stack is empty or all items
// are traversed
if (stack.isEmpty() || curr === n) {
return;
}
// Remove last item
const x = stack.peek();
stack.pop();
// Remove other items
deleteMid(stack, n, curr + 1);
// Put all items back except middle
if (curr != Math.floor((n) / 2)) {
stack.push(x);
}
}
var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack, stack.items.length, 0);
stack.print();

Since you know the middle index when you start, you can check the stack's length after each item's removal, and stop when you hit the middle.
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length === 0) {
return "Underflow";
} else {
return this.items.pop();
}
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length == 0;
}
print() {
console.log(this.items);
}
}
function deleteMid(stack, middle = Math.round(stack.items.length / 2)) {
if (stack.isEmpty()) return;
const isMiddle = stack.items.length === middle;
// Remove last item
const x = stack.pop();
// stop when you get to the middle
if (isMiddle) return;
// Remove other items
deleteMid(stack, middle);
// add the item back
stack.push(x);
}
var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack);
stack.print();

Related

Sorting different arrays in typescript

I am trying to sort some parameter in my typescript model. My model is as follows.
export class DataModel {
ID: String
point1: Point
point2 : Point
point3: Point
AnotherPoint1: AnotherPoint[]
AnotherPoint2: AnotherPoint[]
AnotherPoint3: AnotherPoint[]
}
export class Point {
Name: String
Timestamp: String
}
export class AnotherPoint {
Name: String
Timestamp: String
}
I have sorting logic in my component which take this above Data Model and sorts point as follows:
private sortByNameAndID(dataModel: DataModel[]): DataModel[] {
return dataModel.sort(function (a, b) {
const pointA = a.point1.Name.toLowerCase();
const pointB = b.point1.Name.toLowerCase();
if (pointA === pointB) {
const timeA = a.point1.Timestamp;
const timeB = b.point1.Timestamp;
return Service.compareDate(new Date(timeA), new Date(timeB)); //here again comparing dates
}
if (pointA < pointB ) {
return -1;
}
if (pointA > pointB ) {
return 1;
}
});
}
}
Above sorting logic is working fine for Points but now with this I also need to sort AnotherPoint as well. Means I have to sort all Points and AnotherPoints together as above. How can I do that?
I would start creating two helper functions, to compare two Points and two arrays of AnotherPoints respectively. I'm assuming that the arrays are to be compared element by element, stopping as soon as a pair of elements does not compare to 0.
function comparePoints(pA: Point | AnotherPoint, pB: Point | AnotherPoint)
{
const pointA = pA.Name.toLowerCase();
const pointB = pB.Name.toLowerCase();
if (pointA < pointB ) {
return -1;
}
if (pointA > pointB ) {
return 1;
}
const timeA = pA.Timestamp;
const timeB = pB.Timestamp;
return Service.compareDate(new Date(timeA), new Date(timeB));
}
function comparePointArrays(arrayA: AnotherPoint[], arrayB: AnotherPoint[])
{
const len = Math.min(arrayA.length, arrayB.length);
for (let i = 0; i < len; ++i)
{
const result = comparePoints(arrayA[i], arrayB[i]);
if (result !== 0) {
return result;
}
}
return 0;
}
Then the sorting function can be rewritten using the new helper comparators:
private sortByNameAndID(dataModel: DataModel[]): DataModel[] {
return dataModel.sort(function (a, b) {
return comparePoints(a.point1, b.point1) ||
comparePoints(a.point2, b.point2) ||
comparePoints(a.point3, b.point3) ||
comparePointArrays(a.AnotherPoint1, b.AnotherPoint1) ||
comparePointArrays(a.AnotherPoint2, b.AnotherPoint2) ||
comparePointArrays(a.AnotherPoint3, b.AnotherPoint3);
});
}
Note that the || operator only performs the operation on the right if the result of the operation on the left is falsy (0), meaning that we will stop comparing points as soon as a comparison reports a nonzero result.

Writing a function to detect a cycle in a linked list (Floyd's alg)... Logic looks correct but can't find the bug

I am trying to detect a cycle in a linked list I created (I'm practicing for interviews questions). I understand the logic involved in Floyd's tortoise-hare algorithm but the function is always returning false...
Here's my linked list:
class LinkedList {
constructor() {
this.length = 0;
this.head = null;
}
insert(index, value) {
if (index < 0 || index > this.length) {
throw new Error("Index error");
}
const newNode = {
value
};
if (index == 0) {
newNode.next = this.head;
this.head = newNode;
} else {
const node = this._find(index - 1);
newNode.next = node.next;
node.next = newNode;
}
this.length++;
}
...
}
//Inserting values
const linkedList = new LinkedList();
linkedList.insert(0, 12);
linkedList.insert(1, 24);
linkedList.insert(2, 65);
linkedList.insert(3, 23);
linkedList.insert(4, 9);
linkedList.insert(5, 7);
linkedList.insert(6, 13);
linkedList.insert(7, 65);
linkedList.insert(8, 20);
Here is my cycle-detection function, it returns false even if there is a cycle:
function containsCycle(firstNode) {
// Start both at beginning
let slow = firstNode;
let fast = firstNode;
// Until end of the list
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
// fast is about to "lap" slow
if (fast === slow) {
return true;
}
}
// fast hit the end of the list
return false;
}
//Calling function
containsCycle(linkedList.head);
I just cannot find what's wrong with my function and the more I try to figure it out the more narrow minded I become... any guidance would be very much appreciated!
You're creating new nodes each insertion. E.g. you're 3rd and 8th nodes both have values 65, but are not equal (they're different objects, so the === condition will fail). More importantly, they have different .next nodes and your slwo and fast iterators will not loop back to the 4th element after traversing the 8th element.

Sum of range in Javascript in function local variable

I have range function and output functions they works correct,now I want create sum function for using as callbac function in range function,but when some function executed local variable let us say total or sum initialize 0(zero),how can solve this problem?
function range(start,end,callback,step) {
// body...
step=step || 1;
for(i=start;i<=end;i=i+step){
callback(i);
}
}
function output(a) {
// body...
console.log(a);
}
function sum(m){
var total=0;
// some code
}
range(1,5,output);
range(1,5,sum);
function range(start,end,callback,step) {
// body...
var aggregate;
step=step || 1;
for(i=start;i<=end;i=i+step){
aggregate = callback(i, aggregate);
}
}
function output(a) {
// body...
console.log(a);
}
function sum(m, aggregate){
return m + aggregate;
}
range(1,5,output);
range(1,5,sum);
This way you could even do cool stuff like
function conc(m, aggregate) {
return aggregate + m.toString();
}
range(1,5,conc,2); //prints 135
Continuition style code, like you've started it with range(), can get really weird and cumbersome.
And please, please, mind defining your local variables. like i
function range(start,end,callback,step) {
step=step || 1;
for(var i=start; i<=end; i=i+step)
callback(i);
}
function output(...label) {
return function(...args){
console.log(...label, ...args);
}
}
function sum(callback){
var total = 0;
return function(value){
//will log ever intermediate total, because sum() has no way to tell when the sequence is over.
callback(total += +value || 0);
}
}
range(1,5,output('range:'));
range(1,5,sum(output('sum:')));
In this case, I'd prefer using a generator instead, although the higher order functions get obsolete.
function *range(start,end,step) {
step = +step || (end < start? -1: 1);
for(var value = start, count = (end - start) / step; count-- >= 0; value += step)
yield value
}
function sum(iterator){
var total = 0, v;
for(v of iterator) total += +v || 0;
return total;
}
console.log("range:", ...range(1,5))
console.log("sum of range:", sum(range(1,5)))
//just to show that this works with your regular array as well
console.log("sum of array:", sum([1,2,3,4,5]));
//and some candy, as requested by Bergi ;)
//I like to stay with the interfaces as close as possible to the native ones
//in this case Array#reduce
var fold = (iterator, callback, start = undefined) => {
var initialized = start !== undefined,
acc = start,
index = 0,
value;
for(value of iterator){
acc = initialized?
callback(acc, value, index):
(initialized=true, value);
++index;
}
if(!initialized){
throw new TypeError("fold of empty sequence with no initial value");
}
return acc;
}
//and the ability to compose utility-functions
fold.map = (callback, start = undefined) => iterator => fold(iterator, callback, start);
console.log(" ");
var add = (a,b) => a + b; //a little helper
console.log('using fold:', fold(range(1,5), add, 0));
//a composed utility-function
var sum2 = fold.map(add, 0);
console.log('sum2:', sum2( range(1,5) ));
Clearly a range function should not take a callback but be a generator function in modern JavaScript, however you were asking how to write such a callback.
You've already tagged your questions with closures, and they are indeed the way to go here. By initialising a new total within each call of the outer function, you don't need to worry about how to reset a global counter.
function makeSum() {
var total=0;
return function(m) {
total += m;
return total; // so that we can access the result
}
}
var sum = makeSum();
range(1, 5, sum);
output(sum(0));
Won't simply calling the callback on the range array suffice if the callback is not undefined? Like this:
> function range(n, callback) {
const r = [...Array(n).keys()]
if (callback) {
return callback(r)
}
return r
}
> function sum(arr) {
return arr.reduce((a, b) => a + b, 0)
}
> range(10)
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> range(10, sum)
> 45

How do I quicksort something based on its variable in local storage?

Hi I am trying to sort some data in localStorage via its IDs.
The format of the data is this:
{"Brand":"Acura","Model":"Choose your model","Age":"1998","KM":"10","Name":"Harry","ContactInfo":"123456677"}
where I want to sort in lowest to highest order of the KM value.
My local Storage Key is register and this is the code that I am using:
function Qsort() {
var mymain = JSON.parse(localStorage.getItem("register"));
var result = quicksort(mymain, 0, mymain.length - 1);
// the following line fo code shows the final result of the sorted numbers or strings
console.log(mymain);
console.log(quicksort(mymain, 0, mymain.length - 1));
return result;
}
function quicksort(mymain, left, right) {
var index;
// checks if there are more than one numbers
if (mymain.length > 1) {
// partition will find a pivot then split leist in two either left of right.
// Left list contains everything that is smaller than the pivot and the right contians everythign larger than pivot
index = partition(mymain, left, right);
// will treat left side aas a new problem and will then run the sort
if (left < index - 1){
quicksort(mymain, left, index - 1)
}
// will treat right side as a new problem and will then run the sort
if (index < right) {
quicksort(mymain, index, right)
}
}
return mymain
}
// Divides the whole function
function partition(mymain, left, right) {
var pivot = mymain[Math.floor((right + left) / 2)],
i = left,
j = right;
while (i <= j) {
while (mymain[i] < pivot) {
i++;
}
while (mymain[j] > pivot) {
j--;
}
if (i <= j) {
swap(mymain, i, j);
i++;
j--;
}
}
return i;
}
// swaps the values based on how high or low the number is
function swap(mymain, firstIndex, secondIndex) {
var temp = mymain[firstIndex];
mymain[firstIndex] = mymain[secondIndex];
mymain[secondIndex] = temp;
}
What should I do the var mymain part so that it only picks up the value defined under KM.
Assuming the item at "register" in localStorage is an array you could simply do...
var mymain = JSON.parse(localStorage.getItem("register"))
var justKMs = mymain.map(function(data){ return data.KM; });
but that would return an array of just the KM values, so you would end up having to search through the mymain list to get the the rest of the data, which I assume is not what you want.
Another approach would be to add a "lookup" function to tell quicksort "how" to get the value you want to use for the sort. Let's define our lookup function signature as simply function lookup( item ) => value where item is the thing in the list currently being sorted, and value is the value to sort by.
The following is a version of quicksort from computer-science-in-javascript with the added "lookup" function.
// the swap function doesn't need to change
function swap(items, firstIndex, secondIndex) {
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
}
// you will need to pass the lookup function into partition
function partition(items, left, right, lookup) {
// here you need to use "lookup" to get the proper pivot value
var pivot = lookup(items[Math.floor((right + left) / 2)]),
i = left,
j = right;
while (i <= j) {
// here is where you will do a lookup instead of just "items[i]"
while (lookup(items[i]) < pivot) {
i++;
}
// also use lookup here
while (lookup(items[j]) > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j);
i++;
j--;
}
}
return i;
}
function quickSort(items, left, right, lookup) {
var index;
// performance - don't sort an array with zero or one items
if (items.length > 1) {
// fix left and right values - might not be provided
left = typeof left != "number" ? 0 : left;
right = typeof right != "number" ? items.length - 1 : right;
// set a default lookup function just in case
if (typeof lookup !== 'function') {
// the default lookup function just returns the item passed in
lookup = function (item) {
return item;
};
}
index = partition(items, left, right, lookup);
if (left < index - 1) {
quickSort(items, left, index - 1, lookup);
}
if (index < right) {
quickSort(items, index, right, lookup);
}
}
return items;
}
and then the "lookup" function for your dataset would be...
function kmLookup( data ) {
return data.KM;
}
...ahh the power of higher-order functions
As a side note, if you aren't really married to quicksort you could take the lazy man option (or smart option depending on your point of view) and use the sort method on the Array prototype...
var mymain = JSON.parse(localStorage.getItem("register"));
// the sort function sorts the array in place,
// so after this next line mymain will be sorted
mymain.sort(function (a, b) {
return a.KM - b.KM;
});
That would probably be the best solution assuming you are not working with a very very large dataset. MDN Array.prototype.sort() docs

Why is this recursive function not stopping?

I attempted to create a recursive function to iterate through a data set, but it does not properly break out and is infinite
jsfiddle of code shown
var data = [{a: 1,b: 1}, {a: 2,b: 2}],z = 0;
function some(a, b, cbk) {
console.log(a + ':' +b);
cbk();
}
function main() {
var cbk = function () {
if (z < data.length) {
main();
} else {
console.log('end');
}
z++;
}
some(data[z].a, data[z].b, cbk);
}
main();
Why is this an infinite loop?
jsFiddle Demo
There were a few things going on here that made the recursion fail involving the iteration control. By starting with z = 0, and comparing to .length, z will need to be pre-increased prior to the conditional check if( z < .length ).
The reason is that following the path of recursion, z is never incremented and so the recursion is infinite causing a lockout of the page. So, z needs to be handled before the recursive call takes place, preferably before the comparison to the .length.
In your original version, this was taking place not only after the if statement, but also after the recursive call. Fixing this iterator will fix your recursion.
if (++z < data.length) {
I was told to undelete this because it's answerable although I am gaining much hate, I found have noticed my mistake and did this.
var data = [{
a: 1,
b: 1
}, {
a: 2,
b: 2
}],
z = 0;
function some(a, b, cbk) {
console.log(a + ':' +b);
cbk();
}
function main() {
var cbk = function () {
z++;
if (z < data.length) {
main();
} else {
console.log('end');
}
}
some(data[z].a, data[z].b, cbk);
}
main();
I don't know how fluent at reading code you are, but I've tried to break down the concept of linear recursion into as generic a way as I could imagine
function recurse(data, /* fns */ step, worker, joiner, /* vals */ first, empty) {
function recursor(data, current) {
var result = worker(data, current), // do work with current iteration
next = step(data, current); // find the next iteration
if (next !== null) // if found
return joiner( // return
result, // the result from this time
recursor(data, next) // + the result from next time
);
else // if not found
return joiner( // return
result, // just this result
empty // this join is helpful for joining arrays/objects/etc
);
}
return recursor(data, first); // start it
}
So, an example based on what you were doing
var data = [{a: 1,b: 1}, {a: 2,b: 2}];
function init(data) {
function logger(data, i) { // a function describing what to do
var e = data[i]; // with this iteration
console.log(e.a + ':' + e.b);
return e.a;
}
function step(data, i) { // a function describing how to find
i = i + 1; // the next iteration
if (i < data.length) return i;
return null; // null = end
}
function add(a, b) { // a function describing how to join
return a + b; // two iterations together
}
return recurse(data, step, logger, add, 0, 0);
}
init(data); // run everything safely in it's own closure
/*
1:1
2:2
3 // === 1 + 2 + 0, from return of logger and result of add
*/
Of course in practice you could do a lot of this in-place rather than a function for each thing, and the step can usually be simplified so much that you don't need to var for result and next because you don't have to cache anything for an if test.

Categories

Resources