1.tcl 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/env tclsh
  2. set fp [open input r]
  3. set map ""
  4. while {1} {
  5. set ret [gets $fp line]
  6. if {$ret == -1} {
  7. break
  8. }
  9. if {[string length $line] == 0} {
  10. break
  11. }
  12. lappend map $line
  13. }
  14. proc char_at {x y} {
  15. set line [lindex $::map $y]
  16. return [string index $line $x]
  17. }
  18. set height [llength $map]
  19. set width [string length [lindex $map 0]]
  20. proc find_start {} {
  21. for {set i 0} {$i < $::width} {incr i} {
  22. for {set j 0} {$j < $::height} {incr j} {
  23. if {[char_at $i $j] == "^"} {
  24. return "$i $j"
  25. }
  26. }
  27. }
  28. }
  29. set start_point [find_start]
  30. proc front_point {x y direction} {
  31. if {$direction == "up"} {
  32. return [list $x [expr {$y - 1}]]
  33. } elseif {$direction == "down"} {
  34. return [list $x [expr {$y + 1}]]
  35. } elseif {$direction == "left"} {
  36. return [list [expr {$x - 1}] $y]
  37. } elseif {$direction == "right"} {
  38. return [list [expr {$x + 1}] $y]
  39. }
  40. }
  41. proc out_of_range {x y} {
  42. return [expr {
  43. ($x < 0) || ($x >= $::width) || ($y < 0) || ($y >= $::height)
  44. }]
  45. }
  46. proc turn_right {direction} {
  47. if {$direction == {up}} {
  48. return right
  49. } elseif {$direction == {down}} {
  50. return left
  51. } elseif {$direction == {right}} {
  52. return down
  53. } else {
  54. return up
  55. }
  56. }
  57. proc next_state {x y direction} {
  58. set forward [front_point $x $y $direction]
  59. if {[out_of_range {*}$forward]} {
  60. return [list {*}$forward $direction]
  61. }
  62. if {[char_at {*}$forward] == {#}} {
  63. set forward [front_point $x $y [turn_right $direction]]
  64. return [list {*}$forward [turn_right $direction]]
  65. } else {
  66. return [list {*}$forward $direction]
  67. }
  68. }
  69. set state [list {*}$start_point up]
  70. set visited {}
  71. while {![out_of_range {*}[lrange $state 0 1]]} {
  72. dict set visited [lrange $state 0 1] {}
  73. set state [next_state {*}$state]
  74. }
  75. puts [dict size $visited]