Here is my functional code, as far as coderbyte is concerned.
But I have a feeling it shouldn't be this complicated.
Am I missing a simple trick?
function ArithGeo(arr)
{
var array_type = -1;
if (arr.length <= 2) return true;
var a = arr[1], r = a/arr[0], i;
for (i = 2; i < arr.length; ++i) {
if ((a *= r) == arr[i]){
array_type = "Geometric";
}
else{
array_type = -1;
break;
}
}
if (array_type == "Geometric")
return array_type;
a = arr[1], d = a - arr[0], i;
for (i = 2; i < arr.length; ++i) {
if ((a += d) == arr[i]){
array_type = "Arithmetic";
}
else {
array_type = -1;
break;
}
}
return array_type;
}
ArithGeo([3,9,15,21,27, 28]);
function ArithGeo(arr) {
var diff = arr[1] - arr[0];
var ratio = arr[1] / arr[0];
var arith = true;
var geo = true;
for(var i = 0; i < arr.length - 1; i++)
{
if( arr[i + 1] - arr[i] !== diff )
arith = false;
if(arr[i + 1] / ratio !== arr[i])
geo = false;
}
if(arith === true)
return "arithmetic";
else if(geo === true)
return" geometric";
else
return -1;
}
Here's a simple solution as well. I'm either looking for a geometric pattern, where a given element will be divisible by the previous element, or an arithmetic pattern, where each element increases by a constant amount. Two variables, diff and ratio, contain each pattern to search for throughout the array.
I start by assuming that arith and geo are true, and if I find an example where one is not true, I set its value to false. Note that your code has two for loops, with the exact same conditions. This is a good indication that your code can be condensed into one loop.
With each pass through the loop, I test whether the conditions are present to set either arith or geo to false. Finally, after the loop exits, I will determine if either arith or geo remained true throughout the loop. If not, I return - 1 as the problem from Coderbyte requests.
edit: quick note on my for loop condition. Since I am checking the value of i + 1 with each pass, I make sure that I don't reach out of bounds by setting my exit condition to arr.length - 1. This way, i + 1 can still reach the last element, and will be sure not to overreach.
For arithmetic progression, subtract each element from previous element; their difference should be equal; for geometric, divide each element by the previous element, the ratio should stay the same. As for divide by zero when you meet 0, javascript gives you Inf (and it certainly is not a geometric progression). Because floats are inaccurate, maybe you'd want to store the min and max of these values and then see if they are close enough to each other.
function arithGeo(arr) {
var minRatio = 1/0,
maxRatio = -1/0,
minDiff = 1/0,
maxDiff = -1/0,
epsilon = 0.000001,
i,
ratio,
diff;
if (arr.length <= 2) {
return;
}
for (i = 1; i < arr.length; ++i) {
diff = arr[i] - arr[i - 1];
ratio = arr[i] / arr[i - 1];
minDiff = Math.min(diff, minDiff);
maxDiff = Math.max(diff, maxDiff);
minRatio = Math.min(ratio, minRatio);
maxRatio = Math.max(ratio, maxRatio);
}
if (Math.abs(minDiff - maxDiff) < epsilon) {
return "Arithmetic";
}
if (Math.abs(minRatio - maxRatio) < epsilon) {
return "Geometric";
}
return;
}
alert(arithGeo([3,9,15,21,27,28]));
alert(arithGeo([3,9,15,21,27]));
alert(arithGeo([4,2,1,0.5]));
It might not be the most efficient way to solve the problem, and it doesn't address the epsilon Problem, that Antti Haapala mentioned, but this is my solution to the problem:
function sequenceMatches(arr, fn) {
var compare = fn(arr[0], arr[1]);
for (var i = 2; i < arr.length; i++) {
if (fn(arr[i - 1], arr[i]) !== compare) return false;
}
return true;
}
function ArithGeo(arr) {
if (sequenceMatches(arr, function(a, b) { return b - a; })) return 'Arithemetic';
if (sequenceMatches(arr, function(a, b) { return b / a; })) return 'Geometric';
return -1;
}
I choose to solve that in two different functions, as that helps to clean up the code imho.
function ArithGeo(arr) {
var apCnt = 1;
var gpCnt = 1;
var diff = arr[1] - arr[0]; //ap difference
var div = arr[1]/arr[0]; //gp difference
for(var i=1;i<arr.length-1;i++){ //traverse array
if(arr[i+1] - arr[i] == diff) { //check for ap
apCnt+=1;
}
else if(arr[i+1]/arr[i] == div) { //check for gp
gpCnt+=1;
}
else{
break; //break if not ap or gp
}
}
return apCnt == arr.length-1 ? "Arithmetic": gpCnt == arr.length-1 ? "Geometric": -1; //return if its ap or gp
}
function ArithGeo(arr){
if(arr == null || !Array.isArray(arr)){
return "error";
}
var length = arr.length;
if(length === 0){
return "neither";
}
if(length === 1){
return "both";
}
var arithCount = 0,
geoCount = 0,
d = arr[1] - arr[0],
q = arr[1] / arr[0];
for(var i = length - 1; i > 0; i--){
if((arr[i] - arr[i-1]) === d){
arithCount++;
}
if((arr[i] / arr[i-1]) === q){
geoCount++;
}
}
if(arithCount === length - 1){
return "Arithmetic";
}else if (geoCount === length - 1){
return "Geometric";
}else if((arithCount === length - 1) && (geoCount === length - 1)){
return "both";
}else{
return "neither";
}
}
Sorry, only considered the integer sequence. #Antti Haapala's answer is correct.
Extremely late but I pretty much did the same on my own (novice javascript user).
It calculates the difference between i + 1 and i (or i + 1 / i) and pushes it into a new array. I then use a function to check if every element in the array is the same.
function numberCheck(array) {
var arithResult = null;
var geoResult = null;
var arithCounter = [];
var geoCounter = [];
Array.prototype.allValuesSame = function() {
for(var i = 1; i < this.length; i++) {
if(this[i] !== this[0])
return false;
} return true;
}
for (var b = 0; b < array.length - 1; b++) {
arithCounter.push(array[b + 1] - array[b]);
}
for (var i = 0; i < array.length - 1; i++) {
geoCounter.push(array[i + 1] / array[i])
}
arithResult = arithCounter.allValuesSame();
geoResult = geoCounter.allValuesSame();
if (arithResult === true) { return "Arithmetic";}
else if (geoResult === true) { return "Geometric";}
else { return "-1";}
}
numberCheck([1,2,4,8])
Related
Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
For example, the input [3, 4, -1, 1] should give 2. The input [1, 2, 0] should give 3.
I did this but not able to find what is the error in my logic when taking input as 1. it is giving output as undefined instead of 2.
var firstMissingPositive = function(nums) {
nums.sort(compare);
var arr = [];
for (let i = 0; i < nums.length; i++) {
if (nums[i] > 0)
arr.push(nums[i]);
}
if (arr.length == 0)
return 1;
else {
for (let i = 0; i < arr.length; i++) {
if (!(arr[0] == 1))
return 1;
else if (i > 0)
if (!(arr[i - 1] + 1 == arr[i]))
return i + 1;
else if ((i + 1) == arr.length)
return arr[i] + 1;
else if ((arr[i] == i + 1)) // && (arr[i+1] == arr[i]+1 ))
continue;
else
return i + 1;
}
}
};
function compare(a, b) {
return a - b;
}
Output:
Since O(n) is a requirement, we'll have to prepare some hash table of possible numbers. It will just be the length of the input array (+2 why not), containing possible number 1..n. We iterate the input array and for each number we match (if applicable) it's position = value in the array of possible numbers. We set it to -1 so we won't choose it. Finally, we iterate the possible numbers that are left and pick the first one.
var firstMissingPositive = function(nums) {
var possible = [];
for (var i = 0; i < nums.length + 2; i++) {
possible.push(i);
}
for (var i = 0; i < nums.length; i++) {
var number = nums[i];
if (number <= nums.length && number > 0) {
possible[number] = -1;
}
}
for (var i = 0; i < possible.length; i++) {
if (possible[i] > 0) {
return possible[i]
}
}
};
console.log(firstMissingPositive([3, 4, -1, 1]))
console.log(firstMissingPositive([0, 1, 2]))
console.log(firstMissingPositive([1]))
I have a leetcode question that I tried to use my own method to solve it, but I got an error and I don't know what's wrong.
This is the topic:
This is my attempted solution:
var findMin = function(nums) {
if (nums.length === 0) return undefined;
var minEle = nums[0];
if (nums.length === 1) {
minEle = nums[0];
return minEle;
}
var start = 0;
var end = nums.length - 1;
if (nums[end] > nums[start]) {
end = Math.floor(end / 2);
} else {
start = Math.ceil(end / 2);
}
findMin(nums.slice(start, end + 1));
};
findMin([3,4,5,1,2]);
and the output is undefined.
I tried this too :
var findMin = function(nums) {
if (nums.length === 0) return undefined;
var minEle = nums[0];
if (nums.length === 1) {
minEle = nums[0];
return minEle;
}
var start = 0;
var end = nums.length - 1;
if (nums[end] > nums[start]) {
end = Math.floor(end / 2);
} else {
start = Math.ceil(end / 2);
}
findMin(nums.slice(start, end + 1));
return minEle;
};
findMin([3,4,5,1,2]);
And the output is 3.
I tried to debug it and I got this:
I don't understand why my recursion solution is not correct. Note that I tried to implement a solution with consideration of time complexity.
You are missing the last return statement when recursing.
return findMin(nums.slice(start, end + 1)); //added return here
var findMin = function(nums) {
if (nums.length === 0) return undefined;
var minEle = nums[0];
if (nums.length === 1) {
minEle = nums[0];
return minEle;
}
var start = 0;
var end = nums.length - 1;
if (nums[end] > nums[start]) {
end = Math.floor(end / 2);
} else {
start = Math.ceil(end / 2);
}
return findMin(nums.slice(start, end + 1));
};
console.log(findMin([3,4,5,1,2]));
If you want to find the smallest value in an array, just use Math.min.
Example:
console.log(Math.min.apply(null, [3,4,5,1,2]))
I don't think recursion is necessary for this one. At a high level we just need to go through each element and find the smallest. This could be done pretty simply with a for loop and a variable to store the smallest seen value.
var findMin = function(nums) {
if(nums.length === 0) {
return undefined;
}
if(nums.length === 1) {
return nums[0];
}
// initialize the smallest number placeholder to the first value
let smallestNum = nums[0];
for(let i = 1; i < nums.length; i++) {
if(smallestNum > nums[i]) {
smallestNum = nums[i];
}
}
return smallestNum;
}
This could be simplified with an array reducer, but the logic would be the same.
Another approach could be to assume the numbers will be ascending and once you find a number that is smaller return it. For example, in [3,4,5,1,2] it increases until we go from 5 to 1.
var findMin = function(nums) {
if(nums.length === 0) {
return undefined;
}
if(nums.length === 1) {
return nums[0];
}
for(let i = 1; i < nums.length; i++) {
if(nums[0] > nums[i]) {
return nums[i];
}
}
return nums[0];
}
In this case as soon as we find a number that is smaller than the first we break the loop. If we get all the way through the array we know the first number was the smallest.
I'm not at a rank to comment, so I have to post as an answer. It seems you're changing "end" and "start" in the if conditions, but then you're calling the function again and the function resets those variables to
var start = 0;
var end = nums.length - 1;
So whatever is changed in the second if/else statement, start will get reset to 0, and end will halve. But maybe I've missed something, so if this is irrelevant please ignore.
A string is called a palindrome if it may be read the same way in either direction. For example, “12321” is a palindrome, but “12341” is not. A palindrome string can itself compose of one or more palindrome sub-strings. Now, your task is to find out the length (denoted by L) of the longest palindrome sub-string, maximum-length contiguous substring of a given
string that is also a palindrome, and print "YES" if it is lucky otherwise print "NO". A palindrome sub-string is called lucky iff it's length is a prime number.
For example : Consider a string s =”122321”. The longest palindrome sub-strings in s is of length 3. Hence, you need to output "YES" (quotes only for clarity).
function solution(r) {
if (r.match(/[a-z]/g) || r.match(/[A-Z]/g) || r.match(/[0-9]/g)) {
for (var t = gettingPrimeList(r), o = "", n = 0; n < r.length; n++)
for (var e = t.length; t > 0; t--) {
var a = r.substr(n, t[e - 1]);
console.log(a);
for (var i = a.length; i > 0; i--) {
var g = a.substr(0, i);
console.log(g);
var s = g.split("").reverse().join("");
if (g == s) {
o = "YES";
break
}
o = "NO"
}
}
return o
}
}
function gettingPrimeList(r) {
for (var t = [], o = 2; o <= r.length; o++) {
for (var n = !1, e = 2; e <= o; e++) o % e == 0 && e !== o && (n = !0);
!1 === n && t.push(o)
}
return t
}
alert(solution("random12321random"));
You can do that in following steps:
Create two function isPrime() to check if number is prime or not. Second to check if string is a palindrome or not.
Get all the substrings starting from str.length - 1 then str.length - 2 and so on.
The way to get substrings is that create a variable l which will be length of substring.
Keep making substrings until the length of substring is greater than 1.
If the while loop create a nested for loop which will get all substrings.
Note: I am not sure that you want to check the whole string or not. If you want to check also the whole string then change let l = str.length - 1; to let l = str.length; in check function.
The code returns true and false. You can fix it according to your needs.
function isPal(str){
return [...str].reverse().join('') === str
}
function isPrime(num){
if(num === 3 || num === 2) return true;
if(num === 1) return false;
if(num % 2 === 0) return false;
for(let i = 3;i<Math.sqrt(num) + 1;i+=2){
if(num % i === 0) return false;
}
return true;
}
function check(str){
let l = str.length - 1;
while(l>1){
for(let i = 0;i<str.length-l;i++){
let temp = str.slice(i,l);
if(isPal(temp)) return isPrime(l)
}
l--;
}
return false;
}
console.log(check("122321")) //true
console.log(check("123454321")) // false
function solution(S) {
var max_length = 0,
maxp = '';
for(var i=0; i < S.length; i++){
var subs = S.substr(i, S.length);
for(var j=subs.length; j>=0; j--){
var sub_subs_str = subs.substr(0, j);
if (sub_subs_str.length <= 1)
continue;
if (is_Palindrome(sub_subs_str)){
if (sub_subs_str.length > max_length){
max_length = sub_subs_str.length;
maxp = sub_subs_str;
}
}
}
}
maxp = IsPrimeNumber(maxp.length);
return maxp;
}
function is_Palindrome(S) {
var rev = S.split("").reverse().join("");
return S == rev;
}
function IsPrimeNumber(n){
if (n===1){
return "NO";
}
else if(n === 2){
return "YES";
}
else{
for(var x = 2; x < n; x++)
{
if(n % x === 0)
{
return "NO";
}
}
return "YES";
}
}
console.log(solution('random12321random'))
So what I'm trying to do is use a function that prompts to enter a number and then prints all prime numbers up till that number. I have the code as far as I know but I keep getting an error that the bracket following prime(num) is wrong. Not sure what I'm doing wrong here, would appreciate any help.
function p5Bela() {
var num = prompt("Please enter a number: ", "");
for (i = 2; i <= num; i++) {
if (prime(i)==true) {
alert(i);
}
}
prime(num) {
var flag = true;
var d = 2;
while (flag==true && d <= num/2) {
if (num%d == 0) {
flag = false;
}
d++;
}
return flag;
}
}
Simplest Way
function isPrime(num) {
for(var i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
With the ES6 syntax:
const isPrime = num => {
for(let i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
You can also decrease the complexity of the algorithm from O(n) to O(sqrt(n)) if you run the loop until square root of a number:
const isPrime = num => {
for(let i = 2, s = Math.sqrt(num); i <= s; i++)
if(num % i === 0) return false;
return num > 1;
}
the following code always seems to return true whatever value of n I plug in and I can't see why. If n = 8, then arr2 should contain the value of i for 2, 4 and 8?
Can someone please explain? Thank you very much.
var primetest = function(n){
var divisor = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for (var i = 0; i < divisor.length; i++) {
var arr2 = [];
if(n%divisor[i] == 0) {arr2.push(i);}
if(arr2.length > 1) {prime = false;}
else {prime = true;}
return prime;
};
};
Couple of problems in your original code:
You are doing only one iteration
You declare the array holding divisions inside the loop, causing it to always have maximum 1 item.
Quick fix of the above would be:
var primetest = function(n){
var divisor = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var arr2 = [];
for (var i = 0; i < divisor.length; i++) {
if(n%divisor[i] == 0) {
arr2.push(i);
}
}
return arr2.length <=1;
}
Live test case.
Optimized code that does not iterate through the whole list of divisors if not reuired (guess that's what you were trying to achieve) is:
var primetest = function(n){
var divisor = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var arr2 = [];
for (var i = 0; i < divisor.length; i++) {
if(n % divisor[i] === 0) {
arr2.push(i);
if (arr2.length > 1)
return false;
}
}
return true;
};
Updated fiddle.
Two problems:
Don't declare you array inside the loop, because it will reset in every loop.
And move your return outside of the loop because your function will return at first loop, wich always true for odd numbers(n%2 = 0 for even numbers).
JSFiddle
function primetest(n){
var divisor = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var arr2 = [];
for (var i = 0; i < divisor.length; i++) {
if((n%divisor[i]) === 0)
arr2.push(i);
if(arr2.length > 1)
prime = false;
else prime = true;
};
return prime;
}
$(function (){
var pprime = 7;
if(primetest(pprime))
alert("ok");
});
Return the first 1001 positions into an array of prime numbers.
Usefull code to modify, enjoy!
//cum calculam daca un numar este prim
//chiar mai mult - care este al 1001-lea nr prim
function isPrime(num) {
if(num < 2) return false;
for (var i = 2; i < num; i++) {
if(num%i===0)
return false;
}
return true;
}
var shir=[];
var j=0;
var i=1;
while(j<1001)
{
if(isPrime(i))
{shir[j]=i;
j++;i++}
else{i++}
}
console.log(shir);
console.log (shir[0]);
console.log (shir[1000]);
alert("Al 1001-lea numar prim este " + shir[1000]);
Your condition
if(arr2.length > 1) {prime = false;}
is checking for >1 instead of >0 or >=1 which is ignoring the prime condition that you specified. Hence your corrected code would be something like this:
var primetest = function(n){
var divisor = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for (var i = 0; i < divisor.length; i++) {
var arr2 = [];
if(n%divisor[i] == 0) {arr2.push(i);}
if(arr2.length > 0) {prime = false;}
else {prime = true;}
return prime;
};
};
if(arr2.length > 1) {prime = false;}
There are better ways to check for prime number. Here's the fastest one I could lay my hands on:
var primetest = function(n) {
if (isNaN(n) || !isFinite(n) || n%1 || n<2) return false;
if (n==leastFactor(n)) return true;
return false;
}
// leastFactor(n)
// returns the smallest prime that divides n
// NaN if n is NaN or Infinity
// 0 if n=0
// 1 if n=1, n=-1, or n is not an integer
leastFactor = function(n){
if (isNaN(n) || !isFinite(n)) return NaN;
if (n==0) return 0;
if (n%1 || n*n<2) return 1;
if (n%2==0) return 2;
if (n%3==0) return 3;
if (n%5==0) return 5;
var m = Math.sqrt(n);
for (var i=7;i<=m;i+=30) {
if (n%i==0) return i;
if (n%(i+4)==0) return i+4;
if (n%(i+6)==0) return i+6;
if (n%(i+10)==0) return i+10;
if (n%(i+12)==0) return i+12;
if (n%(i+16)==0) return i+16;
if (n%(i+22)==0) return i+22;
if (n%(i+24)==0) return i+24;
}
return n;
}
Source: http://www.javascripter.net/faq/numberisprime.htm