-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# For most projects, this workflow file will not need changing; you simply need | ||
# to commit it to your repository. | ||
# | ||
# You may wish to alter this file to override the set of languages analyzed, | ||
# or to provide custom queries or build logic. | ||
# | ||
# ******** NOTE ******** | ||
# We have attempted to detect the languages in your repository. Please check | ||
# the `language` matrix defined below to confirm you have the correct set of | ||
# supported CodeQL languages. | ||
# | ||
name: "CodeQL" | ||
|
||
on: | ||
push: | ||
branches: ["main"] | ||
pull_request: | ||
# The branches below must be a subset of the branches above | ||
branches: ["main"] | ||
schedule: | ||
- cron: "28 16 * * 0" | ||
|
||
jobs: | ||
analyze: | ||
name: Analyze | ||
# Runner size impacts CodeQL analysis time. To learn more, please see: | ||
# - https://gh.io/recommended-hardware-resources-for-running-codeql | ||
# - https://gh.io/supported-runners-and-hardware-resources | ||
# - https://gh.io/using-larger-runners | ||
# Consider using larger runners for possible analysis time improvements. | ||
runs-on: ${{ (matrix.language == 'go' && 'macos-latest') || 'ubuntu-latest' }} | ||
timeout-minutes: ${{ (matrix.language == 'go' && 120) || 360 }} | ||
permissions: | ||
actions: read | ||
contents: read | ||
security-events: write | ||
|
||
strategy: | ||
fail-fast: false | ||
matrix: | ||
language: ["go"] | ||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] | ||
# Use only 'java' to analyze code written in Java, Kotlin or both | ||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both | ||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v3 | ||
|
||
# Initialize go version for v1.21 | ||
- name: Install Go | ||
uses: actions/setup-go@v4 | ||
with: | ||
go-version-file: go.mod | ||
|
||
# Initializes the CodeQL tools for scanning. | ||
- name: Initialize CodeQL | ||
uses: github/codeql-action/init@v2 | ||
with: | ||
languages: ${{ matrix.language }} | ||
# If you wish to specify custom queries, you can do so here or in a config file. | ||
# By default, queries listed here will override any specified in a config file. | ||
# Prefix the list here with "+" to use these queries and those in the config file. | ||
|
||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs | ||
# queries: security-extended,security-and-quality | ||
|
||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). | ||
# If this step fails, then you should remove it and run the build manually (see below) | ||
- name: Autobuild | ||
uses: github/codeql-action/autobuild@v2 | ||
|
||
# ℹ️ Command-line programs to run using the OS shell. | ||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun | ||
|
||
# If the Autobuild fails above, remove it and uncomment the following three lines. | ||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. | ||
|
||
# - run: | | ||
# echo "Run, Build Application using script" | ||
# ./location_of_script_within_repo/buildscript.sh | ||
|
||
- name: Perform CodeQL Analysis | ||
uses: github/codeql-action/analyze@v2 | ||
with: | ||
category: "/language:${{matrix.language}}" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# This workflow will build a golang project | ||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go | ||
|
||
name: Go | ||
|
||
on: | ||
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
jobs: | ||
|
||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@v4 | ||
with: | ||
go-version: '1.21' | ||
|
||
- name: Test | ||
run: go test -v ./... |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# go-hashset | ||
|
||
[![Go](https://pkg.go.dev/badge/github.com/1eedaegon/go-hashset.svg)](https://pkg.go.dev/github.com/1eedaegon/go-hashset) | ||
[![CI](https://github.com/1eedaegon/go-hashset/actions/workflows/go.yml/badge.svg)](https://github.com/1eedaegon/go-hashset/actions/workflows/go.yml) | ||
[![CodeQL](https://github.com/1eedaegon/go-hashset/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/1eedaegon/go-hashset/actions/workflows/codeql.yml) | ||
|
||
A go library hashset for O(1) | ||
|
||
## Example | ||
|
||
```go | ||
import ( | ||
... | ||
port "github.com/1eedaegon/go-hashset" | ||
... | ||
) | ||
|
||
ports := port.Get(3) | ||
// ports is something like []int{10000, 10001, 10002} | ||
``` | ||
|
||
Or | ||
|
||
```go | ||
import ( | ||
... | ||
port "github.com/1eedaegon/go-hashset" | ||
... | ||
) | ||
|
||
ports := port.GetS(3) | ||
// ports is something like []string{"10000", "10001", "10002"} | ||
``` | ||
|
||
## License | ||
|
||
[MIT](LICENSE) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module github.com/1eedaegon/go-hashset | ||
|
||
go 1.21.0 | ||
|
||
require github.com/stretchr/testify v1.9.0 | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package hashset | ||
|
||
import "sync" | ||
|
||
// Set represents a thread-safe collection of unique elements. | ||
type Set struct { | ||
mu sync.RWMutex // Guards access to the internal hash map. | ||
hash map[interface{}]bool // Stores elements as keys with a boolean value. | ||
} | ||
|
||
// New initializes and returns a new Set with optional initial elements. | ||
func New(initial ...interface{}) *Set { | ||
s := &Set{ | ||
hash: make(map[interface{}]bool), | ||
} | ||
for _, v := range initial { | ||
s.Add(v) | ||
} | ||
return s | ||
} | ||
|
||
// Add inserts an element into the Set. If the element is already present, it does nothing. | ||
func (s *Set) Add(element interface{}) { | ||
s.mu.Lock() | ||
defer s.mu.Unlock() | ||
s.hash[element] = true | ||
} | ||
|
||
// Remove deletes an element from the Set. If the element is not present, it does nothing. | ||
func (s *Set) Remove(element interface{}) { | ||
s.mu.Lock() | ||
defer s.mu.Unlock() | ||
delete(s.hash, element) | ||
} | ||
|
||
// Contains checks if an element is present in the Set. | ||
func (s *Set) Contains(element interface{}) bool { | ||
s.mu.RLock() | ||
defer s.mu.RUnlock() | ||
_, exists := s.hash[element] | ||
return exists | ||
} | ||
|
||
// Difference returns a new Set containing elements present in the original Set but not in the given Set. | ||
func (s *Set) Difference(set *Set) *Set { | ||
diff := make(map[interface{}]bool) | ||
s.mu.RLock() | ||
defer s.mu.RUnlock() | ||
for k := range s.hash { | ||
if _, exists := set.hash[k]; !exists { | ||
diff[k] = true | ||
} | ||
} | ||
return &Set{hash: diff} | ||
} | ||
|
||
// Do applies a given function to each element of the Set. This can be used for iterating over the Set. | ||
func (s *Set) Do(f func(interface{})) { | ||
s.mu.RLock() | ||
defer s.mu.RUnlock() | ||
for k := range s.hash { | ||
f(k) | ||
} | ||
} | ||
|
||
// Intersection returns a new Set containing elements that are present in both Sets. | ||
func (s *Set) Intersection(set *Set) *Set { | ||
intersect := make(map[interface{}]bool) | ||
s.mu.RLock() | ||
defer s.mu.RUnlock() | ||
for k := range s.hash { | ||
if _, exists := set.hash[k]; exists { | ||
intersect[k] = true | ||
} | ||
} | ||
return &Set{hash: intersect} | ||
} | ||
|
||
// Len returns the number of elements in the Set. | ||
func (s *Set) Len() int { | ||
s.mu.RLock() | ||
defer s.mu.RUnlock() | ||
return len(s.hash) | ||
} | ||
|
||
// SubsetOf checks if the Set is a subset of the given Set. | ||
func (s *Set) SubsetOf(set *Set) bool { | ||
s.mu.RLock() | ||
defer s.mu.RUnlock() | ||
if s.Len() > set.Len() { | ||
return false | ||
} | ||
for k := range s.hash { | ||
if _, exists := set.hash[k]; !exists { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
// Union returns a new Set containing all elements that are present in either Set. | ||
func (s *Set) Union(set *Set) *Set { | ||
union := make(map[interface{}]bool) | ||
s.mu.Lock() | ||
for k := range s.hash { | ||
union[k] = true | ||
} | ||
s.mu.Unlock() | ||
|
||
s.mu.Lock() | ||
for k := range set.hash { | ||
union[k] = true | ||
} | ||
s.mu.Unlock() | ||
return &Set{hash: union} | ||
} | ||
|
||
func (s *Set) ToSlice() []interface{} { | ||
uniTypeSlice := make([]interface{}, 0) | ||
s.mu.RLock() | ||
for key := range s.hash { | ||
uniTypeSlice = append(uniTypeSlice, key) | ||
} | ||
s.mu.RUnlock() | ||
return uniTypeSlice | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package hashset | ||
|
||
import ( | ||
"strconv" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
/* | ||
0. 기본 연산 | ||
1. 추가 | ||
2. 삭제 | ||
3. 요소 확인 | ||
1. 값의 중복이 없어야한다. | ||
2. slice가오면 set으로 변경되어야한다. | ||
3. set을 slice로 변경할 수 있어야한다. | ||
4. set(집합) 연산이 가능해야한다. | ||
1. intersection | ||
2. union | ||
3. difference | ||
5. 거의 모든타입 지원이 되어야한다. | ||
1. 함수타입은 별도의 uuid와 포인터로 보관되어야한다. | ||
2. 구조체타입도 uuid로 할까 마샬링으로 할까 했는데 uuid가 좋아보이넹 | ||
6. 같은 set에 대해 동시작업이 원자성을 보장받아야한다. | ||
*/ | ||
|
||
// func testGongurrency(numOfGoroutine, numOfEashWork int, work func(prefix string, num int)) { | ||
// var wg sync.WaitGroup | ||
// for nthGoroutine := 0; nthGoroutine < numOfGoroutine; nthGoroutine++ { | ||
// wg.Add(1) | ||
// go func(n int) { | ||
// defer wg.Done() | ||
// for nthWork := 0; nthWork < numOfEashWork; nthWork++ { | ||
// work("testing-", nthWork) | ||
// } | ||
|
||
// }(nthGoroutine) | ||
// } | ||
// wg.Wait() | ||
// } | ||
func TestConcurrentAddElement(t *testing.T) { | ||
s := New() | ||
var wg sync.WaitGroup | ||
for nthGoroutine := 0; nthGoroutine < 10; nthGoroutine++ { | ||
wg.Add(1) | ||
go func(n int) { | ||
defer wg.Done() | ||
for nthWork := 0; nthWork < 100; nthWork++ { | ||
s.Add(strconv.Itoa(n) + ".testing-" + strconv.Itoa(nthWork)) | ||
} | ||
|
||
}(nthGoroutine) | ||
} | ||
wg.Wait() | ||
require.Equal(t, 1000, s.Len()) | ||
|
||
// testGongurrency(100, 10, func(prefix string, num int) { | ||
// set.Remove("prefix" + strconv.Itoa(num)) | ||
// }) | ||
// require.Equal(t, set.Len(), 0) | ||
|
||
} | ||
|
||
// func TestConcurrentRemoveElement(t *testing.T) {} | ||
// func TestMembershipCheck(t *testing.T) {} | ||
// func TestDuplicate(t *testing.T) {} | ||
// func TestConvertToSet(t *testing.T) {} | ||
// func TestConvertToSlice(t *testing.T) {} | ||
// func TestUnion(t *testing.T) {} | ||
// func TestIntersection(t *testing.T) {} | ||
// func TestDifference(t *testing.T) {} | ||
// func TestFunctionElement(t *testing.T) {} | ||
// func TestStructElement(t *testing.T) {} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.PHONY: install | ||
install: | ||
go mod tidy | ||
|
||
.PHONY: test | ||
test: install | ||
go test ./... -race | ||
|