Advertisement
Guest User

Untitled

a guest
May 23rd, 2017
781
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.01 KB | None | 0 0
  1. Article 4818 of comp.programming:
  2. Path: news.u.washington.edu!netnews.nwnet.net!ogicse!decwrl!concert!news-feed-1.peachnet.edu!darwin.sura.net!cs.ucf.edu!schnitzi
  3. From: schnitzi@cs.ucf.edu (Mark Schnitzius)
  4. Newsgroups: comp.lang.c,comp.programming,rec.puzzles
  5. Subject: CONCISENESS CONTEST ROUND 2 -- first runner up
  6. Message-ID: <schnitzi.737039339@eola.cs.ucf.edu>
  7. Date: 10 May 93 13:08:59 GMT
  8. Article-I.D.: eola.schnitzi.737039339
  9. Sender: news@cs.ucf.edu (News system)
  10. Distribution: comp,rec
  11. Organization: University of Central Florida
  12. Lines: 220
  13. Xref: news.u.washington.edu comp.lang.c:49006 comp.programming:4818 rec.puzzles:19260
  14.  
  15.  
  16. int n, work[20], top, *ops;
  17.  
  18. /* layout of work array (where N is the number of input values; note
  19. ** that during the most of the code that follows, the variable n holds
  20. ** the value N+1):
  21. ** 0 : target value
  22. ** 1..N : values to be used in expression
  23. ** N+1..N+5 : stack area for evaluating expressions
  24. ** N+6..10 : unused (this area empty for N == 5)
  25. ** 11..19 : record preorder traversal of expression tree
  26. ** top is used to index into the stack area; ops points into the
  27. ** preorder traversal.
  28. */
  29.  
  30. /* note that we do not include stdio.h because doing so would strap us
  31. ** with the macro version of putchar, and that would preclude the
  32. ** conciseness optimization we made in printexp() below, which hides
  33. ** the right paren for putchar within another macro. This way,
  34. ** putchar is implicitly declared as an extern function, so the
  35. ** library version gets called.
  36. */
  37. /* #include <stdio.h> */
  38.  
  39.  
  40. #define SCANF scanf("%d",
  41.  
  42. main()
  43. {
  44. /* the following loop is very convoluted by the drive to conserve
  45. ** tokens. The outer while loop stops when scanf fails to read an
  46. ** integer from stdin. When it succeeds, the value goes into top,
  47. ** (though it will eventually be transferred into n (sort of)). If
  48. ** not for conciseness, the value would go directly into n, where it
  49. ** belongs. Instead, n ends up with the value 1 (value of the true
  50. ** boolean expression).
  51. */
  52. while (n = SCANF &top) == 1)
  53. /* Here's the inner loop. For now, concentrate on the first and
  54. ** last lines... ignoring what comes after "||", the while loop
  55. ** repeats top (which should be n) times, and each time it reads a
  56. ** new integer from stdin. The values are stored in the work
  57. ** array in consecutive locations, starting with 1 (if not for
  58. ** conciseness that would have been 0). When all values have been
  59. ** read, top is -1, n is one more than the number of input values,
  60. ** and the input values are stored in work[1...n-1]. Then the
  61. ** first piece of the while condition fails, so the following
  62. ** alternative is executed (it would be in code following the loop
  63. ** if not for conciseness).
  64. */
  65. while (top-- ||
  66. /* This code should be thought of as following the while loop,
  67. ** as it only executes after the last real iteration. On entry,
  68. ** we have top = -1, and n-1 input values in work[1..n-1]. We
  69. ** scan the target number into work[0], and then invoke testeval
  70. ** to search for solutions. The first arg to testeval is a bit
  71. ** mask that looks like 0...01...10, with a 1 in positions
  72. ** 1...n-1 (counting from the right, starting with 0). Thus
  73. ** there's a 1 bit corresponding to every position in the work
  74. ** array holding an input value. The scanf that reads in the
  75. ** target value returns 1, and that's used in building the mask.
  76. ** The other arguments are unused, and their sole purpose is to
  77. ** initialize some things before testeval actually starts
  78. ** computing, namely: ops will point to the top end of the work
  79. ** array, where the successful expression, if any, will be
  80. ** recorded; and top is made to index the element of the work
  81. ** array just prior to the area that will be used as an
  82. ** expression evaluation stack (if not for conciseness, this
  83. ** stack would be its own array, and top would be set to -1).
  84. ** The return value of testeval is used to select a printf
  85. ** format string corresponding to success or failure, and in the
  86. ** former case, printexp is also called in the process, to print
  87. ** the winning expression. Note that printf will return a
  88. ** nonzero value, so !printf(...) will return zero, causing the
  89. ** inner while loop to terminate in either case, as required.
  90. */
  91. !printf(testeval((SCANF work)<<n)-2, ops=work+19, top += n)
  92. ? printexp(0), "=%d\n"
  93. : "TARGET NUMBER UNREACHABLE\n", *work))
  94. SCANF work+n++); /* the inner loop body */
  95. }
  96.  
  97.  
  98. /* testeval takes two legitimate args (y is just a local int):
  99. ** avail = mask showing which input values are still unused in the
  100. ** current expression: bit (1 << i) on means vals[i] has not yet
  101. ** been used and can therefore be pushed onto the stack (i ranges
  102. ** from 1..n-1)
  103. ** x = value currently at top of stack (or arbitrary value if stack
  104. ** is empty)
  105. **
  106. ** We build all possible expressions using the n input values, and
  107. ** evaluate each one to see whether it equals the target. If so, we
  108. ** return through the recursion with the ops pointer intact.
  109. **
  110. ** The evaluation is performed by means of a stack, which lives within
  111. ** the work array, just past the last input value. Each operation
  112. ** either pushes a value onto the stack, or pops two values, applies a
  113. ** binary operator to them, and pushes the result. The expression
  114. ** itself is recorded in the right portion of the work array,
  115. ** addressed via the pointer "ops". Each operation is recorded either
  116. ** as a non-negative integer (meaning that value was pushed onto the
  117. ** stack) or a negative integer encoding a binary operation: -1 => +,
  118. ** -9 => -, -17 => *, -25 => /. (The codes are spaced by eight in
  119. ** order to support the parenthesizing code in printexp() below.)
  120. ** Following a successful evaluation, ops points to the beginning of a
  121. ** preorder traversal of the expression tree.
  122. **
  123. ** Note: if op codes could be 0, -8, -16, -24, we could save two
  124. ** tokens in printexp() below. But that would mean additions and
  125. ** pushes of zeros would be indistinguishable. The original problem
  126. ** statement was self-contradictory as to whether zero input values
  127. ** need be handled, but the contest moderator clarified in the
  128. ** affirmative.
  129. **/
  130.  
  131. #define SETTOP , work[top] =
  132. #define TRYLEFT testeval(avail SETTOP x
  133. #define TRYRIGHT y, *ops-- -= 8) ||
  134.  
  135. testeval(avail,x)
  136. {
  137. int y = n;
  138. top++;
  139.  
  140. /* first see if there are any unused values to push */
  141. while (y--)
  142. if (avail & 1<<y && testeval(avail ^ 1<<y SETTOP *ops-- = work[y]))
  143. return 1;
  144.  
  145. /* no luck pushing new values... if there are at least */
  146. /* two values on the stack, try reducing by applying a binary op */
  147. return --top > n ? y = work[--top], *ops = 7,
  148. TRYLEFT + TRYRIGHT TRYLEFT - TRYRIGHT TRYLEFT * TRYRIGHT
  149. y && x%y == 0 && TRYLEFT / TRYRIGHT
  150. /* following case is when all binops failed... fix the stack and fail */
  151. (ops++ SETTOP y, top++ SETTOP x, 0)
  152. /* here when the stack had less than two values. Three cases:
  153. ** (1) it was empty, in which case avail != 0, and we're not
  154. ** interested; (2) it contains one element but there are still
  155. ** numbers to be pushed, in which case avail != 0 and we're not
  156. ** interested; (3) we bottomed out, and the sole stack element
  157. ** is the value of the current expression, in which case avail
  158. ** == 0 and we're interested
  159. */
  160. : ops++ && !avail && x == *work;
  161. }
  162.  
  163. /* printexp prints the expression stored in the top of the work array,
  164. ** starting at the element pointed to by ops. If the element in this
  165. ** position is the encoding of a binary operator, printexp is called
  166. ** twice recursively to print the subexpressions, with the operator
  167. ** printed between the recursive calls. Otherwise the value in the
  168. ** ops array is printed as a decimal integer. Each call to printexp
  169. ** leaves ops pointing just past the last element that was part of the
  170. ** expression printed by this call.
  171. **
  172. ** Whether or not a given expression needs to be parenthesized depends
  173. ** on the opcode, that of the immediate parent expression, and whether
  174. ** this expression is the left or right child of its parent. The
  175. ** rules can be encoded in two 4x4 tables, as shown below. The
  176. ** operations across the top represent the parent's opcode, and those
  177. ** along the left side are the child's.
  178. **
  179. ** For left child: For right child:
  180. **
  181. ** + - * / + - * /
  182. ** + 0 0 1 1 + 0 1 1 1
  183. ** - 0 0 1 1 - 0 1 1 1
  184. ** * 0 0 0 0 * 0 0 0 1
  185. ** / 0 0 0 0 / 0 0 0 1
  186. **
  187. ** In the above tables, a 0 means the child expression need not be
  188. ** parenthesized, and a 1 means parens are needed.
  189. **
  190. ** printexp takes a single argument, of which only the low-order four
  191. ** bits are used. Those four bits are the appropriate column from one
  192. ** of the above tables. The parent selects the value to pass on to
  193. ** the child by shifting a 32-bit value (the concatenation of the
  194. ** columns of the appropriate table with 4-bits of filler per column)
  195. ** a number of columns equal to its (negated) opcode. (This is why
  196. ** the opcodes values are spaced at intervals of eight. I could have
  197. ** done without the filler bits and spaced the opcodes by four, but
  198. ** then the opcodes wouldn't give me the correct shift amount for
  199. ** printing the operators themselves (see below), and since I'm going
  200. ** with 32-bit ints for that anyway, I can save myself two tokens by
  201. ** going with 32 bits here too). The child uses its own opcode to
  202. ** select the appropriate bit from this value and prints parens if the
  203. ** bit is 1. Noe that the top-level call to printexp provides a zero
  204. ** arg, so the outermost expression never gets parenthesized.
  205. **
  206. ** The operator itself is printed by shifting a 32-bit value
  207. ** representing the concatenation of the four possible 8-bit character
  208. ** codes. This saves big over the more straightforward approach of
  209. ** indexing a charstring, because the token counter will count a
  210. ** 4-char string as 6 tokens, whereas our 32-bit number is a single
  211. ** token. This obviously won't work on 16-bit machines.
  212. **
  213. ** The shift amounts are extracted in a rather bizarre fashion. The
  214. ** encodings for the operators are -1, -9, -17, and -25, which we need
  215. ** to convert into shift amounts of 0, 8, 16, and 24, respectively.
  216. ** So we could negate and subtract one. But this is identical to
  217. ** complementing the bit pattern, assuming 2's complement arithmetic,
  218. ** so that's what we do instead.
  219. **/
  220.  
  221. #define PAREN key & 1<<~op/8 && putchar(
  222. #define OPSHIFT >> ~op ),
  223.  
  224. printexp(key)
  225. {
  226. int op = *ops++;
  227. op < 0 ?
  228. PAREN '('),
  229. printexp(0x03030000 OPSHIFT
  230. putchar(0x2f2a2d2b OPSHIFT /* this fails with macro version of putchar */
  231. printexp(0x0f030300 OPSHIFT
  232. PAREN ')')
  233. : printf("%d",op);
  234. }
  235.  
  236.  
  237. Article 4819 of comp.programming:
  238. Path: news.u.washington.edu!netnews.nwnet.net!ogicse!decwrl!concert!news-feed-1.peachnet.edu!darwin.sura.net!cs.ucf.edu!schnitzi
  239. From: schnitzi@cs.ucf.edu (Mark Schnitzius)
  240. Newsgroups: comp.programming,rec.puzzles
  241. Subject: CONCISENESS CONTEST ROUND 2 -- the winner
  242. Message-ID: <schnitzi.737039434@eola.cs.ucf.edu>
  243. Date: 10 May 93 13:10:34 GMT
  244. Article-I.D.: eola.schnitzi.737039434
  245. Sender: news@cs.ucf.edu (News system)
  246. Distribution: comp,rec
  247. Organization: University of Central Florida
  248. Lines: 109
  249. Xref: news.u.washington.edu comp.programming:4819 rec.puzzles:19261
  250.  
  251.  
  252. /****************************************************************************/
  253. /* */
  254. /* Entry for Internet Programming Conciseness Contest #2 */
  255. /* by Barry Gorman, University of Central Lancashire, UK. */
  256. /* [gorman_b@p1.uclan.ac.uk OR barry@sc.lancsp.ac.uk] */
  257. /* */
  258. /*********** WARNING: VERY MACHINE DEPENDENT -- NOT FOR VAX OR PC ***********/
  259. /* */
  260. /* As submitted, this program requires an implementation of C with 32-bit, */
  261. /* int's, big-endian addressing and ASCII characters. Otherwise portable. */
  262. /* Numerous warning messages: due to failure to declare anything properly; */
  263. /* but this is a competition after all! Inclusion of stdio.h would involve */
  264. /* the deletion of putchar, which is usually a macro, because of the split */
  265. /* across macro boundaries of its parameter, which upsets pre-processors. */
  266. /* */
  267. /****************************************************************************/
  268.  
  269. #define quote(tokens) #tokens /* ANSI 'stringise' operator */
  270. #define left_op_right stack[stack_level] /* counters stacked to print */
  271. #define left left_op_right/040 /* index to left value, 0..7 */
  272. #define op_bits (left_op_right & 030) /* keep these bits unshifted */
  273. #define right left_op_right%010 /* use / % not >> &, save () */
  274. #define value stack[10+ /* array of the input values */
  275. #define how_many value 0xFFFFFFFFUL] /* main put it into stack[9] */
  276. #define PARAMS (stack_level,flag_bits){ /* a generic function header */
  277.  
  278. int target_number, value 9]={0x25640000L, 0x3D25640AL}; /* format strings */
  279.  
  280. /****************************************************************************/
  281. print_tree PARAMS /*stack_level,flag_bits*/ /* walks the tree and prints */
  282. /****************************************************************************/
  283.  
  284. #define parenthesis flag_bits /* previous operator not a / */\
  285. && op_bits<020 /* this operator either *, / */\
  286. | flag_bits==030 /* previous operator was a + */\
  287. || putchar( /* use shortcut eval for !if */
  288.  
  289. stack_level<=how_many? printf(stack, value stack_level]): /* if a leaf */
  290.  
  291. (parenthesis '('), /* see macro for bit testing */
  292. print_tree(left, op_bits|010), /* use easy parenthesis rule */
  293. putchar(0x2B2D2A2FL>>op_bits), /* stdio.h has putc as macro */
  294. print_tree(right, op_bits), /* use hard parenthesis rule */
  295. parenthesis ')'));} /* test operator level above */
  296.  
  297. /****************************************************************************/
  298. try_all PARAMS /*stack_level,flag_bits*/ /* recurses to do each level */
  299. /****************************************************************************/
  300.  
  301. #define evaluate_if(operator) op_bits == /* code: 0=/%, 1=*, 2=-, 3=+ */\
  302. (025 operator 005 /* magic operator converter! */\
  303. & 030) ? /* clean-up, and test result */\
  304. value left] operator value right]: /* then arithmetic operation */
  305.  
  306. left_op_right=0400; /* starts the packed counter */
  307.  
  308. while(left_op_right--) /* test then decrement, loop */
  309.  
  310. if (left!=right /* start a one-bit mask here */
  311. &flag_bits>>left /* check left operand unused */
  312. &flag_bits>>right /* do same for right operand */
  313.  
  314. &&!(value right] /* skip for division by zero */
  315. && evaluate_if(%) /* get remainder if division */
  316. !op_bits) /* otherwise zero=not divide */
  317.  
  318. && (value stack_level]= /* do the arithmetic at last */
  319. evaluate_if(+) /* if you are going to steal */
  320. evaluate_if(-) /* code, then make sure that */
  321. evaluate_if(*) /* you copy your own program */
  322. evaluate_if(/) 0, /* from the last contest :-) */
  323.  
  324. stack_level<how_many*2? /* alternatives for return 1 */
  325.  
  326. try_all(stack_level+1, /* go up level, marks=in-use */
  327. flag_bits^1<<left^1<<right^1<<stack_level): /* 0/1? */
  328.  
  329. value stack_level]==target_number /* print here if done */
  330. && print_tree(stack_level, 030) /* any non-zero, */
  331. | printf(stack+1, target_number) /* forces return */
  332.  
  333. ) /* should now have a 0/1 for */
  334.  
  335. ) /* IF result, 25 lines above */
  336.  
  337. return 1; /* break out of loop if done */
  338.  
  339. return 0;} /* this level failed to find */
  340.  
  341. /****************************************************************************/
  342. main PARAMS /*stack_level,flag_bits*/ /* read numbers, then search */
  343. /****************************************************************************/
  344.  
  345. while(scanf(stack, stack+10-stack_level)==1/* stop when EOF or an error */
  346.  
  347. && (stack_level--+how_many /* relies on init value argc */
  348.  
  349. || (target_number=value how_many], /* can't leave this on stack */
  350. stack_level= /* resets it to 1 regardless */
  351. try_all(how_many--, 0x1F>>6+stack_level) /* search */
  352. || puts(quote(TARGET NUMBER UNREACHABLE)) /* failed */
  353. ) /* end of scan, value is one */
  354.  
  355. ) /* effective end, scanf loop */
  356.  
  357. );} /* effective end, while loop */
  358.  
  359. /******************************** the end ***********************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement