-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path06.tcl
executable file
·135 lines (132 loc) · 3.21 KB
/
06.tcl
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env tclsh
proc aoc_06 { } {
global map visited
set res [list]
set d [aoc_read "06.data"]
aoc_parse_map $d
aoc_save_map
## = Part 1 =
aoc_play
lappend res [aoc_count_pos]
## = Part 2 =
set count 0
foreach lock [array names visited] {
aoc_load_map
lset map $lock "O"
if { [aoc_play] == 2 } {
puts -nonewline "+"
incr count
} else {
puts -nonewline "."
}
flush stdout
}
puts ""
lappend res $count
return $res
}
proc aoc_play { {i 0} } {
while { 1 } {
if {$i} {
exec clear >@stdout
aoc_show_map
gets stdin
}
set reason [aoc_move_map]
if {$reason} {
break
}
}
return $reason
}
proc aoc_count_pos { } {
global map
llength [regexp -all -inline {[\^><v]} $map]
}
proc aoc_parse_map { d } {
global map pos_y pos_x state
set map [lmap l [split [string trim $d] "\n"] {split $l ""}]
for {set y 0} {$y < [llength $map]} {incr y} {
for {set x 0} {$x < [llength [lindex $map $y]]} {incr x} {
set c [lindex $map $y $x]
if { [lsearch -exact {"<" "^" ">" "v"} $c] != -1 } {
set pos_y $y
set pos_x $x
set state $c
lset map $y $x "."
}
}
}
}
proc aoc_save_map { } {
global s_map s_pos_y s_pos_x s_state map pos_y pos_x state
set s_map $map
set s_pos_y $pos_y
set s_pos_x $pos_x
set s_state $state
}
proc aoc_load_map { } {
global s_map s_pos_y s_pos_x s_state map pos_y pos_x state
set map $s_map
set pos_y $s_pos_y
set pos_x $s_pos_x
set state $s_state
}
proc aoc_show_map { } {
global map pos_y pos_x state
for {set y 0} {$y < [llength $map]} {incr y} {
for {set x 0} {$x < [llength [lindex $map $y]]} {incr x} {
if {$y == $pos_y && $x == $pos_x} {
puts -nonewline $state
} else {
puts -nonewline [lindex $map $y $x]
}
}
puts ""
}
}
proc aoc_move_map { } {
global map pos_y pos_x state visited
set ny $pos_y
set nx $pos_x
switch $state {
"^" { incr ny -1 }
">" { incr nx 1 }
"<" { incr nx -1 }
"v" { incr ny 1 }
}
if {[lindex $map $pos_y $pos_x] == $state} {
# Loop (been here)
return 2
}
set visited([list $pos_y $pos_x]) 1
set g [lindex $map $ny $nx]
switch $g {
"" {
lset map $pos_y $pos_x $state
# Exited
return 1
}
"#" - "O" {
switch $state {
"^" { set state ">" }
">" { set state "v" }
"<" { set state "^" }
"v" { set state "<" }
}
}
default {
lset map $pos_y $pos_x $state
set pos_y $ny
set pos_x $nx
}
}
return 0
}
## -------------------------------------------------------------------
if {[file tail $argv0] eq [file tail [info script]]} {
source "rd.tcl"
# Example results: 41, 6
# My results: 4580, 1480
puts [aoc_06]
}