diff options
author | Aleteoryx <alyx@aleteoryx.me> | 2024-12-09 22:22:04 -0500 |
---|---|---|
committer | Aleteoryx <alyx@aleteoryx.me> | 2024-12-09 22:22:04 -0500 |
commit | 4e699214a9fc35ede70becbd7f5e242732a8c50c (patch) | |
tree | e2fc0817e832cab07d6316d817edf860060e2ce7 /2024/tcl | |
parent | 0f6d3c97e450d129b020b6fe2f3d63bc0bc7aa61 (diff) | |
download | adventofcode-4e699214a9fc35ede70becbd7f5e242732a8c50c.tar.gz adventofcode-4e699214a9fc35ede70becbd7f5e242732a8c50c.tar.bz2 adventofcode-4e699214a9fc35ede70becbd7f5e242732a8c50c.zip |
2024.9
Diffstat (limited to '2024/tcl')
-rwxr-xr-x | 2024/tcl/09.tcl | 111 | ||||
-rw-r--r-- | 2024/tcl/lib.tcl | 2 |
2 files changed, 112 insertions, 1 deletions
diff --git a/2024/tcl/09.tcl b/2024/tcl/09.tcl new file mode 100755 index 0000000..38a156c --- /dev/null +++ b/2024/tcl/09.tcl @@ -0,0 +1,111 @@ +#!/bin/env tclsh + +source lib.tcl +setup 9 data + +puts {Part 1: Compacted Filesystem Checksum} + +## PARSE +set disk {} +set steps 0 +for {set i 0} {$i < [string length $input]} {incr i} { + set chunk [ + if {$i % 2 == 0} { + expr {$i / 2} + } else { + incr steps [string index $input $i] + expr {"."} + }] + append disk [string repeat "$chunk " [string index $input $i]] +} + +## COMPACT +set free_idx -1 +for {set i 0} {$i < $steps} {incr i} { + set fid [lindex $disk end-$i] + if {$fid == "."} continue + + set free_idx [lsearch -start $free_idx+1 -exact $disk .] + + lset disk end-$i . + lset disk $free_idx $fid +} + +set disk [lrange $disk 0 end-$steps] + +## CHECKSUM +set checksum 0 +for {set i 0} {$i < [llength $disk]} {incr i} { + incr checksum [expr {[lindex $disk $i] * $i}] +} + +puts "Checksum: $checksum" + +puts "" +puts {Part 2: Unfragmented Compacted Filesystem Checksum} + +## PARSE +set disk {} +set steps 0 +for {set i 0} {$i < [string length $input]} {incr i} { + if {[string index $input $i] == 0} continue + lappend disk [list [expr {$i % 2 == 0 ? $i / 2 : "."}] [string index $input $i]] +} + +## COMPACT +set free_idx -1 +set max_fid [llength $disk] +for {set i [expr {[llength $disk] - 1}]} {$i >= 0} {incr i -1} { + lassign [lindex $disk $i] fid flen + if {$fid == "."} continue + if {$fid >= $max_fid} continue + set max_fid $fid + +# puts "fid: $fid" + + + set free_idx [lsearch -start $free_idx -index 0 -exact $disk .] + + # find large enough free space or bail + set usable_free_idx $free_idx +# puts "first free_idx: [lindex $disk $usable_free_idx 1] // $flen" + while {[lindex $disk $usable_free_idx 1] < $flen} { +# puts "in this loop" + set usable_free_idx [lsearch -start $usable_free_idx+1 -index 0 -exact $disk .] + if {$usable_free_idx == -1} break + } +# puts "free_idx: $usable_free_idx // $i" + if {$usable_free_idx == -1 || $usable_free_idx > $i} continue + + set free_len [lindex $disk $usable_free_idx 1] +# puts "free_len: $free_len // $flen" + if {$free_len == $flen} { + lset disk $usable_free_idx [list $fid $flen] + } else { + set disk [lreplace $disk $usable_free_idx $usable_free_idx \ + [list $fid $flen] \ + [list . [expr {$free_len - $flen}]]] + incr i + } + + # this can create sequences like {20 1} {. 4} {. 5} {. 3} {22 6} but it won't matter + lset disk $i [list . $flen] +} + +## CHECKSUM +set checksum 0 +set idx 0 +foreach chunk $disk { + lassign $chunk fid flen + if {$fid == "."} { + incr idx $flen + continue + } + + set extent [expr {$idx + $flen}] + for {} {$idx < $extent} {incr idx} { + incr checksum [expr {$idx * $fid}] + } +} + +puts "Checksum: $checksum" diff --git a/2024/tcl/lib.tcl b/2024/tcl/lib.tcl index 588a5e8..9222b78 100644 --- a/2024/tcl/lib.tcl +++ b/2024/tcl/lib.tcl @@ -13,7 +13,7 @@ proc setup {n {mode lines}} { close $fd } data { - set input [read $fd] + set input [string trim [read $fd]] close $fd } fd { |