1

I know there is some problem with the return statement but I cant figure out what.

let arr = ['a', 'b', 'c', 'a']
let size = arr.length - 1
let counter = 0

function findOcc(arr, size, x) {
  if (size === 0) {
    return counter
  } else {
    if (arr[size] === x) return counter++
      findOcc(arr, size - 1, 'a')
  }
}

console.log(findOcc(arr, size, "a"))

4
  • I know there is some problem with the return statement which return statement? There's no return in a branch of your function Commented Apr 27, 2022 at 13:59
  • Check this and this Commented Apr 27, 2022 at 14:00
  • 1
    Also the ++ in return counter++ has no effect. You are before returning the variable and then incrementing it, but since you just exited the function there's no point in incrementing it Commented Apr 27, 2022 at 14:01
  • @CristianTraìna Thanks I understood my mistake. Commented Apr 27, 2022 at 14:16

3 Answers 3

2

A simpler recursive version uses array destructuring to test the first value against the target value, adding one if it matches, and zero if it doesn't, then recurring on the remainder of the array. We stop when the value is undefined, meaning we've run out of elements in the array.

const countOcc = (target) => ([x, ...xs]) =>
  x == undefined ? 0 : (x == target ? 1 : 0) + countOcc (target) (xs)

const arr = ['a', 'b', 'c', 'a']

console .log (countOcc ('a') (arr))
console .log (countOcc ('b') (arr))
console .log (countOcc ('c') (arr))
console .log (countOcc ('d') (arr))

While we could alter this to make it tail-recursive, current JS engines still do not do tail-call optimization, so it seems a bit pointless. If you were going to do this on large arrays, you would probably need to rewrite with iteration in place of recursion.

Sign up to request clarification or add additional context in comments.

4 Comments

I like Haskellesque JS coding too.
@Redu: I think of it as mostly basic recursion. The only thing that feels Haskell-like is the array destructuring. Even that has analogs everywhere there's decent pattern-matching.
Pattern matching is just fine but you also paritally apply. :) Not everybody care about that. Cool.
Oh, yes, I certainly understand currying. I'm one of the founders of Ramda where we use it extensively.
1

It seems you got the logic right in your head, but didn't implement it well.

  • So for the base condition you say if (size===0) return counter. This means that you just return counter but arr[0] is a valid check. So what you want really when you are checking elements is arr[size-1] in the next line i.e. else

  • For the else condition you meant to increment the counter which is right, but you should n't return. Instead you return the value of the next call with size-1

  • Also your declaration of size should be let size = arr.length

  • Also the last argument should be x and not a inside the recursive call.

With that the code is:

let arr = ['a', 'b', 'c', 'a']
let size = arr.length
let counter = 0

function findOcc(arr,size,x) {
  if (size === 0) return counter
  if(arr[size-1]===x)  ++counter
  return findOcc(arr,size-1,x)
}

console.log(findOcc(arr, size, "a"))

2 Comments

May be I'm wrong here - but if the objective is to find the number of occurrences (which is what my noggin indicates by reading findOcc), would it be dumb to expect the response to be 2 (as there are two 'a's in the array arr)? I'm guessing the last 'a' isn't being counted as the first call goes with size = arr.length - 1 and the first conditional does an additional arr[size-1].
@jsN00b now? the size declaration should be arr.length
-1

If one is okay with mutating the original array, then the function may be simplified like below:

const origArr = ['a', 'b', 'c', 'a'];

// a simpler implementation of the same recursive function
function findOcc(arr, x) {
  return (
    arr.length                // if "arr" length is 1 or more
    ? arr.pop() === x         // ".pop()" the last elt & compare with "x"
      ? 1 + findOcc(arr, x)   // add 1 & recurse using the shorted/mutated "arr"
      : findOcc(arr, x)       // do not add 1, but recurse using the mutate "arr"
    : 0                       // no more elements in "arr", so return 0
  )
}

// using "..." spread to avoid "arr" from being changed
console.log('number of times "a" occurs is: ', findOcc([...origArr], "a"))

console.log(
  `"d" occurs in ["${origArr.join('", "')}"] ${findOcc([...origArr], "d")} times...`
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.