Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

439
Views
recursive function works, generative version is wrong

this recursive functions works just fine to get combinations of values from an array:

function combinations(set, k) {
  if (k > set.length || k <= 0) return []
  if (k === set.length) return [set]
  if (k === 1) return set.map(x => [x])

  return set.reduce((p, c, i) => {
    combinations(set.slice(i + 1), k - 1).forEach(tailArray =>
      p.push([c].concat(tailArray)),
    )

    return p
  }, [])
}

I tried to convert that to a generative version:

function* combinations(set, k) {
  if (k > set.length || k <= 0) yield []
  if (k === set.length) yield set
  if (k === 1) yield* set.map(x => [x])

  for (let i in set) {
    for (const next of combinations(set.slice(+i + 1), k - 1)) {
      yield [set[i]].concat(next)
    }
  }

  return
}

however this returns far more results than it should, and they are not all the right length

function timeFn(fn){
  const pre = performance.now()
  const r = fn()
  const post = performance.now()
  console.log('time', (post - pre)/1000 , 's')
  return r
}

timeFn(()=> [...combinations([...Array(4)].map((_,i)=>i+1), 3)])
VM2045:5 time 0.00009999999403953553 s
(20) [Array(3), Array(3), Array(3), Array(4), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(2), Array(3), Array(3), Array(3), Array(3), Array(3), Array(2), Array(1), Array(2), Array(1)]

sadly, its not just for...in:

function* combinations(set, k) {
  if (k > set.length || k <= 0) yield []
  if (k === set.length) yield set
  if (k === 1) yield* set.map(x => [x])

    for (let i=0,lim=set.length; i<lim; i++) {
      for (const next of combinations(set.slice(i + 1), k - 1)) {
        yield [set[i]].concat(next)
      }
    }
return
}
undefined
timeFn(()=> [...combinations([...Array(4)].map((_,i)=>i+1), 3)])
VM2045:5 time 0.00020000000298023223 s
(20) [Array(3), Array(3), Array(3), Array(4), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(2), Array(3), Array(3), Array(3), Array(3), Array(3), Array(2), Array(1), Array(2), Array(1)]
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

You have not correctly converted the base cases to the generator version:

if (k > set.length || k <= 0) return []
if (k === set.length) return [set]
if (k === 1) return set.map(x => [x])

Notice that these return, while your generator function carries on, emitting all of them.

function* combinations(set, k) {
  if (k > set.length || k <= 0) {
    // notice this yields nothing
    return
  }
  if (k === set.length) {
    yield set
    return
  }
  if (k === 1) {
    yield* set.map(x => [x])
    return
  }

  for (let i=0; i<set.length; i++) {
    for (const next of combinations(set.slice(i + 1), k - 1)) {
      yield [set[i]].concat(next)
    }
  }
}

Btw, k === set.length and k === 1 are not base cases but (unnecessary) optimisations, and your functions don't work correctly for k === 0 - that should generate one empty array. Better:

function* combinations(set, k) {
  if (k >= 0 && k <= set.length) {
    if (k == 0) {
      yield [];
    } else {
      for (const [i, v] of set.entries())
        for (const next of combinations(set.slice(i + 1), k - 1)) {
          yield [v, ...next];
        }
      }
    }
  }
}
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!