2.tcl 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. set fp [open "input"]
  2. gets $fp line
  3. close $fp
  4. set line_len [string length $line]
  5. set layout {}
  6. set is_file 1
  7. set file_no 0
  8. for {set i 0} {$i < $line_len} {incr i} {
  9. set num [string index $line $i]
  10. if {$is_file} {
  11. for {set j 0} {$j < $num} {incr j} {
  12. lappend layout $file_no
  13. }
  14. incr file_no
  15. } else {
  16. for {set j 0} {$j < $num} {incr j} {
  17. lappend layout -1
  18. }
  19. }
  20. set is_file [expr {! $is_file}]
  21. }
  22. proc swap {lst lstart rstart len} {
  23. upvar $lst uplst
  24. set lend [expr {$lstart + $len - 1}]
  25. set rend [expr {$rstart + $len - 1}]
  26. set t [lrange $uplst $rstart $rend]
  27. set uplst [lreplace $uplst $rstart $rend {*}[lrange $uplst $lstart $lend]]
  28. set uplst [lreplace $uplst $lstart $lend {*}$t]
  29. }
  30. proc skip_space {layout rp} {
  31. while {[lindex $layout $rp] == -1 && $rp >= 0} {
  32. incr rp -1
  33. }
  34. return $rp
  35. }
  36. proc find_next_file {layout rp} {
  37. set c [lindex $layout $rp]
  38. while {$rp >= 0 && [lindex $layout $rp] == $c} {
  39. incr rp -1
  40. }
  41. incr rp
  42. return $rp
  43. }
  44. proc find_space {layout len end} {
  45. set size 0
  46. for {set i 0} {$i < $end} {incr i} {
  47. set x [lindex $layout $i]
  48. if {$x == -1} {
  49. incr size
  50. }
  51. if {$size == $len} {
  52. return [expr {$i - $len + 1}]
  53. }
  54. if {$x != -1} {
  55. set size 0
  56. }
  57. }
  58. return -1
  59. }
  60. set rp [expr {[llength $layout] - 1}]
  61. while {$rp >= 0} {
  62. set rp [skip_space $layout $rp]
  63. if {$rp < 0} { break }
  64. set new_rp [find_next_file $layout $rp]
  65. set len [expr {$rp - $new_rp + 1}]
  66. if {$rp < 0} { break }
  67. set lp [find_space $layout $len $new_rp]
  68. if {$lp >= 0} {
  69. swap layout $lp $new_rp $len
  70. }
  71. set rp $new_rp
  72. incr rp -1
  73. }
  74. set checksum 0
  75. set i 0
  76. while {1} {
  77. if {$i >= [llength $layout]} {
  78. break
  79. }
  80. if {([lindex $layout $i] == -1)} {
  81. incr i
  82. continue
  83. }
  84. incr checksum [expr {[lindex $layout $i] * $i}]
  85. incr i
  86. }
  87. puts $checksum