Решение на Concurrent Tasks от Стоил Янчев

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

Към профила на Стоил Янчев

Резултати

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

Код

package main
import (
"errors"
"time"
)
// type adder struct {
// augend int
// }
// func (a adder) Execute(addend int) (int, error) {
// result := a.augend + addend
// if result > 127 {
// return 0, fmt.Errorf("Result %d exceeds the adder threshold", a)
// }
// return result, nil
// }
type Task interface {
Execute(int) (int, error)
}
type PipelineTask struct {
pipelineTasks []Task
}
func (tmp PipelineTask) Execute(addent int) (int, error) {
if len(tmp.pipelineTasks) == 0 {
return 0, errors.New("Not active pipeline tasks")
} else {
// iterate over pipelineTasks and Execute them
iter := addent
for _, pipelineTask := range tmp.pipelineTasks {
if value, err := pipelineTask.Execute(iter); err != nil {
return 0, err
} else {
iter = value
}
}
return iter, nil
}
}
func Pipeline(tasks ...Task) Task {
return PipelineTask{tasks}
}
// type lazyAdder struct {
// adder
// delay time.Duration
// }
// func (la lazyAdder) Execute(addend int) (int, error) {
// time.Sleep(la.delay * time.Millisecond)
// return la.adder.Execute(addend)
// }
type FastTask struct {
fastTasks []Task
}
func (tmp FastTask) Execute(addent int) (int, error) {
if len(tmp.fastTasks) == 0 {
return 0, errors.New("Not active tasks")
} else {
var res int
var err error
return res, err
}
}
func Fastest(tasks ...Task) Task {
return FastTask{tasks}
}
type TimedTask struct {
task Task
timeout time.Duration
}
type TimedResult struct {
res int
err error
}
func (tmp TimedTask) Execute(addent int) (int, error) {
ch := make(chan TimedResult)
go func() {
helper, err := tmp.task.Execute(addent)
ch <- TimedResult{helper, err}
}()
select {
case v1 := <-ch:
return v1.res, v1.err
case <-time.After(tmp.timeout):
return 0, errors.New("The task returned an error.")
}
}
func Timed(task Task, timeout time.Duration) Task {
return TimedTask{task, timeout}
}
type ConcurrentMapReduceTask struct {
reduce func([]int) int
tasks []Task
}
func (tmp ConcurrentMapReduceTask) Execute(addent int) (int, error) {
if len(tmp.tasks) == 0 {
return 0, errors.New("Not active tasks")
} else {
var res []int
return tmp.reduce(res), nil
}
}
func ConcurrentMapReduce(reduce func(results []int) int, tasks ...Task) Task {
return ConcurrentMapReduceTask{reduce, tasks}
}
type GreatestSearcherTask struct {
errorLimit int
tasks <-chan Task
}
func (tmp GreatestSearcherTask) Execute(addent int) (int, error) {
return addent, nil
}
func GreatestSearcher(errorLimit int, tasks <-chan Task) Task {
return GreatestSearcherTask{errorLimit, tasks}
}
// func main() {
// if res, err := Pipeline(adder{50}, adder{60}).Execute(10); err != nil {
// fmt.Printf("The pipeline returned an error\n")
// } else {
// fmt.Printf("The pipeline returned %d\n", res)
// }
// if res1, err := Pipeline(adder{20}, adder{10}, adder{-50}).Execute(100); err != nil {
// fmt.Printf("The pipeline returned an error\n")
// } else {
// fmt.Printf("The pipeline returned %d\n", res1)
// }
// f := Fastest(
// lazyAdder{adder{20}, 500},
// lazyAdder{adder{50}, 300},
// adder{41},
// )
// if result, err := f.Execute(1); err != nil {
// t.Errorf("Received an unexpected error %s", err)
// } else if result != 42 {
// t.Errorf("Expected to receive 42 but received %d", result)
// }
// }

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

PASS
ok  	_/tmp/d20161129-30451-te1o29	0.003s
PASS
ok  	_/tmp/d20161129-30451-te1o29	0.003s
--- FAIL: TestFastestErrors (0.00s)
	solution_test.go:81: Expected error did not occur instead got 0
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.003s
--- FAIL: TestFastestSimple (0.10s)
	solution_test.go:94: Expected to receive 42 but received 0
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.103s
--- FAIL: TestFastestWaitsForGoroutines (0.20s)
	solution_test.go:154: Expected to receive 1 but received 0
	solution_test.go:134: Expected that there will be atleast 1 more goroutines than at the start(3) after one of two fastest task finishes but got 3
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.204s
PASS
ok  	_/tmp/d20161129-30451-te1o29	0.134s
--- FAIL: TestTimedDoesntLeaveGoroutineHanging (0.20s)
	solution_test.go:216: Expected that there will be as many goroutines as at the start(3) after Timed task has finished after it has timeouted but got 4
		
		BEFORE:
		goroutine profile: total 2
		1 @ 0x42a8aa 0x42a99e 0x40464f 0x404365 0x46c406 0x46f47d 0x46c0a1 0x46d115 0x46c735 0x401276 0x42a444 0x459f01
		#	0x46c405	testing.(*T).Run+0x315		/usr/local/go/src/testing/testing.go:647
		#	0x46f47c	testing.RunTests.func1+0x6c	/usr/local/go/src/testing/testing.go:793
		#	0x46c0a0	testing.tRunner+0x80		/usr/local/go/src/testing/testing.go:610
		#	0x46d114	testing.RunTests+0x2f4		/usr/local/go/src/testing/testing.go:799
		#	0x46c734	testing.(*M).Run+0x84		/usr/local/go/src/testing/testing.go:743
		#	0x401275	main.main+0xc5			_/tmp/d20161129-30451-te1o29/_test/_testmain.go:78
		#	0x42a443	runtime.main+0x1f3		/usr/local/go/src/runtime/proc.go:183
		
		1 @ 0x4c202f 0x4c1e30 0x4beae1 0x472e46 0x46c0a1 0x459f01
		#	0x4c202e	runtime/pprof.writeRuntimeProfile+0x9e					/usr/local/go/src/runtime/pprof/pprof.go:614
		#	0x4c1e2f	runtime/pprof.writeGoroutine+0x9f					/usr/local/go/src/runtime/pprof/pprof.go:576
		#	0x4beae0	runtime/pprof.(*Profile).WriteTo+0x340					/usr/local/go/src/runtime/pprof/pprof.go:298
		#	0x472e45	_/tmp/d20161129-30451-te1o29.TestTimedDoesntLeaveGoroutineHanging+0x175	/tmp/d20161129-30451-te1o29/solution_test.go:191
		#	0x46c0a0	testing.tRunner+0x80							/usr/local/go/src/testing/testing.go:610
		
		
		
		AFTER:
		goroutine profile: total 4
		1 @ 0x42a8aa 0x42a99e 0x4039a8 0x40376d 0x474cf3 0x459f01
		#	0x474cf2	_/tmp/d20161129-30451-te1o29.TimedTask.Execute.func1+0x92	/tmp/d20161129-30451-te1o29/solution.go:92
		
		1 @ 0x42a8aa 0x42a99e 0x40464f 0x404365 0x46c406 0x46f47d 0x46c0a1 0x46d115 0x46c735 0x401276 0x42a444 0x459f01
		#	0x46c405	testing.(*T).Run+0x315		/usr/local/go/src/testing/testing.go:647
		#	0x46f47c	testing.RunTests.func1+0x6c	/usr/local/go/src/testing/testing.go:793
		#	0x46c0a0	testing.tRunner+0x80		/usr/local/go/src/testing/testing.go:610
		#	0x46d114	testing.RunTests+0x2f4		/usr/local/go/src/testing/testing.go:799
		#	0x46c734	testing.(*M).Run+0x84		/usr/local/go/src/testing/testing.go:743
		#	0x401275	main.main+0xc5			_/tmp/d20161129-30451-te1o29/_test/_testmain.go:78
		#	0x42a443	runtime.main+0x1f3		/usr/local/go/src/runtime/proc.go:183
		
		1 @ 0x42a8aa 0x42a99e 0x40464f 0x404365 0x472fdf 0x46c0a1 0x459f01
		#	0x472fde	_/tmp/d20161129-30451-te1o29.TestTimedDoesntLeaveGoroutineHanging+0x30e	/tmp/d20161129-30451-te1o29/solution_test.go:225
		#	0x46c0a0	testing.tRunner+0x80							/usr/local/go/src/testing/testing.go:610
		
		1 @ 0x4c202f 0x4c1e30 0x4beae1 0x475641 0x459f01
		#	0x4c202e	runtime/pprof.writeRuntimeProfile+0x9e						/usr/local/go/src/runtime/pprof/pprof.go:614
		#	0x4c1e2f	runtime/pprof.writeGoroutine+0x9f						/usr/local/go/src/runtime/pprof/pprof.go:576
		#	0x4beae0	runtime/pprof.(*Profile).WriteTo+0x340						/usr/local/go/src/runtime/pprof/pprof.go:298
		#	0x475640	_/tmp/d20161129-30451-te1o29.TestTimedDoesntLeaveGoroutineHanging.func2+0x1a0	/tmp/d20161129-30451-te1o29/solution_test.go:212
		
		
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.203s
--- FAIL: TestConcurrentMapReduceFails (0.00s)
	solution_test.go:244: Expected error did not occur instead got 128
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.003s
--- FAIL: TestConcurrentMapReduceSimple (0.00s)
	solution_test.go:253: Expected result to be 55 but is 128
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.003s
--- FAIL: TestGreatestSearcherSimple (0.00s)
	solution_test.go:289: Received result 1 when expecting 2
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.003s
--- FAIL: TestGreatestSearcherComplex (0.00s)
	solution_test.go:302: Received result 10 when expecting 42
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.003s
--- FAIL: TestGreatestSearcherErrors (0.00s)
    --- FAIL: TestGreatestSearcherErrors/like_the_example (0.00s)
    	solution_test.go:313: Expected error did not occur instead got 10
    --- FAIL: TestGreatestSearcherErrors/close_immediately (0.00s)
    	solution_test.go:322: Expected error did not occur instead got 10
    --- FAIL: TestGreatestSearcherErrors/only_failure (0.00s)
    	solution_test.go:335: Expected error did not occur instead got 10
FAIL
exit status 1
FAIL	_/tmp/d20161129-30451-te1o29	0.003s
panic: runtime error: index out of range

goroutine 8 [running]:
panic(0x4fb7c0, 0xc4200100f0)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
_/tmp/d20161129-30451-te1o29.TestThemAll.func2(0x0, 0x0, 0x0, 0x44f410)
	/tmp/d20161129-30451-te1o29/solution_test.go:352 +0x76
_/tmp/d20161129-30451-te1o29.ConcurrentMapReduceTask.Execute(0x52ab20, 0xc420016780, 0x4, 0x4, 0x28, 0x1, 0x474cf3, 0x1)
	/tmp/d20161129-30451-te1o29/solution.go:118 +0xc5
_/tmp/d20161129-30451-te1o29.(*ConcurrentMapReduceTask).Execute(0xc42000e420, 0x28, 0xc420026770, 0x0, 0x0)
	<autogenerated>:5 +0x77
_/tmp/d20161129-30451-te1o29.TimedTask.Execute.func1(0x597580, 0xc42000e420, 0xbebc200, 0x28, 0xc4200543c0)
	/tmp/d20161129-30451-te1o29/solution.go:91 +0x3f
created by _/tmp/d20161129-30451-te1o29.TimedTask.Execute
	/tmp/d20161129-30451-te1o29/solution.go:93 +0xa3
exit status 2
FAIL	_/tmp/d20161129-30451-te1o29	0.025s

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

Стоил обнови решението на 29.11.2016 14:26 (преди над 1 година)

+package main
+
+import (
+ //"fmt"
+ "errors"
+)
+
+type Task interface {
+ Execute(int) (int, error)
+}
+
+type PipelineTask struct {
+ pipelineTasks []Task
+}
+
+func (tmp PipelineTask) Execute(addent int) (int, error) {
+ if len(tmp.pipelineTasks) == 0 {
+ return 0, errors.New("Not active pipeline tasks")
+ } else {
+ // iterate over pipelineTasks and Execute them
+ iter := addent
+ for _, pipelineTask := range tmp.pipelineTasks {
+ if value, err := pipelineTask.Execute(iter); err != nil {
+ return 0, err
+ } else {
+ iter = value
+ }
+ }
+ return iter, nil
+ }
+}
+
+func Pipeline(tasks ...Task) Task {
+ return PipelineTask{tasks}
+}
+
+// type adder struct {
+// augend int
+// }
+
+// func (a adder) Execute(addend int) (int, error) {
+// result := a.augend + addend
+// if result > 127 {
+// return 0, fmt.Errorf("Result %d exceeds the adder threshold", a)
+// }
+// return result, nil
+// }
+
+// func main() {
+// if res, err := Pipeline(adder{50}, adder{60}).Execute(10); err != nil {
+// fmt.Printf("The pipeline returned an error\n")
+// } else {
+// fmt.Printf("The pipeline returned %d\n", res)
+// }
+
+// if res1, err := Pipeline(adder{20}, adder{10}, adder{-50}).Execute(100); err != nil {
+// fmt.Printf("The pipeline returned an error\n")
+// } else {
+// fmt.Printf("The pipeline returned %d\n", res1)
+// }
+// }

Стоил обнови решението на 29.11.2016 16:19 (преди над 1 година)

package main
import (
- //"fmt"
"errors"
+ "time"
)
+// type adder struct {
+// augend int
+// }
+
+// func (a adder) Execute(addend int) (int, error) {
+// result := a.augend + addend
+// if result > 127 {
+// return 0, fmt.Errorf("Result %d exceeds the adder threshold", a)
+// }
+// return result, nil
+// }
+
type Task interface {
Execute(int) (int, error)
}
type PipelineTask struct {
pipelineTasks []Task
}
func (tmp PipelineTask) Execute(addent int) (int, error) {
if len(tmp.pipelineTasks) == 0 {
return 0, errors.New("Not active pipeline tasks")
} else {
// iterate over pipelineTasks and Execute them
iter := addent
for _, pipelineTask := range tmp.pipelineTasks {
if value, err := pipelineTask.Execute(iter); err != nil {
return 0, err
} else {
iter = value
}
}
return iter, nil
}
}
func Pipeline(tasks ...Task) Task {
return PipelineTask{tasks}
}
-// type adder struct {
-// augend int
+// type lazyAdder struct {
+// adder
+// delay time.Duration
// }
-// func (a adder) Execute(addend int) (int, error) {
-// result := a.augend + addend
-// if result > 127 {
-// return 0, fmt.Errorf("Result %d exceeds the adder threshold", a)
-// }
-// return result, nil
+// func (la lazyAdder) Execute(addend int) (int, error) {
+// time.Sleep(la.delay * time.Millisecond)
+// return la.adder.Execute(addend)
// }
+type FastTask struct {
+ fastTasks []Task
+}
+
+func (tmp FastTask) Execute(addent int) (int, error) {
+ if len(tmp.fastTasks) == 0 {
+ return 0, errors.New("Not active tasks")
+ } else {
+ var res int
+ var err error
+ return res, err
+ }
+}
+
+func Fastest(tasks ...Task) Task {
+ return FastTask{tasks}
+}
+
+type TimedTask struct {
+ task Task
+ timeout time.Duration
+}
+
+type TimedResult struct {
+ res int
+ err error
+}
+
+func (tmp TimedTask) Execute(addent int) (int, error) {
+ ch := make(chan TimedResult)
+
+ go func() {
+ helper, err := tmp.task.Execute(addent)
+ ch <- TimedResult{helper, err}
+ }()
+
+ select {
+ case v1 := <-ch:
+ return v1.res, v1.err
+ case <-time.After(tmp.timeout):
+ return 0, errors.New("The task returned an error.")
+ }
+}
+
+func Timed(task Task, timeout time.Duration) Task {
+ return TimedTask{task, timeout}
+}
+
+
+type ConcurrentMapReduceTask struct {
+ reduce func([]int) int
+ tasks []Task
+}
+
+func (tmp ConcurrentMapReduceTask) Execute(addent int) (int, error) {
+ if len(tmp.tasks) == 0 {
+ return 0, errors.New("Not active tasks")
+ } else {
+ var res []int
+ return tmp.reduce(res), nil
+ }
+}
+
+func ConcurrentMapReduce(reduce func(results []int) int, tasks ...Task) Task {
+ return ConcurrentMapReduceTask{reduce, tasks}
+}
+
+type GreatestSearcherTask struct {
+ errorLimit int
+ tasks <-chan Task
+}
+
+func (tmp GreatestSearcherTask) Execute(addent int) (int, error) {
+ return addent, nil
+}
+
+func GreatestSearcher(errorLimit int, tasks <-chan Task) Task {
+ return GreatestSearcherTask{errorLimit, tasks}
+}
+
// func main() {
// if res, err := Pipeline(adder{50}, adder{60}).Execute(10); err != nil {
// fmt.Printf("The pipeline returned an error\n")
// } else {
// fmt.Printf("The pipeline returned %d\n", res)
// }
// if res1, err := Pipeline(adder{20}, adder{10}, adder{-50}).Execute(100); err != nil {
// fmt.Printf("The pipeline returned an error\n")
// } else {
// fmt.Printf("The pipeline returned %d\n", res1)
// }
-// }
+
+ // f := Fastest(
+ // lazyAdder{adder{20}, 500},
+ // lazyAdder{adder{50}, 300},
+ // adder{41},
+ // )
+ // if result, err := f.Execute(1); err != nil {
+ // t.Errorf("Received an unexpected error %s", err)
+ // } else if result != 42 {
+ // t.Errorf("Expected to receive 42 but received %d", result)
+ // }
+// }