Knight's Tour Generator
Tourneys and the Fast Generation and Obfuscation of Closed Knight's Tours
Input.cpp
Go to the documentation of this file.
1 
4 // MIT License
5 //
6 // Copyright (c) 2019 Ian Parberry
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 
26 #include "Input.h"
27 #include "Includes.h"
28 
35 
36 bool ReadUnsigned(UINT& n, Parity parity, UINT lo){
37  char b[256]; //buffer for input line
38  bool ferror; //format error
39  bool nerror; //numerical error
40 
41  do{ //prompt user and get input
42  ferror = false; //no format error yet
43  nerror = false; //no numerical error yet
44 
45  printf("> "); //prompt user
46  const char* result = fgets(b, sizeof(b), stdin); //read a line of text
47 
48  if(result != nullptr && b[0] == 'r' || b[0] == 'R')
49  return true; //'r' means restart
50 
51  else{
52  const int args = sscanf(b, "%u\n", &n); //parse input
53  ferror = args != 1; //format error if number of arguments is not 1
54  bool perror = false; //parity error
55 
56  switch(parity){ //check for parity error
57  case Parity::ZeroMod4:
58  perror = n%4 != 0;
59  break;
60 
61  case Parity::Even:
62  perror = (n & 1) != 0;
63  break;
64 
65  case Parity::Odd:
66  perror = (n & 1) != 1;
67  break;
68  } //switch
69 
70  nerror = perror || n < lo; //n has the wrong parity or is too small
71 
72  if(ferror) //format error
73  printf("**** Error: Invalid input. Please try again.\n");
74 
75  else if(nerror) //numerical error
76  printf("**** Error: Number unsuitable. Please try again.\n");
77  } //else
78  }while(ferror || nerror); //try again until we get an acceptable input
79 
80  return false; //got a valid input, don't quit
81 } //ReadUnsigned
82 
90 
91 bool ReadBoardSize(UINT& n, const CTourneyDesc& t){
92  const Parity parity = (t.m_eGenerator == GeneratorType::FourCover)?
93  Parity::ZeroMod4: Parity::Even;
94  const UINT lo = (t.m_eCycle == CycleType::Tourney)? 4: 6;
95 
96  return ReadUnsigned(n, parity, lo);
97 } //ReadBoardSize
98 
105 
106 char ReadCharacter(std::set<char>& s){
107  char b[256]; //buffer for input line
108  bool ferror; //format error
109  bool cerror; //character error
110  char c; //result
111 
112  do{ //prompt user and get input
113  ferror = false; //no format error yet
114  cerror = false; //no numerical error yet
115 
116  printf("> "); //prompt user
117  const char* result = fgets(b, sizeof(b), stdin); //read a line of text
118 
119  if(result != nullptr){
120  const int args = sscanf(b, "%c\n", &c); //parse input
121  ferror = args != 1; //format error if number of arguments is not 1
122  cerror = s.find(c) == s.end();
123 
124  if(ferror) //format error
125  printf("**** Error: Invalid input. Please try again.\n");
126 
127  else if(cerror) //character error
128  printf("**** Error: Invalid character. Please try again.\n");
129  } //if
130  }while(ferror || cerror); //try again until we get an acceptable input
131 
132  if('A' <= c && c <= 'Z') //upper case
133  c += 'a' - 'A'; //remap to lower case
134 
135  return c;
136 } //ReadCharacter
137 
139 
141  printf(" w: random walk with Warnsdorff's heuristic\n");
142  printf(" t: Takefuji-Lee neural network\n");
143  printf(" d: divide-and-conquer\n");
144  printf(" c: concentric braid\n");
145  printf(" 4: 4-cover\n");
146 } //PrintGeneratorTypeHelp
147 
151 
153  bool finished = false;
154 
155  while(!finished){
156  printf("Enter generation algorithm [wtdc4], h for help, r to restart.\n");
157  finished = true;
158 
159  std::set<char> s = {'w', 't', 'd', 'c', 'h', '4', 'r'}; //admissible chars
160  const char c = ReadCharacter(s); //read admissible character from user
161 
162  //decode character entered by user into a generator type and print response
163 
164  t = GeneratorType::Unknown;
165 
166  switch(c){
167  case 'w':
168  t = GeneratorType::Warnsdorff;
169  printf("Warnsdorff's algorithm selected.\n");
170  break;
171 
172  case 't':
173  t = GeneratorType::TakefujiLee;
174  printf("Takefuji-Lee neural network algorithm selected.\n");
175  break;
176 
177  case 'd':
178  t = GeneratorType::DivideAndConquer;
179  printf("Divide-and-conquer algorithm selected.\n");
180  break;
181 
182  case 'c':
183  t = GeneratorType::ConcentricBraid;
184  printf("Concentric braid algorithm selected.\n");
185  break;
186 
187  case '4':
188  t = GeneratorType::FourCover;
189  printf("Four-cover algorithm selected.\n");
190  break;
191 
192  case 'h':
194  finished = false;
195  break;
196 
197  case 'r': return true; //restart
198  } //switch
199  } //if
200 
201  return false; //don't restart
202 } //ReadGeneratorType
203 
205 
207  printf(" t: knight's tour\n");
208  printf(" y: tourney\n");
209  printf(" j: joined tourney\n");
210 } //PrintCycleTypeHelp
211 
215 
217  bool finished = false;
218 
219  while(!finished){
220  printf("Enter tourney type [tyj], h for help, r to restart.\n");
221  finished = true;
222 
223  std::set<char> s = {'t', 'y', 'j', 'h', 'r'}; //admissible characters
224  const char c = ReadCharacter(s); //read admissible character from user
225 
226  //decode character entered by user into a cycle type and print response
227 
228  t = CycleType::Unknown;
229 
230  switch(c){
231  case 't':
232  t = CycleType::Tour;
233  printf("Knight's tour selected.\n");
234  break;
235 
236  case 'y':
237  t = CycleType::Tourney;
238  printf("Tourney selected.\n");
239  break;
240 
241  case 'j':
242  t = CycleType::TourFromTourney;
243  printf("Joined tourney selected.\n");
244  break;
245 
246  case 'h':
248  finished = false;
249  break;
250 
251  case 'r': return true; //restart
252  } //switch
253  } //if
254 
255  return false; //don't restart
256 } //ReadCycleType
257 
261 
262 bool ReadObfuscate(bool& obfuscate){
263  printf("Obfuscated [yn], r to restart?\n");
264 
265  std::set<char> s = {'y', 'n', 'r'}; //admissible characters
266  const char c = ReadCharacter(s); //read admissible character from user
267  obfuscate = c == 'y'; //yes to obfuscate
268 
269  const bool bRestart = c == 'r'; //r to restart
270 
271  if(!bRestart){
272  if(obfuscate)
273  printf("Obfuscating.\n");
274  else
275  printf("No obfuscation\n");
276  } //if
277 
278  return bRestart;
279 } //ReadObfuscate
280 
282 
284  printf(" g: generate and save a single tourney\n");
285  printf(" m: measure statistics on many tourneys of the same size\n");
286  printf(" t: time the generation of many tourneys for a size range\n");
287 } //PrintTaskHelp
288 
292 
293 bool ReadTask(Task& t){
294  bool finished = false;
295 
296  while(!finished){
297  printf("Select task [gmt], h for help, q to quit.\n");
298  finished = true;
299 
300  std::set<char> s = {'g', 'm', 't', 'h', 'q'}; //admissible characters
301  const char cTask = ReadCharacter(s); //read admissible character from user
302 
303  //decode character entered by user into a task and print response
304 
305  t = Task::Unknown;
306 
307  switch(cTask){
308  case 'g':
309  t = Task::Generate;
310  printf("Generating a single tourney.\n");
311  break;
312 
313  case 'm':
314  t = Task::Measure;
315  printf("Measuring single and double move statistics.\n");
316  break;
317 
318  case 't':
319  t = Task::Time;
320  printf("Timing the generation of tourneys.\n");
321  break;
322 
323  case 'h':
324  PrintTaskHelp();
325  finished = false;
326  break;
327 
328  case 'q': return true; //quit
329  } //switch
330  } //while
331 
332  return false; //don't quit
333 } //ReadTask
bool ReadUnsigned(UINT &n, Parity parity, UINT lo)
Read a UINT from stdin.
Definition: Input.cpp:36
Parity
Parity.
Definition: Defines.h:78
char ReadCharacter(std::set< char > &s)
Read a single character from stdin.
Definition: Input.cpp:106
void PrintCycleTypeHelp()
Print keyboard mapping for cycle type.
Definition: Input.cpp:206
Useful includes.
Tourney descriptor.
Definition: Structs.h:40
bool ReadObfuscate(bool &obfuscate)
Read obfuscate status from stdin.
Definition: Input.cpp:262
bool ReadBoardSize(UINT &n, const CTourneyDesc &t)
Read board size from stdin.
Definition: Input.cpp:91
void PrintGeneratorTypeHelp()
Print keyboard mapping for generator.
Definition: Input.cpp:140
bool ReadTask(Task &t)
Read the task from stdin.
Definition: Input.cpp:293
unsigned int UINT
Abbreviation for unsigned integer.
Definition: Defines.h:84
void PrintTaskHelp()
Print keyboard mapping for tasks.
Definition: Input.cpp:283
GeneratorType
Generator type.
Definition: Defines.h:47
GeneratorType m_eGenerator
Generator type.
Definition: Structs.h:41
Task
Task type.
Definition: Defines.h:68
CycleType m_eCycle
Cycle type.
Definition: Structs.h:42
bool ReadGeneratorType(GeneratorType &t)
Read the generator type from stdin.
Definition: Input.cpp:152
Header for input functions.
CycleType
Cycle type.
Definition: Defines.h:58
bool ReadCycleType(CycleType &t)
Read the cycle type from stdin.
Definition: Input.cpp:216