001      /*    Author Malte Pagel    */
002      
003      
var TOTAL 81;
004                  
005      
/**
006       * TOTAL will be adjusted if not square of square
007       */
008      
var LINE parseInt(Math.sqrt(TOTAL));
009      var 
SMALL_LINE parseInt(Math.sqrt(LINE));
010      
LINE Math.pow(SMALL_LINE2);
011      
TOTAL Math.pow(LINE2);
012      
013      
014      
/**
015       * Define what to do with found numbers
016       */
017      
function show_single (riddle_index) {
018          
// some code
019      
}
020      
/**
021       * Define what to do with unnecessary numbers
022       */
023      
function hide_single (riddle_indexvalue) {
024          
// some code
025      
}
026      
/**
027       * Define what to do with messages
028       */
029      
function personal_debug (message) {
030          
// some code
031      
}
032      
033      
034      
/**
035       * Takes a position inside the large square and returns
036       *        - [0]        the row number
037       *        - [1]        the column number
038       *        - [2]        the small square number
039       * where this position is situated in
040       */
041      
function get_collection (index) {
042          var 
ret = [];
043          
ret[0] = parseInt(index LINE);
044          
ret[1] = index LINE;
045          
ret[2] = SMALL_LINE parseInt(ret[0] / SMALL_LINE)
046          + 
parseInt(ret[1] / SMALL_LINE);
047      
048          return 
ret;
049      }
050      
051      
/**
052       * Is 'the_element' in 'the_array'?
053       */
054      
function contains_element (the_arraythe_element) {
055          for ( var 
0the_array.lengthi++ )
056              if ( 
the_array[i] == the_element )
057                  return 
1;
058          return 
0;
059      }
060      
061      
/**
062       * Returns all members of row 'row'
063       */
064      
function get_horizontal (row) {
065          var 
ret = [];
066          var 
i;
067          var 
0;
068      
069          for ( 
= (row LINE); < (row LINE) + LINEi++ ) {
070              
ret[j] = riddle[i];
071              
j++;
072          }
073      
074          return 
ret;
075      }
076      
/**
077       * Returns all members of column 'col'
078       */
079      
function get_vertical (col) {
080          var 
ret = [];
081          var 
i;
082          var 
0;
083      
084          for ( 
colTOTAL+= LINE ) {
085              
ret[j] = riddle[i];
086              
j++;
087          }
088      
089          return 
ret;
090      }
091      
/**
092       * Returns all members of small square 'which'
093       */
094      
function get_square (which) {
095          var 
ret = [];
096          var 
ij;
097      
098          for ( 
0SMALL_LINEi++ )
099              for ( 
0SMALL_LINEj++ ) {
100                  
ret[SMALL_LINE j] = riddle[LINE which SMALL_LINE j
101                  
+ (parseInt(which SMALL_LINE) * (SMALL_LINE 1) * LINE)];
102              }
103      
104          return 
ret;
105      }
106      
107      
/**
108       * Unweighted randomization:
109       * 'raw' numbers (i.e. indices) from 0 to (limit - 1).
110       * Fetch random value from 'raw', push it to the end of 'target',
111       * clear this value in 'raw'.
112       * Repeat until 'raw' is empty
113       */
114      
function randomize_unweighted (offsetlimit) {
115          var 
raw = [];
116          var 
target = [];
117          var 
i;
118          
119          for ( 
0limiti++ )
120              
raw[i] = offset;
121          
122          
0;
123          while ( 
raw.length ) {
124              
random Math.floor(Math.random() * raw.length);
125              
target[i] = raw[random];
126              
raw.splice(random1);
127              
i++;
128          }
129          
130          return 
target;
131      }
132      
133      
134      var 
multi_raw = [];
135      var 
indices = [];
136      var 
riddle = [];
137      var 
irandomredundanttmpunset_countsmall_rowssmall_cols;
138      var 
tries_to_set 0;
139      
140      
/**
141       * Initialization:
142       * Fields are set to 0 ( = we dont' know the number yet)
143       */
144      
for ( 0TOTALi++ )
145          
riddle[i] = 0;
146      
147      
148      
/**
149       * Second initialization:
150       * LINE times numbers from 0 to (LINE - 1),
151       * i.e. every square
152       */
153      
for ( var big_rows 0big_rows SMALL_LINEbig_rows++ )
154          for ( var 
big_cols 0big_cols SMALL_LINEbig_cols++ ) {
155              
start_value big_rows LINE SMALL_LINE + (big_cols SMALL_LINE);
156              
multi_raw.length;
157              
multi_raw[i] = [];
158              for ( 
small_rows 0small_rows SMALL_LINEsmall_rows++ )
159                  for ( 
small_cols 0small_cols SMALL_LINEsmall_cols++ )
160                      
multi_raw[i].push(small_rows LINE small_cols start_value);
161          }
162      
163      
/**
164       * Randomization for every element ('element') of multi_raw.
165       * Fetch random value from 'element', push it to the end of 'indices',
166       * clear this value in 'element'.
167       * Repeat until 'element' is empty
168       */
169      
for ( 0multi_raw.lengthi++ ) {
170          while ( 
multi_raw[i].length ) {
171              
random Math.floor(Math.random() * multi_raw[i].length);
172              
indices[indices.length] = multi_raw[i][random];
173              
multi_raw[i].splice(random1);
174          }
175      }
176      
177      
/**
178       * Recursive function:
179       * Try for each position the numbers from 1 to LINE
180       *      (except 'forbidden_number' if given).
181       * If all numbers collide with already set numbers, move is bad.
182       * If a number doesn't collide with already set numbers,
183       *        - move is bad if next move collides with the already set numbers
184       *              (including actual one)
185       *        - move is good if it's the last one
186       */
187      
function set_values (indexforbidden_number) {
188                      
189          var 
real_index indices[index];
190      
191          var 
blocks get_collection(real_index);
192      
193          for ( var 
1<= LINEi++ ) {
194              if ( 
forbidden_number && == forbidden_number )
195                  continue;
196              
197              
tries_to_set++;
198              
199              if ( 
contains_element(get_horizontal(blocks[0]), i) )
200                  continue;
201              if ( 
contains_element(get_vertical(blocks[1]), i) )
202                  continue;
203              if ( 
contains_element(get_square(blocks[2]), i) )
204                  continue;
205      
206              
riddle[real_index] = i;
207      
208              if ( 
index == (TOTAL 1) || set_values((index 1), 0) )
209                  return 
1;
210          }
211      
212          
riddle[real_index] = 0;
213      
214          return 
0;
215      }
216      
217      
/**
218       * Setting numbers, start with the first one.
219       * Variable 'redundant' is needed only for formal reasons
220       */
221      
redundant set_values(00);
222      
223      
224      
/**
225       * Reshuffle 'indices' (so that the user doesn't recognize
226       * the previous used randomized order)
227       */
228      
indices randomize_unweighted(0TOTAL);
229      
230      
231      
/**
232       * We probably want to see the result
233       */
234      
for ( 0TOTALi++ )
235          
show_single(i);
236      
237      
238      
personal_debugtries_to_set " tries to set the " TOTAL " numbers" );
239      
240      
241      
/**
242       * Some steps:
243       *        a) Define last piece as 'special piece'
244       *        b) Remember this piece's value
245       *        c) Try to create riddle from this position on,
246       *          but forbid the value of the special piece
247       *        d) If operation fails, define the piece before the special piece
248       *          as 'special piece' and continue with b)
249       */
250      
tries_to_set 0;
251      
unset_count 1;
252      do {
253          
tmp riddle[indices[TOTAL unset_count]];
254          
redundant set_values((TOTAL unset_count), tmp);
255      
256          if ( !
redundant )
257              
hide_single(indices[TOTAL unset_count], tmp);
258          
unset_count++;
259      }
260      while ( !
redundant );
261      
262      
263      
personal_debugtries_to_set " tries to remove " + (unset_count 2) + " numbers" );
264      
265