// Sorting algorithms. May also contain deduplication operations. package sort import ( "fmt" ) // Mergesorts and deduplicates the list. func SortedAndDedup(timeout <-chan bool, list []int) (res []int, err error) { sorted, err := Mergesort(timeout, list) if err != nil { return nil, err } deduped := dedupSortedList(sorted) return deduped, nil } // Deduplicate the sorted list and return a new one with a potentially different // size. func dedupSortedList(list []int) []int { newList := []int{} if len(list) <= 1 { return list } var prev int = list[0] newList = append(newList, list[0]) for i := 1; i < len(list); i++ { if prev != list[i] { newList = append(newList, list[i]) } prev = list[i] } return newList } // Mergesorts the given list and returns it as a result. The input list // is not modified. // The algorithm is a bottom-up iterative version and not explained // in detail here. func Mergesort(timeout <-chan bool, list []int) (res []int, err error) { newList := append([]int{}, list...) temp := append([]int{}, list...) n := len(newList) for m := 1; m < (n - 1); m = 2 * m { for i := 0; i < (n - 1); i += 2 * m { select { case <-timeout: return nil, fmt.Errorf("Sorting timed out") default: } from := i mid := i + m - 1 to := min(i+2*m-1, n-1) merge(timeout, newList, temp, from, mid, to) } } return newList, nil } // The merge part of the mergesort. func merge(timeout <-chan bool, list []int, temp []int, from int, mid int, to int) { k := from i := from j := mid + 1 for i <= mid && j <= to { if list[i] < list[j] { temp[k] = list[i] i++ } else { temp[k] = list[j] j++ } k++ } for i <= mid && i < len(temp) { temp[k] = list[i] i++ k++ } for i := from; i <= to; i++ { list[i] = temp[i] } } // Get the minimum of two integers. func min(l int, r int) int { if l < r { return l } else { return r } }