From 41d2b3268929aeda8c100ffa63acaeecc20a6d6e Mon Sep 17 00:00:00 2001 From: Kistaro Windrider Date: Sat, 9 Mar 2024 22:23:43 -0800 Subject: [PATCH] protype shuffling version -- unreachable --- manualsort.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/manualsort.go b/manualsort.go index 28f7f63..c750a7a 100644 --- a/manualsort.go +++ b/manualsort.go @@ -6,15 +6,18 @@ import ( "bufio" "fmt" "log" + "math/rand" "os" "slices" "strings" + "sync" + "time" ) // handwritten merge sort because it minimizes comparisons, which are // the expensive part when asking a human for every comparison. // quicksort's "in-place" behavior isn't necessary. -func merge(a, b []string) []string { +func merge(a, b []string, less func(string, string) bool) []string { if len(a) == 0 { return b } @@ -23,7 +26,7 @@ func merge(a, b []string) []string { } ret := make([]string, 0, len(a)+len(b)) for len(a) > 0 && len(b) > 0 { - if better(a[0], b[0]) { + if less(a[0], b[0]) { ret = append(ret, a[0]) a = a[1:] } else { @@ -50,6 +53,48 @@ var ( } ) +type Question struct { + First string + Second string + Reply chan<- bool +} + +func (q *Question) Ask() { + q.Reply <- better(q.First, q.Second) +} + +func (q *Question) Push(qc chan<- *Question) bool { + c := make(chan bool, 1) + q.Reply = c + qc <- q + return <-c +} + +func betterLoop(qq <-chan *Question) { + var pool []*Question + drain := time.After(100 * time.Millisecond) + for { + select { + case q, ok := <-qq: + if !ok { + qq = nil + continue + } + pool = append(pool, q) + case <-drain: + rand.Shuffle(len(pool), func(i, j int) { pool[i], pool[j] = pool[j], pool[i] }) + for _, q := range pool { + q.Ask() + } + pool = pool[:0] + if qq == nil { + return + } + drain = time.After(100 * time.Millisecond) + } + } +} + func better(first, second string) bool { for { fmt.Println() @@ -74,12 +119,42 @@ func better(first, second string) bool { } } +func parallelBetter(first, second string, qq chan<- *Question) bool { + q := Question{ + First: first, + Second: second, + } + return q.Push(qq) +} + func mergeSort(items []string) []string { if len(items) <= 1 { return items } midpoint := len(items) / 2 - return merge(mergeSort(items[:midpoint]), mergeSort(items[midpoint:])) + return merge(mergeSort(items[:midpoint]), mergeSort(items[midpoint:]), better) +} + +func parallelMergeSort(questions chan<- *Question, items []string) []string { + if len(items) <= 1 { + return items + } + midpoint := len(items) / 2 + var wg sync.WaitGroup + wg.Add(2) + var r1, r2 []string + go func() { + r1 = parallelMergeSort(questions, items[:midpoint]) + wg.Done() + }() + go func() { + r2 = parallelMergeSort(questions, (items[midpoint:])) + wg.Done() + }() + wg.Wait() + return merge(r1, r2, func(a, b string) bool { + return parallelBetter(a, b, questions) + }) } func main() { @@ -107,6 +182,9 @@ func main() { log.Fatalf("can't read %q: %v", os.Args[1], err) } + rand.Shuffle(len(items), func(i, j int) { + items[i], items[j] = items[j], items[i] + }) sorted := mergeSort(items) fmt.Println("Sorted. Saving...") obuf := bufio.NewWriter(ofile)