Skip to content

Commit e03a9da

Browse files
Add solution for Challenge 27
1 parent ba72dff commit e03a9da

File tree

1 file changed

+290
-0
lines changed

1 file changed

+290
-0
lines changed
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
package generics
2+
3+
import (
4+
"errors"
5+
)
6+
7+
// ErrEmptyCollection is returned when an operation cannot be performed on an empty collection
8+
var ErrEmptyCollection = errors.New("collection is empty")
9+
10+
//
11+
// 1. Generic Pair
12+
//
13+
14+
// Pair represents a generic pair of values of potentially different types
15+
type Pair[T, U any] struct {
16+
First T
17+
Second U
18+
}
19+
20+
// NewPair creates a new pair with the given values
21+
func NewPair[T, U any](first T, second U) Pair[T, U] {
22+
return Pair[T, U]{
23+
First: first,
24+
Second: second,
25+
}
26+
}
27+
28+
// Swap returns a new pair with the elements swapped
29+
func (p Pair[T, U]) Swap() Pair[U, T] {
30+
return Pair[U, T]{
31+
First: p.Second,
32+
Second: p.First,
33+
}
34+
}
35+
36+
//
37+
// 2. Generic Stack
38+
//
39+
40+
// Stack is a generic Last-In-First-Out (LIFO) data structure
41+
type Stack[T any] struct {
42+
elements []T
43+
}
44+
45+
// NewStack creates a new empty stack
46+
func NewStack[T any]() *Stack[T] {
47+
return &Stack[T]{
48+
elements: []T{},
49+
}
50+
}
51+
52+
// Push adds an element to the top of the stack
53+
func (s *Stack[T]) Push(value T) {
54+
s.elements = append(s.elements, value)
55+
}
56+
57+
// Pop removes and returns the top element from the stack
58+
// Returns an error if the stack is empty
59+
func (s *Stack[T]) Pop() (T, error) {
60+
var zero T
61+
if s.IsEmpty() {
62+
return zero, ErrEmptyCollection
63+
}
64+
last := s.Size() - 1
65+
e := s.elements[last]
66+
s.elements = s.elements[:last]
67+
return e, nil
68+
}
69+
70+
// Peek returns the top element without removing it
71+
// Returns an error if the stack is empty
72+
func (s *Stack[T]) Peek() (T, error) {
73+
var zero T
74+
if s.IsEmpty() {
75+
return zero, ErrEmptyCollection
76+
}
77+
last := s.Size() - 1
78+
e := s.elements[last]
79+
return e, nil
80+
}
81+
82+
// Size returns the number of elements in the stack
83+
func (s *Stack[T]) Size() int {
84+
return len(s.elements)
85+
}
86+
87+
// IsEmpty returns true if the stack contains no elements
88+
func (s *Stack[T]) IsEmpty() bool {
89+
return s.Size() == 0
90+
}
91+
92+
//
93+
// 3. Generic Queue
94+
//
95+
96+
// Queue is a generic First-In-First-Out (FIFO) data structure
97+
type Queue[T any] struct {
98+
elements []T
99+
}
100+
101+
// NewQueue creates a new empty queue
102+
func NewQueue[T any]() *Queue[T] {
103+
return &Queue[T]{
104+
elements: []T{},
105+
}
106+
}
107+
108+
// Enqueue adds an element to the end of the queue
109+
func (q *Queue[T]) Enqueue(value T) {
110+
q.elements = append(q.elements, value)
111+
}
112+
113+
// Dequeue removes and returns the front element from the queue
114+
// Returns an error if the queue is empty
115+
func (q *Queue[T]) Dequeue() (T, error) {
116+
var zero T
117+
if q.IsEmpty() {
118+
return zero, ErrEmptyCollection
119+
}
120+
frontEl := q.elements[0]
121+
q.elements = q.elements[1:]
122+
return frontEl, nil
123+
}
124+
125+
// Front returns the front element without removing it
126+
// Returns an error if the queue is empty
127+
func (q *Queue[T]) Front() (T, error) {
128+
var zero T
129+
if q.IsEmpty() {
130+
return zero, ErrEmptyCollection
131+
}
132+
frontEl := q.elements[0]
133+
return frontEl, nil
134+
}
135+
136+
// Size returns the number of elements in the queue
137+
func (q *Queue[T]) Size() int {
138+
return len(q.elements)
139+
}
140+
141+
// IsEmpty returns true if the queue contains no elements
142+
func (q *Queue[T]) IsEmpty() bool {
143+
return q.Size() == 0
144+
}
145+
146+
//
147+
// 4. Generic Set
148+
//
149+
150+
// Set is a generic collection of unique elements
151+
type Set[T comparable] struct {
152+
elements map[T]struct{}
153+
}
154+
155+
// NewSet creates a new empty set
156+
func NewSet[T comparable]() *Set[T] {
157+
return &Set[T]{
158+
elements: make(map[T]struct{}),
159+
}
160+
}
161+
162+
// Add adds an element to the set if it's not already present
163+
func (s *Set[T]) Add(value T) {
164+
s.elements[value] = struct{}{}
165+
}
166+
167+
// Remove removes an element from the set if it exists
168+
func (s *Set[T]) Remove(value T) {
169+
delete(s.elements, value)
170+
}
171+
172+
// Contains returns true if the set contains the given element
173+
func (s *Set[T]) Contains(value T) bool {
174+
_, ok := s.elements[value]
175+
return ok
176+
}
177+
178+
// Size returns the number of elements in the set
179+
func (s *Set[T]) Size() int {
180+
return len(s.elements)
181+
}
182+
183+
// Elements returns a slice containing all elements in the set
184+
func (s *Set[T]) Elements() []T {
185+
result := []T{}
186+
for key := range s.elements {
187+
result = append(result, key)
188+
}
189+
return result
190+
}
191+
192+
// Union returns a new set containing all elements from both sets
193+
func Union[T comparable](s1, s2 *Set[T]) *Set[T] {
194+
result := NewSet[T]()
195+
for key := range s1.elements {
196+
result.Add(key)
197+
}
198+
for key := range s2.elements {
199+
result.Add(key)
200+
}
201+
return result
202+
}
203+
204+
// Intersection returns a new set containing only elements that exist in both sets
205+
func Intersection[T comparable](s1, s2 *Set[T]) *Set[T] {
206+
result := NewSet[T]()
207+
for key := range s1.elements {
208+
if s2.Contains(key) {
209+
result.Add(key)
210+
}
211+
}
212+
return result
213+
}
214+
215+
// Difference returns a new set with elements in s1 that are not in s2
216+
func Difference[T comparable](s1, s2 *Set[T]) *Set[T] {
217+
result := NewSet[T]()
218+
for key := range s1.elements {
219+
if !s2.Contains(key) {
220+
result.Add(key)
221+
}
222+
}
223+
return result
224+
}
225+
226+
//
227+
// 5. Generic Utility Functions
228+
//
229+
230+
// Filter returns a new slice containing only the elements for which the predicate returns true
231+
func Filter[T any](slice []T, predicate func(T) bool) []T {
232+
result := []T{}
233+
for _, v := range slice {
234+
if predicate(v) {
235+
result = append(result, v)
236+
}
237+
}
238+
return result
239+
}
240+
241+
// Map applies a function to each element in a slice and returns a new slice with the results
242+
func Map[T, U any](slice []T, mapper func(T) U) []U {
243+
result := []U{}
244+
for _, v := range slice {
245+
result = append(result, mapper(v))
246+
}
247+
return result
248+
}
249+
250+
// Reduce reduces a slice to a single value by applying a function to each element
251+
func Reduce[T, U any](slice []T, initial U, reducer func(U, T) U) U {
252+
result := initial
253+
for _, v := range slice {
254+
result = reducer(result, v)
255+
}
256+
return result
257+
}
258+
259+
// Contains returns true if the slice contains the given element
260+
func Contains[T comparable](slice []T, element T) bool {
261+
for _, v := range slice {
262+
if v == element {
263+
return true
264+
}
265+
}
266+
return false
267+
}
268+
269+
// FindIndex returns the index of the first occurrence of the given element or -1 if not found
270+
func FindIndex[T comparable](slice []T, element T) int {
271+
for k, v := range slice {
272+
if v == element {
273+
return k
274+
}
275+
}
276+
return -1
277+
}
278+
279+
// RemoveDuplicates returns a new slice with duplicate elements removed, preserving order
280+
func RemoveDuplicates[T comparable](slice []T) []T {
281+
seen := make(map[T]struct{}, len(slice))
282+
result := []T{}
283+
for _, v := range slice {
284+
if _, ok := seen[v]; !ok {
285+
seen[v] = struct{}{}
286+
result = append(result, v)
287+
}
288+
}
289+
return result
290+
}

0 commit comments

Comments
 (0)