diff --git a/genericsum/README.md b/genericsum/README.md new file mode 100644 index 0000000..8349014 --- /dev/null +++ b/genericsum/README.md @@ -0,0 +1,10 @@ +# genericsum + +Реализуйте несколько небольших функций с дженериками. + +* `Min` - минимум из 2 переменных +* `SortSlice` - сортировка слайса inplace +* `MapsEqual` - равенство 2 мап. Значения мап сравниваются через обычный оператор = +* `SliceContains` - содержит ли слайс заданный элемент +* `MergeChans` - сделать из нескольких каналов один. При отправке значения в любой из входных каналов, его можно получить в выходном канале. Необходимо закрыть созданный канал, когда все входные каналы будут закрыты - это единственный корректный вариант завершения работы. +* `IsHermitianMatrix` - проверка, является ли квадратная матрица эрмитовой. Подсказка: достаточно проверить, что транспонированная комплексно сопряженная матрица равна исходной матрице \ No newline at end of file diff --git a/genericsum/genericsum.go b/genericsum/genericsum.go new file mode 100644 index 0000000..ed27623 --- /dev/null +++ b/genericsum/genericsum.go @@ -0,0 +1,31 @@ +//go:build !solution + +package genericsum + +func Min(a, b int) int { + panic("implement me") +} + +func SortSlice(a []int) { + panic("implement me") +} + +func MapsEqual(a, b map[int]int) bool { + panic("implement me") +} + +func SliceContains(s []int, v int) bool { + panic("implement me") +} + +func MergeChans(chs ...<-chan int) <-chan int { + panic("implement me") +} + +func MergeChans(chs ...<-chan int) <-chan int { + panic("implement me") +} + +func IsHermitianMatrix(m [][]int) bool { + panic("implement me") +} diff --git a/genericsum/genericsum_test.go b/genericsum/genericsum_test.go new file mode 100644 index 0000000..656e907 --- /dev/null +++ b/genericsum/genericsum_test.go @@ -0,0 +1,207 @@ +package genericsum + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/goleak" +) + +func TestMin(t *testing.T) { + assert.Equal(t, 10, Min(10, 20)) + assert.Equal(t, -10, Min(20, -10)) + + assert.Equal(t, 1.0, Min(1.0, 2.0)) + assert.Equal(t, int64(10), Min(int64(10), 20)) + + assert.Equal(t, "abc", Min("def", "abc")) + type myString string + assert.Equal(t, myString("abc"), Min(myString("def"), myString("abc"))) +} + +func TestSortSlice(t *testing.T) { + t.Run("ints", func(t *testing.T) { + inputs, expected := []int{3, 6, 2, 4, 5, 1}, []int{1, 2, 3, 4, 5, 6} + SortSlice(inputs) + assert.Equal(t, expected, inputs) + }) + t.Run("ints64", func(t *testing.T) { + inputs, expected := []int64{3, 6, 2, 4, 5, 1}, []int64{1, 2, 3, 4, 5, 6} + SortSlice(inputs) + assert.Equal(t, expected, inputs) + }) + t.Run("strings", func(t *testing.T) { + inputs, expected := []string{"d", "b", "ab", "a"}, []string{"a", "ab", "b", "d"} + SortSlice(inputs) + assert.Equal(t, expected, inputs) + }) + + type myStringSlice []string + t.Run("strings custom type", func(t *testing.T) { + inputs, expected := myStringSlice([]string{"d", "b", "ab", "a"}), myStringSlice([]string{"a", "ab", "b", "d"}) + SortSlice(inputs) + assert.Equal(t, expected, inputs) + }) +} + +func TestMapsEqual(t *testing.T) { + assert.True(t, MapsEqual(map[string]string{"1": "3", "2": "4"}, map[string]string{"2": "4", "1": "3"})) + + var i int + assert.False(t, MapsEqual(map[string]*int{"1": &i, "2": nil}, map[string]*int{"1": &i})) + assert.False(t, MapsEqual(map[string]*int{"1": &i}, map[string]*int{"1": &i, "2": nil})) + + assert.False(t, MapsEqual(map[string]*int{"1": new(int)}, map[string]*int{"1": new(int)}), + "different pointers") + + type k struct { + i int + s string + } + assert.True(t, MapsEqual(map[k]k{{10, "abc"}: {20, "def"}}, map[k]k{{10, "abc"}: {20, "def"}})) + + type myMap map[int]int + assert.True(t, MapsEqual(myMap(nil), myMap(nil)), "type aliases must also be ok") +} + +func TestSliceContains(t *testing.T) { + assert.True(t, SliceContains([]int{5, 9, 12}, 5)) + assert.False(t, SliceContains([]int{5, 9, 12}, 7)) + + type k struct{ i, j int } + assert.True(t, SliceContains([]k{{1, 2}, {5, 7}, {9, 12}}, k{5, 7})) + + type mySlice []k + assert.True(t, SliceContains(mySlice{{1, 2}, {5, 7}, {9, 12}}, k{5, 7})) +} + +func TestMergeChansTypes(t *testing.T) { + t.Run("floats", func(t *testing.T) { + defer goleak.VerifyNone(t) + + chans := make([]chan float64, 5) + chanArgs := make([]<-chan float64, 5) + for i := range chans { + chans[i] = make(chan float64, 1) + chanArgs[i] = chans[i] + } + + ch := MergeChans(chanArgs...) + + for _, ch := range chans { + close(ch) + } + + for range ch { + } + }) + + t.Run("structs", func(t *testing.T) { + defer goleak.VerifyNone(t) + + type tp struct{} + + chans := make([]chan tp, 5) + chanArgs := make([]<-chan tp, 5) + for i := range chans { + chans[i] = make(chan tp, 1) + chanArgs[i] = chans[i] + } + + ch := MergeChans(chanArgs...) + + for _, ch := range chans { + close(ch) + } + + for range ch { + } + }) +} + +func TestMergeChans(t *testing.T) { + defer goleak.VerifyNone(t) + + const numChans = 10 + + chans := make([]chan int, numChans) + chanArgs := make([]<-chan int, numChans) + for i := range chans { + chans[i] = make(chan int, 1) + chanArgs[i] = chans[i] + } + + ch := MergeChans(chanArgs...) + chans[5] <- 10 + assert.Equal(t, 10, <-ch) + chans[1] <- 5 + assert.Equal(t, 5, <-ch) + + const numIter = 1000 + receivedNumbers := make([]bool, numIter) + + go func() { + for i := 0; i < numIter; i++ { + chans[i%numChans] <- i + } + for _, ch := range chans { + close(ch) + } + }() + + // don't ever deadlock + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + var receivedNum int + +Loop: + for { + select { + case v, ok := <-ch: + if !ok { + break Loop + } + require.True(t, v >= 0 && v < len(receivedNumbers), "invalid received number", v) + require.False(t, receivedNumbers[v], "shouldn't receive number twice", v) + receivedNumbers[v] = true + receivedNum++ + case <-ctx.Done(): + require.FailNow(t, "timeouted") + } + } + assert.Equal(t, numIter, receivedNum) +} + +func TestIsHermitianMatrix(t *testing.T) { + assert.True(t, IsHermitianMatrix([][]int{ + {1, 7, 9}, + {7, 2, 12}, + {9, 12, 19}, + })) + assert.False(t, IsHermitianMatrix([][]int{ + {1, 12, 8}, + {3, 4, 7}, + {8, 7, 11}, + })) + assert.True(t, IsHermitianMatrix([][]complex64{ + {1, 3 + 2i}, + {3 - 2i, 4}, + })) + assert.True(t, IsHermitianMatrix([][]complex128{ + {1, 3 + 2i, 9 - 1i}, + {3 - 2i, 5, 7 - 3i}, + {9 + 1i, 7 + 3i, 19}, + })) + assert.False(t, IsHermitianMatrix([][]complex64{ + {1 + 1i, 3 + 2i}, + {3 - 2i, 4}, + })) + + first, second := [][]int{{1, 2}, {3, 4}}, [][]int{{1, 2}, {3, 4}} + assert.False(t, IsHermitianMatrix(first)) + assert.Equal(t, second, first, "shouldn't change matrix in the method") +} diff --git a/go.mod b/go.mod index 15928df..1113eae 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/testcontainers/testcontainers-go v0.9.0 go.uber.org/goleak v1.0.0 go.uber.org/zap v1.14.0 + golang.org/x/exp v0.0.0-20220328175248-053ad81199eb golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f golang.org/x/perf v0.0.0-20191209155426-36b577b0eb03 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c @@ -78,9 +79,9 @@ require ( go.uber.org/atomic v1.5.0 // indirect go.uber.org/multierr v1.3.0 // indirect go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect - golang.org/x/mod v0.5.1 // indirect + golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a // indirect diff --git a/go.sum b/go.sum index 3f3e452..8bd0a53 100644 --- a/go.sum +++ b/go.sum @@ -48,7 +48,6 @@ github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwj github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -203,7 +202,6 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -219,7 +217,6 @@ github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye47 github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -234,7 +231,6 @@ github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCM github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.3.0 h1:l8JvKrby3RI7Kg3bYEeU9TA4vqC38QDpFCfcrC7KuN0= github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik= -github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= @@ -401,7 +397,6 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -435,13 +430,16 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20220328175248-053ad81199eb h1:pC9Okm6BVmxEw76PUu0XUbOTQ92JX11hfvqTjAV3qxM= +golang.org/x/exp v0.0.0-20220328175248-053ad81199eb/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -457,8 +455,8 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -526,9 +524,9 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=