Home  >  Article  >  Backend Development  >  Why are these tuples not generated correctly?

Why are these tuples not generated correctly?

WBOY
WBOYforward
2024-02-09 10:00:11969browse

Why are these tuples not generated correctly?

php Editor Apple often encounters some problems when writing code. One of the common problems is incorrect tuple generation. This may be due to code logic errors, data type mismatches, or other errors. Before solving this problem, we need to carefully analyze the code, find possible error points, and troubleshoot them one by one. Only when the problem is found can corresponding repairs be made to ensure that the tuples are generated correctly to ensure the normal operation of the code.

Question content

I have been working on a project that requires me to generate all possible tuples of a specific length from a set of (plural) numbers. To do this, I tried to implement a version of Mathematica's Tuples[] command, but found that it did not generate all tuples correctly.

After much frustration, I discovered that when my program generates tuples of length 4, it adds duplicates instead of new elements, causing problems with any tuples of longer length. I looked online to see if anyone had any other similar problems and found some other code to accomplish the same task and noticed that my solution was similar to theirs. I don't know what's wrong with me.

After more frustration I found that if I add elements to the list everything works fine, only appending is the problem. I tried to figure out what was wrong with my original code but found nothing.

Below is the code I wrote to demonstrate the problem. I'm by no means a professional coder, so you'll have to forgive me if this isn't the most idiomatic way to accomplish this task. Currently, I'm using the tuplesByPrepend function in my actual code and it works just fine, I'm really just hoping to understand what's going wrong with the tuplesByAppend function. Likewise, it seemed to perform well at third, fifth, eighth, and any other level I tested it on. I can provide more information about my OS and build and all that if needed.

package main

import "fmt"

func tuplesByAppend[T any](list []T, depth int) [][]T {
    var l1 [][]T
    var l2 [][]T

    for _, v := range list {
        l1 = append(l1, []T{v})
    }

    for i := 1; i < depth; i++ {
        for _, u := range l1 {
            for _, v := range list {
                // Differs here
                next := append(u, v)
                // next is calculated properly, but added to l2 incorrectly at the fourth level only
                // at the fifth level it functions properly
                // fmt.Println(next)
                l2 = append(l2, next)
                // fmt.Println(l2)

                // it appears that at the fourth level it is writing over the previous entries
                // Printing here yields
                // [[1 1 1 1]]
                // [[1 1 1 2] [1 1 1 2]]
                // [[1 1 1 3] [1 1 1 3] [1 1 1 3]]
                // [[1 1 1 3] [1 1 1 3] [1 1 1 3] [1 1 2 1]]
                // [[1 1 1 3] [1 1 1 3] [1 1 1 3] [1 1 2 2] [1 1 2 2]]
                // and so on.
            }
        }
        l1 = l2
        l2 = [][]T{}
    }

    return l1
}

func tuplesByPrepend[T any](list []T, depth int) [][]T {
    var l1 [][]T
    var l2 [][]T

    for _, v := range list {
        l1 = append(l1, []T{v})
    }

    for i := 1; i < depth; i++ {
        for _, u := range l1 {
            for _, v := range list {
                // Differs here
                next := append([]T{v}, u...)
                l2 = append(l2, next)
            }
        }
        l1 = l2
        l2 = [][]T{}
    }

    return l1
}

func main() {
    ourlist := []int{1, 2, 3}
    ourdepth := 4
    appended := tuplesByAppend(ourlist, ourdepth)
    prepended := tuplesByPrepend(ourlist, ourdepth)

    // We should expect this slice to start [1 1 1 1] [1 1 1 2] [1 1 1 3] [1 1 2 1] ...
    // In fact, it starts                   [1 1 1 3] [1 1 1 3] [1 1 1 3] [1 1 2 3]
    fmt.Println(appended)
    // This slice is as expected
    fmt.Println(prepended)
}

Workaround

In some cases, the following line does not work as you expect:

next := append(u, v)

This example demonstrates what happens:

package main

import "fmt"

func main() {
    u := append([]int{1, 2}, 3)
    // The length is 3 but the capacity is 4.
    fmt.Printf("u %v\n  len: %d\n  cap: %d\n", u, len(u), cap(u))

    // Since u has enough capacity for the new element "4",
    // v1 will share the same underlying array.
    v1 := append(u, 4)
    fmt.Println("v1:", v1)

    // As what happened to v1, v2 will share the same underlying array too.
    // But the last element "4" in the underlying array is changed to "5".
    v2 := append(u, 5)
    fmt.Println("v2:", v2)

    // Since v1 uses the same underlying array, it sees the change in the last step.
    fmt.Println("v1:", v1)
}

To prevent it from sharing the underlying array, replace next :=append(u, v) with the following code:

next := make([]T, len(u)+1)
copy(next, u)
next[len(u)] = v

See Go Slices: Usage and Internals for more information.

The above is the detailed content of Why are these tuples not generated correctly?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete