Created
February 26, 2020 17:11
-
-
Save tcolgate/107e1c59e9f43cd6be843e64831fa5c3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"math/rand" | |
"sort" | |
"time" | |
) | |
type intslice struct { | |
vals []int | |
i int | |
curr int | |
} | |
func newslice() *intslice { | |
size := 2 + rand.Intn(10) | |
sl := make([]int, size) | |
for i := range sl { | |
sl[i] = 1 + rand.Intn(10_000_000) | |
} | |
sort.Ints(sl) | |
return &intslice{ | |
vals: sl, | |
} | |
} | |
func (intslice) Err() error { | |
return nil | |
} | |
func (intslice) Close() error { | |
return nil | |
} | |
func (sl *intslice) Value() int { | |
return sl.curr | |
} | |
func (sl *intslice) Next() bool { | |
if sl.i >= len(sl.vals) { | |
return false | |
} | |
sl.curr = sl.vals[sl.i] | |
sl.i++ | |
return true | |
} | |
type iterator interface { | |
Next() bool | |
Value() int | |
Err() error | |
Close() error | |
} | |
type mergeSortIterator struct { | |
is []iterator | |
curVals []int | |
next int | |
lastUsed int | |
} | |
func mergeSort(is []iterator) *mergeSortIterator { | |
return &mergeSortIterator{ | |
is: is, | |
lastUsed: -1, | |
} | |
} | |
func (ms *mergeSortIterator) Next() bool { | |
for i := range ms.is { | |
log.Printf("is[%d]: %v", i, ms.is[i]) | |
} | |
if len(ms.is) == 0 { | |
return false | |
} | |
if ms.curVals == nil { | |
ms.curVals = make([]int, len(ms.is)) | |
} | |
smallest := -1 | |
smallestn := -1 | |
n := 0 | |
for i, it := range ms.is { | |
if !it.Next() { | |
it.Close() | |
continue | |
} | |
ms.is[n] = it | |
if ms.lastUsed == -1 || i == ms.lastUsed { | |
ms.curVals[n] = it.Value() | |
} | |
if smallest == -1 || ms.curVals[n] < smallest { | |
smallest = ms.curVals[n] | |
smallestn = n | |
} | |
n++ | |
} | |
log.Printf("smallest: %d n: %d", smallest, smallestn) | |
if n == 0 { | |
return false | |
} | |
ms.is = ms.is[:n] | |
ms.curVals = ms.curVals[:n] | |
ms.next = smallest | |
ms.lastUsed = smallestn | |
return true | |
} | |
func (ms *mergeSortIterator) Value() int { | |
return ms.next | |
} | |
func (ms *mergeSortIterator) Err() error { | |
return nil | |
} | |
func (ms *mergeSortIterator) Close() error { | |
return nil | |
} | |
func main() { | |
rand.Seed(time.Now().UnixNano()) | |
sls := make([]iterator, rand.Intn(10)) | |
for i := range sls { | |
sls[i] = newslice() | |
} | |
mit := mergeSort(sls) | |
for mit.Next() { | |
fmt.Printf("v: %v\n", mit.Value()) | |
} | |
if err := mit.Err(); err != nil { | |
log.Printf("err: %v", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I need to merge a series of streams of data. The streams are naturally orderered (it's actually log data)., but must finally be presented to the user in order. This is an initial "correct" implementation. The final approach needs to be non-blocking when iterating over to backfill values.