Skip to content

Commit 4178ed3

Browse files
Johrespigo-interview-practice-bot[bot]coderabbitai[bot]
authored
Add solution for Challenge 27 by Johrespi (#723)
* Add solution for Challenge 27 * Update challenge-27/submissions/Johrespi/solution-template.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: go-interview-practice-bot[bot] <230190823+go-interview-practice-bot[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent accf97c commit 4178ed3

File tree

1 file changed

+355
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)