2017-06-30 1 views
0

J'essaie de créer un programme capable de générer des combinaisons à partir d'une plage donnée.Générer des combinaisons à partir d'une plage donnée

j'ai commencé à éditer ce code ci-dessous qui génère des combinaisons:

package main 

import "fmt" 

func nextPassword(n int, c string) func() string { 
    r := []rune(c) 
    p := make([]rune, n) 
    x := make([]int, len(p)) 
    return func() string { 
     p := p[:len(x)] 
     for i, xi := range x { 
      p[i] = r[xi] 
     } 
     for i := len(x) - 1; i >= 0; i-- { 
      x[i]++ 
      if x[i] < len(r) { 
       break 
      } 
      x[i] = 0 
      if i <= 0 { 
       x = x[0:0] 
       break 
      } 
     } 
     return string(p) 
    } 
} 

func main() { 
    np := nextPassword(2, "ABCDE") 
    for { 
     pwd := np() 
     if len(pwd) == 0 { 
      break 
     } 
     fmt.Println(pwd) 
    } 
} 

Ceci est la sortie du code:

AA 
AB 
AC 
AD 
AE 
BA 
BB 
BC 
BD 
BE 
CA 
CB 
CC 
CD 
CE 
DA 
DB 
DC 
DD 
DE 
EA 
EB 
EC 
ED 
EE 

Et ceci est le code que j'édité:

package main 

import "fmt" 

const (
    Min = 5 
    Max = 10 
) 

func nextPassword(n int, c string) func() string { 
    r := []rune(c) 
    p := make([]rune, n) 
    x := make([]int, len(p)) 
    return func() string { 
     p := p[:len(x)] 
     for i, xi := range x { 
      p[i] = r[xi] 
     } 
     for i := len(x) - 1; i >= 0; i-- { 
      x[i]++ 
      if x[i] < len(r) { 
       break 
      } 
      x[i] = 0 
      if i <= 0 { 
       x = x[0:0] 
       break 
      } 
     } 
     return string(p) 
    } 
} 

func main() { 
    cont := 0 
    np := nextPassword(2, "ABCDE") 
    for { 
     pwd := np() 
     if len(pwd) == 0 { 
      break 
     } 
     if cont >= Min && cont <= Max{ 
      fmt.Println(pwd) 
     } else if cont > Max{ 
      break 
     } 
     cont += 1 
    } 
} 

Sortie:

BA 
BB 
BC 
BD 
BE 
CA 

Mon code fonctionne, mais si j'augmente la longueur de la combinaison et que ma gamme commence à partir du milieu, le programme générera même les combinaisons que je ne veux pas (et bien sûr cela prendra beaucoup de temps) . Comment puis-je résoudre ce problème?

+2

Pouvez-vous réduire cela à code minimum nécessaire pour reproduire le problème, et de préciser exactement ce que la question est? – Adrian

+1

Avez-vous modifié la fonction 'nextPassword'? Ugh, quiconque a écrit cette fonction l'a délibérément obscurci, ou a besoin d'une leçon de noms de variables utiles. – RayfenWindspear

Répondre

1

Je n'ai vraiment pas aimé comment nextPassword a été écrit, donc j'ai fait une variation. Plutôt que de commencer à 0 et de retourner à plusieurs reprises la valeur suivante, celle-ci prend un entier et le convertit en "mot de passe" correspondant. Par exemple. toPassword(0, 2, []rune("ABCDE")) est AA, et toPassword(5, ...) est BA. À partir de là, il est facile de faire une boucle sur la plage que vous voulez. Mais j'ai aussi écrit un wrapper nextPassword qui se comporte de la même manière que le code original. Celui-ci utilise toPassword sous la couverture et prend un départ n.

Version Runnable ici: https://play.golang.org/p/fBo6mx4Mji

code ci-dessous:

package main 

import (
    "fmt" 
) 

func toPassword(n, length int, alphabet []rune) string { 
    base := len(alphabet) 

    // This will be our output 
    result := make([]rune, length) 

    // Start filling from the right 
    i := length - 1 

    // This is essentially a conversion to base-b, where b is 
    // the number of possible letters (5 in the case of "ABCDE") 
    for n > 0 { 
     // Filling from the right, put the right digit mod b 
     result[i] = alphabet[n%base] 

     // Divide the number by the base so we're ready for 
     // the next digit 
     n /= base 

     // Move to the left 
     i -= 1 
    } 

    // Fill anything that's left with "zeros" (first letter of 
    // the alphabet) 
    for i >= 0 { 
     result[i] = alphabet[0] 
     i -= 1 
    } 

    return string(result) 
} 

// Convenience function that just returns successive values from 
// toPassword starting at start 
func nextPassword(start, length int, alphabet []rune) func() string { 
    n := start 
    return func() string { 
     result := toPassword(n, length, alphabet) 
     n += 1 
     return result 
    } 
} 

func main() { 
    for i := 5; i < 11; i++ { 
     fmt.Println(toPassword(i, 2, []rune("ABCDE"))) 
    } // BA, BB, BC, BD, BE, CA 

    // Now do the same thing using nextPassword 
    np := nextPassword(5, 2, []rune("ABCDE")) 
    for i := 0; i < 6; i++ { 
     fmt.Println(np()) 
    } // BA, BB, BC, BD, BE, CA 
}