Last stone weight 2 in javascript, 1d array - javascript

last stone weight 2 solution in cpp
This is able to pass all test cases.
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int n = stones.size();
int total = 0;
for(int i = 0; i < n; i++){
total += stones[i];
}
int req = total / 2;
vector <bool> dp(req + 1, false);
dp[0] = true;
int reach = 0;
for(int i = 0; i < n; i++){
for(int j = req; j - stones[i] >= 0; j--){
dp[j] = dp[j] || dp[j - stones[i]];
if(dp[j]) reach = max(reach, j);
}
}
return total - (2 * reach);
}
};
I tried to replicate it in javascript and not able to pass
a simple test cases like [2,7,4,1,8,1]
Here is my attempt
var lastStoneWeightII = function(st) {
// stone #
const n = st.length;
// sum up
const sum = st.reduce((acc, curr) => {return acc+curr});
// e.g. half
const ha = Math.floor(sum / 2);
// half+1
const dp = Array(ha+1).fill(false);
// 1st ele = true
dp[0] = true;
// store tmp_max
let max = 0;
// loop element
for(let i=0; i<n; i++) {
// single element
const w = n[i];
// backward, half
for(let j=ha; j-w>=0; j--) {
// update condi
dp[j] = dp[j] || dp[j-w];
// never comes in
if(dp[j]) {
//test
console.log('++++ max', max, 'j', j)
max = Math.max(max, j);
}
}
}
return (sum - max) - max;
}

Related

How to find the biggest prime number

I'm trying to solve a problem on an educational website platform.
This is the task/problem:
Write a program that finds and prints the biggest prime number which is <= N.
Input
On the first line you will receive the number N
Output
Print the biggest prime number which is <= N
Constraints
2 <= N <= 10 000 000
Examples
If N=13, then the biggest prime number is also 13.
If N=126, then the biggest prime number is also 113.
If N=26, then the biggest prime number is also 23
This is my code, which works fine, but the system does not accept it as fully correct because my code is slow/exceeds the memory limit:
const inputnumber = theNumberN; // Comes dymanically from the system
function getPrimes(max) {
let sieve = [];
let primes = [];
for (let i = 2; i <= max; ++i) {
if (!sieve[i]) {
primes.push(i);
for (let j = i << 1; j <= max; j += i) {
sieve[j] = true;
}
}
}
return primes;
}
let result = getPrimes(inputnumber);
let biggest = Math.max(...result);
console.log(biggest);
So, how can this be solved?
Can you offer a faster logic/algorithm
Assuming you are looking for only the biggest prime in a given range (2 <= N <= 10 000 000), the "simple" approach might actually be faster, since spread in primes below 10 000 000 is preety low (hence, the i-loop won't do so many rotations, disclaimer: this will not necessarly be true for all ranges).
function getBiggestPrime(max) {
let sieve = [];
let primes = [];
for (let i = 2; i <= max; ++i) {
if (!sieve[i]) {
primes.push(i);
for (let j = i << 1; j <= max; j += i) {
sieve[j] = true;
}
}
}
return primes[primes.length - 1];
}
function getBiggestPrimeTwo(max){
let biggestPrime = 1;
for (let i = max; i >= 2; i--){
let isPrime = true;
for (let j = 2; j < i; j++){
if (i % j == 0){ //break the loop, the number is not a prime
isPrime = false;
break;
}
}
if (isPrime){
biggestPrime = i;
break;
}
}
return biggestPrime;
}
function runTests(val, times){
var t0, t1, res, testStep;
testStep = val / times;
t0 = performance.now();
for (let i = 1; i <= times; i++){
res = getBiggestPrime(testStep*i);
}
t1 = performance.now();
console.log("Test1: " + res + ", took: " + (t1-t0) + "msec");
t0 = performance.now();
for (let i = 1; i <= times; i++){
res = getBiggestPrimeTwo(testStep*i);
}
t1 = performance.now();
console.log("Test2: " + res + ", took: " + (t1-t0) + "msec");
}
runTests(10000000, 50);

Solving the seventh with O(n)

I have solved the seventh problem of Euler, it says:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can
see that the 6th prime is 13.
What is the 10 001st prime number?
I solved it using, and in the array in which I keep the cousins, when it reaches the length of 10001, I return that number. The algorithm takes 1300 ms, which I tink that is very inefficient, what am I doing particularly in my implementation?
var start = performance.now();
function eratosthenes(n) {
var arr = [2], acc = 0;
// matrix to save the found prime numbers and mark their multiples
for(var i = 3; true; i += 2) { // loop
if(arr.length === n) return arr[arr.length - 1]; // if the array length is equal to n return the last number
if(!resolve(arr, i)) { // check if is multiple of the prime numbers, already found.
arr.push(i); // if isnt multiple, save it
}
}
}
function resolve(array, n) {
return array.some(cur => !(n%cur));
}
console.log(eratosthenes(10001)); // Tooks 1300 ms
var end = performance.now();
var time = end - start;
console.log(time);
Euler sieve, Pham knows this one :) 12ms
Uchu, I don't see where your code is marking the multiples. Isn't that what Sieve of Eratosthenes is supposed to do?
JavaScript code (this code is actually an adaptation of code by btilly, optimizing an idea of mine):
var start = performance.now();
n = 115000
a = new Array(n+1)
total = 0
s = []
p = 1
count = 0
while (p < n){
p = p + 1
if (!a[p]){
count = count + 1
if (count == 10001){
console.log(p);
end = performance.now();
time = end - start;
console.log(time);
break;
}
a[p] = true
s.push(p)
limit = n / p
new_s = []
for (i of s){
j = i
while (j <= limit){
new_s.push(j)
a[j*p] = true;
j = j * p
}
}
s = new_s
}
}
As requested by JaromandaX, this is the code for Sieve of Eratosthenes. 51 ms on my browser (OP solution is 750 ms)
var max = 1000000;
function eratosthenes(n) {
var arr = [], count = 0;
for (var i = 0; i < max; i++){
arr.push(true);
}
for (var i = 2; i < max; i++){
if(arr[i]){
count++;
if(count == n){
return i;
}
for (var j = i + i; j < max; j += i ){
arr[j] = false;
}
}
}
}
var start = performance.now();
console.log(eratosthenes(10001));
var end = performance.now();
var time = end - start;
console.log(time);
This has a similar running time to גלעד ברקן's answer (actually about 10% faster on my machine), but doesn't rely on knowing an approximate max before starting. It performs a seive of Eratosthenes up to max (starting at 2) and then doubles max, initialises the new elements in the array per the previously found primes and repeats.
function eratosthenes(n) {
let prev_max = 1, max = 2, i, j;
const primes = [], is_prime = new Array(max+1).fill(true);
while( true ) {
for ( i = prev_max + 1; i <= max; i++){
if ( ! is_prime[i] ) continue;
primes.push( i );
if ( primes.length === n )
return i;
for ( j = i + i; j <= max; j += i )
is_prime[j] = false;
}
const next_max = max*2;
is_prime.length = next_max + 1;
is_prime.fill( true, max + 1, next_max );
for ( i = 0; i < primes.length; i++ ) {
const prime = primes[i];
for ( j = max + prime - max%prime; j <= next_max; j += prime )
is_prime[j] = false;
}
prev_max = max;
max = next_max;
}
}
var start = performance.now();
console.log(eratosthenes(10001));
var end = performance.now();
var time = end - start;
console.log(time);
If it is a code-writing exercise, it is better to explore the earlier answers.
But if you are after a simple and fast solution, here's how you can solve it using prime-lib, which I created:
import {generatePrimes} from 'prime-lib';
const seekIndex = 10_001; // index of the prime being sought
const start = Date.now();
let a, c = 0;
const i = generatePrimes({boost: seekIndex + 1});
while ((a = i.next()) && !a.done && c++ < seekIndex) ;
console.log(`Prime: ${a.value}, took ${Date.now() - start}ms`);
On my PC it spits out:
Prime: 104759, took 5ms
And with the modern RXJS this becomes even simpler still:
import {generatePrimes} from 'prime-lib';
import {from, last} from 'rxjs';
const seekIndex = 10_001; // index of the prime being sought
const i = generatePrimes({boost: seekIndex + 1});
from(i).pipe(last()).subscribe(console.log);
//=> 104759

I'm trying to raise numbers to their consecutive powers and my code isn't working

https://codepen.io/aholston/pen/ZJbrjd
The codepen link has commented code as well as actual instructions in HTML
Otherwise.... what I ultimately have to do is write a function that takes two params(a and b) and takes all the numbers between those two params (a-b) and put every number that can be added to the consecutive fowers and be equal to that number into a new array. Ex: 89 = 8^1 + 9^2 = 89 or 135 = 1^1 + 3^2 + 5^3 = 135
function sumDigPow(a, b) {
// Your code here
var numbers = [];
var checkNum = [];
var finalNum = [];
var total = 0;
for (var i = 1; i <= b; i++) {
if (i >= a && i <= b) {
numbers.push(i);
}
}
for (var x = 0; x < numbers.length; x++) {
var checkNum = numbers[x].toString().split('');
if (checkNum.length == 1) {
var together = parseInt(checkNum);
finalNum.push(together);
} else if (checkNum.length > 1) {
var together = checkNum.join('');
var togNumber = parseInt(together);
for (var y = checkNum.length; y > 0; y--) {
total += Math.pow(checkNum[y - 1], y);
}
if (total == togNumber) {
finalNum.push(togNumber);
}
}
}
return finalNum;
}
try this:
function listnum(a, b) {
var finalNum = [];
for (var i = a; i <= b; i++) {
var x = i;
var y = i;
var tot = 0;
j = i.toString().length;
while (y) {
tot += Math.pow((y%10), j--);
y = Math.floor(y/10);
}
if (tot == x)
finalNum.push(i);
}
return finalNum;
}
console.log(listnum(1, 200));
Okay, after debugging this is what I learned.
for (var y = checkNum.length; y > 0; y--) {
total += Math.pow(checkNum[y - 1], y);
}
if (total == togNumber) {
finalNum.push(togNumber);
}
}
}
return finalNum;
}
Everytime this loop happened, I neglected to reset the 'total' variable back to 0. So I was never getting the right answer for my Math.pow() because my answer was always adding to the previous value of total. In order to fix this, I added var total = 0; after i decided whether or not to push 'togNumber' into 'finalNum.' So my code looks like this..
for (var y = checkNum.length; y > 0; y--) {
total += Math.pow(checkNum[y - 1], y);
}
if (total == togNumber) {
finalNum.push(togNumber);}
}
var total = 0;
}
return finalNum;
}

javascript canvas: draw moving average line with curves

So basically, I want to draw a curved average line over a certain amount of points of a time-series line chart. Like this:
I want it to span the entire length of the chart but I can't figure out how to calculate the start and end points because the average would (I think) be a point in the middle of each section. Looking at a stock chart with moving average you can see what I want to acheive:
I calculate the averages first by splitting the data array up into chunks based on a period of time. So if I start with:
[
{ time: 1, value: 2 },
{ time: 2, value: 4 },
{ time: 3, value: 5 },
{ time: 4, value: 7 },
]
I get to:
var averages = [
{
x: 1.5,
y: 3,
},
{
x: 3.5 (the average time)
y: 6 (the average value)
},
]
This is what I've tried where I end up with an incomplete line, one that doesnt start at the beginning of the chart and doesnt stop at the end, but stars and ends inside the chart at the first average time:
ctx.moveTo((averages[0].x), averages[0].y);
for(var i = 0; i < averages.length-1; i ++)
{
var x_mid = (averages[i].x + averages[i+1].x) / 2;
var y_mid = (averages[i].y + averages[i+1].y) / 2;
var cp_x1 = (x_mid + averages[i].x) / 2;
var cp_x2 = (x_mid + averages[i+1].x) / 2;
ctx.quadraticCurveTo(cp_x1, averages[i].y ,x_mid, y_mid);
ctx.quadraticCurveTo(cp_x2, averages[i+1].y ,averages[i+1].x, averages[i+1].y);
}
ctx.stroke();
How would you do this?
To get a moving mean you need to just get the mean of n points either side of the current sample.
For example
// array of data points
const movingMean = []; // the resulting means
const data = [12,345,123,53,134,...,219]; // data with index representing x axis
const sampleSize = 5;
for(var i = sampleSize; i < data.length - sampleSize; i++){
var total = 0;
for(var j = i- sampleSize; j < i + sampleSize; j++){
total += data[j];
}
movingMean[i] = total / (sampleSize * 2);
}
This method does not pull the mean forward giving the most accurate mean for each data point.
The problem with this method is that you do not get a mean for the first n and last n samples, where n is the number of samples either side of the mean.
You can do an alternative that will pull the mean forward a little but by applying a weighted mean you can reduce the bias a little
for(var i = sampleSize; i < data.length + Math.floor(sampleSize / 4); i++){
var total = 0;
var count = 0;
for(var j = sampleSize; j > 0; j --){
var index = i - (sampleSize - j);
if(index < data.length){
total += data[index] * j; // linear weighting
count += j;
}
}
movingMean[i-Math.floor(sampleSize / 4)] = total / count;
}
This method keeps that mean closer to the current sample end.
The example show a random data set and the two types of means plotted over it. Click to get a new plot. The red line is the moving mean and the blue is the weighted mean. Note how the blue line tends to follow the data a little slow.
The green line is a weighted mean that has a sample range 4 times greater than the other two.
// helper functions
const doFor = (count, callback) => {var i = 0; while (i < count) { callback(i ++) } };
const setOf = (count, callback) => {var a = [],i = 0; while (i < count) { a.push(callback(i ++)) } return a };
const rand = (min, max = min + (min = 0)) => Math.random() * (max - min) + min;
const randG = (dis, min, max) => {var r = 0; doFor(dis,()=>r+=rand(min,max)); return r / dis};
function getMinMax(data){
var min = data[0];
var max = data[0];
doFor(data.length - 1, i => {
min = Math.min(min,data[i+1]);
max = Math.max(max,data[i+1]);
});
var range = max-min;
return {min,max,range};
}
function plotData(data,minMax){
ctx.beginPath();
for(var i = 0; i < data.length; i++){
if(data[i] !== undefined){
var y = (data[i] - minMax.min) / minMax.range;
y = y *(ctx.canvas.height - 2) + 1;
ctx.lineTo(i/2,y);
}
}
ctx.stroke();
}
function getMovingMean(data,sampleSize){
const movingMean = []; // the resulting means
for(var i = sampleSize; i < data.length - sampleSize; i++){
var total = 0;
for(var j = i- sampleSize; j < i + sampleSize; j++){
total += data[j];
}
movingMean[i] = total / (sampleSize * 2);
}
return movingMean[i];
}
function getMovingMean(data,sampleSize){
const movingMean = []; // the resulting means
for(var i = sampleSize; i < data.length - sampleSize; i++){
var total = 0;
for(var j = i- sampleSize; j < i + sampleSize; j++){
total += data[j];
}
movingMean[i] = total / (sampleSize * 2);
}
return movingMean;
}
function getWeightedMean(data,sampleSize){
const weightedMean = [];
for(var i = sampleSize; i < data.length+Math.floor(sampleSize/4); i++){
var total = 0;
var count = 0;
for(var j = sampleSize; j > 0; j --){
var index = i - (sampleSize - j);
if(index < data.length){
total += data[index] * j; // linear weighting
count += j;
}
}
weightedMean[i-Math.floor(sampleSize/4)] = total / count;
}
return weightedMean;
}
const dataSize = 1000;
const sampleSize = 50;
canvas.width = dataSize/2;
canvas.height = 200;
const ctx = canvas.getContext("2d");
function displayData(){
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
var dataPoint = 100;
var distribution = Math.floor(rand(1,8));
var movement = rand(2,20);
const data = setOf(dataSize,i => dataPoint += randG(distribution, -movement, movement));
const movingMean = getMovingMean(data, sampleSize);
const weightedMean = getWeightedMean(data, sampleSize*2);
const weightedMean1 = getWeightedMean(data, sampleSize*8);
var minMax = getMinMax(data);
ctx.strokeStyle = "#ccc";
plotData(data,minMax);
ctx.strokeStyle = "#F50";
plotData(movingMean,minMax);
ctx.strokeStyle = "#08F";
plotData(weightedMean,minMax);
ctx.strokeStyle = "#4C0";
plotData(weightedMean1,minMax);
}
displayData();
document.onclick = displayData;
body { font-family : arial; }
.red { color : #F50; }
.blue { color : #0AF; }
.green { color : #4C0; }
canvas { position : absolute; top : 0px; left :130px; }
<canvas id="canvas"></canvas>
<div class="red">Moving mean</div>
<div class="blue">Weighted mean</div>
<div class="green">Wide weighted mean</div>
<div>Click for another sample</div>

Binary to Decimal Javascript

This code is supposed to take in a string ("100101") and output the result in decimal.I'm not quite sure why it's not working.Any help would be appreciated.
function BinaryConverter(str) {
var num=str.split("");
var powers=[];
var sum=0;
for(var i=0;i<num.length;i++){
powers.push(i);
}
for(var i=powers.length-1;i>=0;i--){
for(var j=0;j<num.length;i++){
sum+=Math.pow(2,i)*num[j];
}
}
return sum;
};
Here's my updated code below .For an input "011" it should do( 2^2*0 +2^1*1 +2^0*1)to =3 but it returns 14.Anybody know where I'm going wrong?
function BinaryConverter(str) {
var num=str.split("");
var powers=[];
var sum=0;
for(var i=0;i<num.length;i++){
powers.push(i);
}
for(var i=powers.length-1;i>=0;i--){
for(var j=0;j<num.length;j++){
sum+=Math.pow(2,i)*num[j];
}
}
return sum;
};
The two nested for loops have a problem. The first one subtracts an i, while the second adds an i forever creating a never ending loop.
ALSO your code should be this:
function BinaryConverter(str) {
var num=str.split("");
var powers=[];
var sum=0;
var numlength=num.length;
for(var i=0;i<num.length;i++){
powers.push(i);
}
for(var i=powers.length-1;i>=0;i--){
sum+=Math.pow(2,i)*num[numlength-i-1];
}
return sum;
};
I don't think you need the nested for loop
If you don't want to do that with parseInt() for some reason (like, because the homework problem says you can't), you can do this without the complexity and expense of calling Math.pow() for each digit:
function parseBinary(str) {
var i, value = 0;
for (i = 0; i < str.length; ++i)
value = value * 2 + +str[i];
return value;
}
That doesn't check for invalid input strings.
ace040686 only inverted the pow(2,i) and num[len-1-i] in his answer, otherwise it would be correct. Also you're pushing 0..str.length-1 unnecessarily to powers, those are implicit indices.
function convertNaive(str) {
var num = str.split("");
var len = num.length;
var sum = 0;
for(var i = len - 1; i >= 0; --i)
sum += Math.pow(2, len - 1 - i) * num[i];
return sum;
}
You can improve this a bit to avoid the unnecessary array and especially Math.pow:
function convertImproved(str) {
var len = str.length;
var sum = 0;
for(var i = 0, fac = 1; i < len; ++i, fac *= 2)
sum += fac * str[len - 1 - i];
return sum;
}
Try it yourself:
var input = "100101";
var logNode = document.getElementById("log");
function log(line) {
var text = document.createTextNode(line);
var node = document.createElement("p");
node.appendChild(text);
logNode.appendChild(node);
}
function convertNaive(str) {
var num = str.split("");
var len = num.length;
var sum = 0;
for(var i = len - 1; i >= 0; --i)
sum += Math.pow(2, len - 1 - i) * num[i];
return sum;
}
function convertImproved(str) {
var len = str.length;
var sum = 0;
for(var i = 0, fac = 1; i < len; ++i, fac *= 2)
sum += fac * str[len - 1 - i];
return sum;
}
log("input: " + input);
log("parseInt(input, 2): " + parseInt(input, 2));
log("convertNaive(input): " + convertNaive(input));
log("convertImproved(input): " + convertImproved(input));
<div id="log" />
Here is the simple implementation of binary to decimal in javascript.
main();
function main() {
let binaryInput = 10000100111;
let decimalOutput = binaryTodecimal(binaryInput);
console.log(decimalOutput);
}
function binaryTodecimal(input) {
let inputString = input.toString();
let result = 0;
let exponent = 1;
let currentBit = 0;
for (let i = inputString.length - 1; i >= 0; i--) {
currentBit = parseInt(inputString[i]);
currentBit *= exponent;
result += currentBit;
exponent *= 2;
}
return result;
}

Categories