<commit_before>package main

import (
	"fmt"
	"github.com/lzcqd/sedgewick/chap2_sorting/sortable"
	"reflect"
	"runtime"
	"sync"
	"time"
)

type floatslice []float64

func (a floatslice) Len() int           { return len(a) }
func (a floatslice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a floatslice) Less(i, j int) bool { return a[i] < a[j] }

func timesort(sort func(sortable.Interface), to_sort []floatslice, out chan string) {
	defer close(out)

	start := time.Now()
	for _, s := range to_sort {
		sort(s)
	}

	duration := time.Since(start)
	out <- fmt.Sprintf("%s completed in %v milliseconds", runtime.FuncForPC(reflect.ValueOf(sort).Pointer()).Name(), duration/time.Millisecond)
}

func merge(cs ...<-chan string) <-chan string {
	var wg sync.WaitGroup
	out := make(chan string)

	output := func(c <-chan string) {
		for n := range c {
			out <- n
		}
		wg.Done()
	}

	wg.Add(len(cs))
	for _, c := range cs {
		go output(c)
	}

	go func() {
		wg.Wait()
		close(out)
	}()

	return out
}

//func startsorts<commit_msg>Sort comparer: implement startsorts and manageOutput functions<commit_after>package main

import (
	"fmt"
	"github.com/lzcqd/sedgewick/chap2_sorting/sortable"
	"reflect"
	"runtime"
	"sync"
	"time"
)

type floatslice []float64

func (a floatslice) Len() int           { return len(a) }
func (a floatslice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a floatslice) Less(i, j int) bool { return a[i] < a[j] }

func timesort(sort func(sortable.Interface), to_sort []floatslice, out chan string) {
	defer close(out)

	start := time.Now()
	for _, s := range to_sort {
		sort(s)
	}

	duration := time.Since(start)
	out <- fmt.Sprintf("%s completed in %v milliseconds", runtime.FuncForPC(reflect.ValueOf(sort).Pointer()).Name(), duration/time.Millisecond)
}

func merge(cs ...chan string) <-chan string {
	var wg sync.WaitGroup
	out := make(chan string)

	output := func(c <-chan string) {
		for n := range c {
			out <- n
		}
		wg.Done()
	}

	wg.Add(len(cs))
	for _, c := range cs {
		go output(c)
	}

	go func() {
		wg.Wait()
		close(out)
	}()

	return out
}

func startsorts(sorts []func(sortable.Interface), to_sort []floatslice, timeout int) {
	outs := make([]chan string, len(sorts))
	for i := range outs {
		outs[i] = make(chan string)
	}

	out := merge(outs...)
	done := make(chan bool)
	go manageOutput(out, timeout, done)

	for i, s := range sorts {
		go timesort(s, to_sort, outs[i])
	}

	<-done
}

func manageOutput(out <-chan string, timeout int, done chan bool) {
	defer func() {
		done <- true
	}()

	quit := time.Tick(time.Duration(timeout) * time.Second)

	for {
		select {
		case s, ok := <-out:
			fmt.Println(s)
			if !ok {
				break
			}
		case <-quit:
			break
		}
	}
}
{'fraction_non_alphanumeric': 0.16538320498716538, 'fraction_numerical': 0.0022002200220022, 'mean_word_length': 3.378812199036918, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1754406', 'n_tokens_mistral': 1151, 'n_tokens_neox': 1054, 'n_words': 277}