File: pyramid.e

package info (click to toggle)
smarteiffel 1.1-11
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 12,288 kB
  • ctags: 40,785
  • sloc: ansic: 35,791; lisp: 4,036; sh: 1,783; java: 895; ruby: 613; python: 209; makefile: 115; csh: 78; cpp: 50
file content (219 lines) | stat: -rw-r--r-- 5,507 bytes parent folder | download | duplicates (3)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
class PYRAMID
   --
   -- Solving the problem of the Pyramid for small pyramid only.
   --
   -- This program uses the back-tracking method.
   -- Its goal is to try to fill a pyramid by making a substraction
   -- between two succesive columns and to take its absolute value.
   -- The result is put on the next line.
   -- Example:
   --  6   14   15   3   13
   --    8    1   12  10
   --       7   11   2
   --         4    9
   --            5
   --
   -- See also pyramid2, which run faster than this first solution.

inherit ANY redefine out_in_tagged_out_memory end;

creation make

feature

   size: INTEGER;

   make is
      do
         if argument_count = 0 then
            std_output.put_string("Want to compute a small pyramid ?%N%
                                  %Enter a small number (> 1): ");
            std_output.flush;
            std_input.read_integer;
            size := std_input.last_integer;
         else
            size := argument(1).to_integer;
         end;
         if size <= 1 then
            std_output.put_string("You feel sick ?%N");
         elseif size > biggest_one then
            std_output.put_string("Value too big for this method.%N");
         else
            !!elem.make(1,max);
            if fill_up(1) then
               std_output.put_string("Full pyramid:%N");
               print_on(std_output);
            else
               std_output.put_string("Unable to fill_up such one.%N");
            end;
         end;
      end;

   max: INTEGER is
      do
         Result := (size * (size + 1)) // 2;
      end;

   out_in_tagged_out_memory is
      local
         lig,col,nb: INTEGER;
      do
         from
            lig := 1;
            col := 1;
            nb := 0;
         until
            nb = max
         loop
            if col = 1 then
               tagged_out_memory.extend('%N');
            end;
            (elem.item(indice(lig,col))).append_in(tagged_out_memory);
            tagged_out_memory.append(" ");
            if col = size - lig + 1 then
               col := 1 ;
               lig := lig + 1 ;
            else
               col := col + 1;
            end;
            nb := nb + 1;
         end;
         tagged_out_memory.extend('%N');
      end;

   belongs_to(nb: INTEGER): BOOLEAN is
      require
         too_small: nb >= 1;
         too_large: nb <= max
      local
         i: INTEGER;
         found: BOOLEAN;
      do
         from
            i := 1;
         until
            ((i > max) or found)
         loop
            found := (nb = elem.item(i));
            i := i + 1;
         end;
         Result := found;
      end;

   propagate (col, val_column_1: INTEGER): BOOLEAN is
      require
         val_column_1.in_range(1,max);
         col.in_range(1,size)
      local
         stop: BOOLEAN;
         lig: INTEGER;
         val: INTEGER;
      do
         if belongs_to(val_column_1) then
            Result := false ;
         else
            from
               elem.put(val_column_1,indice(1,col));
               lig := 1;
               val := val_column_1;
               stop := false;
               Result := true;
            until
               stop
            loop
               lig := lig + 1;
               if lig > col then
                  stop := true;
               else
                  val := val - elem.item(indice(lig-1,col-lig+1));
		  val := val.abs;
                  if belongs_to(val) then
                     clear_column(col);
                     stop := true;
                     Result := false;
                  else
                     elem.put(val,indice(lig,col-lig+1));
                  end;
               end;
            end;
         end;
      end;

   fill_up (col: INTEGER): BOOLEAN is
      require
         col >= 1;
      local
         stop: BOOLEAN;
         nb: INTEGER;
      do
         if col > size then
            Result := true;
         else
            from
               stop := false;
               nb := max;
            until
               stop
            loop
               if belongs_to(nb) then
                  nb := nb - 1;
                  stop := (nb = 0);
               elseif propagate(col,nb) then
                  if  fill_up(col + 1) then
                     stop := true;
                  else
                     clear_column(col);
                     nb := nb - 1;
                     stop := (nb = 0);
                  end;
               else
                  nb := nb - 1;
                  stop := (nb = 0);
               end;
            end;
            Result := (nb > 0);
         end;
      end;

feature {NONE}

   elem: ARRAY[INTEGER];

   case_vide: INTEGER is 0;

   biggest_one: INTEGER is 10;

   indice (lig,col: INTEGER): INTEGER is
      require
         lig_trop_petit: lig >= 1 ;
         lig_trop_grand: lig <= size ;
         col_trop_petit: col >= 1 ;
         col_trop_grand: col <= size ;
      local
         l: INTEGER ;
      do
         l:= size - lig + 1;
         Result := max - ((l * (l + 1)) // 2) + col;
      ensure
         Result >= 1 ;
         Result <= max ;
      end;

   clear_column (col: INTEGER) is
      require
         col >= 1;
         col <= size;
      local
         lig: INTEGER;
      do
         from
            lig := 1;
         until
            lig > col
         loop
            elem.put(case_vide,indice(lig,col-lig+1));
            lig := lig + 1;
         end;
      end; -- clear_column

end --  PYRAMID