#!/usr/bin/env tclsh9.0 namespace import ::tcl::mathop::* proc defrag {line} { set disk [list] set state 0 set id 0 set block 0 foreach c [split $line ""] { if {! [string is digit $c]} continue switch -- $state { 0 { for {set i 0} {$i < $c} {incr i} { lappend disk $id incr block } if {$c != 0} {incr id} set state 1 } 1 { for {set i 0} {$i < $c} {incr i} { lappend disk -1 lappend free $block incr block } set state 0 } } } set last [- [llength $disk] 1] while {[llength $free]} { # if {$last <= 50135} { # puts "Loop, last=$last free=[lrange $free 0 9]" # puts "Disk starting 50120: [lrange $disk 50120 50140]" # } # Abort if there are no more file blocks to move. if {[lindex $free 0] >= $last} break # Find last file block. while {[lindex $disk $last] < 0} { incr last -1 } # Abort if it's already in place. if {[lindex $free 0] >= $last} break # Move it to the first free spot. set j [lindex $free 0] lset disk $j [lindex $disk $last] lset disk $last -1 incr last -1 set free [lrange $free 1 end] # puts "[join $disk ""] last=$last free=$free" } # puts "After defrag, last=$last free=[lrange $free 0 9] ..." # puts "Disk = [lrange $disk 0 19] ..." # puts "Disk starting 50120: [lrange $disk 50120 50140]" return $disk } proc checksum {disk} { set i 0 set sum 0 while {[lindex $disk $i] >= 0} { incr sum [* [lindex $disk $i] $i] incr i } return $sum } set line [read stdin] set disk [defrag $line] puts [checksum $disk] # 6349343813585 too low