closest number, based on two numbers - javascript

Im currently checking what the closest number would be compared to an array:
var testarray1 = [4054,4938,4983,1928,8833];
var test = 5000;
var result = testarray1.reduce(function(prev, curr) {
return (Math.abs(curr - postcode) < Math.abs(prev - postcode) ? curr : prev);
}
This works fine.
but when i have it like multi numbers in one, it dosent work:
var testarray1 = ["4000-5595","4400-4720"];
var test = 4630;
for (var x =0; x < testarray1.length; x++) {
var selectedPostcode = testarray1[x][0];
var splitted = selectedPostcode.split("-");
var from = parseInt(splitted[0]);
var to = parseInt(splitted[1]);
if (postcode >= from && postcode <= to) {
return selectedPostcode;
break;
}
}
in the example code above, it would return "4000-5595", but how can i do so it selects the closest one, in this case it would be the "4400-4720"?

Try like below. Explanation is in comments.
var testarray1 = ["4000-5595", "4400-4720"];
var postcode = 4630;
// Take two variables to set difference and result
// set difference default value to -1
var difference = -1;
var result = "";
for (var x = 0; x < testarray1.length; x++) {
// use testarray1[x] instead of testarray1[x][0]
var selectedPostcode = testarray1[x];
var splitted = selectedPostcode.split("-");
var from = parseInt(splitted[0]);
var to = parseInt(splitted[1]);
if (postcode >= from && postcode <= to) {
// get difference
let currDiff = Math.abs(postcode - from) + Math.abs(postcode - to);
// difference = -1 means there is no existing value so set current as result
// check current difference is less than existing one.
if (difference == -1 || currDiff < difference) {
difference = currDiff;
result = selectedPostcode;
}
}
}
console.log(result);
If you want closest value based on minimum difference from either one of the value then use let currDiff = Math.min(Math.abs(postcode - from), Math.abs(postcode - to));.
var testarray1 = ["4000-5595", "4400-4720", '4800-5000'];
var postcode = 4630;
// Take two variables to set difference and result
// set difference default value to -1
var difference = -1;
var result = "";
for (var x = 0; x < testarray1.length; x++) {
// use testarray1[x] instead of testarray1[x][0]
var selectedPostcode = testarray1[x];
var splitted = selectedPostcode.split("-");
var from = parseInt(splitted[0]);
var to = parseInt(splitted[1]);
if (postcode >= from && postcode <= to) {
// get difference
let currDiff = Math.min(Math.abs(postcode - from), Math.abs(postcode - to));
// difference = -1 means there is no existing value so set current as result
// check current difference is less than existing one.
if (difference == -1 || currDiff < difference) {
difference = currDiff;
result = selectedPostcode;
}
}
}
console.log(result);

You have to check for every interval and check if previous ans is closet or current interval is closet and change ans accordingly like this.
var testarray1 = ['4000-5595', '4400-4720']
var test = 4630
let ans
for (var x = 0; x < testarray1.length; x++) {
var selectedPostcode = testarray1[x]
var splitted = selectedPostcode.split('-')
var from = parseInt(splitted[0])
var to = parseInt(splitted[1])
if (ans) {
if (ans[0] < from || ans[1] > to) ans = [from, to]
} else {
if (test >= from && test <= to) {
ans = [from, to]
}
}
}
console.log(ans.join('-'))

Related

Javascript - String matching wrong output

I have coded Boyer-Moore horspool string matching algorithm using node.js. The program works, but always outputs -1, which is what it should output if the pattern string is not in the specified text.
I am unable to figure out for the life of me what isn't working, and I would be most appreciative of a hint for what I need to fix.
My code
var horsPool = function(sText,sPattern)
{
var m = sPattern.length;
var n = sText.length;
var i = m - 1;
while(i<=n-1)
{
var k = 0;
while ((k <= m) && (sPattern[m - 1 - k]) == sText[i - k])
{
k++;
}
if(k==m)
{
return (i - m + 1);
}
else
{
i += t[sText[i]];
}
}
return -1;
}
var shiftTable = function (sPat)
{
var i;
var j;
var m;
m = sPat.length;
for(i=0; i < MAX; i++)
{
t[i] = m;
}
for (j = 0; j<m-2; j++)
{
t[sPat[j]] = m-1 -j;
}
}
var program = function()
{
var text = 'lklkababcabab';
var pattern = 'ka';
shiftTable(pattern);
var pos = horsPool(text,pattern);
if(pos >= 0)
console.log('Pattern found in %d',pos);
else
console.log('Pattern not found');
}
var MAX = new Array(256);
var t = [MAX];
program();
Any help would be greatly appreciated. Thank You!
Let's start from down under:
var MAX = new Array(256);
var t = [MAX];
does not work at all. The first line initiates an array with 256 empty entries, the second line initiates an array with one element: the array build in the line above. That's not what you wanted to do, I presume. So
var MAX = 256;
var t = new Array(MAX);
does what you want.
The lines with t[sPat[j]] and t[sText[i]] will not work as expected, because sText[i] and sPat[j] return a character instead of a number. You might give t[sPat.charCodeAt(j)] and t[sText.charCodeAt(i)] a try.
To give you a start without helping too much, here is a straight-forward implementation of the algorithm given at Wikipedia:
var horsPool = function (haystack, needle)
{
var nl = needle.length;
var hl = haystack.length;
var skip = 0;
while (hl - skip >= nl)
{
var i = nl - 1;
while (haystack[skip + i] == needle[i])
{
if (i == 0) {
return skip;
}
i--;
}
skip = skip + t[haystack.charCodeAt(skip + nl - 1)];
}
return - 1;
}
var shiftTable = function (pattern)
{
for (var i = 0; i < MAX; i++) {
t[i] = pattern.length;
}
for (var i = 0; i < pattern.length - 1; i++) {
t[pattern.charCodeAt(i)] = pattern.length - 1 - i;
}
}
var program = function ()
{
var text = 'lklkababcabab';
var pattern = 'kab';
shiftTable(pattern);
var pos = horsPool(text, pattern);
if (pos >= 0)
console.log('Pattern found in %d', pos);
else
console.log('Pattern not found');
}
var MAX = 256;
var t = new Array(256);
program();

A while loop to add the digits of a multi-digit number together? (Javascript)

I need to add the digits of a number together (e.g. 21 is 2+1) so that the number is reduced to only one digit (3). I figured out how to do that part.
However,
1) I may need to call the function more than once on the same variable (e.g. 99 is 9+9 = 18, which is still >= 10) and
2) I need to exclude the numbers 11 and 22 from this function's ambit.
Where am I going wrong below?
var x = 123;
var y = 456;
var z = 789;
var numberMagic = function (num) {
var proc = num.toString().split("");
var total = 0;
for (var i=0; i<proc.length; i++) {
total += +proc[i];
};
};
while(x > 9 && x != 11 && x != 22) {
numberMagic(x);
};
} else {
xResult = x;
};
console.log(xResult);
//repeat while loop for y and z
Here are the problems with your code
var x = 123;
var y = 456;
var z = 789;
var numberMagic = function (num) {
var proc = num.toString().split("");
var total = 0;
for (var i=0; i<proc.length; i++) {
total += +proc[i]; // indentation want awry
}; // don't need this ; - not a show stopper
// you're not returning anything!!!!
};
while(x > 9 && x != 11 && x != 22) {
numberMagic(x);
}; // ; not needed
// because x never changes, the above while loop would go on forever
} else { // this else has no if
xResult = x; // even if code was right, x remains unchanged
};
console.log(xResult);
Hope that helps in some way
Now - here's a solution that works
var x = 123;
var y = 456;
var z = 789;
var numberMagic = function (num) {
while (num > 9) {
if (num == 11 || num == 22) {
return num;
}
var proc = num.toString().split("");
num = proc.reduce(function(previousInt, thisValueString) {
return previousInt + parseInt(thisValueString);
}, 0);
}
return num;
}
console.log(numberMagic(x));
console.log(numberMagic(y));
console.log(numberMagic(z));
I'm not sure to understand what you want..
with this function you reduce any number to one single digit
while(num > 9){
if(num == 11 || num == 22) return;
var proc = num.toString();
var sum = 0;
for(var i=0; i<proc.length; i++) {
sum += parseInt(proc[i]);
}
num = sum;
}
is it what you are looking at?
I wrote an example at Jsfiddle that you can turn any given number into a single digit:
Example input: 551
array of [5, 5, 1] - add last 2 digits
array of [5, 6] - add last 2 digits
array of [1, 1] - add last 2 digits
array of [2] - output
Here is the actual code:
var number = 1768;
var newNumber = convertToOneDigit(number);
console.log("New Number: " + newNumber);
function convertToOneDigit(number) {
var stringNumber = number.toString();
var stringNumberArray = stringNumber.split("");
var stringNumberLength = stringNumberArray.length;
var tmp;
var tmp2;
var tmp3;
console.log("Array: " + stringNumberArray);
console.log("Array Length: " + stringNumberLength);
while (stringNumberLength > 1) {
tmp = parseInt(stringNumberArray[stringNumberLength - 1]) + parseInt(stringNumberArray[stringNumberLength - 2]);
stringNumberArray.pop();
stringNumberArray.pop();
tmp2 = tmp.toString();
if (tmp2.length > 1) {
tmp3 = tmp2.split("");
for (var i = 0; i < tmp3.length; i++) {
stringNumberArray.push(tmp3[i]);
}
} else {
stringNumberArray.push(tmp2);
}
stringNumberLength = stringNumberArray.length;
console.log("Array: " + stringNumberArray);
console.log("Array Length: " + stringNumberLength);
}
return stringNumberArray[0];
}
function addDigits(n) {
let str = n.toString().split('');
let len = str.length;
let add,
acc = 0;
for (i=0; i<=len-1; i++) {
acc += Number(str[i]);
}
return acc;
}
console.log( addDigits(123456789) ); //Output: 45
Just make it a While loop, remember a While loops it's just the same as a For loop, only you add the counter variable at the end of the code, the same way you can do with a Do{code}while(condition) Only need to add a counter variable at the end and its gonna be the same. Only that the variable its global to the loop, I mean comes from the outside.
Ej.
let i = 0; //it's global to the loop, ( wider scope )
while (i<=x) {
//Code line;
//Code line;
//Code line;
//Code line;
i++
}
Now this is working with an outside variable and it's NOT recommended.. unless that var its local to a Function.
Please look at the this solution also
var x = 123;
var y = 456;
var z = 789;
var numberMagic = function (num) {
var total = 0;
while (num != 0) {
total += num % 10;
num = parseInt(num / 10);
}
console.log(total);
if (total > 9)
numberMagic(total);
else
return total;
}
//Call first time function
numberMagic(z);

try to not add the elements already in the array

function neighbor(color_indices) {
var neighbor_face = [];
var neighbor_index_temp = [];
//initialize to the given length
var color_indices_length = color_indices.length;
for (var i = 0; i < color_indices_length; i++) {
if (color_indices[i] % 2 == 0 ) {
if (color_indices[i] % 10 == 8) {
neighbor_index_temp[0] = (color_indices[i]) + 1;
neighbor_index_temp[1] = (color_indices[i]) - 17;
neighbor_index_temp[2] = (color_indices[i]) - 19;
//check if it is in the array
for (var k = 0; k < 3; k++){
if ($.inArray(neighbor_index_temp[k],color_indices) != -1){
color_indices.push(neighbor_index_temp[k]);
}
}
The input : color_indices would be an array of the global variable. I am trying to push neighbor_index_temp of only new to the color_indices. I tried to implement $.inArray but it doesn't seem to work. Any suggestions?
Thanks!
You can use indexOf to achieve this. Ie.
if(color_indices.indexOf(neighbor_index_temp[k]) == -1) {
// value neighbor_index_temp[k] is not in color_indices array
}
Edit : $.inArray might do the same as indexOf, in this case you might want to change '!= -1' to '== -1'

formatMoney function in Javascript doesn't work

I need a function which can transform the number 10000 to this number: 10.000.
So I tried the following:
function formatMoney(money){
var value = money.toString();
var l = value.length;
var new_value = 0;
new_value = new_value.toString();
if(l > 3){
var moneyarray = value.split('');
var u = 0;
for(i = l;i >= 0;i--){
if(u > 3){
u = 0;
new_value = "."+new_value;
}
new_value = moneyarray[i]+new_value;
u++;
}
}
return new_value;
}
And then call this:
formatMoney("10000");
But the result is
10.000undefined0"
What did I do wrong?
You're assigning the index counter to the length of the string;
var l = value.length;
...
for(i = l;i >= 0;i--){
And the down count starts with the length-index, which isn't present since arrays are zero-based. Subtract beforehand instead;
for(i = l;i >= 0;--i){
EDIT: Disregard this, I wasn't paying enough attention to the question.
If all you're looking to do is take numbers that are 4 digits or greater and put a dot in three digits from the right, you could give this a shot:
function formatMoney(money) {
var moneyString = money.toString();
var moneyLength = moneyString.length;
if(moneyLength < 4) {
return 0;
}
var dotIndex = moneyLength - 3;
return moneyString.substr(0, dotIndex) + "." + moneyString.substr(dotIndex);
}
Also, formatting your code in the post is good stuff. Indent it all by four spaces.
function formatMoney(money){
var value = money.toString();
var l = value.length;
var new_value = 0;
new_value = new_value.toString();
if(l > 3){
var moneyarray = value.split('');
for(var i = l-1;i >= 0;i--){
if((l-i)%3 === 0){
new_value = "."+new_value;
}
new_value = moneyarray[i]+new_value;
}
} else {
new_value = value;
}
return new_value;
}
A couple of things:
You were counting down with the wrong index (you were starting at l, instead of l-1)
You were not handling any value less than 1000
You don't need to use a counter variable u, you can just use modulo math to keep track of threes.
I cut off some parts:
function formatMoney(money) {
var value = money.toString();
var l = value.length;
var new_value = "";
if (l > 3) {
var u = 0;
for (i = l-1;i >= 0;i--) {
if (u == 3) {
u = 0;
new_value = "." + new_value;
}
new_value = value[i]+new_value;
u++;
}
}
return new_value;
}
You could do it like this:
function money(m) {
m = m.toString().split('');
for (var i = m.length - 3; i > 0; i -= 3)
m.splice(i,0,".");
return m.join('');
}
console.log(money(1000000)); // "1.000.000
See this JsBin

Sort an array of objects by hour minutes in ascending order from earliest to latest

I have this code to sort an array of objects. The data in the objects is channel and time (hour, minutes). I want the sort to be by channels based on time from earliest to latest.
The channel data is accessed in this way:
channel_array[icount].data[0].hour
channel_array[icount].data[0].minutes
That data object array is like this and is already sorted:
[{hour:1, minutes:10},{hour:4, minutes:01}...]
Now all I need is to sort the channels from earliest to latest on the first element of the data array {hour:1, minutes: 10}. I do this with three nested loops. But this is not ideal. Is there a better way to do the sorting?
var current_time = new Date();
var current_hour = current_time.getHours();
var comp_hour = current_hour - 1;
for (var ih = 0; ih < 24; ih++) {
comp_hour += 1;
if (comp_hour == 24) { comp_hour = 0; }
for (var minutes = 0; minutes < 60; minutes++) {
for (var icount = 0; icount < channel_array.length; icount++) {
if (channel_array[icount].data.length > 0) {
var channel_hour = channel_array[icount].data[0].hour;
var channel_minutes = channel_array[icount].data[0].minutes;
var channel_phase = channel_array[icount].data[0].phase;
var next_day = channel_array[icount].data[0].next_day;
if (channel_phase.toLowerCase() == "pm" && channel_hour != 12) { channel_hour += 12; }
if ( parseInt(channel_hour) == parseInt(comp_hour) && parseInt(channel_minutes) == parseInt(minutes) && next_day != 1 ) {
channel_array_sort.push(channel_array[icount]);
}
}
}
}
}
Good lord, this is overcomplicated! How about just passing a custom comparator to Array.sort?
I'm honestly having a hard time figuring out exactly which array you are trying to sort, but in general, it would look something like this:
var input = [{hour:1, minutes:10},{hour:4, minutes: 1}, ...];
input.sort(function (a, b)
{
// compare hours first
if (a.hour < b.hour) return -1;
if (a.hour > b.hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.minute < b.minute) return -1;
if (a.minute > b.minute) return 1;
// couldn't break the tie
return 0;
});
N.B. this performs an in-place sort, which means that the original array is modified. If that's not acceptable, just make a copy of the array before sorting it.
var input = /* same as before */;
var output = input.concat();
output.sort(function ()
{
// same as before
});
Starting point for the solution, from the OP:
channel_array_sort = channel_array.concat();
channel_array_sort.sort(function (a, b)
{
if (a.data == undefined || b.data == undefined) return 0;
if (a.data.length <= 0 || b.data.length <= 0) return 0;
// compare hours first
var a_hour = a.data[0].hour;
if (a.data[0].phase == "pm") a_hour += 12;
var b_hour = b.data[0].hour;
if (b.data[0].phase == "pm") b_hour += 12;
if (a_hour < b_hour) return -1;
if (a_hour > b_hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.data[0].minutes < b.data[0].minutes) return -1;
if (a.data[0].minutes > b.data[0].minutes) return 1;
// couldn't break the tie
return 0;
});
var print_sort = JSON.stringify(channel_array_sort);
alert('print_sort b '+print_sort);

Categories

Resources