-1

Problem statement:

// m is the number, n is upto-length of subsequences
// m = 20125, n =3  should print 201, 202, 205, 212, 215, 225, 012, 015, 125
// m = 20125, n =2 should print 20, 21, 22, 25, 01, 02, 05, 12, 15, 25
// m = 20125, n =1 should print 2, 0, 1, 2, 5
// m = 20125, n =4 should print 2012, 2015, 2125, 0125, 2025
// m = 20125, n =5 should print 20125

Below is the recursive solution implemented in GoLang:

package recursion

import (
    "fmt"
    "strconv"
)

// m is the number, n is upto-length of subsequences
// m = 20125, n =3  should print 201, 202, 205, 212, 215, 225, 012, 015, 125
// m = 20125, n =2 should print 20, 21, 22, 25, 01, 02, 05, 12, 15, 25
// m = 20125, n =1 should print 2, 0, 1, 2, 5
// m = 20125, n =4 should print 20125

func PrintSubSequence(m int, n int) {

    numDigits := digits(m)

    if n >= 1 && numDigits >= n { // m != 0
        for i := 1; i <= numDigits-n+1; i++ { // tree recurion
            firstInvocToIter := true
            var slice []string
            var findSubSequence func(int, int)

            findSubSequence = func(m int, n int) {

                if n == 1 { // base case
                    for m != 0 {
                        slice = append(slice, strconv.Itoa(m%10))
                        m = m / 10
                    }
                    return
                } else {
                    if firstInvocToIter {
                        firstInvocToIter = false
                        findSubSequence(m/tenToThePower(i), n-1)
                    } else {
                        findSubSequence(m/10, n-1)
                    }

                    for i, value := range slice {
                        slice[i] = value + strconv.Itoa(m%10)
                    }
                }

            }
            findSubSequence(m, n) // (20125, 3)
            fmt.Println(slice)
        }

    } else {
        return
    }

    PrintSubSequence(m/10, n)
}

func tenToThePower(times int) int {
    number := 1
    for times > 0 {
        number *= 10
        times--
    }
    return number
}

// Return the number of the digits of positive integer n
func digits(n int) int {
    if n <= 0 {
        return 0
    } else if n < 10 {
        return 1
    } else {
        allButLast, _ := split(n)
        return digits(allButLast) + 1
    }
}

package main

import (
    "github.com/myhub/cs61a/recursion"
)

func main() {

    recursion.PrintSubSequence(20125, 2) // prints duplicates as per debugging
    recursion.PrintSubSequence(20125, 3) // Works fine 
}

For recursion.PrintSubSequence(20125, 3) output is fine:

[125 025 225]
[015 215]
[205]
[012 212]
[202]

For recursion.PrintSubSequence(20125, 2) output has duplicates(problem output):

[25 15 05 25]        --> Valid
[15 05 25] --> duplicate
[05 25] --> duplicate
[25] --> duplicate
[12 02 22]           --> Valid
[02 22] --> duplicate
[22] --> duplicate
[01 21]              --> Valid
[21] --> duplicate
[20]                 --> Valid

Does this require maintaining a set of strings? to include slice in a set

or

How to handle duplicates? Looks like n==1 base case of tree recursion is giving issue?

overexchange
  • 15,768
  • 30
  • 152
  • 347
  • For 20125 , 25 at comes twice as subsequence , if you want to ignore duplicate remove duplicate digit and try to generate subsequence – Eklavya Jun 06 '20 at 08:12
  • @Eklavya first entry in the problem output has two times mention ing 25. What about the second entry? Which is actual duplicate... – overexchange Jun 06 '20 at 10:09
  • That is obviously duplicate – Eklavya Jun 07 '20 at 08:04
  • @Eklavya So, my question is, how to avoid those duplicates in the above code? – overexchange Jun 07 '20 at 08:55
  • I think best to rewrite your code, are you want to remove all duplicate ? means two times 25 is valid for your input. I will try to post a new way to this if you want – Eklavya Jun 07 '20 at 09:00
  • 1
    @Eklavya I never said twotimes 25 is invalid. Infact am not referring to that point anywhere in my query. I shown arrows for duplicate entries... I don't know, why you are behind those two times 25... Please post your recursive solution to this problem, wil go through – overexchange Jun 07 '20 at 09:03
  • I understand. I post a recursive solution – Eklavya Jun 07 '20 at 12:49

2 Answers2

0

If you convert your integer into string then it will more easier I think.

func PrintSubSequence(digits string, tmp string, idx int, sz int) {
    if len(tmp) == sz {  // if size reach then print
        fmt.Println(tmp)
        return
    }
    // here idx indicate in tmp string we already use till idx-1
    for i := idx; i < len(digits); i++ {
        tmp2 := tmp + string(digits[i]) // Add new digit in new variable to pass in recursion without change current tmp
        PrintSubSequence(digits, tmp2, i+1, sz)
    }
}
func main() {
    PrintSubSequence(strconv.Itoa(21025), "", 0, 2) // Convert interger into string
}

Full code in go playground here

Eklavya
  • 17,618
  • 4
  • 28
  • 57
0

Algo here:-

  1. You need to think from a each digit perspective. So, when you generating subsequence, either a digit can be part of the subsequence, or it cannot be.
  2. When you consider a particular digit, increment a counter (say, currentLength). Add the sequence which is formed till now to a Set to avoid duplicates.
  3. If the currentLength counter has reached your given upto-length, then stop the formation of current subsequence.
  4. Move onto next sequence formation.
Sugyan sahu
  • 129
  • 1
  • 8