home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / progs / cross.icn < prev    next >
Text File  |  2000-07-29  |  5KB  |  197 lines

  1. ############################################################################
  2. #
  3. #    File:     cross.icn
  4. #
  5. #    Subject:  Program to display intersection of words
  6. #
  7. #    Author:   William P. Malloy
  8. #
  9. #    Date:     June 10, 1988
  10. #
  11. ############################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #  
  17. #     This program takes a list of words and tries to arrange them
  18. #  in cross-word format so that they intersect. Uppercase letters
  19. #  are mapped into lowercase letters on input.  For example, the
  20. #  input
  21. #  
  22. #          and
  23. #          eggplants
  24. #          elephants
  25. #          purple
  26. #  
  27. #  produces the output
  28. #       +---------+
  29. #       | p       |
  30. #       | u e     |
  31. #       | r g     |
  32. #       | p g     |
  33. #       |elephants|
  34. #       | e l     |
  35. #       |   and   |
  36. #       |   n     |
  37. #       |   t     |
  38. #       |   s     |
  39. #       +---------+
  40. #  
  41. #  Diagnostics: The program objects if the input contains a nonal-
  42. #  phabetic character.
  43. #  
  44. #  Comments: This program produces only one possible intersection
  45. #  and it does not attempt to produce the most compact result.  The
  46. #  program is not very fast, either.  There is a lot of room for
  47. #  improvement here. In particular, it is natural for Icon to gen-
  48. #  erate a sequence of solutions.
  49. #  
  50. ############################################################################
  51.  
  52. global fast, place, array, csave, fsave, number
  53.  
  54. procedure main()
  55.    local words, nonletter, line
  56.    nonletter := ~&letters
  57.    words := []
  58.  
  59.    while line := map(read()) do
  60.       if upto(nonletter,line) then stop("input contains nonletter")
  61.       else put(words,line)
  62.    number := *words
  63.    kross(words)
  64.  
  65. end
  66.  
  67. procedure kross(words)
  68.    local one, tst, t
  69.    array := [get(words)]
  70.    t := 0
  71.    while one := get(words) do {
  72.       tst := *words
  73.       if fit(one,array,0 | 1) then
  74.      t := 0
  75.       else {
  76.      t +:= 1
  77.          put(words,one)
  78.      if t > tst then
  79.         break
  80.      }
  81.       }
  82.    if *words = 0 then Print(array)
  83.    else write(&errout,"cannot construct puzzle")
  84. end
  85.  
  86. procedure fit(word,matrix,where)
  87.    local i, j, k, l, one, test, t, s
  88.    s := *matrix
  89.    t := *matrix[1]
  90.    every k := gen(*word) do
  91.       every i := gen(s) do
  92.          every j := gen(t) do
  93.         if matrix[i][j] == word[k] then {
  94.                # test for vertical fit
  95.                if where = 0 then {
  96.                   test := 0
  97.                   every l := (i - k + 1) to (i + (*word - k)) do
  98.                      if tstv(matrix,i,j,l,s,t) then {
  99.                         test := 1
  100.                         break
  101.                         }
  102.                   if test = 0 then
  103.                      return putvert(matrix,word,i,j,k)
  104.                   }
  105.                if where = 1 then {
  106.                   test := 0
  107.                   every l := (j - k + 1) to (j + (*word - k)) do
  108.                      if tsth(matrix,i,j,l,s,t) then {
  109.                         test := 1
  110.                         break
  111.                         }
  112.                   if test = 0 then
  113.                      return puthoriz(matrix,word,i,j,k)
  114.                   }
  115.                }
  116. end
  117.  
  118. procedure tstv(matrix,i,j,l,s,t)
  119.    return ((matrix[(l ~= i) & (s >= l) & (0 < l)][0 < j-1] ~== " ") |
  120.       (matrix[(l ~= i) & (s >= l) & (0 < l)][t >= j + 1] ~== " ") |
  121.       (matrix[(i ~= l-1) & (s >= l-1) & (0 < l-1)][j] ~== " ") |
  122.       (matrix[(i ~= l + 1) & (s >= l+1) & (0 < l + 1)][j] ~== " ") |
  123.       (matrix[(l ~= i) & (s >= l) & (0 < l)][j] ~== " "))
  124. end
  125.  
  126. procedure tsth(matrix,i,j,l,s,t)
  127.    return ((matrix[0 < i-1][(l ~= j) & (t >= l) & (0 < l)] ~== " ") |
  128.       (matrix[s >= i + 1][(l ~= j) & (t >= l) & (0 < l)] ~== " ") |
  129.       (matrix[i][(j ~= l-1) & (t >= l-1) & (0 < l-1)] ~== " ") |
  130.       (matrix[i][(j ~= l + 1) & (t >= l + 1) & (0 < l + 1)] ~== " ") |
  131.       (matrix[i][(l ~= j) & (t >= l) & (0 < l)] ~== " "))
  132. end
  133.  
  134. procedure gen(i)
  135.    local tmp, up, down
  136.    tmp := i / 2
  137.    if (i % 2) = 1 then
  138.       tmp +:= 1
  139.    suspend tmp
  140.    up := tmp
  141.    down := tmp
  142.    while (up < i) do {
  143.       suspend up +:= 1
  144.       suspend (down > 1) & (down -:= 1)
  145.       }
  146. end
  147.  
  148. # put `word' in vertically at pos(i,j)
  149.  
  150. procedure putvert(matrix,word,i,j,k)
  151.    local hdim, vdim, up, down, l, m, n
  152.    vdim := *matrix
  153.    hdim := *matrix[1]
  154.    up := 0
  155.    down := 0
  156.    up := abs(0 > (i - k))
  157.    down := abs(0 > ((vdim - i) - (*word - k)))
  158.    every m := 1 to up do
  159.       push(matrix,repl(" ",hdim))
  160.    i +:= up
  161.    every m := 1 to down do
  162.       put(matrix,repl(" ",hdim))
  163.    every l := 1 to *word do
  164.       matrix[i + l - k][j] := word[l]
  165.    return matrix
  166. end
  167.  
  168. # put `word' in horizontally at position i,j in matrix
  169.  
  170. procedure puthoriz(matrix,word,i,j,k)
  171.    local hdim, vdim, left, right, l, m, n
  172.    vdim := *matrix
  173.    hdim := *matrix[1]
  174.    left := 0
  175.    right := 0
  176.    left := (abs(0 > (j - k))) | 0
  177.    right := (abs(0 > ((hdim - j) - (*word - k)))) | 0
  178.    every m := 1 to left do
  179.       every l := 1 to vdim do
  180.        matrix[l] := " " || matrix[l]
  181.    j +:= left
  182.    every m := 1 to right do
  183.       every l := 1 to vdim do
  184.       matrix[l] ||:= " "
  185.    every l := 1 to *word do
  186.       matrix[i][j + l - k] := word[l]
  187.    return matrix
  188. end
  189.  
  190. procedure Print(matrix)
  191.    local i
  192.    write("+",repl("-",*matrix[1]),"+")
  193.    every i := 1 to *matrix do
  194.       write("|",matrix[i],"|")
  195.    write("+",repl("-",*matrix[1]),"+")
  196. end
  197.