package bitint

import (
	"bytes"
	"fmt"
)

type IntSet struct {
	// 将words从uint64切片改为uint切片，以适应32位和64位平台
	words []uint
}

const (
	// PlatformCompatible 用于适应32位和64位平台
	PlatformCompatible = 32 << (^uint(0) >> 63)

	// 将代码中所有的64改为PlatformCompatible, 就完成了适配
)

// 展示一下效果

func (s *IntSet) Has(x int) bool {
	word, bit := x/PlatformCompatible, uint(x%PlatformCompatible)
	fmt.Println("word, bit: ", word, bit)
	return word < len(s.words) && s.words[word]&(1<<bit) != 0
}

func (s *IntSet) Add(x int) {
	word, bit := x/PlatformCompatible, uint(x%PlatformCompatible)
	for word >= len(s.words) {
		s.words = append(s.words, 0)
	}
	s.words[word] |= 1 << bit
}

func (s *IntSet) AddAll(nums ...int) {
	for _, num := range nums {
		s.Add(num)
	}
}

// Elems returns a slice containing the elements of the set.
// Elems 返回一个包含集合中所有元素的切片。
func (s *IntSet) Elems() (elems []int) {
	// 创建一个空的切片
	//var elems []int
	// 遍历s.words
	for i, word := range s.words {
		// 判断word是否为空
		if word == 0 {
			// 如果为空, 则跳过
			continue
		}
		// 遍历word
		for j := 0; j < PlatformCompatible; j++ {
			// 判断word的第j位是否为1
			if word&(1<<uint(j)) != 0 {
				// 如果为1, 则将PlatformCompatible*i+j添加到elems中
				elems = append(elems, PlatformCompatible*i+j)
			}
		}
	}
	// 返回elems
	return elems
}

func (s *IntSet) UnionWith(t *IntSet) {
	for i, tword := range t.words {
		if i < len(s.words) {
			s.words[i] |= tword
		} else {
			s.words = append(s.words, tword)
		}
	}
}

func (s IntSet) Show() {
	fmt.Printf("%v\n", s.words)
}

// IntersectWith computes the intersection of s and t.
// 这个不解释了=_=|
func (s *IntSet) IntersectWith(t *IntSet) {
	// 遍历s.words
	for i, word := range s.words {
		// 判断i是否越界
		if i >= len(t.words) {
			// 如果越界, 则将word置为0
			// 越界代表t中没有这个word, 与任何数都是0, 所以将s中的word置为0
			s.words[i] = 0
		} else {
			// 如果没有越界, 则将s.words[i]和t.words[i]进行与运算
			// 与运算的结果就是s和t的交集
			s.words[i] = word & t.words[i]
		}
	}
}

// DifferenceWith computes the difference of s and t.
// s集扣掉s与t的交集就是s与t的差集
func (s *IntSet) DifferenceWith(t *IntSet) {
	// 遍历s.words
	for i, word := range s.words {
		// 判断i是否越界
		if i >= len(t.words) {
			// 如果越界, 则跳过
			continue
		}
		// 如果没有越界, 则将s.words[i]和t.words[i]进行异或运算
		// 异或运算的结果就是s和t的差集
		s.words[i] = word ^ t.words[i]
	}
}

// SymmetricDifference computes the symmetric difference of s and t.
// s和t的并集扣掉他们的交集就是差并集(对称差集)
func (s *IntSet) SymmetricDifference(t *IntSet) {
	// 创建一个空的IntSet
	var u IntSet
	// 将s和t的并集赋值给u, 相当于u里面有s和t的所有元素
	u.UnionWith(s)
	u.UnionWith(t)
	// 将s和t的交集赋值给s, 相当于s中只有s和t中共同都有的元素了, 这也就是交集
	s.IntersectWith(t)
	// 将u和s的差集赋值给u, 相当于u扣掉了s和t的交集
	u.DifferenceWith(s)
	// 将u赋值给s
	*s = u
}

// String returns the set as a string of the form "{1 2 3}".
func (s *IntSet) String() string {
	var buf bytes.Buffer
	buf.WriteByte('{')
	for i, word := range s.words {
		if word == 0 {
			continue
		}
		for j := 0; j < PlatformCompatible; j++ {
			if word&(1<<uint(j)) != 0 {
				if buf.Len() > len("{") {
					buf.WriteByte(' ')
				}
				fmt.Fprintf(&buf, "%d", PlatformCompatible*i+j)
			}
		}
	}
	buf.WriteByte('}')
	return buf.String()
}

// Len returns the number of elements.
func (s *IntSet) Len() (l int) {
	//遍历s.words
	for _, word := range s.words {
		// 判断是否为空切片
		if word == 0 {
			// 为空则跳过
			continue
		}
		// 不为空则遍历word
		for j := 0; j < PlatformCompatible; j++ {
			// 判断word的第j位是否为1
			// 如果为1, 则代表这个位置存在数字
			if word&(1<<uint(j)) != 0 {
				// 为1则l++
				l++
			}
		}
	}
	// 返回l
	return l
}

// Remove removes x from the set.
func (s *IntSet) Remove(x int) {
	// 取得x的word和bit
	word, bit := x/PlatformCompatible, uint(x%PlatformCompatible)
	// 判断word是否越界
	if word < len(s.words) {
		// 如果没有越界, 则将word的第bit位置为0
		s.words[word] &= ^(1 << bit)
	}
}

// Clear removes all elements from the set.
func (s *IntSet) Clear() {
	// 将s.words置为nil
	s.words = nil
}

// Copy returns a copy of the set.
func (s *IntSet) Copy() *IntSet {
	// 创建一个新的IntSet
	var newIntSet IntSet
	// 将s.words赋值给new.words
	newIntSet.words = append(newIntSet.words, s.words...)
	// 返回newIntSet
	return &newIntSet
}
