Skip to content

Instantly share code, notes, and snippets.

@Vostbur
Created December 18, 2022 14:34
Show Gist options
  • Save Vostbur/59a525ac55532eaa531ec4c8c8817043 to your computer and use it in GitHub Desktop.
Save Vostbur/59a525ac55532eaa531ec4c8c8817043 to your computer and use it in GitHub Desktop.
Stepic.Golang. Goroutines. The End

Необходимо написать функцию func merge2Channels(fn func(int) int, in1 <-chan int, in2 <- chan int, out chan<- int, n int).

Описание ее работы:

n раз сделать следующее

  • прочитать по одному числу из каждого из двух каналов in1 и in2, назовем их x1 и x2.
  • вычислить f(x1) + f(x2)
  • записать полученное значение в out

Функция merge2Channels должна быть неблокирующей, сразу возвращая управление.

Функция fn может работать долгое время, ожидая чего-либо или производя вычисления.

Формат ввода:

количество итераций передается через аргумент n. целые числа подаются через аргументы-каналы in1 и in2. функция для обработки чисел перед сложением передается через аргумент fn.

Формат вывода:

канал для вывода результатов передается через аргумент out.

package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const N = 20
func main() {
in1 := make(chan int, N)
in2 := make(chan int, N)
out := make(chan int, N)
fn := func(x int) int {
time.Sleep(time.Duration(rand.Int31n(N)) * time.Second)
return x * 2
}
start := time.Now()
merge2Channels(fn, in1, in2, out, N+1)
for i := 0; i < N+1; i++ {
in1 <- i
in2 <- i
}
orderFail := false
EvenFail := false
for i, prev := 0, 0; i < N; i++ {
c := <-out
if c%2 != 0 {
EvenFail = true
}
if prev >= c && i != 0 {
orderFail = true
}
prev = c
fmt.Println(c)
}
if orderFail {
fmt.Println("порядок нарушен")
}
if EvenFail {
fmt.Println("Есть не четные")
}
duration := time.Since(start)
if duration.Seconds() > N {
fmt.Println("Время превышено")
}
fmt.Println("Время выполнения: ", duration)
}
func merge2Channels(fn func(int) int, in1 <-chan int, in2 <-chan int, out chan<- int, n int) {
go func() {
array := make([]int, n)
wg := new(sync.WaitGroup)
for i := 0; i < n; i++ {
wg.Add(1)
x1 := <-in1
x2 := <-in2
go func(in1 <-chan int, in2 <-chan int, i int, wg *sync.WaitGroup) {
defer wg.Done()
r1 := make(chan int)
r2 := make(chan int)
defer close(r1)
defer close(r2)
go calc(fn, x1, r1)
go calc(fn, x2, r2)
array[i] = <-r1 + <-r2
}(in1, in2, i, wg)
}
wg.Wait()
for i := 0; i < n; i++ {
out <- array[i]
}
}()
}
func calc(fn func(int) int, x int, res chan<- int) {
res <- fn(x)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment