day13.ps (5798B)
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- day13.ps <day13.txt | display 19 20 /datafile (%stdin) (r) file def 21 /stderr (%stderr) (w) file def 22 23 % [ item_1 ... item_n ] item_0 -> [ item_0 item_1 ... item_n ] 24 /apush { 25 % array new_item 26 exch aload length 1 add array astore 27 } bind def 28 29 % [ item_0 ... item_n-1 ] item_n -> [ item_0 item_1 ... item_n ] 30 /aappend { 31 exch aload length 32 % new-item item-0 item-1 ... item-n-1 n 33 dup dup 2 add exch 1 add roll 34 % item-0 item-1 ... item-n-1 n new-item 35 exch 36 % item-0 item-1 ... item-n-1 new-item n 37 1 add array astore 38 } bind def 39 40 % [ item_0 item_1 ... item_n ] -> [ item_1 ... item_n ] item_0 41 /apop { 42 aload length 1 sub array astore exch 43 } bind def 44 45 % (item) -> item 46 /parse-item { 47 { % (suffix) 48 dup length 0 eq { pop exit } if 49 % (suffix) 50 { %%% 1-iteration loop to use `exit` as a short circuit 51 ([) anchorsearch 52 { % (next-suffix) ([) 53 pop [ exch 54 % mark (next-suffix) 55 exit 56 } if 57 58 (]) anchorsearch 59 { % (next-suffix) (]) 60 pop 61 % mark items (next-suffix) 62 counttomark 1 add 63 % mark items (next-suffix) item-count+2 64 1 roll 65 % (next-suffix) mark items 66 ] exch 67 % array (next-suffix) 68 exit 69 } if 70 71 (,) anchorsearch 72 { % (next-suffix) (,) 73 pop exit 74 } if 75 76 0 { 77 % (suffix) digit-count 78 2 copy get 79 % (suffix) digit-count cur-char 80 dup 48 ge exch 57 le and 81 % (suffix) digit-count cur-char-is-digit? 82 { 1 add } 83 { exit } 84 ifelse 85 } loop 86 % (suffix) digit-count 87 dup 0 eq { 2.125 pstack quit } if 88 % (suffix) digit-count 89 2 copy 0 exch getinterval 90 % (suffix) digit-count (num) 91 cvi 3 1 roll 92 % num (suffix) digit-count 93 1 index length 1 index sub getinterval 94 % num (next-suffix) 95 exit 96 } loop 97 } loop 98 } bind def 99 100 % left right -> num 101 % -1 if left < right 102 % 0 if left = right 103 % 1 if left > right 104 /cmp-items { 105 % left right 106 1 index type /integertype eq 107 { % int-left right 108 dup type /integertype eq 109 { % int-left int-right 110 2 copy eq 111 { pop pop 0 } 112 { lt { -1 } { 1 } ifelse} 113 ifelse 114 % result 115 } 116 { % int-left list-right 117 exch 1 array astore exch 118 % list-left list-right 119 cmp-items 120 % result 121 } 122 ifelse 123 } 124 { % list-left right 125 dup type /integertype eq 126 { % list-left int-right 127 1 array astore 128 % list-left list-right 129 cmp-items 130 % result 131 } 132 { 0 % list-left list-right index 133 { 134 2 index length 1 index le 135 % list-left list-right index list-left-too-short? 136 2 index length 2 index le 137 % list-left list-right index list-left-too-short? list-right-too-short? 138 2 copy or 139 { 2 copy and 140 { pop pop pop pop pop 0 } 141 { 5 1 roll pop pop pop pop { 1 } { -1 } ifelse } 142 ifelse 143 % result 144 exit 145 } 146 { pop pop } 147 ifelse 148 % list-left list-right index 149 2 index 1 index get 150 % list-left list-right index left-item 151 2 index 2 index get 152 % list-left list-right index left-item right-item 153 cmp-items 154 % list-left list-right index item-cmp 155 dup 0 eq 156 { pop } 157 { 4 1 roll pop pop pop exit } 158 ifelse 159 % list-left list-right index 160 1 add 161 % list-left list-right next-index 162 } loop 163 % result 164 } 165 ifelse 166 } 167 ifelse 168 } bind def 169 170 /data [ 171 [ 172 { 173 datafile 200 string readline 174 not { pop exit } if 175 % line 176 dup length 0 eq 177 { pop ] [ } 178 { parse-item } 179 ifelse 180 } loop 181 ] 182 ] def 183 184 185 /Helvetica 20 selectfont 186 187 188 (First Puzzle: ) 189 72 700 moveto show 190 0 0 data { 191 % sum prev-rank pair 192 exch 1 add exch 193 % sum rank pair 194 dup length 2 eq not 195 { 1.125 pstack quit } if 196 % sum rank pair 197 aload pop 198 % sum rank left right 199 cmp-items 200 % sum rank cmp 201 stderr (Pair ) writestring 202 stderr 2 index 15 string cvs writestring 203 stderr (: ) writestring 204 stderr 1 index 15 string cvs writestring 205 stderr 10 write 206 % sum rank cmp 207 -1 eq 208 { exch 1 index add exch } if 209 % sum rank 210 } forall 211 pop 212 % sum 213 15 string cvs show 214 215 216 (Second Puzzle: ) 217 72 664 moveto show 218 219 1 [[2]] 2 [[6]] 0 data { 220 % rank-A item-A rank-B item-B prev-index pair 221 exch 1 add exch 222 % rank-A item-A rank-B item-B index pair 223 { 224 % rank-A item-A rank-B item-B index item 225 dup 5 index cmp-items -1 le 226 % rank-A item-A rank-B item-B index item item<item-A? 227 { 6 5 roll 1 add 6 1 roll } if 228 % rank-A item-A rank-B item-B index item 229 2 index cmp-items -1 le 230 % rank-A item-A rank-B item-B index item<item-B? 231 { 3 2 roll 1 add 3 1 roll } if 232 % rank-A item-A rank-B item-B index 233 } forall 234 % rank-A item-A rank-B item-B index 235 } forall 236 % rank-A item-A rank-B item-B index 237 pop pop exch pop 238 % rank-A rank-B 239 240 1 index 15 string cvs show 241 ( * ) show 242 dup 15 string cvs show 243 ( = ) show 244 mul 15 string cvs show 245 246 showpage 247 quit