diff --git a/impl_ring_array.go b/impl_ring_array.go new file mode 100644 index 0000000..a4fe534 --- /dev/null +++ b/impl_ring_array.go @@ -0,0 +1,13 @@ +package ds + +type ArrayRing[T any] struct { + *ListRing[T, *ArrayList[*T]] +} + +var _ Ring[int] = &ArrayRing[int]{} + +func NewArrayRing[T any](size int) *ArrayRing[T] { + return &ArrayRing[T]{ + ListRing: NewListRing[T](NewArrayList[*T](size), size), + } +} diff --git a/impl_ring_linked_list.go b/impl_ring_linked_list.go new file mode 100644 index 0000000..a8f74fe --- /dev/null +++ b/impl_ring_linked_list.go @@ -0,0 +1,13 @@ +package ds + +type LinkedListRing[T any] struct { + *ListRing[T, *LinkedList[*T]] +} + +var _ Ring[int] = &LinkedListRing[int]{} + +func NewLinkedListRing[T any](size int) *LinkedListRing[T] { + return &LinkedListRing[T]{ + ListRing: NewListRing[T](NewLinkedList[*T](), size), + } +} diff --git a/impl_ring_list.go b/impl_ring_list.go new file mode 100644 index 0000000..a0e84c5 --- /dev/null +++ b/impl_ring_list.go @@ -0,0 +1,65 @@ +package ds + +type ListRing[T any, L List[*T]] struct { + list L + current int +} + +var _ Ring[int] = &ListRing[int, List[*int]]{} + +func NewListRing[T any, L List[*T]](list L, size int) *ListRing[T, L] { + preAllocList[*T, List[*T]](list, nil, size) + return &ListRing[T, L]{ + list: list, + current: 0, + } +} + +func (r *ListRing[T, L]) Next() Ring[T] { + return &ListRing[T, L]{ + list: r.list, + current: modAbs(r.current+1, r.list.Size()), + } +} + +func (r *ListRing[T, L]) Prev() Ring[T] { + return &ListRing[T, L]{ + list: r.list, + current: modAbs(r.current-1, r.list.Size()), + } +} + +func (r *ListRing[T, L]) Set(v T) { + r.list.Set(r.current, &v) +} + +func (r *ListRing[T, L]) Has() bool { + return r.list.Get(r.current) != nil +} + +func (r *ListRing[T, L]) Get() (T, bool) { + if !r.Has() { + return *new(T), false + } + return *r.list.Get(r.current), true +} + +func (r *ListRing[T, L]) GetOrDefault(defaultValue T) T { + value, ok := r.Get() + if !ok { + return defaultValue + } + return value +} + +func (r *ListRing[T, L]) Each(f func(value *T)) { + var t Ring[T] = r + for i := 0; i < r.list.Size(); i++ { + if value, ok := t.Get(); ok { + f(&value) + } else { + f(nil) + } + t = t.Next() + } +} diff --git a/int_ring.go b/int_ring.go new file mode 100644 index 0000000..e3f8593 --- /dev/null +++ b/int_ring.go @@ -0,0 +1,13 @@ +package ds + +type Ring[T any] interface { + Iterable[*T] + + Next() Ring[T] + Prev() Ring[T] + + Set(T) + Has() bool + Get() (T, bool) + GetOrDefault(defaultValue T) T +} diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..d0db53d --- /dev/null +++ b/utils.go @@ -0,0 +1,15 @@ +package ds + +func modAbs(a, b int) int { + v := a % b + if v < 0 { + return b + v + } + return v +} + +func preAllocList[T any, L List[T]](list L, value T, size int) { + for list.Size() < size { + list.Add(value) + } +}