func Squeeze(str, pattern string) string {
	var last, r rune
	var size int
	var skipSqueeze, matched bool
	var tr *Translator
	var output *bytes.Buffer
	orig := str
	last = -1
	if len(pattern) > 0 {
		tr = NewTranslator(pattern, "")
	}
	for len(str) > 0 {
		r, size = utf8.DecodeRuneInString(str)
		if last == r && !skipSqueeze {
			if tr != nil {
				if _, matched = tr.TranslateRune(r); !matched {
					skipSqueeze = true
				}
			}
			if output == nil {
				output = allocBuffer(orig, str)
			}
			if skipSqueeze {
				output.WriteRune(r)
			}
		} else {
			if output != nil {
				output.WriteRune(r)
			}
			last = r
			skipSqueeze = false
		}
		str = str[size:]
	}
	if output == nil {
		return orig
	}
	return output.String()
}
Squeeze deletes adjacent repeated runes in str.
If pattern is not empty, only runes matching the pattern will be squeezed.

Samples:
Squeeze("hello", "")             => "helo"
Squeeze("hello", "m-z")          => "hello"
Squeeze("hello   world", " ")    => "hello world"
package xstrings
import (
	"bytes"
	"unicode"
	"unicode/utf8"
)
type runeRangeMap struct {
	FromLo rune  
	FromHi rune  
	ToLo   rune
	ToHi   rune
}
type runeDict struct {
	Dict [unicode.MaxASCII + 1]rune
}
type runeMap map[rune]rune
type Translator struct {
	quickDict  *runeDict        
	runeMap    runeMap          
	ranges     []*runeRangeMap  
	mappedRune rune             
	reverted   bool             
	hasPattern bool
}
func NewTranslator(from, to string) *Translator {
	tr := &Translator{}
	if from == "" {
		return tr
	}
	reverted := from[0] == '^'
	deletion := len(to) == 0
	if reverted {
		from = from[1:]
	}
	var fromStart, fromEnd, fromRangeStep rune
	var toStart, toEnd, toRangeStep rune
	var fromRangeSize, toRangeSize rune
	var singleRunes []rune
	updateRange := func() {
		if toEnd == utf8.RuneError {
			return
		}
		if toRangeStep == 0 {
			to, toStart, toEnd, toRangeStep = nextRuneRange(to, toEnd)
			return
		}
		if toStart != toEnd {
			toStart += toRangeStep
			return
		}
		if to == "" {
			toEnd = utf8.RuneError
			return
		}
		to, toStart, toEnd, toRangeStep = nextRuneRange(to, utf8.RuneError)
	}
	if deletion {
		toStart = utf8.RuneError
		toEnd = utf8.RuneError
	} else {
		if reverted {
			var size int
			for len(to) > 0 {
				toStart, size = utf8.DecodeRuneInString(to)
				to = to[size:]
			}
			toEnd = utf8.RuneError
		} else {
			to, toStart, toEnd, toRangeStep = nextRuneRange(to, utf8.RuneError)
		}
	}
	fromEnd = utf8.RuneError
	for len(from) > 0 {
		from, fromStart, fromEnd, fromRangeStep = nextRuneRange(from, fromEnd)
		if fromRangeStep == 0 {
			singleRunes = tr.addRune(fromStart, toStart, singleRunes)
			updateRange()
			continue
		}
		for toEnd != utf8.RuneError && fromStart != fromEnd {
			if toRangeStep == 0 {
				singleRunes = tr.addRune(fromStart, toStart, singleRunes)
				updateRange()
				fromStart += fromRangeStep
				continue
			}
			fromRangeSize = (fromEnd - fromStart) * fromRangeStep
			toRangeSize = (toEnd - toStart) * toRangeStep
			if fromRangeSize > toRangeSize {
				fromStart, toStart = tr.addRuneRange(fromStart, fromStart+toRangeSize*fromRangeStep, toStart, toEnd, singleRunes)
				fromStart += fromRangeStep
				updateRange()
				if fromStart == fromEnd {
					singleRunes = tr.addRune(fromStart, toStart, singleRunes)
					updateRange()
				}
				continue
			}
			fromStart, toStart = tr.addRuneRange(fromStart, fromEnd, toStart, toStart+fromRangeSize*toRangeStep, singleRunes)
			updateRange()
			break
		}
		if fromStart == fromEnd {
			fromEnd = utf8.RuneError
			continue
		}
		fromStart, toStart = tr.addRuneRange(fromStart, fromEnd, toStart, toStart, singleRunes)
		fromEnd = utf8.RuneError
	}
	if fromEnd != utf8.RuneError {
		singleRunes = tr.addRune(fromEnd, toStart, singleRunes)
	}
	tr.reverted = reverted
	tr.mappedRune = -1
	tr.hasPattern = true
	if deletion || reverted {
		tr.mappedRune = toStart
	}
	return tr
}
func (tr *Translator) addRune(from, to rune, singleRunes []rune) []rune {
	if from <= unicode.MaxASCII {
		if tr.quickDict == nil {
			tr.quickDict = &runeDict{}
		}
		tr.quickDict.Dict[from] = to
	} else {
		if tr.runeMap == nil {
			tr.runeMap = make(runeMap)
		}
		tr.runeMap[from] = to
	}
	singleRunes = append(singleRunes, from)
	return singleRunes
}
func (tr *Translator) addRuneRange(fromLo, fromHi, toLo, toHi rune, singleRunes []rune) (rune, rune) {
	var r rune
	var rrm *runeRangeMap
	if fromLo < fromHi {
		rrm = &runeRangeMap{
			FromLo: fromLo,
			FromHi: fromHi,
			ToLo:   toLo,
			ToHi:   toHi,
		}
	} else {
		rrm = &runeRangeMap{
			FromLo: fromHi,
			FromHi: fromLo,
			ToLo:   toHi,
			ToHi:   toLo,
		}
	}
	for _, r = range singleRunes {
		if rrm.FromLo <= r && r <= rrm.FromHi {
			if r <= unicode.MaxASCII {
				tr.quickDict.Dict[r] = 0
			} else {
				delete(tr.runeMap, r)
			}
		}
	}
	tr.ranges = append(tr.ranges, rrm)
	return fromHi, toHi
}
func nextRuneRange(str string, last rune) (remaining string, start, end rune, rangeStep rune) {
	var r rune
	var size int
	remaining = str
	escaping := false
	isRange := false
	for len(remaining) > 0 {
		r, size = utf8.DecodeRuneInString(remaining)
		remaining = remaining[size:]
		if !escaping {
			if r == '\\' {
				escaping = true
				continue
			}
			if r == '-' {
				if last == utf8.RuneError {
					continue
				}
				start = last
				isRange = true
				continue
			}
		}
		escaping = false
		if last != utf8.RuneError {
			if isRange && last == r {
				isRange = false
				continue
			}
			start = last
			end = r
			if isRange {
				if start < end {
					rangeStep = 1
				} else {
					rangeStep = -1
				}
			}
			return
		}
		last = r
	}
	start = last
	end = utf8.RuneError
	return
}
func (tr *Translator) Translate(str string) string {
	if !tr.hasPattern || str == "" {
		return str
	}
	var r rune
	var size int
	var needTr bool
	orig := str
	var output *bytes.Buffer
	for len(str) > 0 {
		r, size = utf8.DecodeRuneInString(str)
		r, needTr = tr.TranslateRune(r)
		if needTr && output == nil {
			output = allocBuffer(orig, str)
		}
		if r != utf8.RuneError && output != nil {
			output.WriteRune(r)
		}
		str = str[size:]
	}
	if output == nil {
		return orig
	}
	return output.String()
}
func (tr *Translator) TranslateRune(r rune) (result rune, translated bool) {
	switch {
	case tr.quickDict != nil:
		if r <= unicode.MaxASCII {
			result = tr.quickDict.Dict[r]
			if result != 0 {
				translated = true
				if tr.mappedRune >= 0 {
					result = tr.mappedRune
				}
				break
			}
		}
		fallthrough
	case tr.runeMap != nil:
		var ok bool
		if result, ok = tr.runeMap[r]; ok {
			translated = true
			if tr.mappedRune >= 0 {
				result = tr.mappedRune
			}
			break
		}
		fallthrough
	default:
		var rrm *runeRangeMap
		ranges := tr.ranges
		for i := len(ranges) - 1; i >= 0; i-- {
			rrm = ranges[i]
			if rrm.FromLo <= r && r <= rrm.FromHi {
				translated = true
				if tr.mappedRune >= 0 {
					result = tr.mappedRune
					break
				}
				if rrm.ToLo < rrm.ToHi {
					result = rrm.ToLo + r - rrm.FromLo
				} else if rrm.ToLo > rrm.ToHi {
					result = rrm.ToLo - r + rrm.FromLo
				} else {
					result = rrm.ToLo
				}
				break
			}
		}
	}
	if tr.reverted {
		if !translated {
			result = tr.mappedRune
		}
		translated = !translated
	}
	if !translated {
		result = r
	}
	return
}
func (tr *Translator) HasPattern() bool {
	return tr.hasPattern
}
func Translate(str, from, to string) string {
	tr := NewTranslator(from, to)
	return tr.Translate(str)
}
func Delete(str, pattern string) string {
	tr := NewTranslator(pattern, "")
	return tr.Translate(str)
}
func Count(str, pattern string) int {
	if pattern == "" || str == "" {
		return 0
	}
	var r rune
	var size int
	var matched bool
	tr := NewTranslator(pattern, "")
	cnt := 0
	for len(str) > 0 {
		r, size = utf8.DecodeRuneInString(str)
		str = str[size:]
		if _, matched = tr.TranslateRune(r); matched {
			cnt++
		}
	}
	return cnt
}