This is the second day of my participation in the August More text Challenge. For details, see: August More Text Challenge

Examples of the intersection and difference sets of integer intervals:

[1,5] + [6,10] = [1,10]

[1,100] – [10,20] = [1,9] + [21,100]

If you were asked to design a program that calculated the set, intersection, and difference of integer intervals, what would it be?

I’ll think about how hard it is, and then go to Github to see if there’s any open source code I can reuse.

Go – intervals

Go-intervals is a library for performing collection operations on one-dimensional intervals, such as time intervals, and fits my integer interval calculation needs just fine. Github: github.com/google/go-i…

Choose reason

There are three reasons why we chose Go-intervals:

  1. Google’s name is enough to convince me of the quality of the code

  2. Complete test cases

  3. The code is open source and easy to understand

Code analysis

Go-intervals library can operate on a variety of one-dimensional interval sets, such as time, integers, etc. Also can support a variety of opening and closing interval, such as left open right closed, left closed right open, left closed right closed, etc. How is the code designed? Did the author implement all the details inside the code?

DIP: High-level modules do not rely on low-level modules. High-level and low-level modules should rely on each other through abstractions. In addition to this, abstractions should not be dependent on implementation details as details depend on abstractions. The details are covered in Go Design Patterns (3)- Design Principles.

The interval is the basic unit of a set. Crossover union of sets is essentially crossover union of intervals.

Combined with the above two points, the author’s implementation method is to interface the interval. Go-intervals are only responsible for the intersection and difference operation of two intervals of two sets at the framework level, and the implementation logic of intersection and difference is implemented by the caller himself.

type Interval interface {
  // Intersect returns the intersection of an interval with another
  // interval. The function may panic if the other interval is incompatible.
  / / intersection
  Intersect(Interval) Interval

  // Before returns true if the interval is completely before another interval.
  // Is one interval in front of another interval
  Before(Interval) bool

  // IsZero returns true for the zero value of an interval.
  // Whether the interval is empty
  IsZero() bool

  // Bisect returns two intervals, one on the lower side of x and one on the
  // upper side of x, corresponding to the subtraction of x from the original
  // interval. The returned intervals are always within the range of the
  // original interval.
  / / difference set
  Bisect(x Interval) (Interval, Interval)

  // Adjoin returns the union of two intervals, if the intervals are exactly
  // adjacent, or the zero interval if they are not.
  / / and set
  Adjoin(Interval) Interval

  // Encompass returns an interval that covers the exact extents of two
  // intervals.
  // Whether the interval is inclusive
  Encompass(Interval) Interval
}
Copy the code

implementation

Callers who want to implement which Interval, which open and close mode, just need to implement their own Interval. I need to implement integer, left closed right closed interval union, difference set operation.

Left closed and right open

In the code test case, the author gives the integer interval, left closed right open implementation:

type span struct {
	min, max int
}

// case returns a *span from an Interval interface, or it panics.
func cast(i Interval) *span {
	x, ok := i.(*span)
	if! ok {panic(fmt.Errorf("interval must be an span: %v", i))
	}
	return x
}

// zero returns the zero value for span.
func zero(a) *span {
	return &span{}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func (s *span) String(a) string {
	return fmt.Sprintf("[%d, %d)", s.min, s.max)
}

func (s *span) Equal(t *span) bool {
	return s.min == t.min && s.max == t.max
}

// Intersect returns the intersection of an interval with another
// interval. The function may panic if the other interval is incompatible.
func (s *span) Intersect(tInt Interval) Interval {
	t := cast(tInt)
	result := &span{
		max(s.min, t.min),
		min(s.max, t.max),
	}
	if result.min < result.max {
		return result
	}
	return zero()
}

// Before returns true if the interval is completely before another interval.
func (s *span) Before(tInt Interval) bool {
	t := cast(tInt)
	return s.max <= t.min
}

// IsZero returns true for the zero value of an interval.
func (s *span) IsZero(a) bool {
	return s.min == 0 && s.max == 0
}

// Bisect returns two intervals, one on either lower side of x and one on the
// upper side of x, corresponding to the subtraction of x from the original
// interval. The returned intervals are always within the range of the
// original interval.
func (s *span) Bisect(tInt Interval) (Interval, Interval) {
	intersection := cast(s.Intersect(tInt))
	if intersection.IsZero() {
		if s.Before(tInt) {
			return s, zero()
		}
		return zero(), s
	}
	maybeZero := func(min, max int) *span {
		if min == max {
			return zero()
		}
		return &span{min, max}
	}
	return maybeZero(s.min, intersection.min), maybeZero(intersection.max, s.max)

}

// Adjoin returns the union of two intervals, if the intervals are exactly
// adjacent, or the zero interval if they are not.
func (s *span) Adjoin(tInt Interval) Interval {
	t := cast(tInt)
	if s.max == t.min {
		return &span{s.min, t.max}
	}
	if t.max == s.min {
		return &span{t.min, s.max}
	}
	return zero()
}

// Encompass returns an interval that covers the exact extents of two
// intervals.
func (s *span) Encompass(tInt Interval) Interval {
	t := cast(tInt)
	return &span{min(s.min, t.min), max(s.max, t.max)}
}

Copy the code

Left closed right closed interval

Since the author’s offer does not meet the requirements, you need to modify it yourself. Refer to the left closed right open code to change to the left closed right closed code, the only drawback is that if there is overlap between the set building interval will panic, overlap can be checked in the business layer, but no problem.

type span struct {
   min, max int64
}

// case returns a *span from an Interval interface, or it panics.
func cast(i intervalset.Interval) *span {
   x, ok := i.(*span)
   if! ok {panic(fmt.Errorf("interval must be an span: %v", i))
   }
   return x
}

// zero returns the zero value for span.
func zero(a) *span {
   return &span{}
}

func min(a, b int64) int64 {
   if a < b {
      return a
   }
   return b
}

func max(a, b int64) int64 {
   if a > b {
      return a
   }
   return b
}

func (s *span) String(a) string {
   return fmt.Sprintf("[%d, %d]", s.min, s.max) //done
}

func (s *span) Equal(t *span) bool {
   return s.min == t.min && s.max == t.max
}

/ / modified
// Before returns true if the interval is completely before another interval.
func (s *span) Before(tInt intervalset.Interval) bool {
   t := cast(tInt)
   //if s.min == s.max && s.max == t.min && t.min == t.max { //done
   // return false
   / /}
   //if (s.min == s.max) && (s.min == t.min || s.min == t.max || s.max == t.min || s.max == t.max) {
   // return false
   / /}
   //if (t.min == t.max) && (t.min == s.max || t.min == s.min || t.max == s.max || t.max == s.min) {
   // return false
   / /}

   return s.max < t.min
}

// IsZero returns true for the zero value of an interval.
func (s *span) IsZero(a) bool {
   return s.min == 0 && s.max == 0
}

// The intersection has been modified
// Intersect returns the intersection of an interval with another
// interval. The function may panic if the other interval is incompatible.
func (s *span) Intersect(tInt intervalset.Interval) intervalset.Interval {
   t := cast(tInt)
   result := &span{
      max(s.min, t.min),
      min(s.max, t.max),
   }
   if result.min <= result.max { //done
      return result
   }
   return zero()
}

// The adjacent splices have been modified
// Adjoin returns the union of two intervals, if the intervals are exactly
// adjacent, or the zero interval if they are not.
func (s *span) Adjoin(tInt intervalset.Interval) intervalset.Interval {
   t := cast(tInt)
   if s.max == t.min || s.max == t.min- 1 { //done
      return &span{s.min, t.max}
   }
   if t.max == s.min || t.max == s.min- 1 { //done
      return &span{t.min, s.max}
   }
   return zero()
}

// The difference set has been modified
// Bisect returns two intervals, one on either lower side of x and one on the
// upper side of x, corresponding to the subtraction of x from the original
// interval. The returned intervals are always within the range of the
// original interval.
func (s *span) Bisect(tInt intervalset.Interval) (intervalset.Interval, intervalset.Interval) {
   intersection := cast(s.Intersect(tInt))
   if intersection.IsZero() {
      if s.Before(tInt) {
         return s, zero()
      }
      return zero(), s
   }
   maybeZero := func(min, max int64) *span {
      if min > max { //done
         return zero()
      }
      return &span{min, max}
   }
   return maybeZero(s.min, intersection.min- 1), maybeZero(intersection.max+1, s.max) //done

}

// Encompass returns an interval that covers the exact extents of two
// intervals.
func (s *span) Encompass(tInt intervalset.Interval) intervalset.Interval {
   t := cast(tInt)
   return &span{min(s.min, t.min), max(s.max, t.max)}
}

Copy the code

test

What are some ways to check your code for problems? There are at least two things, code review and unit testing. For this third party library, and their own implementation of part of the logic, we must do a good job of unit testing, which is a good thing for predecessors to plant trees for descendants to enjoy the cool.

The test case is arranged as follows:

[20,40] is the specified interval, and other intervals and the specified interval are used for intersection and difference operations. The vertical lines indicate that the values of the left and right intervals are the same.

I spent the night writing test cases, and the initial tests were fine.

/**
@author: Jason Pang
@desc:
@date: 2021/7/1
**/
package service

import (
   "github.com/google/go-intervals/intervalset"
   "reflect"
   "testing"
)

func TestAddTest(t *testing.T) {
   type args struct {
      s1 *intervalset.Set
      s2 *intervalset.Set
   }
   tests := []struct {
      name    string
      args    args
      wantRes *intervalset.Set
   }{
      {
         name: "empty + empty = empty",
         args: args{
            s1: intervalset.NewSet([]intervalset.Interval{}),
            s2: intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: Empty + [30,111] = [30,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{}),
            intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
      },
      {
         name: "[20, 40] + empty = [20, 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: "[20, 40] + [60111]." ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{60.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}, &span{60.111}}),
      },
      {
         name: "[20, 40] + [39111]." ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.111}}),
      },
      {
         name: "[20, 40] + [40111]." ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.111}}),
      },
      {
         name: "[20, 40] + [41111]." ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.111}}),
      },
      {
         name: "[20, 40] + [30111]." ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.111}}),
      },
      {
         name: [20,40] + [25, 28] = [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25.28}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] + [10, 30] = [10,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.30}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.40}}),
      },
      {
         name: [10, 19] + [20,40] = [10,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10.19}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.40}}),
      },
      {
         name: [20,40] + [10, 20] = [10,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.40}}),
      },
      {
         name: [20,40] + [10, 21] = [10,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.40}}),
      },
      {
         name: [20,40] + [10,15] = [10,15] [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.15}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.15}, &span{20.40}}),
      },
      {
         name: [20,40] + [10,100] = [10,100],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.100}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.100}}),
      },
      {
         name: [20,40] + [10,10] = [10,10] [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.10}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.10}, &span{20.40}}),
      },
      {
         name: "[20,40] + [19, 19] = [19 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{19.19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{19.40}}),
      },
      {
         name: [20,40] + [20, 20] = [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] + [21, 21] = [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{21.21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] + [25, 25] = [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25.25}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: "[20,40] + [39, 39] = [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39.39}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] + [40, 40] = [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40.40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] + [41, 41] = [20 41]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41.41}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.41}}),
      },
      {
         name: "[20,40] + [50, 50] = [20 40] [50, 50]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{50.50}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}, &span{50.50}})},/////////
      {
         name: "[20, 40] + [41, 50] + [50, 60] + [61111] = [20111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}, &span{41.50}}),
            intervalset.NewSet([]intervalset.Interval{&span{50.60}, &span{61.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.111}}),
      },

      {
         name: [10, 19] + [20,20] = [10,20],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10.19}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.20}}),
      },
      {
         name: [20] + [10, 19] = [10,20]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.20}}),
      },
      {
         name: "[10, 19] + [21,30] + [20,20] = [10,30]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10.19}, &span{21.30}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.30}}),
      },
      {
         name: "[10, 15] + [20, 20]." ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10.15}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.15}, &span{20.20}}),
      },
      {
         name: [20,20] + [10, 15],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.15}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10.15}, &span{20.20}})}},for _, tt := range tests {
      t.Run(tt.name, func(t *testing.T) {
         ifgotRes := AddTest(tt.args.s1, tt.args.s2); ! reflect.DeepEqual(gotRes.AllIntervals(), tt.wantRes.AllIntervals()) { t.Errorf("Add() = %v, want %v", gotRes, tt.wantRes)
         }
      })
   }
}

func TestSubTest(t *testing.T) {
   type args struct {
      s1 *intervalset.Set
      s2 *intervalset.Set
   }
   tests := []struct {
      name    string
      args    args
      wantRes *intervalset.Set
   }{
      {
         name: "empty - empty = empty",
         args: args{
            s1: intervalset.NewSet([]intervalset.Interval{}),
            s2: intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: "empty - [30,111] = empty",
         args: args{
            intervalset.NewSet([]intervalset.Interval{}),
            intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: "Empty = [30,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
            intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
      },
      {
         name: "[20, 40] - [30,111] = [20,29]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{30.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.29}}),
      },
      {
         name: "[20, 40] - [41,111] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: "[20, 40] - [40,111] = [20,39]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.39}}),
      },
      {
         name: "[20, 40] - [39,111] = [20,38]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39.111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.38}}),
      },
      {
         name: [20, 40] - [25,28] = [20,24] [29,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25.28}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.24}, &span{29.40}}),
      },
      {
         name: [20, 40] - [15,28] = [29,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15.28}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{29.40}}),
      },
      {
         name: "[20, 40] - [15,20] = [21,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{21.40}}),
      },
      {
         name: "[20, 40] - [15,21] = [22,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15.21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{22.40}}),
      },
      {
         name: "[20, 40] - [15,19] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15.19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] - [10,15] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10.15}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: "[20, 40] - [5,5] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{5.5}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: "[20, 40] - [20,20] = [21,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{21.40}}),
      },
      {
         name: [20, 40] - [25,25] = [20,24] [26,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25.25}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.24}, &span{26.40}}),
      },
      {
         name: "[20, 40] - [40,40] = [20,39]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40.40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.39}}),
      },
      {
         name: "[20, 40] - [45,45] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{45.45}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20,40] - [19,19] = [20,40],
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{19.19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: "[20, 40] - [21,21] = [20,20] [22,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{21.21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.20}, &span{22.40}}),
      },
      {
         name: "[20, 40] - [39,39] = [20,38] [40, 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39.39}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.38}, &span{40.40}}),
      },
      {
         name: "[20, 40] - [41,41] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41.41}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
      },
      {
         name: [20, 40] - [11,41] = []",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
            intervalset.NewSet([]intervalset.Interval{&span{11.41}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: "[11,41] - [20, 40] = [11,19] [41 41]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{11.41}}),
            intervalset.NewSet([]intervalset.Interval{&span{20.40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{11.19}, &span{41.41}})}},for _, tt := range tests {
      t.Run(tt.name, func(t *testing.T) {
         ifgot := SubTest(tt.args.s1, tt.args.s2); ! reflect.DeepEqual(got.AllIntervals(), tt.wantRes.AllIntervals()) { t.Errorf("Sub() = %v, want %v", got, tt.wantRes)
         }
      })
   }
}

Copy the code

conclusion

Many times you really don’t need to reinvent the wheel, and it’s hard to argue that your own wheel is better than anyone else’s. Sometimes it’s more important to use resources rationally and to meet deadlines. Writing code is a delicate business, and unit testing is essential. Not only will it help you clear your mind and identify your problems, but it will also prevent future generations from making mistakes.

The last

If you like my article, you can follow my public number (programmer Malatang)

My personal blog is shidawuhen.github. IO /

Review of previous articles:

  1. Design patterns

  2. recruitment

  3. thinking

  4. storage

  5. The algorithm series

  6. Reading notes

  7. Small tools

  8. architecture

  9. network

  10. The Go