4 "github.com/zclconf/go-cty/cty"
7 // LongestCommonSubsequence finds a sequence of values that are common to both
8 // x and y, with the same relative ordering as in both collections. This result
9 // is useful as a first step towards computing a diff showing added/removed
10 // elements in a sequence.
12 // The approached used here is a "naive" one, assuming that both xs and ys will
13 // generally be small in most reasonable Terraform configurations. For larger
14 // lists the time/space usage may be sub-optimal.
16 // A pair of lists may have multiple longest common subsequences. In that
17 // case, the one selected by this function is undefined.
18 func LongestCommonSubsequence(xs, ys []cty.Value) []cty.Value {
19 if len(xs) == 0 || len(ys) == 0 {
20 return make([]cty.Value, 0)
23 c := make([]int, len(xs)*len(ys))
24 eqs := make([]bool, len(xs)*len(ys))
27 for y := 0; y < len(ys); y++ {
28 for x := 0; x < len(xs); x++ {
29 eqV := xs[x].Equals(ys[y])
31 if eqV.IsKnown() && eqV.True() {
33 eqs[(w*y)+x] = true // equality tests can be expensive, so cache it
36 // Sequence gets one longer than for the cell at top left,
37 // since we'd append a new item to the sequence here.
41 c[(w*y)+x] = c[(w*(y-1))+(x-1)] + 1
44 // We follow the longest of the sequence above and the sequence
45 // to the left of us in the matrix.
63 // The bottom right cell tells us how long our longest sequence will be
64 seq := make([]cty.Value, c[len(c)-1])
66 // Now we will walk back from the bottom right cell, finding again all
67 // of the equal pairs to construct our sequence.
72 for x > -1 && y > -1 {
74 // Add the value to our result list and then walk diagonally
75 // up and to the left.
81 // Take the path with the greatest sequence length in the matrix.
99 // should never happen if the matrix was constructed properly
100 panic("not enough elements in sequence")