I'm a novice programmer who just started learning JavaScript. While I was reading about array sorting, I came across QuickSort and looked into its algorithm. Then I thought I could come up with my own 'algorithm'.
My solution works like this. It starts by looking for the smallest and largest values and swaps them with the corner values simultaneously. It then runs recursively until both ends are equal or pass each other.
So, is this a new algorithm or a rediscovery?
This is my version of a sorting algorithm. My question is :
Do you know of any other sorting algorithm that works like this?
how can I test it's speed vis-a-vis quicksort, bubble sort...?
'use strict';
// + Name : CornerSort function for sorting arrays +
// + Author : Kedyr +
// + Date : Jan 15 , 2020 +
// + Description : The corner sort function is my first shot at sorting +
// + algorithms.After looking into the quick sort algorithm +
// + i tried to come up with my own sorting logic.It works +
// + by finding the lowest and highest values in an array +
// + and then replacing these values with the corner values. +
// + These process continues recursively until all values are +
// + correctly sorted.Now , from what i can see i believe it +
// + to be a stable sorting algorithm.I haven't tested its +
// + sorting speed and would love it if some one did that. +
// + That is , if it is not an already known algorithm which +
// + I haven't come across yet.Whatever the case is , I am +
// + going to elaborately discuss my 'new' discovery step by +
// + step in the comments . So please bear with me . +
// + For the geniuses who created this algorith before me , +
// + (if there are any), I bow down to you dear masters. +
// + please forgive my insolence. You know I wouldn't do it +
// + intentionally . It is just that genius minds think +
// + alike . :) +
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function cornerSort(array, startIndex = 0, endIndex = array.length - 1) {
// These checks if the function is already ordered .
if (checkOrder(array, startIndex, endIndex)) {
return;
}
// the lowest and highest values.initialised to corner values.
let lowest = array[startIndex],
highest = array[endIndex];
// Indices for the lowest and highest numbers in each recursion.
let lowIndex = startIndex,
highIndex = endIndex;
let temp;
if (startIndex >= endIndex) {
return;
}
for (let i = startIndex; i <= endIndex; i++) {
if (array[i] >= highest) {
//'or-equal-to' is added to ensure the sorting doesn't change the
//order of equal numbers.Thus , a stable sorting algorithm.
highest = array[i];
highIndex = i;
}
if (array[i] < lowest) {
lowest = array[i];
lowIndex = i;
}
}
// A PRECAUTION 'IF' : for when the highest number is at the beginning of the array.
if (highIndex == startIndex) {
highIndex = lowIndex;
}
// The opposite case , lowest number at the end of array ; doesn't cause any issues.
if (lowIndex != startIndex) {
temp = array[startIndex];
array[startIndex] = array[lowIndex];
array[lowIndex] = temp;
}
if (endIndex != highIndex) {
temp = array[endIndex];
array[endIndex] = array[highIndex];
array[highIndex] = temp;
}
cornerSort(array, ++startIndex, --endIndex);
return array;
}
// The CHECKORDER function checks if the array is actually sorted so as to avoid
// unnecessary rounds of recursion.
function checkOrder(array, startIndex, endIndex) {
let unsortedCount = 0; // count of cases where array[i] > array[i+1].
for (let i = startIndex; i <= endIndex; i++) {
if (array[i] > array[i + 1]) {
unsortedCount++;
}
}
if (!unsortedCount) {
return true;
}
return false;
}
//..............................................................................
It's certainly not impossible to invent a genuinely new sorting algorithm, since there are so many different possible ways to sort. However, your algorithm exists: it is called double-ended selection sort.
Selection sort works by iteratively selecting the smallest element in the unsorted part of the array, and swapping it into place. Your algorithm is a variation of selection sort because it also selects the largest element in the unsorted part of the array and swaps that into place in the same iteration of the outer loop. This means the unsorted part is a middle segment rather than an end segment of the array.
Your implementation is also quite a lot more complicated than it needs to be: here's a simplified version which should be very slightly more efficient due to the else if in the inner loop. An element cannot be both lower than lowest and higher than highest. Since we're scanning for both the lowest and highest elements, it's also possible to detect when the "unsorted" part of the array is constant (i.e. all its values are the same) and break early.
function doubleEndedSelectionSort(arr) {
for(var i = 0, j = arr.length - 1; i < j; i++, j--) {
var minIdx = i, maxIdx = i;
var lowest = arr[minIdx], highest = arr[maxIdx];
for(var k = i + 1; k <= j; k++) {
var value = arr[k];
if(value < lowest) {
minIdx = k;
lowest = value;
} else if(value > highest) {
maxIdx = k;
highest = value;
}
}
if(minIdx === maxIdx) { break; } // the "unsorted" part of the array is constant
var iValue = arr[i], jValue = arr[j];
arr[minIdx] = iValue;
arr[i] = lowest;
arr[maxIdx] = jValue;
arr[j] = highest;
}
}
Regarding performance, the time complexity of the algorithm is the same as selection sort's O(nĀ²), because it still has nested loops which iterate O(n) times each. In your implementation, the outer loop is replaced with recursion, but it still recurses O(n) times, so the effect is the same. That means for large enough inputs it will perform worse than O(n log n) sorting algorithms such as quicksort, merge sort, or heap sort.
Before I start, I'd suggest that this is probably more appropriate for computer science
I can't really say whether or not this is a new sorting algorithm; I think for someone to answer such a question they'd need to have a fairly comprehensive knowledge of sorting algorithms, as there are quite a few.
What I can demonstrate is how to compare performance. You'd need to do something similar in other languages, if you want to test those, and this only tests the first implementations of each I could find on the internet.
To properly understand the speed of the algorithm you have, you'd probably need to find a way to describe how it performs in different circumstances; I understand this normally involves a relatively mathematical description of the algorithm; perhaps someone with more computer science knowledge could fill in that gap.
But, despite those provisos, here's something that can work in stack overflow:
function cornerSort(array, startIndex = 0, endIndex = array.length - 1) {
// These checks if the function is already ordered .
if (checkOrder(array, startIndex, endIndex)) {
return;
}
// the lowest and highest values.initialised to corner values.
let lowest = array[startIndex],
highest = array[endIndex];
// Indices for the lowest and highest numbers in each recursion.
let lowIndex = startIndex,
highIndex = endIndex;
let temp;
if (startIndex >= endIndex) {
return;
}
for (let i = startIndex; i <= endIndex; i++) {
if (array[i] >= highest) {
//'or-equal-to' is added to ensure the sorting doesn't change the
//order of equal numbers.Thus , a stable sorting algorithm.
highest = array[i];
highIndex = i;
}
if (array[i] < lowest) {
lowest = array[i];
lowIndex = i;
}
}
// A PRECAUTION 'IF' : for when the highest number is at the beginning of the array.
if (highIndex == startIndex) {
highIndex = lowIndex;
}
// The opposite case , lowest number at the end of array ; doesn't cause any issues.
if (lowIndex != startIndex) {
temp = array[startIndex];
array[startIndex] = array[lowIndex];
array[lowIndex] = temp;
}
if (endIndex != highIndex) {
temp = array[endIndex];
array[endIndex] = array[highIndex];
array[highIndex] = temp;
}
cornerSort(array, ++startIndex, --endIndex);
return array;
}
// The CHECKORDER function checks if the array is actually sorted so as to avoid
// unnecessary rounds of recursion.
function checkOrder(array, startIndex, endIndex) {
let unsortedCount = 0; // count of cases where array[i] > array[i+1].
for (let i = startIndex; i <= endIndex; i++) {
if (array[i] > array[i + 1]) {
unsortedCount++;
}
}
if (!unsortedCount) {
return true;
}
return false;
}
function bubbleSort(a) {
var swapped;
do {
swapped = false;
for (var i=0; i < a.length-1; i++) {
if (a[i] > a[i+1]) {
var temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
swapped = true;
}
}
} while (swapped);
}
function swap(items, leftIndex, rightIndex){
var temp = items[leftIndex];
items[leftIndex] = items[rightIndex];
items[rightIndex] = temp;
}
function partition(items, left, right) {
var pivot = items[Math.floor((right + left) / 2)], //middle element
i = left, //left pointer
j = right; //right pointer
while (i <= j) {
while (items[i] < pivot) {
i++;
}
while (items[j] > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j); //sawpping two elements
i++;
j--;
}
}
return i;
}
function quickSort(items, left, right) {
var index;
if (items.length > 1) {
index = partition(items, left, right); //index returned from partition
if (left < index - 1) { //more elements on the left side of the pivot
quickSort(items, left, index - 1);
}
if (index < right) { //more elements on the right side of the pivot
quickSort(items, index, right);
}
}
return items;
}
const testData = [...Array(10000).keys()].map(x => Math.random() * 1000)
console.time('corner')
const x = cornerSort(testData);
console.timeEnd('corner')
console.time('bubble')
const y = bubbleSort(testData);
console.timeEnd('bubble')
console.time('quick')
const z = quickSort(testData);
console.timeEnd('quick')
Related
This question is specific to the hacker rank problem Largest Permutation
I wrote a solution in javascript that works for most cases (A), but there are some select test cases where it times out. Ok... so then it must not be very efficient. I found someone else's solution to the problem (B) which is highly iterative. This loops through the given array at least once total, and then through the rest of the array at least K times. This seems very inefficient to me but this approach did not cause a timeout and I can't figure out why that is... one of these seems to be A: O(n) vs B: O(n^2) in my analysis but I guess im wrong... so I am asking here to see if anyone can help me figure out why this is or what the correct algorithm speed analysis is
These code snippets are the function body of a function that takes arr as an argument
A) My solution
const indices = {}
arr.forEach((n,i) => {
indices[n] = i
})
let count = 0
while(count < k){
// swap to earliest index (count)
const targetValue = arr.length - count
const targetIndex = indices[targetValue]
let tmp = arr[count]
arr[count] = arr[targetIndex]
arr[targetIndex] = tmp
//update indices
indices[targetValue] = count
indices[tmp] = targetIndex
count++
}
return arr
B) an alternative that to me should be slower but seems to be faster...
let n = arr.length
for(var i = 0; i < n - 1; i++) {
if( k > 0) {
var max = i;
for(var j = i + 1; j < n; j++){
if(arr[j] > arr[max])
max = j;
}
if(max != i) {
var temp = arr[max];
arr[max] = arr[i];
arr[i] = temp;
k--;
}
}
}
return arr
There are these issues with your implementation:
When k is larger than arr.length, then the arr.length - count will become 0 or less and thus targetValue will be a value that is not in the array. And so targetIndex will be undefined.
Your loop represents O(š), and as š can be much larger than š, this can make a huge difference in running time.
When the swap is a none-operation because the value happens to already be in its optimal position, then count is still incremented, reducing the number of actual swaps that are done.
Not an issue, but a for loop seems more appropriate here than a while.
Here is a correction of your main loop:
for (let count = 0; count < k && count < arr.length; count++) {
const targetValue = arr.length - count
if (arr[count] != targetValue) { // target not at optimal index?
// swap to earliest index (count)
const targetIndex = indices[targetValue]
let tmp = arr[count]
arr[count] = arr[targetIndex]
arr[targetIndex] = tmp
//update indices
indices[targetValue] = count
indices[tmp] = targetIndex
}
else k++; // Allow one more swap, as this was a no-op
}
Hi I did not pass the all the tests, only 9/16. so I want to know what is the problem in my code
problem link:https://www.hackerrank.com/challenges/electronics-shop/problem
function getMoneySpent(keyboards, drives, b) {
let arr = [];
let lenOfArr1 = keyboards.length;
let lenOfArr2 = drives.length;
let j = drives.length;
arr = keyboards.slice(0);
for (let number of drives) {
arr.push(number);
}
return (challenge(arr, lenOfArr1, b));
}
function challenge(arr, lenOfArr1, m) {
let result = [];
let j = lenOfArr1;
for (let i = 0; i < lenOfArr1; i++) {
if (arr[i] >= m || arr[j] >= m) return -1;
if (arr[i] + arr[j] < m) {
result.push(arr[i] + arr[j]);
}
i--;
j++;
if (j == arr.length) {
i++;
j = lenOfArr1;
}
}
if (result.length == 0) return -1;
return result.sort()[result.length - 1];
}
From the given constraints in the problem statement, you don't need such a complex solution.
Here is the Algorithm:
Initialize a variable maxValue to have value as -1.
Start two for loops over drives and keyboards and take all combinations and sum the value of each drive with each keyboard.
Inside the for loops, check if the sum of drive + keyboard and it should be less than or equal to the money Monica has and keep track of the maximum value you get from any combination in maxValue.
After the code computation, return maxValue.
Code:-
function getMoneySpent(keyboards, drives, b) {
let maxValue = -1;
for (let drive of drives) {
for(let keyboard of keyboards) {
let cost = drive + keyboard;
if(cost > maxValue && cost <= b) {
maxValue = cost;
}
}
}
return maxValue;
}
Overall Time complexity - O(n^2).
Hope this helps!
The following line causes your code to return -1 when there might be a solution:
if (arr[i] >= m || arr[j] >= m) return -1;
Even though one price may be above budget, you need to consider that there might be cheaper items available. You might even already have solutions in result, or they might still be found in a later iteration.
It is not clear to me why you first create a merged array of both input arrays. It does not seem to bring any benefit.
If you sort the input arrays, you can use a two-pointer system where you decide which one to move depending on whether the current sum is within limits or it is too great:
function getMoneySpent(keyboards, drives, b) {
keyboards = [...keyboards].sort((a, b) => b - a) // descending
drives = [...drives].sort((a, b) => a - b); // ascending
let k = keyboards.length - 1; // cheapest
let d = drives.length - 1; // most expensive
let maxSum = -1;
while (d >= 0 && k >= 0) {
let sum = keyboards[k] + drives[d];
if (sum === b) return b;
if (sum < b) {
if (sum > maxSum) maxSum = sum;
k--; // will increase sum
} else {
d--; // will decrease sum
}
}
return maxSum;
}
I have a huge array of length over 200,000. I need to get top 10 values. I know sort is not the best solution. I have tried the following solution:
const sortBy = 'key';
const results = [];
const m = 10;
const N = array.length;
while (array.length && results.length < m) {
let currentMax = 0;
let currentMaxIndex = 0;
array.forEach((record, i) => {
if (record[sortBy] >= currentMax) {
currentMax = record[sortBy];
currentMaxIndex = i;
}
});
results.push(...array.splice(currentMaxIndex, 1));
}
Here array is an Array of length 200,000.
Problem is, I think if m equals N, then this
is going to take more time than sort itself. I want to know if there
is a better solution, that can handle both the cases.
Thank you for the help, but the actual question is m ā (0, N). m can take any value up to N. So, at which point would it be advisable to switch to in-built sort?
As per my understanding as m reaches N the complexity increases and sort is the best solution when m === N
I have tested with the example provided by #t-j-crowder here. A test to get top 10 from 100 entries.
When testing with different values in m, the faster algorithm is changing to sort at m === 85. So, I want to find out if there is any way to determine when we should switch back to sort, to have optimal performance in all cases.
You don't need to sort the whole array, you just need to insert into your top 10 array in numeric order and drop any additional entries:
var a = Array.from({length:100}, () => Math.floor(Math.random() * 1000000));
var check = a.slice().sort((left, right) => right - left).slice(0, 10);
console.log("check", check);
function checkResult(top10) {
var n;
for (n = 0; n < 10; ++n) {
if (top10[n] !== check[n]) {
console.log("Error in test at #" + n + ", expected " + check[n] + ", got " + top10[n]);
return false;
}
}
return true;
}
var top10 = [];
var cutoff = -Infinity;
var full = false;
var n, len, value;
for (n = 0, len = a.length; n < len; ++n) {
value = a[n];
// If the value may be in the top 10...
if (!full || value >= cutoff) {
// Insert into top10
let found = false;
for (let n = 0; n < top10.length; ++n) {
if (top10[n] <= value) {
top10.splice(n, 0, value);
found = true;
break;
}
}
if (!found) {
top10.push(value);
}
// Trim it
if (top10.length > 10) {
full = true;
top10.length = 10;
}
// Remember the lowest of the top 10 candidates we have now so we can not bother with checking lower ones
cutoff = top10[top10.length - 1];
}
}
console.log("top10", top10);
console.log("Good? " + checkResult(top10));
.as-console-wrapper {
max-height: 100% !important;
}
You can probably tidy that up a bit, optimize it further, but you get the idea. Maintaining a list of just the top 10 highest you've seen, dropping ones off the bottom if others join it.
Benchmark here, easily beats sorting and then grabbing the top 10 on Chrome and Firefox; the converse is true on Edge.
function limitSort(array, sortBy, limit) {
const result = [];
// Iterate over the array *once*
for(const el of array) {
// Exclude all elements that are definetly not in the resulting array
if(result.length < limit || el[sortBy] > result[0]) {
// Determine the position were the element needs to be inserted (Insertion sort)
let insertAt = 0;
while(insertAt < result.length && result[insertAt][sortBy] < el[sortBy]) insertAt++;
// Finally insert it
result.splice(insertAt, 0, el);
// If the results are getting to long, remove the lowest element
if(result.length > limit)
result.splice(0, 1);
}
}
return result;
}
This implements the algorithm, Niet the Dark Absol proposed above. Try it!
I have this working insertion sort javascript code.
Array.prototype.insertionSort = function() {
var A = this;
var time = 0;
var n = A.length;
for (var i = 1; i < n; i++) {
var v = A[i];
var j = i-1;
while (j >= 0 && A[j] > v) {
A[j+1] = A[j];
j--;
var temp = new Array(this);
setTimeout(callback(JSON.stringify(temp)), 500*(time++));
}
A[j+1] = v;
var temp = new Array(this);
setTimeout(callback(JSON.stringify(temp)), 500*(time++));
}
return time;
}
I need something similar for quciksort, but I don't know how to do it. Can someone help me, please?
This might be the late posting, but I hope this may help somebody. QuickSort is a Divide and Conquer algorithm. It picks an element as pivot and partitions the given array around the picked pivot. You can select pivot in the following ways.
a)pick the first element as the pivot(Implemented below) b)pick the last element as pivot c)Pick a random element as pivot.d)pick median as a pivot.
if your array is already sorted then time complexity would be O(n^2) but for the average and best case it is O(N log N). It is in place algorithm and nonstable(as partitioning does one of the long-range exchanges). In some cases quicksort might take quadratic time. Quicksort has more overhead even for tiny arrays for sizes less than 10-20. If you use insertion sort for the small size of arrays then you might reduce the processing time by 15-20 %. Sharing my code below, also if you want to reduce more processing time then try to estimate partitioning element to be middle of an array.
class QuickSort{
constructor(){
this.cutoff = 10;
}
partition(arr, lo, hi){
let i = lo, j = hi+1;
debugger;
while(true){
while(arr[++i] < arr[lo]) if(i == hi) break;
while(arr[lo] < arr[--j]) if(j == lo) break;
if(i >= j) break;
this.swap(arr, i, j);
}
this.swap(arr, lo, j);
return j;
}
swap(arr, i, j){
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
sort(arr, lo, hi){
//if(hi <= lo) return;
if((this.cutoff + lo) -1 >= hi){
let insertionSort = new InsertionSort();
insertionSort.sort(arr); return;
}
console.log('Inside Quick Sort');
let j = this.partition(arr, lo, hi);
this.sort(arr, lo, j-1);
this.sort(arr, j+1, hi);
}
shuffle(arr) {
let n = arr.length;
for (let i = 0; i < n; i++) {
// choose index uniformly in [0, i]
let r = Math.floor(Math.random() * (i + 1));
this.swap(arr, i, r);
}
console.log('After uniform random Shuffle');
console.log(arr);
this.sort(arr, 0, n-1);
}
}
class InsertionSort{
constructor(){
this.quickSort = new QuickSort();
}
sort(arr){
console.log("Inside Insertion sort");
for(let i = 1; i < arr.length; i++){
for(let j = i; j > 0; j--){
if(arr[j-1] > arr[j]){
this.quickSort.swap(arr, j, j-1);
}
}
}
}
}
let arr = [101, 22,4,22,2,7,9,10,49,101,-1,4,1,6,99];
console.log('Before sorting an array');
console.log(arr);
let quickSort = new QuickSort();
quickSort.shuffle(arr);
console.log('After Sorting an array');
console.log(arr);
you can get to know the time complexity of from this post time complexity
The Wikipedia article on Quick Sort is pretty thorough and even includes a few pseudocode implementations.
Wikipedia summarizes the problem like so:
Quicksort is a divide and conquer algorithm. Quicksort first divides a
large array into two smaller sub-arrays: the low elements and the high
elements. Quicksort can then recursively sort the sub-arrays.
The steps are:
Pick an element, called a pivot, from the array.
Partitioning: reorder the array so that all elements with values less than the pivot come before the pivot, while all elements with values greater than the pivot come after it (equal values can go either way). After this partitioning, the pivot is in its final position. This is called the partition operation.
Recursively apply the above steps to the sub-array of elements with smaller values and separately to the sub-array of elements with greater values.
The base case of the recursion is arrays of size zero or one, which are in order by definition, so they never need to be sorted.
The pivot selection and partitioning steps can be done in several
different ways; the choice of specific implementation schemes greatly
affects the algorithm's performance.
And just a heads-up, I remember off-by-one errors being the biggest headache with this problem when I did it in school, so if you don't get the right answer right away, double-check your pivot selection and partitioning logic.
You should check google before posting a question: Quicksort is a very common algorithm and you have plenty of resources describing it.
function swap(items, firstIndex, secondIndex){
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
}
function partition(items, left, right) {
var pivot = items[Math.floor((right + left) / 2)],
i = left,
j = right;
while (i <= j) {
while (items[i] < pivot) {
i++;
}
while (items[j] > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j);
i++;
j--;
}
}
return i;
}
function quickSort(items, left, right) {
var index;
if (items.length > 1) {
left = typeof left != "number" ? 0 : left;
right = typeof right != "number" ? items.length - 1 : right;
index = partition(items, left, right);
if (left < index - 1) {
quickSort(items, left, index - 1);
}
if (index < right) {
quickSort(items, index, right);
}
}
return items;
}
// first call
var result = quickSort(items);
Code credits: N.C.Zakas
Furthermore, note that Quicksort is used by V8 when calling Array.prototype.sort() on arrays > 10 items (V8 source). On smaller arrays, InsertionShort is actually faster.
heres a short version of quick sort written in pure JS!
as seen in Intro To Algorithms
var partition = function (arr, low, high) {
var x = arr[high]
var i = low - 1
for (var j = low; j <= high - 1; j++) {
if (arr[j] <= x) {
i++
var temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
}
var temp = arr[i + 1]
arr[i + 1] = arr[high]
arr[high] = temp
return i + 1
}
var quickSort = function (arr, low, high) {
if (low < high) {
index = partition(arr,low,high)
if (low < index-1) quickSort(arr,low,index-1)
if (index+1 < high) quickSort(arr,index+1,high)
}
}
var list2 = [1000,13,12,1001,82,1,2,4,3,0]
console.log(quickSort(list2,0,list2.length))
also on my GitHub
I am new to Javascript, I am doing a coding challenge to learn more about the language. This is not school related or anything like that, totally for my own personal growth. Here is the challenge:
Return the sum of all odd Fibonacci numbers up to and including the
passed number if it is a Fibonacci number.
I have spent the past 2 evenings working on solving this challenge. When I run my code using underscore.js it works. When I use Ramda.js it says NaN. I would think both would return NaN. I'm very surprised that I can get the correct answer from one and not the other. Any insights would be greatly appreciated!
var R = require('ramda');
function sumFibs(num) {
var fib_Arr = [];
var new_Arr = [];
var total = 0;
// I use this to tell if the fib num is greater than 2
var the_Bit = "false";
// This is used to keep track of when to stop the loop
var fib_Num = 0;
// THIS WORKS FROM HERE
// This loop generates a list of fibonacci numbers then pushes them to the fib_Arr
for(var i = 0; total < num; i++){
if (i < 1){
fib_Arr.push(0);
}
else if (i === 1){
fib_Arr.push(i);
fib_Arr.push(1);
}
else if (i === 2){
fib_Arr.push(2);
the_Bit = "true";
}
else if (the_Bit === "true"){
temp_Arr = R.last(fib_Arr,2);
temp_Arr = temp_Arr[0] + temp_Arr[1];
fib_Arr.push(temp_Arr);
total = R.last(fib_Arr);
}
// Generating the fib Array works TO HERE!!!!
}
// console.log(fib_Arr); // Print out the generated fibonacci array
// if last Array element is greater than the original in
var last_Element = R.last(fib_Arr);
if (last_Element > num){
console.log("The last element of the array is bigger!");
fib_Arr.splice(-1,1); // This removes the last item from the array if it is larger than the original num input
}
// This loop removes all of the EVEN fibonacci numbers and leaves all of the ODD numbers
for (var j = 0; j < fib_Arr.length; j++){
if (fib_Arr[j] % 2 !== 0){
new_Arr.push((fib_Arr[j]));
}
}
// This checks if the original input num was a
if (num % 2 !== 0){
new_Arr.push(num);
}
else{
console.log("The original num was not a Fibonacci number!");
}
// if last Array element is the same as the original input num
var last = R.last(fib_Arr);
if (last === num){
console.log("Removing the last element of the array!");
new_Arr.splice(-1,1); // This removes the last item from the array if it is the same as the original num input
}
// Now to add all of the numbers up :-)
for (var k = 0; k < new_Arr.length; k++){
console.log("This is fib_Num: " + fib_Num);
// console.log(fib_N`);
fib_Num = fib_Num += new_Arr[k];
}
return fib_Num;
}
// TEST CASES:
// console.log(sumFibs(75025)); //.to.equal(135721);
console.log(sumFibs(75024)); //.to.equal(60696);
You have a problem on these lines :
temp_Arr = R.last(fib_Arr,2);
temp_Arr = temp_Arr[0] + temp_Arr[1];
Besides the fact that R.last does not take a second argument (that will not fail though), you are using temp_arr as an array, when it is a number. Therefore, temp_arr gets a NaN value.
You are probably looking for R.take (combined with R.reverse) or R.slice.
By changing :
temp_Arr = R.last(fib_Arr,2);
with :
temp_Arr = R.take(2, R.reverse(fib_Arr));
or with :
temp_Arr = R.slice(fib_Arr.length - 2, fib_Arr.length)(fib_Arr);
or with (bonus play with a reduce from the right) :
temp_Arr = R.reduceRight(function(arr, elem) {
return arr.length < 2 ? [elem].concat(arr) : arr;
}, [])(fib_Arr);
We get :
sumFibs(75024) === 60696
For the record, here's how you do this problem:
function fibSumTo(n) {
var f1 = 1, f2 = 1, sum = 1, t;
while (f2 <= n) {
if (f2 & 1) sum += f2;
t = f1 + f2;
f1 = f2;
f2 = t;
}
return sum;
}
There's really no need for any sort of library because there's really no need for any sort of data structure.
var _ = require('underscore');function sumUpFibs (number){
arr_of_fibs = [1,1];
current = 1; //cursor for previous location
while (true){
var num = arr_of_fibs[current] + arr_of_fibs[current - 1];
if (num <= number) {
arr_of_fibs.push(num);
current++;
} else {
break;
}
}
console.log(arr_of_fibs);
var total = 0;
_.each(arr_of_fibs, function(fib){
total += fib;
})
return total;}console.log(sumUpFibs(75025));
This may be a better implementation... Though I know you're just starting so I don't want to come off as mean : D.... Also, maybe check your test cases too.