aboutsummaryrefslogtreecommitdiff
path: root/09/2.tcl
blob: dd4fb9b5024a73731a22c3749a2bd8d40a7c5eb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
set fp [open "input"]
gets $fp line
close $fp

set line_len [string length $line]
set layout {}
set is_file 1
set file_no 0
for {set i 0} {$i < $line_len} {incr i} {
    set num [string index $line $i]
    if {$is_file} {
        for {set j 0} {$j < $num} {incr j} {
            lappend layout $file_no
        }
        incr file_no
    } else {
        for {set j 0} {$j < $num} {incr j} {
            lappend layout -1
        }
    }
    set is_file [expr {! $is_file}]
}

proc swap {lst lstart rstart len} {
    upvar $lst uplst
    set lend [expr {$lstart + $len - 1}]
    set rend [expr {$rstart + $len - 1}]
    set t [lrange $uplst $rstart $rend]
    set uplst [lreplace $uplst $rstart $rend {*}[lrange $uplst $lstart $lend]]
    set uplst [lreplace $uplst $lstart $lend {*}$t]
}

proc skip_space {layout rp} {
    while {[lindex $layout $rp] == -1 && $rp >= 0} {
        incr rp -1
    }
    return $rp
}

proc find_next_file {layout rp} {
    set c [lindex $layout $rp]
    while {$rp >= 0 && [lindex $layout $rp] == $c} {
        incr rp -1
    }
    incr rp
    return $rp
}

proc find_space {layout len end} {
    set size 0
    for {set i 0} {$i < $end} {incr i} {
        set x [lindex $layout $i]
        if {$x == -1} {
            incr size
        }
        if {$size == $len} {
            return [expr {$i - $len + 1}]
        }
        if {$x != -1} {
            set size 0
        }
    }
    return -1
}

set rp [expr {[llength $layout] - 1}]

while {$rp >= 0} {
    set rp [skip_space $layout $rp]
    if {$rp < 0} { break }
    set new_rp [find_next_file $layout $rp]
    set len [expr {$rp - $new_rp + 1}]
    if {$rp < 0} { break }
    set lp [find_space $layout $len $new_rp]
    if {$lp >= 0} {
        swap layout $lp $new_rp $len
    }
    set rp $new_rp
    incr rp -1
}
set checksum 0
set i 0
while {1} {
    if {$i >= [llength $layout]} {
        break
    }
    if {([lindex $layout $i] == -1)} {
        incr i
        continue
    }
    incr checksum [expr {[lindex $layout $i] * $i}]
    incr i
}
puts $checksum