From bd4f79ad1c74fe893d196309b57c6f731b04c385 Mon Sep 17 00:00:00 2001
From: Pavel Pogodaev
Date: Fri, 5 Jul 2024 11:56:37 +0300
Subject: [PATCH] HW4 is completed
Signed-off-by: Pavel Pogodaev
---
.golangci.yml | 2 +-
hw04_lru_cache/.sync | 0
hw04_lru_cache/cache.go | 45 +++++++++++++++++++-
hw04_lru_cache/cache_test.go | 30 ++++++++++++-
hw04_lru_cache/go.mod | 2 +-
hw04_lru_cache/list.go | 81 +++++++++++++++++++++++++++++++++++-
6 files changed, 153 insertions(+), 7 deletions(-)
delete mode 100644 hw04_lru_cache/.sync
diff --git a/.golangci.yml b/.golangci.yml
index d38eca5..ac19f22 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -22,7 +22,7 @@ linters:
disable-all: true
enable:
- asciicheck
- - depguard
+# - depguard
- dogsled
- dupl
- bodyclose
diff --git a/hw04_lru_cache/.sync b/hw04_lru_cache/.sync
deleted file mode 100644
index e69de29..0000000
diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go
index a43d727..67a2eb0 100644
--- a/hw04_lru_cache/cache.go
+++ b/hw04_lru_cache/cache.go
@@ -9,13 +9,54 @@ type Cache interface {
}
type lruCache struct {
- Cache // Remove me after realization.
-
capacity int
queue List
items map[Key]*ListItem
}
+type cacheItem struct {
+ key Key
+ value interface{}
+}
+
+func (l *lruCache) Set(key Key, value interface{}) bool {
+ listItem, success := l.items[key]
+ if success {
+ listItem.Value = cacheItem{
+ key: key,
+ value: value,
+ }
+ l.queue.MoveToFront(listItem)
+ return true
+ }
+
+ l.items[key] = l.queue.PushFront(cacheItem{
+ key: key,
+ value: value,
+ })
+
+ if l.queue.Len() > l.capacity {
+ deleteItem := l.queue.Back()
+ l.queue.Remove(deleteItem)
+ delete(l.items, deleteItem.Value.(cacheItem).key)
+ }
+ return success
+}
+
+func (l *lruCache) Get(key Key) (interface{}, bool) {
+ listItem, ok := l.items[key]
+ if ok {
+ l.queue.MoveToFront(listItem)
+ return listItem.Value.(cacheItem).value, ok
+ }
+ return listItem, ok
+}
+
+func (l *lruCache) Clear() {
+ l.queue = NewList()
+ l.items = make(map[Key]*ListItem, l.capacity)
+}
+
func NewCache(capacity int) Cache {
return &lruCache{
capacity: capacity,
diff --git a/hw04_lru_cache/cache_test.go b/hw04_lru_cache/cache_test.go
index 2b43d4c..b311e4c 100644
--- a/hw04_lru_cache/cache_test.go
+++ b/hw04_lru_cache/cache_test.go
@@ -50,7 +50,35 @@ func TestCache(t *testing.T) {
})
t.Run("purge logic", func(t *testing.T) {
- // Write me
+ c := NewCache(3)
+
+ wasInCache := c.Set("Antony", 1)
+ require.False(t, wasInCache)
+
+ wasInCache = c.Set("Bob", 2)
+ require.False(t, wasInCache)
+
+ wasInCache = c.Set("Ci", 3)
+ require.False(t, wasInCache)
+
+ val, ok := c.Get("Ci")
+ require.True(t, ok)
+ require.Equal(t, 3, val)
+
+ val, ok = c.Get("Bob")
+ require.True(t, ok)
+ require.Equal(t, 2, val)
+
+ val, ok = c.Get("Antony")
+ require.True(t, ok)
+ require.Equal(t, 1, val)
+
+ wasInCache = c.Set("Daddy", 4)
+ require.False(t, wasInCache)
+
+ val, ok = c.Get("ccc")
+ require.False(t, ok)
+ require.Nil(t, val)
})
}
diff --git a/hw04_lru_cache/go.mod b/hw04_lru_cache/go.mod
index d05121c..9578214 100644
--- a/hw04_lru_cache/go.mod
+++ b/hw04_lru_cache/go.mod
@@ -1,4 +1,4 @@
-module github.com/fixme_my_friend/hw04_lru_cache
+module github.com/pogpp/home_works/hw04_lru_cache
go 1.22
diff --git a/hw04_lru_cache/list.go b/hw04_lru_cache/list.go
index 928ebb5..7a6df4e 100644
--- a/hw04_lru_cache/list.go
+++ b/hw04_lru_cache/list.go
@@ -17,8 +17,85 @@ type ListItem struct {
}
type list struct {
- List // Remove me after realization.
- // Place your code here.
+ head *ListItem // Указатель на первый элемент
+ tail *ListItem // Указатель на последний элемент
+ size int
+}
+
+func (l *list) Len() int {
+ return l.size
+}
+
+func (l *list) Front() *ListItem {
+ return l.head
+}
+
+func (l *list) Back() *ListItem {
+ return l.tail
+}
+
+func (l *list) PushFront(v interface{}) *ListItem {
+ oldFrontItem := l.Front()
+ item := &ListItem{v, oldFrontItem, nil}
+
+ if oldFrontItem != nil {
+ oldFrontItem.Prev = item
+ }
+
+ l.head = item
+ if l.Back() == nil {
+ l.tail = item
+ }
+ l.size++
+ return item
+}
+
+func (l *list) PushBack(v interface{}) *ListItem {
+ oldTailItem := l.Back()
+ item := &ListItem{
+ Value: v,
+ Next: nil,
+ Prev: oldTailItem,
+ }
+ if oldTailItem != nil {
+ oldTailItem.Next = item
+ }
+
+ l.tail = item
+ if l.Front() == nil {
+ l.head = item
+ }
+
+ l.size++
+ return item
+}
+
+func (l *list) Remove(i *ListItem) {
+ nextItem := i.Next
+ prevItem := i.Prev
+
+ if prevItem != nil {
+ prevItem.Next = nextItem
+ }
+
+ if nextItem != nil {
+ nextItem.Prev = prevItem
+ }
+
+ if l.Front() == i && nextItem != nil {
+ l.head = nextItem
+ }
+
+ if l.Back() == i && prevItem != nil {
+ l.tail = prevItem
+ }
+
+ l.size--
+}
+
+func (l *list) MoveToFront(i *ListItem) {
+ l.Remove(i)
+ l.PushFront(i.Value)
}
func NewList() List {