question 9A
This commit is contained in:
1 parent
8198014f66
commit
6e61950ee2
4 files changed
+496
No files matched your search
@@ -0,0 +1,154 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Inode struct {
|
||||
fileId int // inode with id -1 are empty
|
||||
length int
|
||||
}
|
||||
|
||||
func (inode *Inode) String() string {
|
||||
v := ""
|
||||
if inode.fileId < 0 {
|
||||
v = "."
|
||||
} else {
|
||||
v = strconv.Itoa(inode.fileId)
|
||||
}
|
||||
return strings.Repeat(v, inode.length)
|
||||
}
|
||||
|
||||
func (inode *Inode) IsFreeSpace() bool {
|
||||
return inode.fileId < 0
|
||||
}
|
||||
|
||||
func (inode *Inode) Copy() *Inode {
|
||||
return &Inode{inode.fileId, inode.length}
|
||||
}
|
||||
|
||||
type FileSystem struct {
|
||||
inodes *DoubleLinkedList[*Inode]
|
||||
}
|
||||
|
||||
func (fs *FileSystem) String() string {
|
||||
ret := ""
|
||||
for inode := range fs.inodes.Iter() {
|
||||
ret += inode.String()
|
||||
}
|
||||
return ret
|
||||
|
||||
}
|
||||
|
||||
func (fs *FileSystem) CheckSum() int {
|
||||
ret, idx := 0, 0
|
||||
for inode := range fs.inodes.Iter() {
|
||||
if inode.IsFreeSpace() {
|
||||
idx += inode.length
|
||||
continue
|
||||
}
|
||||
for j := 0; j < inode.length; j++ {
|
||||
ret = ret + idx*inode.fileId
|
||||
idx++
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func parseString(s string) *FileSystem {
|
||||
dll := NewDLL[*Inode]()
|
||||
inode := &Inode{-1, 0}
|
||||
for _, c := range s {
|
||||
fileId := -1
|
||||
|
||||
if c != '.' {
|
||||
fileId, _ = strconv.Atoi(string(c))
|
||||
}
|
||||
if inode.fileId == fileId {
|
||||
inode.length += 1
|
||||
} else {
|
||||
dll.InsertLast(inode)
|
||||
inode = &Inode{fileId, 1}
|
||||
}
|
||||
}
|
||||
dll.InsertLast(inode)
|
||||
if inode, ok := dll.Last(); !ok || !inode.IsFreeSpace() {
|
||||
dll.InsertLast(&Inode{-1, 0})
|
||||
}
|
||||
return &FileSystem{dll}
|
||||
}
|
||||
|
||||
func parseInput(input string) *FileSystem {
|
||||
dll := NewDLL[*Inode]()
|
||||
id := 0
|
||||
for i, c := range input {
|
||||
var inode *Inode
|
||||
length, _ := strconv.Atoi(string(c))
|
||||
if isFreeSpace := i%2 == 1; isFreeSpace {
|
||||
inode = &Inode{-1, length}
|
||||
} else {
|
||||
inode = &Inode{id, length}
|
||||
id++
|
||||
}
|
||||
dll.InsertLast(inode)
|
||||
}
|
||||
if inode, ok := dll.Last(); !ok || !inode.IsFreeSpace() {
|
||||
dll.InsertLast(&Inode{-1, 0})
|
||||
}
|
||||
return &FileSystem{dll}
|
||||
}
|
||||
|
||||
func (fs *FileSystem) takeFilesFromTheEnd(id DllId) *Inode {
|
||||
for node, ok := fs.inodes.nodes[fs.inodes.LastNode]; ok; node, ok = fs.inodes.nodes[node.PreviousId] {
|
||||
if node.Id == id {
|
||||
break
|
||||
}
|
||||
if inode, _ := fs.inodes.GetById(node.Id); !inode.IsFreeSpace() && inode.length > 0 {
|
||||
return inode
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *FileSystem) OptimizeDiskFragmentation() {
|
||||
emptySpaceAtTheEndId, _ := fs.inodes.LastId()
|
||||
emptySpaceAtTheEnd, _ := fs.inodes.Last()
|
||||
for discId, ok := fs.inodes.FirstId(); ok; discId, ok = fs.inodes.NextId(discId) {
|
||||
freeSpaceInode, _ := fs.inodes.GetById(discId)
|
||||
if !freeSpaceInode.IsFreeSpace() || discId == emptySpaceAtTheEndId {
|
||||
continue
|
||||
}
|
||||
fileInodeAtTheEnd := fs.takeFilesFromTheEnd(discId)
|
||||
if fileInodeAtTheEnd == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if freeSpaceInode.length <= fileInodeAtTheEnd.length {
|
||||
newInode := &Inode{fileInodeAtTheEnd.fileId, freeSpaceInode.length}
|
||||
fs.inodes.InsertBefore(discId, newInode)
|
||||
emptySpaceAtTheEnd.length += freeSpaceInode.length
|
||||
fileInodeAtTheEnd.length -= freeSpaceInode.length
|
||||
freeSpaceInode.length = 0
|
||||
} else {
|
||||
newFreeSpaceInode := &Inode{-1, freeSpaceInode.length - fileInodeAtTheEnd.length}
|
||||
fs.inodes.InsertAfter(discId, newFreeSpaceInode)
|
||||
fs.inodes.InsertBefore(discId, fileInodeAtTheEnd.Copy())
|
||||
emptySpaceAtTheEnd.length += fileInodeAtTheEnd.length
|
||||
fileInodeAtTheEnd.length = 0
|
||||
freeSpaceInode.length = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Question9A(input string) int {
|
||||
fs := parseInput(input)
|
||||
fs.OptimizeDiskFragmentation()
|
||||
return fs.CheckSum()
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("The answer to question 9A is: ", Question9A(realInput))
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user