I'm trying to implement a function that takes a string as input and returns the longest palindrome subsequence in the string.
I've tried using dynamic programming and have come up with the following code:
function longestPalindromicSubsequence(str) {
let n = str.length;
let dp = Array(n);
for (let i = 0; i < n; i++) {
dp[i] = Array(n);
dp[i][i] = 1;
}
for (let cl = 2; cl <= n; cl++) {
for (let i = 0; i < n - cl + 1; i++) {
let j = i + cl - 1;
if (str[i] === str[j] && cl === 2)
dp[i][j] = 2;
else if (str[i] === str[j])
dp[i][j] = dp[i + 1][j - 1] + 2;
else
dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]);
}
}
return dp[0][n - 1];
}
However, this code doesn't seem to be giving me efficient and better results for all test cases. The Time and Space Complexity is also be reduced. I've been struggling with this for days and can't seem to find the issue. Can someone help me figure out what's going wrong and how to fix it?
Oh, I think Dynamic Programming does not work with this sort of problem, because it does not break down recursively, i.e. to find the longest palindrome in a string, you don't need all second-largest palindromes. You can just check at each position and see if it is the center of a palindrome longer than any before. This can be solved with a greedy algorithm:
const pals = "asd1234321fghjkl1234567887654321qwertzu1234321"
function palindromeAtPos(str, pos, checkEven = false){
let ix = 0
const off = checkEven ? 2 : 1
while(pos-ix-1 >= 0 && pos+ix+1+off < str.length && str[pos-ix-1] === str[pos+ix+off]){
ix++
}
return ix === 0 ? str[pos] : str.substring(pos-ix, pos+ix+off)
}
function longestPalindrome(str){
let longest = ''
for(let i = 1; i < str.length; i++){
const odd = palindromeAtPos(str, i)
longest = odd.length > longest.length ? odd : longest
const even = palindromeAtPos(str, i, true)
longest = even.length > longest.length ? even : longest
}
return longest
}
console.log(longestPalindrome(pals))
On paper (and for a string like aaaaaaaaaa), this has quadratic complexity, but for most strings, it will be almost linear.
/*
* s => string
* return [] of strings witch have the max lenth
*/
function maxLenPalindromes(s) {
const l = s.length
let c, z, zz, a, b, a1, b1, maxl = 0, result = []
if (l < 2) return result
for (c = 0; c < l - 1; c++) {
a = -1
if (maxl>(l-c)*2+1) return result
if (c > 0 && s[c - 1] == s[c + 1]) {
zz = Math.min(c, l - c - 1)
for (z = 1; z <= zz; z++) {
if (s[c - z] != s[c + z]) {
a = c - z + 1; b = c + z
break
}
else if (z == zz) {
a = c - z; b = c + z + 1
break
}
}
if (a >= 0) {
if (b-a > maxl) {
result = [s.slice(a, b)]
maxl = b-a
}
else if (b-a == maxl) {
result.push(s.slice(a, b))
}
}
}
a=-1
if (s[c] == s[c + 1]) {
if (c == 0 || c == l - 2) {
a = c; b = c + 2
}
else {
zz = Math.min(c, l - c - 2)
for (z = 1; z <= zz; z++) {
if (s[c - z] != s[c + z + 1]) {
a = c - z + 1; b = c + z + 1
break
}
else if (z == zz) {
a = c - z; b = c + z + 2
break
}
}
}
if (a >= 0) {
if (b-a > maxl) {
result = [s.slice(a, b)]
maxl = b-a
}
else if (b-a == maxl) {
result.push(s.slice(a, b))
}
}
}
}
return result
}
const s1="112233111222333"
const s2="11_22_33_111_222_333"
const s3="12345_54321xqazws_swzaq_qwertytrewq"
const s4="sdfgsdfg1qqqqqAAAAA_123456789o o987654321_AAAAAqqqqq;lakdjvbafgfhfhfghfh"
console.log(maxLenPalindromes(s1))
console.log(maxLenPalindromes(s2))
console.log(maxLenPalindromes(s3))
console.log(maxLenPalindromes(s4))
I have a java-script function that carries out a calculation. I would like to use the answer to that calculation in my php code.
document.write(Fixed((PoissonTerm( X, Y )),8,4))
Both values X and Y come from variables within my php code so
<?php
$valueofx;
$valueofy;
?>
In the ideal world I would like to to look like this
<?php
$thejavascriptvalue = document.write(Fixed((PoissonTerm( $valueofx, $valueofy )),8,4))
?>
I know this can't be done and i have 5 different values i need to pull and use. Is there anyway I can work around it? I dont mind refreshing the page or grabbing it from another page as long as i can have 5 values to use in my php code.
I would need to run the javascript 10 times before redirecting like
document.write(Fixed((PoissonTerm(0.1, 0 )),8,4))
document.write(Fixed((PoissonTerm( 8, 2 )),8,4))
document.write(Fixed((PoissonTerm( 6, 3 )),8,4))
below if the javascript
function Fixed( s, wid, dec ) {
// many combinations of possibilities
// maybe prepare for upcoming truncate
var z = 1
if (dec > 0) {
z /= Math.pow( 10, dec );
if (s < -z) s -= 0.5 * z;
else
if (s > z) s += 0.5 * z;
else
s = 0;
}
// assure a string
s = "" + s;
// chop neg, if any
var neg = 0;
if (s.charAt(0) == "-") {
neg = 2;
s = s.substring( 1, s.length );
}
// chop exponent, if any
var exp = "";
var e = s.lastIndexOf( "E" );
if (e < 0) e = s.lastIndexOf( "e" );
if (e > -1) {
exp = s.substring( e, s.length );
s = s.substring( 0, e );
}
// if dec > 0 assure "."; dp == index of "."
var dp = s.indexOf( ".", 0 );
if (dp == -1) {
dp = s.length;
if (dec > 0) {
s += ".";
dp = s.length - 1;
}
}
// assure leading digit
if (dp == 0) {
s = '0' + s;
dp = 1;
}
// not enough dec pl? add 0's
while ((dec > 0) && ((s.length - dp - 1) < dec))
s += "0";
// too many dec pl? take a substring
var places = s.length - dp - 1;
if (places > dec)
if (dec == 0)
s = s.substring( 0, dp );
else
s = s.substring( 0, dp + dec + 1 );
// recover exponent, if any
s += exp;
// recover neg, if any
if (neg > 0)
s = "-" + s;
// if not enough width, add spaces IN FRONT
// too many places? tough!
while (s.length < wid)
s = " " + s;
return s
}
function Prb( x ) {
if (x < 0) x = 0;
else
if (x > 1) x = 1;
return x;
}
function PosV( x ) {
if (x < 0) x = -x;
return x;
}
// FACTORIALS
function Fact( x ) {
// x factorial
var t=1;
while (x > 1)
t *= x--;
return t;
}
function LnFact( x ) {
// ln(x!) by Stirling's formula
// see Knuth I: 111
if (x <= 1) x = 1;
if (x < 12)
return Math.log( Fact(Math.round(x)) );
else {
var invx = 1 / x;
var invx2 = invx * invx;
var invx3 = invx2 * invx;
var invx5 = invx3 * invx2;
var invx7 = invx5 * invx2;
var sum = ((x + 0.5) * Math.log(x)) - x;
sum += Math.log(2*Math.PI) / 2;
sum += (invx / 12) - (invx3 / 360);
sum += (invx5 / 1260) - (invx7 / 1680);
return sum;
}
}
// POISSON
function PoissonPD( u, k ) {
// Peizer & Pratt 1968, JASA 63: 1416-1456
var s = k + (1/2);
var d1 = k + (2/3) - u;
var d2 = d1 + 0.02/(k+1);
var z = (1 + g(s/u)) / u;
z = d2 * Math.sqrt(z);
z = NormalP( z );
return z;
}
function PoissonTerm( u, k ) {
// by logs
return Math.exp( (k * Math.log(u)) - u - LnFact(k) );
}
function PoissonP( u, k ) {
// term-by-term summation
if (k >= 20) return PoissonPD( u, k );
else {
var sum = 0.0, j = 0;
while (j <= k)
sum += PoissonTerm( u, j++ );
if (sum > 1) sum = 1;
return sum;
}
}
function DoPoi( aform ) {
var u = PosV(parseFloat(aform.u.value));
aform.u.value = Fixed(u,10,4);
var k = PosV(parseInt(aform.k.value));
aform.k.value = Fixed(k,8,0);
aform.tnk.value = Fixed(PoissonTerm( u, k ),8,4);
var t = PoissonP( u, k );
aform.puk.value = Fixed(t,8,4);
aform.quk.value = Fixed(1-t,8,4);
}
This is very generic. You're going to have to modify this to your needs. But this will give you the basic idea:
<form name="thisform" action="phpPage.php" method="POST">
X: <input type="text" name="val_x" id="val_x" value="40" /><br />
Y: <input type="text" name="val_y" id="val_y" value="60" /><br />
<input type="button" onclick="sendForm();" value="send form"/>
</form>
JavaScript:
function sendForm(){
//Choose one of these methods:
//This will generate a string that you can use as a location.
//use $_GET in PHP to retrieve the values
var valofX = document.getElementById("val_x").value;
var valofy = document.getElementById("val_y").value;
generateURL = 'phpPage.php?val_x=' + valofX;
generateURL += '&val_y=' + valofy;
document.location = generateURL;
//This will submit the form.
//use $_POST in PHP to retrieve the values
document.getElementById("thisform").submit();
}
Once the form is submitted, or the location is sent, you'll need to grab the values in PHP:
$val_x = $_POST['val_x'];
$val_y = $_POST['val_y'];
//OR
$val_x = $_GET['val_x'];
$val_y = $_GET['val_y'];
You would use $_GET or $_POST depending on how the values are sent.
I made a map using the diamond-square algorithm. It works, but there are areas exclusively at the top of the map that seem to be using values from the other side of the map. I do not know what is causing this, and would like some help finding it.
Here's an image of the problem:
This is the relevant code, but I do not know where the problem occurs.
p = [
[y[0] + c, y[1]],
[y[0] - c, y[1]],
[y[0], y[1] + c],
[y[0], y[1] - c]
];
for (var m = 0; m < 4; m++) {
//Calculate Current Suare
var t = [];
// Add only those points to t that do not cross the edge in
// the direction in which they move away from p[m]:
if (p[m][0] + c <= s) {
t.push([p[m][0] + c, p[m][1]]);
}
if (p[m][0] - c >= 0) {
t.push([p[m][0] - c, p[m][1]]);
}
if (p[m][1] + c <= s) {
t.push([p[m][0], p[m][1] + c]);
}
if (p[m][1] - c >= 0) {
t.push([p[m][0], p[m][1] - c]);
}
var z = [
p[m],
y
];
//Check for edge
if ((p[m][0] === 0 || p[m][0] == s) || (p[m][1] === 0 || p[m][1] == s)) {
for (var k = 0; k < t.length; k++) {
if ((t[k][0] < 0 || t[k][0] > s) || (t[k][1] < 0 || t[k][1] > s)) {
t.splice(k, 1);
break;
}
}
}
//Set values
ar[p[m][0]][p[m][1]] = (t.map(function (e) {
return ar[e[0]][e[1]];
}).reduce(function (a, b) {
return a + b;
}) / t.length) + rand(n);
}
Here is a fiddle of the complete code:
http://jsfiddle.net/Shamadruu/7zutLnfL/18/
The problem is in the for(var k loop: you stop looking for cross-edge conditions once
you have found one (you break), but there could be two of them.
Although you could solve that by removing the break and adding k--;, there is a more
efficient way to deal with the edges: test before adding the points to t whether they
are within the edges. With these particular points that means you need to test them only
against one edge each, which is a savings of factor 4!
var t = [];
// Add only those points to t that do not cross the edge in
// the direction in which they move away from p[m]:
if (p[m][0] + c <= s) {
t.push([p[m][0] + c, p[m][1]]);
}
if ([p[m][0] - c >= 0) {
t.push([p[m][0] - c, p[m][1]]);
}
if (p[m][1] + c <= s) {
t.push([p[m][0], p[m][1] + c]);
}
if (p[m][1] - c >= 0) {
t.push([p[m][0], p[m][1] - c]);
}
var z = [
p[m],
y,
];
//Set values ...etc.
Similarly, you will have to review the inclusion of squares in z to make sure they do not cross the edge:
//Find New Square
switch (m) {
case 0:
if (p[m][0] - c >= 0 && p[m][1] + c <= s) {
z.push([p[m][0] - c, p[m][1] + c], [p[m][0], p[m][1] + c]);
}
break;
// ... etc.
I'm trying to convert a number between 1 and 16,777,215 to any colour format (RGB/HSL/HEX) that increments through the colour spectrum using Javascript/jQuery.
The number 16,777,215 is the total possible combinations of RGB(255,255,255) which is 32 bit colour.
I initially thought converting the value to a hex value using toString(16) would increment through the spectrum, however as the number increases it seems to work through different lightness values instead and flashes. An example of this unwanted behaviour is here http://jsfiddle.net/2z82auka/
var colour = 16777215;
window.setInterval(function(){
colour -= 1000;
$('body').css({background:'#' + colour.toString(16)});
}, 50);
How can I convert a value between 1 and 16777215 to a colour on the colour spectrum shown below?
The code below will do exactly what you want - it'll give you vibrant colors of the color spectrum exactly as the image below, and to prove it, the demo will print out the integer values beside the color. The result will look like this. Please use the rainbow function in your setInterval code.
var colours = 16777215;
function rainbow(numOfSteps, step) {
var r, g, b;
var h = 1 - (step / numOfSteps);
var i = ~~(h * 6);
var f = h * 6 - i;
var q = 1 - f;
switch(i % 6){
case 0: r = 1, g = f, b = 0; break;
case 1: r = q, g = 1, b = 0; break;
case 2: r = 0, g = 1, b = f; break;
case 3: r = 0, g = q, b = 1; break;
case 4: r = f, g = 0, b = 1; break;
case 5: r = 1, g = 0, b = q; break;
}
var c = "#" + ("00" + (~ ~(r * 235)).toString(16)).slice(-2) + ("00" + (~ ~(g * 235)).toString(16)).slice(-2) + ("00" + (~ ~(b * 235)).toString(16)).slice(-2);
return (c);
}
function render(i) {
var item = "<li style='background-color:" + rainbow(colours, i) + "'>" + i + "</li>";
$("ul").append(item);
}
function repeat(fn, times) {
for (var i = 0; i < times; i+=10000) fn(i);
}
repeat(render, colours);
li {
font-size:8px;
height:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul></ul>
(I can't take credit for this code, but I can take credit for not giving up and settling for jerky color changes. Ref: https://gist.github.com/ruiwen/6163115)
Convert to range the initial value from 1 > 16777216 from 0 > 360
Technique here: Convert a number range to another range, maintaining ratio
Then use the HSL colour model, and increment from H0 S100 L100 > H360 S100 L100
Sticking to RGB: Always incrementing by one will not result in a steady grade through the spectrum. For example, when you go from #0000ff (which is blue) to that +1, you end up at #000100, which is essentially black.
Instead, you will probably want to do something more like incrementing each of the three values (the R value, the G value, and the B value) by one. However, that will omit many, many colors. But if smoothness is what you value over comprehensiveness, that's a simple way to get there.
#nada points out that this will give you an awful lot of grey. If you want to avoid that, you can try variations like: increment R until it can't be incremented anymore. Leave it at max value while you increment G until it hits max, then increment B to max. Now reverse it: Decrement R to minimum, then G, then B. This will still miss a ton of colors (in fact, it will miss most colors), but it should be smooth and it should avoid being nothing but grey.
Although this will work (if you don't mind missing most colors), I'm sure there is a better solution. I hope someone weighs in with it. I'm very curious.
You have the hue value, so you need to turn that into the various color formats using fixed brightness and saturation.
To properly scale the hue from [1, 16777215] to a [0, 1] scale, you'll need to do (x - 1) / 16777215. Take this number and feed it into hsl2rgb (here's a JS implementation) with a high lum and relatively high sat.
Something like so:
// From this answer: https://stackoverflow.com/a/9493060/129032
function hslToRgb(h, s, l) {
var r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
var hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
function scaleHue(hue) {
return ((hue - 1) / 16777215);
}
var colour = 0;
window.setInterval(function() {
colour = (colour + 100000) % 16777215;
var hue = scaleHue(colour);
var current = hslToRgb(hue, 0.8, 0.8);
$('body').css({
background: '#' + current[0].toString(16) + current[1].toString(16) + current[2].toString(16)
});
}, 50);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I increased the step from 1000 to 100000 to make the demo more obvious.
This works for me...
export function intToHex(colorNumber)
{
function toHex(n) {
n = n.toString(16) + '';
return n.length >= 2 ? n : new Array(2 - n.length + 1).join('0') + n;
}
var r = toHex(Math.floor( Math.floor(colorNumber / 256) / 256 ) % 256),
g = toHex(Math.floor( colorNumber / 256 ) % 256),
b = toHex(colorNumber % 256);
return '#' + r + g + b;
}
Generally, this is the formula for converting an integer to rgba
r = (val)&0xFF;
g = (val>>8)&0xFF;
b = (val>>16)&0xFF;
a = (val>>24)&0xFF;
Expressed as javascript
function ToRGBA(val){
var r = (val)&0xFF;
var g = (val>>8)&0xFF;
var b = (val>>16)&0xFF;
var a = (val>>24)&0xFF;
return "rgb(" + r + "," + g + "," + b + ")";
}
Updated fiddle: http://jsfiddle.net/2z82auka/2/
Something like that ?
<script>
function intToHex(colorNumber) {
var R = (colorNumber - (colorNumber%65536)) / 65536;
var G = ((colorNumber - R*65536) - ((colorNumber - R*65536)%256)) / 256;
var B = colorNumber - R*65536 - G*256;
var RGB = R.toString(16) + G.toString(16) + B.toString(16);
return RGB;
}
</script>
Marrying this answer with Drake's:
function colorNumberToHex(colorNumber) {
function toHex(n) {
n = n.toString(16) + '';
return n.length >= 2 ? n : new Array(2 - n.length + 1).join('0') + n;
}
var r = toHex(colorNumber % 256),
g = toHex(Math.floor( colorNumber / 256 ) % 256),
b = toHex(Math.floor( Math.floor(colorNumber / 256) / 256 ) % 256);
return '#' + r + g + b;
}
The picture you've shown suggests you really just want to rotate through a set of continuous colors, not every possible rgb color (since many of them essentially look white or black). I would suggest using HSV as a base instead of RGB. Trying to increment a number that represents an RGB value will lead to the stuttering you see (like #Trott pointed out, going from 0000ff to 000100 jumps from a blue to a black).
Try something like this (Fiddle):
$(document).ready(function(){
var h = 0;
window.setInterval(function(){
h += .01;
if (h >= 1) h-=1;
var rgbColor = HSVtoRGB(h, 1, 1);
var colorString = '#' + convertComponentToHex(rgbColor.r)
+ convertComponentToHex(rgbColor.g)
+ convertComponentToHex(rgbColor.b);
$('body').css({background:colorString});
}, 50);
});
function convertComponentToHex(v) {
return ("00" + v.toString(16)).substr(-2);
}
function HSVtoRGB(h, s, v) {
var r, g, b, i, f, p, q, t;
if (h && s === undefined && v === undefined) {
s = h.s, v = h.v, h = h.h;
}
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return {
r: Math.floor(r * 255),
g: Math.floor(g * 255),
b: Math.floor(b * 255)
};
}
(Thanks to this SO answer for the conversion code. I was too lazy to go figure it out for myself.)
My implementation....
var r = 255;
var g = 0;
var b = 0;
var stage = 1;
var step = 5;
var int = setInterval(function () {
if (stage == 1) {
g += step;
if (g >= 255) {
g = 255;
stage = 2;
}
} else if (stage == 2) {
r -= step;
if (r <= 0) {
r = 0;
stage = 3;
}
} else if (stage == 3) {
b += step;
if (b >= 255) {
b = 255;
stage = 4;
}
} else if (stage == 4) {
g -= step;
if (g <= 0) {
g = 0
stage = 5;
}
} else if (stage == 5) {
r += step;
if (r >= 255) {
r = 255;
stage = 6;
}
} else if (stage == 6) {
b -= step;
if (b <= 0) {
b = 0;
clearInterval(int);
}
}
//console.log(r,g,b);
$('body').css('background-color', 'RGB('+r+','+g+','+b+')');
}, 10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm writing Nano like editor in javascript and have problem with calculating cursor position and file offset for display:
I have two variables _rows and settings.verticalMoveOffset (which is default set to 9 like in Nano) when you move cursor in line 20 and there are 19 rows the cursor is offset by verticalMoveOffset.
I work on this few hours and can't figure out how to map file pointer (line) to editor cursor and offset of the file (the line from which it start the view).
Last try was
if (y >= this._rows) {
var page = Math.floor(y / (this._rows-this._settings.verticalMoveOffset))-1;
var new_offset = (this._rows - this._settings.verticalMoveOffset) * page;
if (this._offset !== new_offset) {
this._view(new_offset);
}
cursor_y = y - (this._rows*page) + this._settings.verticalMoveOffset;
} else {
if (y <= this._rows - this._settings.verticalMoveOffset - 1 &&
this._offset !== 0) {
this._pointer.x = x;
this._pointer.y = y;
this._view(0);
cursor_y = y;
} else if (this._offset !== 0) {
cursor_y = (y - this._settings.verticalMoveOffset) + 1;
} else {
cursor_y = y;
}
}
It work when I swich from page 1st to page 2nd and back, to 3rd page it switch for 1 line to fast, the cursor_y is -1. I try to put plus or minus 1 in various places when calculating page but it didn't work.
Anybody can help me with this?
I found solution (this._offset is set by this._view)
var offset = this._offset + this._rows - cursor_offset;
if (y-this._offset >= this._rows) {
cursor_y = y - offset;
if (this._offset !== offset) {
this._pointer.x = x;
this._pointer.y = y;
this._view(offset);
}
} else if (y-this._offset < 0) {
var new_offset = this._offset - this._rows + cursor_offset;
this._pointer.x = x;
this._pointer.y = y;
this._view(new_offset);
cursor_y = y - new_offset;
} else {
cursor_y = y - offset + cursor_offset + 1;
}