day24.ps (5636B)
1 %!PS 2 % 3 % Copyright (c) 2022, Natacha Porté 4 % 5 % Permission to use, copy, modify, and distribute this software for any 6 % purpose with or without fee is hereby granted, provided that the above 7 % copyright notice and this permission notice appear in all copies. 8 % 9 % THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 % WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 % MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 % ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 % WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 % ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 % OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 % 17 % Usage: 18 % gs -q- -sDEVICE=png16m -o- day24.ps <day24.txt | display 19 20 /datafile (%stdin) (r) file def 21 /stderr (%stderr) (w) file def 22 23 /data [ 24 { 25 datafile 200 string readline 26 not { exit } if 27 } loop 28 pop 29 ] def 30 31 /width data 0 get length def 32 /starty 0 def 33 /endy data length 1 sub def 34 35 /init-wind-list [ 36 -1 data { 37 % ... prev-y line 38 exch 1 add exch -1 exch 39 % ... y -1 line 40 { 41 % ... y prev-x char 42 exch 1 add exch 43 % ... y x char 44 dup 94 eq { % `^` 45 [ 2 index 4 index 0 -1 ] 4 1 roll 46 } if 47 dup 118 eq { % `v` 48 [ 2 index 4 index 0 1 ] 4 1 roll 49 } if 50 dup 62 eq { % `>` 51 [ 2 index 4 index 1 0 ] 4 1 roll 52 } if 53 dup 60 eq { % `<` 54 [ 2 index 4 index -1 0 ] 4 1 roll 55 } if 56 dup 46 eq { % `.` 57 2 index 0 eq { 58 /startx 2 index def 59 } if 60 2 index endy eq { 61 /endx 2 index def 62 } if 63 } if 64 % ... y x char 65 pop 66 } forall 67 % ... y x 68 pop 69 } forall 70 % ... y 71 pop 72 ] def 73 74 % prev-x prev-y dx dy -> x y dx dy 75 /next-wind { 76 % prev-x prev-x dx dy 77 4 2 roll 78 % dx dy prev-x prev-y 79 exch 3 index add exch 2 index add 80 % dx dy tentative-x tentative-y 81 dup 0 eq { pop endy 1 sub } if 82 dup endy eq { pop 1 } if 83 % dx dy tentative-x y 84 exch 85 dup 0 eq { pop width 2 sub } if 86 dup width 1 sub eq { pop 1 } if 87 exch 88 % dx dy x y 89 4 2 roll 90 } bind def 91 92 % prev-wind-list -> wind-list 93 /next-wind-list { 94 % prev-wind-list 95 [ exch 96 % mark prev-wind-list 97 { 98 % ... prev-wind-array 99 aload pop 100 next-wind 101 4 array astore 102 % ... new-wind-array 103 } forall 104 ] 105 } bind def 106 107 % wind-list -> wind-dict 108 /wind-dict { 109 << exch 110 { 111 % ... wind-array 112 aload pop pop pop 113 % ... x y 114 width mul add 115 % ... key 116 1 117 } forall 118 >> 119 } bind def 120 121 122 % prev-time prev-wind-list prev-pos-dict -> time wind-list pos-dict 123 /cycle { 124 % prev-time prev-wind-list pos-dict 125 3 2 roll 1 add 3 1 roll 126 % time prev-wind-list pos-dict 127 exch next-wind-list exch 128 % time wind-list pos-dict 129 1 index wind-dict exch 130 % time wind-list wind-dict pos-dict 131 endy width mul dict exch 132 % time wind-list wind-dict next-pos-dict pos-dict 133 { pop 134 % time wind-list wind-dict next-pos-dict key 135 dup width mod exch width idiv 136 % time wind-list wind-dict next-pos-dict x y 137 movelist { aload pop 138 % time wind-list wind-dict next-pos-dict x y dx dy 139 exch 3 index add exch 2 index add 140 % time wind-list wind-dict next-pos-dict x y next-x next-y 141 true 142 2 index 0 gt and 143 % dup { ( true\012) } { ( false\012) } ifelse stderr exch writestring 144 2 index width 1 sub lt and 145 1 index 0 ge and 146 1 index endy le and 147 1 index starty gt 3 index startx eq or and 148 1 index endy lt 3 index endx eq or and 149 % time wind-list wind-dict next-pos-dict x y next-x next-y is-valid? 150 { 151 width mul add 152 % time wind-list wind-dict next-pos-dict x y next-key 153 4 index 1 index known 154 4 index 1 index known or 155 % time wind-list wind-dict next-pos-dict x y next-key is-known? 156 not { 157 % time wind-list wind-dict next-pos-dict x y next-key 158 3 index 1 index 1 put 159 } if 160 % time wind-list wind-dict next-pos-dict x y next-key 161 pop 162 } 163 { pop pop } 164 ifelse 165 % time wind-list wind-dict next-pos-dict x y 166 } forall 167 % time wind-list wind-dict next-pos-dict x y 168 pop pop 169 } forall 170 % time wind-list wind-dict next-pos-dict 171 exch pop 172 % time wind-list next-pos-dict 173 } bind def 174 175 176 /Helvetica 20 selectfont 177 178 179 (First Puzzle: ) 180 72 700 moveto show 181 182 /endkey endy width mul endx add def 183 /movelist [[0 0] [0 1] [0 -1] [1 0] [-1 0]] def 184 0 init-wind-list << startx 1 >> 185 { % prev-time prev-wind-list pos-dict 186 cycle 187 % time next-wind-list next-pos-dict 188 % dup { pop 189 % dup width mod exch width idiv 190 % % time next-wind-list next-pos-dict x y 191 % stderr 5 index 15 string cvs writestring 192 % stderr (: ) writestring 193 % stderr 2 index 15 string cvs writestring 194 % stderr (, ) writestring 195 % stderr 1 index 15 string cvs writestring 196 % stderr 10 write 197 % pop pop 198 % } forall 199 % stderr (Cycle ) writestring 200 % stderr 3 index 15 string cvs writestring 201 % stderr (, ) writestring 202 % stderr 1 index length 15 string cvs writestring 203 % stderr ( states\012) writestring 204 % stderr flushfile 205 % time next-wind-list next-pos-dict 206 dup endkey known { exit } if 207 dup length 0 eq { 1.125 pstack quit } if 208 } loop 209 % time next-wind-list next-pos-dict 210 2 index 15 string cvs show 211 % time next-wind-list next-pos-dict 212 213 (Second Puzzle: ) 214 72 664 moveto show 215 216 % time next-wind-list next-pos-dict 217 pop << endkey 1 >> 218 { cycle dup startx known { exit } if } loop 219 pop << startx 1 >> 220 { cycle dup endkey known { exit } if } loop 221 2 index 15 string cvs show 222 223 showpage 224 quit