question 9A

This commit is contained in:
didier committed 2024-12-10 12:21:42 -05:00
1 parent 8198014f66
commit 6e61950ee2
4 files changed
+496

No files matched your search

+263
View File
@@ -0,0 +1,263 @@
package main
type DllId int64
type DoubleLinkedList[T any] struct {
data map[DllId]T
nodes map[DllId]*DLLNode
FirstNode DllId
LastNode DllId
length int
lastGeneratedId DllId
}
func NewDLL[T any]() *DoubleLinkedList[T] {
return &DoubleLinkedList[T]{
make(map[DllId]T),
make(map[DllId]*DLLNode),
-1,
-1,
0,
-1,
}
}
type DLLNode struct {
Id DllId
NextId DllId
PreviousId DllId
}
func (l *DoubleLinkedList[T]) IsEmpty() bool {
return l.length == 0
}
func (l *DoubleLinkedList[T]) insertEmpty(data T) DllId {
newId := l.nextId()
node := standaloneNode(newId)
l.data[newId] = data
l.nodes[newId] = node
l.FirstNode = newId
l.LastNode = newId
l.length++
return newId
}
func (l *DoubleLinkedList[T]) InsertBefore(id DllId, data T) (DllId, bool) {
if node, ok := l.nodes[id]; ok {
return l.insertBetween(l.previousNode(node), node, data)
} else {
return -1, false
}
}
func (l *DoubleLinkedList[T]) InsertAfter(id DllId, data T) (DllId, bool) {
if node := l.nodes[id]; node.Id == id {
return l.insertBetween(node, l.nextNode(node), data)
}
return -1, false
}
func (l *DoubleLinkedList[T]) InsertFirst(data T) DllId {
if l.IsEmpty() {
return l.insertEmpty(data)
}
newId := l.nextId()
node := standaloneNode(newId)
l.data[newId] = data
l.nodes[newId] = node
firstNode := l.nodes[l.FirstNode]
node.NextId = firstNode.Id
firstNode.PreviousId = newId
l.FirstNode = newId
l.length++
return newId
}
func (l *DoubleLinkedList[T]) InsertLast(data T) DllId {
if l.IsEmpty() {
return l.insertEmpty(data)
}
newId := l.nextId()
node := standaloneNode(newId)
l.data[newId] = data
l.nodes[newId] = node
lastNode := l.nodes[l.LastNode]
node.PreviousId = lastNode.Id
lastNode.NextId = newId
l.LastNode = newId
l.length++
return newId
}
func standaloneNode(id DllId) *DLLNode {
return &DLLNode{id, -1, -1}
}
func (l *DoubleLinkedList[T]) nextId() DllId {
l.lastGeneratedId++
return l.lastGeneratedId
}
func mapNodes[T, K any](l *DoubleLinkedList[T], fn func(T, *DLLNode) K) <-chan K {
ch := make(chan K)
go func() {
defer close(ch)
iterId := l.FirstNode
for iterId > -1 {
val := fn(l.data[iterId], l.nodes[iterId])
ch <- val
iterId = l.nodes[iterId].NextId
}
}()
return ch
}
func (l *DoubleLinkedList[T]) Iter() <-chan T {
return mapNodes(l, func(datum T, node *DLLNode) T { return datum })
}
func (l *DoubleLinkedList[T]) IterIds() <-chan DllId {
return mapNodes(l, func(datum T, node *DLLNode) DllId { return node.Id })
}
func (l *DoubleLinkedList[T]) IterNodes() <-chan *DLLNode {
return mapNodes(l, func(datum T, node *DLLNode) *DLLNode { return node })
}
func (l *DoubleLinkedList[T]) IterIdsFromLast() <-chan DllId {
ch := make(chan DllId)
go func() {
defer close(ch)
iterId := l.LastNode
for iterId > -1 {
ch <- iterId
iterId = l.nodes[iterId].PreviousId
}
}()
return ch
}
func (l *DoubleLinkedList[T]) GetById(id DllId) (T, bool) {
if d, ok := l.data[id]; ok {
return d, ok
} else {
var empty T
return empty, false
}
//for iterId := range l.IterIds() {
// if iterId == id {
// return l.data[id], true
// }
//}
//var nilValue T
//return nilValue, false
}
func (l *DoubleLinkedList[T]) Last() (T, bool) {
if l.IsEmpty() {
var empty T
return empty, false
}
return l.data[l.lastGeneratedId], true
}
func (l *DoubleLinkedList[T]) LastId() (DllId, bool) {
if l.IsEmpty() {
return -1, false
}
return l.LastNode, true
}
func (l *DoubleLinkedList[T]) FirstId() (DllId, bool) {
if l.IsEmpty() {
return -1, false
}
return l.FirstNode, true
}
func (l *DoubleLinkedList[T]) NextId(id DllId) (DllId, bool) {
nextId := l.nodes[id].NextId
return nextId, nextId > -1
}
func (l *DoubleLinkedList[T]) previousNode(node *DLLNode) *DLLNode {
if node.PreviousId != -1 {
return l.nodes[node.PreviousId]
}
return nil
}
func (l *DoubleLinkedList[T]) nextNode(node *DLLNode) *DLLNode {
if node.NextId != -1 {
return l.nodes[node.NextId]
}
return nil
}
func (l *DoubleLinkedList[T]) insertBetween(before *DLLNode, after *DLLNode, data T) (DllId, bool) {
if before == nil && after == nil {
return l.insertEmpty(data), true
}
if before == nil {
return l.InsertFirst(data), true
}
if after == nil {
return l.InsertLast(data), true
}
id := l.nextId()
node := standaloneNode(id)
l.data[id] = data
l.nodes[id] = node
node.PreviousId = before.Id
node.NextId = after.Id
before.NextId = id
after.PreviousId = id
l.length++
return id, true
}
func (l *DoubleLinkedList[T]) GroupByInPlace(combineValues func(a, b T) (T, bool)) {
for node := l.nodes[l.FirstNode]; node.NextId > -1; node = l.nodes[node.NextId] {
if _, ok := combineValues(l.data[node.Id], l.data[node.NextId]); ok {
//l.InsertAfter(nodeId, combinedVal)
//toRemove = append(toRemove, nodeId)
}
}
}
func (l *DoubleLinkedList[T]) FilterInPlace(predicate func(a T) bool) {
toRemove := make([]DllId, 0)
for node := range l.IterNodes() {
//node := l.nodes[nodeId]
if !predicate(l.data[node.Id]) {
toRemove = append(toRemove, node.Id)
}
}
for _, id := range toRemove {
l.RemoveById(id)
}
}
func (l *DoubleLinkedList[T]) RemoveById(id DllId) {
node := l.nodes[id]
if nextNode, nextOk := l.nodes[node.NextId]; nextOk {
nextNode.PreviousId = node.PreviousId
}
if prevNode, prevOk := l.nodes[node.PreviousId]; prevOk {
prevNode.NextId = node.NextId
}
delete(l.data, id)
delete(l.nodes, id)
l.length--
}
+6
View File
@@ -0,0 +1,6 @@
package main
const mockInput = "2333133121414131402"
const realInput = "704219278632287990157699389137759051173674176731519296433286809791368032791140804947394872662883692030734066918811375380315365946839884166725631883721349744981219785931738783661388125291795094512825242653511224344529672845877440596053786651997438268528266165877583264557764173257385107419113787961030843576369495156648607657305874974661342619859328104531363471956724144212686069472359909869782614837687412570278737636326532376654382479287314266216918399170381077374510753227602710837636353716486681754835117825158969402129114465198022264725519819115325335973411693168734904771142148782070387338504289387764846941276757746745106522138751194925533964573938179464827312306659599452182915973931773888255284375737997926166063489425643510644965438594524948703271505840402183767662574395756016552120135818566767138019941474772631862790487823438346257220408227416143679949374873323944606175885554784117984240628282969861642587588081316998464783302311604413776524659055292565694491379767947834223730617422333962111675807050666964389321334639586438406155526685126488178765415817948095855244321294582248756310796353956453907355968841584393107856349270912239245445715589273071788831214557439060709564134360881547651179958190879894701433432977738692207939989951915983551493776054681662557142987527678584259263554537304599324220506430594950518666862663426287835874324142262721579546211173304934736454912427662334184787558628937176161679602724891043375294218580214260739346464948698982798732241896854288538099187411137974746434901631692573606226429880181516389418796266327260298787325960361527581291481417404452522966443131663178394133589820212292125531411782759679271593462979437141634681896082138332462488207471444329946249767575323412321173378682686024796654481211784156405870857435221296571115105059339579779771904127212214793622528470337959644850728854513529262416401354682568543684424381483155574661933711845891836982753826366117317554416372728991717630823285403332223781684166753854111049563271766977755588836967112637337875355710285421601448195983751392386558364097653427771013512333833593951620492537122418536197142032197429592329277138227725983470686227236281764368754949204348228212248889854666234923201525292679528910224727888834476936652438789232826886705483509247528051817144277195596489299872419292568399107114809019791839804160715093262986248890759289248970648690442935895837508094937099202079462562903523808241416640891381152029339355699956653833661235215273361626383781213644195485944652613782964784847886255227238478917746987128382016919028687045545840857788827523152731968998587290441697505297184553688731517364462420224682709452324249129437229692911683466367248157866750208281448448858758248320514399157077264628152883875742796392967085854872212318367547462922934582983429745394204086136781676964255411753885534184652819315595923281988090159416521151799778192164804871698212699320118785439220363234964731728327545039908116278440961017446371498776478831583448219897956127565137548495232060416927745696717626204971354091384694999543701029819071565380298388685692323480576687205295205949816011989047865594892429735788347778389263811898225663745237592111587429814450211424511475453937107227621843707121213235532618661188695253384221792152811474149959729473701465666110311517608082355251679226465859591476368390869048839266517357219314235214172277111760224025144847157653618635887740687526311113662198204683324741748285708492444899419999541269128386362920652392378212156230723499176234166058463111802893731862696348199270948215487723342682203286217072601912332139478096333756155197483538433553795989784843548692325572866645614833335410539475473448451488982767578185956684218867531311417888583516262123688492883938971242284067238781464880991744952895768345519544465680332240484322708056752755295691196658597065202527347057139848428223625374173376951371446869596014538195459583827018333246562659135934819829768233413738478921955743403632627190188684941519144923353410578764984829487476413258822087327080841525901970865490939855946650986812258878522841476833679930117484496067455170512583899982118166977853966616999972681097989284115247683655371543823094434420854170492975368425883634606237316289989585317346186090978532841116122569897892786811873264996774247661178084491673357330799660728214636381487583557480343472204986901044511424151695271357362643383344953348413627971490283937893756531590434343425947386857677498831691532873721924504887143693888993371036479340956877775649911189538989822372485719724691248154598668533577701748988672147624698486251570993699627417815046611827692676861138752543754526869310889712106226424417595238568982799464478181571194963322609077715963508019313334643532775862329682646172504541559818775361509249732552562776118189488558263073218866584084799519626621294110958473298554262796269449315343723052802316509727556623764589966647137149732020553087304456628112311181126776596350734280533499495951652537203141613283665049455821677172639438128435173918Line truncated
const mediumInput = "7042192786322879901576993891377590511736741767315192964332868097913680327911408049473948726628836920307340669188113753803153659468398841667256318837213497449812197859317387836613881252917950945128252426535112243445296728458774405960537866519974382685282661658775832645577641732573851074191137879610308435763694951566486076573058749746613426198593281045313634719567241442126860694723599098697826148376874125702787376363265323766543824792873142662169183991703810773745107532276027108376363537164866817548351178251589694021291144651980222647255198191153253359734116931687349047711421487820703873385042893877648469412767577467451065221387511949255339645739381794648273123066595994521829159739317738882552843757379979261660634894256435106449654385945249487032715058404021837676625743957560165521201358185667671380199414747726318627904878234383462572204082274161436799493748733239446061758855547841179842406282829698616425875880813169984647833023116044137765246590552925656944913797679478342237306174223339621116758070506669643893213346395864384061555266851264881787654158179480958552443212945822487563107963539564539073559688415843931078563492709122392454457155892730717888312145574390607095641343608815476511799581908798947014334329777386922079399899519159835514937760546816625571429875276785842592635545373045993242205064305949505186668626634262878358743241422627215795462111733049347364549124276623341847875586289371761616796027248910433752942185802142607393464649486989827987322418968542885380991874111379747464349016316925736062264298801815163894187962663272602987873259603615275812914814174044525229664431316631783941335898202122921255314117827596792715934629794371416346818960821383324624882074714443299462497675753234123211733786826860247966544812117841564058708574352212965711151050593395797797719041272122147936225284703379596448507288545135292624164013546825685436844243814831555746619337118458918369827538263661173175544163727289917176308232854033322237816841667538541110495632717669777555888369671126373378753557102854216014481959837513923865583640976534277710135123338335939516204925371224185361971420321974295923292771382277259834706862272362817643687549492043482282122488898546662349232015252926795289102247278888344769366524387892328268867054835092475280518171442771955964892998724192925683991071148090197918398041607150932629862488907592892489706486904429358958375080949370992020794625629035238082414166408913811520293393556999566538336612352152733616263837812136441954859446526137829647848478862552272384789177469871283820169190286870455458408577888275231527319689985872904416975052971845536887315173644624202246827094523242491294372296929116834663672481578667502082814484488587582483205143991570772646281528838757427963929670858548722123183675474629229345829834297453942040861367816769642554117538855341846528193155959232819880901594165211517997781921648048716982126993201187854392203632349647317283275450399081162784409610174463714987764788315834482198979561275651375484952320604169277456967176262049713540913846949995437010298190715653802983886856923234805766872052952059498160119890478655948924297357883477783892638118982256637452375921115874298144502114245114754539371072276218437071212132355326186611886952533842217921528114741499597294737014656661103115176080823552516792264658595914763683908690488392665173572193142352141722771117602240251448471576536186358877406875263111136621982046833247417482857084924448994199995412691283863629206523923782121562307234991762341660584631118028937318626963481992709482154877233426822032862170726019123321394780963337561551974835384335537959897848435486923255728666456148333354105394754734484514889827675781859566842188675313114178885835162621236884928839389712422840672387814648809917449528957683455195444656803322404843227080567527552956911966585970652025273470571398484282236253741733769513714468695960145381954595838270183332465626591359348198297682334137384789219557434036326271901886849415191449233534105787649848294874764132588220873270808415259019708654909398559466509868122588785228414768336799301174844960674551705125838999821181669778539666169999726810979892841152476836553715438230944344208541704929753684258836346062373162899895853173461860909785328411161225698978927868118732649967742476611780844916733573307996607282146363814875835574803434722049869010445114241516952713573626433833449533484136279714902839378937565315904343434259473868576774988316915328737219245048871436938889933710364793409568777756499111895389898223724857197246912481545986685335777017489886721476246984862515709936996274178150466118276926768611387525437545268693108897121062264244175952385689827994644781815711949633226090777159635080193133346435327758623296826461725045415598187753615092497325525627761181894885582630732188665840847995196266212941109584732985542627962694493153437230528023165097275566237645899666471371497320205530873044566281123111811267765963507342805334994959516525372031416132836650494558216771726394381284351739Line truncated
+154
View File
@@ -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))
}
+73
View File
@@ -0,0 +1,73 @@
package main
import (
"testing"
)
func TestParseString(t *testing.T) {
input := "00.23"
fs := parseString(input)
if ret := fs.String(); ret != input {
t.Errorf("Expected %s received %s", input, ret)
}
}
func TestDefragmentize1(t *testing.T) {
fs := parseString("00..11")
fs.OptimizeDiskFragmentation()
expt := "0011.."
if ret := fs.String(); ret != expt {
t.Errorf("Expected %s received %s", expt, ret)
}
}
func TestDefragmentize2(t *testing.T) {
fs := parseString("00.112")
fs.OptimizeDiskFragmentation()
expt := "00211."
if ret := fs.String(); ret != expt {
t.Errorf("Expected %s received %s", expt, ret)
}
}
func TestDefragmentize3(t *testing.T) {
fs := parseString("00...112.")
fs.OptimizeDiskFragmentation()
expt := "00211...."
if ret := fs.String(); ret != expt {
t.Errorf("Expected %s received %s", expt, ret)
}
}
func TestDefragmentize4(t *testing.T) {
fs := parseString("00...111...2...333.44.5555.6666.777.888899")
fs.OptimizeDiskFragmentation()
expt := "0099811188827773336446555566.............."
if ret := fs.String(); ret != expt {
t.Errorf("Expected %s received %s", expt, ret)
}
}
func TestFilterInPlace(t *testing.T) {
dll := NewDLL[int]()
dll.InsertFirst(4)
dll.InsertFirst(3)
dll.InsertFirst(2)
dll.InsertFirst(1)
dll.FilterInPlace(func(x int) bool { return x%2 == 0 })
}
func TestGroupByInPlace(t *testing.T) {
dll := NewDLL[int]()
dll.InsertFirst(4)
dll.InsertFirst(6)
dll.InsertFirst(3)
dll.InsertFirst(5)
dll.InsertFirst(2)
dll.GroupByInPlace(func(x, y int) (int, bool) {
if x%2 != y%2 {
return 0, false
}
return x + y, true
})
}