Переходные срезы и циклы: многократный цикл по элементам среза, уменьшая количество элементов на 1 в каждом цикле

#go

#Вперед

Вопрос:

У меня есть срез целых чисел, который я хочу перебирать несколько раз, но каждый раз, когда я делаю еще один цикл, я хочу исключить элемент из родительского цикла.

Что-то вроде этого:

 func main() {
    as := []int{0, 1, 2, 3}
    for i, a := range as {
        bs := make([]int, len(as))
        copy(bs, as)
        bs = append(bs[:i], bs[i 1:]...)
        for i, b := range bs {
            cs := make([]int, len(bs))
            copy(cs, bs)
            cs = append(cs[:i], cs[i 1:]...)
            for i, c := range cs {
                ds := make([]int, len(cs))
                copy(ds, cs)
                ds = append(ds[:i], ds[i 1:]...)
                for _, d := range ds {
                    fmt.Println(a, b, c, d)
                }
            }
        }
    }
}
  

Вывод этого кода:

 0123
0132
0213
0231
0312
0321
1023
1032
1203
1230
1302
1320
2013
2031
2103
2130
2301
2310
3012
3021
3102
3120
3201
3210
  

Чего я и хотел. Но этот код выглядит не так хорошо. Я должен скопировать срез несколько раз, прежде чем удалить элемент, а затем перебирать элементы в этом срезе. Есть ли лучший и более простой способ для меня добиться того, что я здесь делаю? Я собираюсь сделать то же самое для среза, который выглядит следующим образом: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

Я не думаю, что писать каждый цикл так, как я делал 10 раз, — это хороший способ делать вещи. Есть предложения, как я могу это сделать?

Ответ №1:

Похоже, вы не знаете, что то, что вы делаете, называется генерацией перестановок. В противном случае было бы легко найти в Google эффективный алгоритм для этого.