Решение на Concurrent Retry Executor от Йончо Йончев

Обратно към всички решения

Към профила на Йончо Йончев

Резултати

  • 1 точка от тестове
  • 0 бонус точки
  • 1 точка общо
  • 1 успешни тест(а)
  • 7 неуспешни тест(а)

Код

package main
import (
//"fmt"
"reflect"
"strconv"
)
func OrderedLogDrainer(logs chan (chan string)) chan string {
numChans := len(logs)
var chans = []chan string{}
for i := 0; i < numChans; i++ {
ch := make(chan string)
chans = append(chans, ch)
}
cases := make([]reflect.SelectCase, len(chans))
for i, ch := range chans {
cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)}
}
result := make(chan string)
remaining := len(cases)
curr := 0
for remaining > 0 {
chosen, value, ok := reflect.Select(cases)
if !ok {
cases[chosen].Chan = reflect.ValueOf(nil)
remaining -= 1
curr += 1
continue
}
entry := strconv.Itoa(curr) + "\t" + value.String()
result <- entry
}
close(result)
return result
}

Лог от изпълнението

--- FAIL: TestWithOneMessage (0.50s)
	solution_test.go:27: Test exceeded allowed time of 500 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.503s
--- FAIL: TestWithExample1 (0.50s)
	solution_test.go:27: Test exceeded allowed time of 500 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.504s
--- FAIL: TestWithExample2 (0.50s)
	solution_test.go:27: Test exceeded allowed time of 500 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.504s
PASS
ok  	_/tmp/d20151110-19113-1q41hds	0.003s
--- FAIL: TestWithTwoEmptyLogs (0.50s)
	solution_test.go:27: Test exceeded allowed time of 500 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.504s
--- FAIL: TestWithDelays (0.90s)
	solution_test.go:185: Invalid first result '', expected '1	first'
	solution_test.go:27: Test exceeded allowed time of 900 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.903s
--- FAIL: TestTheLimits (0.50s)
	solution_test.go:27: Test exceeded allowed time of 500 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.503s
--- FAIL: TestWithManyLogs (0.80s)
	solution_test.go:27: Test exceeded allowed time of 800 milliseconds
FAIL
exit status 1
FAIL	_/tmp/d20151110-19113-1q41hds	0.803s

История (2 версии и 3 коментара)

Йончо обнови решението на 07.11.2015 22:52 (преди над 2 години)

+package main
+
+import (
+ "bytes"
+ "strconv"
+)
+
+func OrderedLogDrainer(logs chan (chan string)) chan string {
+ result := make(chan string)
+ go func() {
+ for entry := range logs {
+ for e := range entry {
+ var counter = 1
+ var buffer bytes.Buffer
+ buffer.WriteString(strconv.Itoa(counter))
+ buffer.WriteString("\t")
+ buffer.WriteString(e)
+ result <- buffer.String()
+ }
+ }
+ }()
+ return result
+}

Йончо обнови решението на 10.11.2015 10:59 (преди над 2 години)

package main
import (
- "bytes"
+ //"fmt"
+ "reflect"
"strconv"
)
func OrderedLogDrainer(logs chan (chan string)) chan string {
+ numChans := len(logs)
+ var chans = []chan string{}
+
+ for i := 0; i < numChans; i++ {
+ ch := make(chan string)
+ chans = append(chans, ch)
+ }
+
+ cases := make([]reflect.SelectCase, len(chans))
+ for i, ch := range chans {
+ cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)}
+ }
+
result := make(chan string)
- go func() {
- for entry := range logs {
- for e := range entry {
- var counter = 1
- var buffer bytes.Buffer
- buffer.WriteString(strconv.Itoa(counter))
- buffer.WriteString("\t")
- buffer.WriteString(e)
- result <- buffer.String()
- }
+
+ remaining := len(cases)
+ curr := 0
+ for remaining > 0 {
+ chosen, value, ok := reflect.Select(cases)
+ if !ok {
+ cases[chosen].Chan = reflect.ValueOf(nil)
+ remaining -= 1
+ curr += 1
+ continue
}
- }()
+ entry := strconv.Itoa(curr) + "\t" + value.String()
+ result <- entry
+ }
+ close(result)
return result
-}
+}

Благодаря, по принцип ми е ясно, че трябва да стане със select, за да се чете едновременно. За рефлекта, казват, че така е около 10 пъти по-бързо. Нямам идея, защо всички рутини заспиват.