File: 8q.azm

package info (click to toggle)
zoem 11-166-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,476 kB
  • sloc: ansic: 18,291; sh: 785; makefile: 111
file content (131 lines) | stat: -rw-r--r-- 4,475 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

\:    N queens problem solved in zoem.

\:    This solution uses recursion (naturally), maintaining dictionaries
\:    with push#1 and pop#1. It also uses a crude form of iteration
\:    using apply#2. Failure is escalated back using throw#2 and catch#2.
\:    This constitutes a non-trivial example of apply#2 / throw#2 / catch#2
\:    used in conjunction.

\:    A more customary solution is to use while#2 rather than the
\:    latter method -- see 8q2.azm.

\:    This solution has caused two zoem weak spots to be addressed:
\:    -  inability to cleanly assign a vararg to a data key.
\:     -> now possible with \set{{modes}{u}}{%{key}}{{a}{b}{c}{e}{t}{c}}
\:    -  inability to effect global key updates while dictionaries are pushed.
\:     -> now possible with \set{''key}{..} (and \''key access).


\if{\let{!\defined{key}{N} || \N < 1}}{
   \write{stderr}{device}{Use e.g. zoem -i 8q -s N=9 to solve the 9-queen problem\@{\N}}
   \set{N}{8}
}{}
\setx{N}{\let{floor(\N)}}

\set{n_backtrack}{0}
\set{p_backtrack}{0}
                  \: When updating these we have to be careful
                  \: to do it in the bottom global dictionary,
                  \: not in a higher stacked transient dictionary.

\set{%{lists}{0}}{}

\set{n1}{0}
\set{n}{1}

                  \: Precompute all lists that we are going to feed
                  \: to apply#2. This is only slightly wasteful.
\while{\let{\n<=\N}}{
                  \: This uses recently introduced primitive set#3.
                  \: The u modifier indicates the value argument
                  \: should not be parsed as a key-value list.
   \set{{modes}{xu}}{%{lists}{\n}}{\%{lists}{\n1} {\n1}}

   \set{%{positions}{\n}}{}
   \setx{n1}{\n}
   \setx{n}{\let{\n+1}}
}

                  \: for shorter print statement
\def{pp#1}{\%{positions}{\1}}


                  \:
                  \:
                  \:     5 |  .  .  .  .  .  .         
                  \:     4 |  .  .  *  .  .  .
                  \:     3 |  .  .  .  .  ?  .
                  \:     2 |  .  *  .  .  .  .
                  \:     1 |  .  .  .  *  .  .
                  \:     0 |  *  .  .  .  .  .
                  \:       |________________________
                  \: col:  |              4  5  6  7
                  \: c:       0  1  2  3

                  \: for c in 0..col-1 get the position and see whether it
                  \: is compatible with col,row
\formatted{

   \def{testcompat#1}{
      \setx{c}{\1}

      \if{\let{
            \%{positions}{\c}==\row
         || \%{positions}{\c}-\row==\col-\c
         || \%{positions}{\c}-\row==\c-\col
         }
       }{\setx{''n_backtrack}{\let{\''n_backtrack+1}}
         \throw{towel}{}
      }{}
   }

                  \: Try whether row would fit col.
   \def{testrow#1}{
      \push{testrow}
         \setx{row}{\1}
         \catch{towel}{
            \apply{testcompat#1}{\%{lists}{\col}}
         }
                  \: Alternative is to use \while rather than apply+catch
                  \: still, timing seems to be OK for this approach.

         \if{\cmp{eq}{\__zoemstat__}{done}}{
            \setx{%{positions}{\col}}{\row}
            \if{\let{\col<\N-1}}{
               \extendcol{\let{\col+1}}
            }{
               \write{\__fnout__}{device}{\@{\N}\pp{0}}
               \set{t}{1}
               \while{\let{\t<\N}}{
                  \write{\__fnout__}{device}{\`{s}\pp{\t}}
                  \setx{t}{\let{\t+1}}
               }
               \setx{d_bt}{\let{\''n_backtrack-\''p_backtrack}}
               \write{\__fnout__}{device}{\ifdef{key}{trace}{\`{s}(\''n_backtrack, \d_bt)}\@{\n}}
               \setx{''p_backtrack}{\''n_backtrack}
            }
         }{}
      \pop{testrow}
   }

                  \: 0..col-1 columns are OK
                  \: Try to extend to column col.
   \def{extendcol#1}{
      \push{extendcol}
         \setx{col}{\1}
         \apply{testrow#1}{\%{lists}{\N}}
      \pop{extendcol}
   }
}

                  \: vanish#1 omits the filter/output stage in an attempt
                  \: to gain some speed -- it only results in side effects (yay!)
                  \: such as the \write#2 invocation above.
                  \: However, because we used formatted#1 we really don't
                  \: gain anything as all result strings have length zero
                  \: anyway.
\vanish{\extendcol{0}}

\write{stderr}{device}{Backtracked \''n_backtrack times\@{\n}}