turing_machine_ai/
verifier.rs

1use std::fmt::Debug;
2
3use arrayvec::ArrayVec;
4
5use crate::code::{Code, Set, Order};
6
7/// Get a verifier by its (one-indexed) number in the game.
8#[must_use]
9pub fn get_verifier_by_number(number: usize) -> Verifier {
10    let verifiers: [Verifier; 48] = [
11        // 1
12        Verifier::from_description_and_options(
13            "the △ number compared to 1",
14            &[
15                VerifierOption::from_description_and_closure("△ = 1", |code| {
16                    code.triangle() == 1
17                }),
18                VerifierOption::from_description_and_closure("△ > 1", |code| code.triangle() > 1),
19            ],
20        ),
21        // 2
22        Verifier::from_description_and_options(
23            "the △ number compared to 3",
24            &[
25                VerifierOption::from_description_and_closure("△ < 3", |code| code.triangle() < 3),
26                VerifierOption::from_description_and_closure("△ = 3", |code| {
27                    code.triangle() == 3
28                }),
29                VerifierOption::from_description_and_closure("△ > 3", |code| code.triangle() > 3),
30            ],
31        ),
32        // 3
33        Verifier::from_description_and_options(
34            "the □ number compared to 3",
35            &[
36                VerifierOption::from_description_and_closure("□ < 3", |code| code.square() < 3),
37                VerifierOption::from_description_and_closure("□ = 3", |code| code.square() == 3),
38                VerifierOption::from_description_and_closure("□ > 3", |code| code.square() > 3),
39            ],
40        ),
41        // 4
42        Verifier::from_description_and_options(
43            "the □ number compared to 4",
44            &[
45                VerifierOption::from_description_and_closure("□ < 4", |code| code.square() < 4),
46                VerifierOption::from_description_and_closure("□ = 4", |code| code.square() == 4),
47                VerifierOption::from_description_and_closure("□ > 4", |code| code.square() > 4),
48            ],
49        ),
50        // 5
51        Verifier::from_description_and_options(
52            "if △ is even or odd",
53            &[
54                VerifierOption::from_description_and_closure("△ is even", |code| {
55                    code.triangle() % 2 == 0
56                }),
57                VerifierOption::from_description_and_closure("△ is odd", |code| {
58                    code.triangle() % 2 == 1
59                }),
60            ],
61        ),
62        // 6
63        Verifier::from_description_and_options(
64            "if □ is even or odd",
65            &[
66                VerifierOption::from_description_and_closure("□ is even", |code| {
67                    code.square() % 2 == 0
68                }),
69                VerifierOption::from_description_and_closure("□ is odd", |code| {
70                    code.square() % 2 == 1
71                }),
72            ],
73        ),
74        // 7
75        Verifier::from_description_and_options(
76            "if ○ is even or odd",
77            &[
78                VerifierOption::from_description_and_closure("○ is even", |code| {
79                    code.circle() % 2 == 0
80                }),
81                VerifierOption::from_description_and_closure("○ is odd", |code| {
82                    code.circle() % 2 == 1
83                }),
84            ],
85        ),
86        // 8
87        Verifier::from_description_and_options(
88            "the number of 1s in the code",
89            &[
90                VerifierOption::from_description_and_closure("zero 1s", |code| {
91                    code.count_digit(1) == 0
92                }),
93                VerifierOption::from_description_and_closure("one 1", |code| {
94                    code.count_digit(1) == 1
95                }),
96                VerifierOption::from_description_and_closure("two 1s", |code| {
97                    code.count_digit(1) == 2
98                }),
99                VerifierOption::from_description_and_closure("three 1s", |code| {
100                    code.count_digit(1) == 3
101                }),
102            ],
103        ),
104        // 9
105        Verifier::from_description_and_options(
106            "the number of 3s in the code",
107            &[
108                VerifierOption::from_description_and_closure("zero 3s", |code| {
109                    code.count_digit(3) == 0
110                }),
111                VerifierOption::from_description_and_closure("one 3", |code| {
112                    code.count_digit(3) == 1
113                }),
114                VerifierOption::from_description_and_closure("two 3s", |code| {
115                    code.count_digit(3) == 2
116                }),
117                VerifierOption::from_description_and_closure("three 3s", |code| {
118                    code.count_digit(3) == 3
119                }),
120            ],
121        ),
122        // 10
123        Verifier::from_description_and_options(
124            "the number of 4s in the code",
125            &[
126                VerifierOption::from_description_and_closure("zero 4s", |code| {
127                    code.count_digit(4) == 0
128                }),
129                VerifierOption::from_description_and_closure("one 4", |code| {
130                    code.count_digit(4) == 1
131                }),
132                VerifierOption::from_description_and_closure("two 4s", |code| {
133                    code.count_digit(4) == 2
134                }),
135                VerifierOption::from_description_and_closure("three 4s", |code| {
136                    code.count_digit(4) == 3
137                }),
138            ],
139        ),
140        // 11
141        Verifier::from_description_and_options(
142            "the △ number compared to the □ number",
143            &[
144                VerifierOption::from_description_and_closure("△ < □", |code| {
145                    code.triangle() < code.square()
146                }),
147                VerifierOption::from_description_and_closure("△ = □", |code| {
148                    code.triangle() == code.square()
149                }),
150                VerifierOption::from_description_and_closure("△ > □", |code| {
151                    code.triangle() > code.square()
152                }),
153            ],
154        ),
155        // 12
156        Verifier::from_description_and_options(
157            "the △ number compared to the ○ number",
158            &[
159                VerifierOption::from_description_and_closure("△ < ○", |code| {
160                    code.triangle() < code.circle()
161                }),
162                VerifierOption::from_description_and_closure("△ = ○", |code| {
163                    code.triangle() == code.circle()
164                }),
165                VerifierOption::from_description_and_closure("△ > ○", |code| {
166                    code.triangle() > code.circle()
167                }),
168            ],
169        ),
170        // 13
171        Verifier::from_description_and_options(
172            "the □ number compared to the ○ number",
173            &[
174                VerifierOption::from_description_and_closure("□ < ○", |code| {
175                    code.square() < code.circle()
176                }),
177                VerifierOption::from_description_and_closure("□ = ○", |code| {
178                    code.square() == code.circle()
179                }),
180                VerifierOption::from_description_and_closure("□ > ○", |code| {
181                    code.square() > code.circle()
182                }),
183            ],
184        ),
185        // 14
186        Verifier::from_description_and_options(
187            "which colour's number is smaller than either of the others",
188            &[
189                VerifierOption::from_description_and_closure("△ < □, ○", |code| {
190                    code.triangle() < code.square() && code.triangle() < code.circle()
191                }),
192                VerifierOption::from_description_and_closure("□ < △, ○", |code| {
193                    code.square() < code.triangle() && code.square() < code.circle()
194                }),
195                VerifierOption::from_description_and_closure("○ < □, △", |code| {
196                    code.circle() < code.square() && code.circle() < code.triangle()
197                }),
198            ],
199        ),
200        // 15
201        Verifier::from_description_and_options(
202            "which colour's number is larger than either of the others",
203            &[
204                VerifierOption::from_description_and_closure("△ > □, ○", |code| {
205                    code.triangle() > code.square() && code.triangle() > code.circle()
206                }),
207                VerifierOption::from_description_and_closure("□ > △, ○", |code| {
208                    code.square() > code.triangle() && code.square() > code.circle()
209                }),
210                VerifierOption::from_description_and_closure("○ > □, △", |code| {
211                    code.circle() > code.square() && code.circle() > code.triangle()
212                }),
213            ],
214        ),
215        // 16
216        Verifier::from_description_and_options(
217            "the number of even numbers compared to the number of odd numbers",
218            &[
219                VerifierOption::from_description_and_closure("EVEN > ODD", |code| {
220                    code.count_even() >= 2
221                }),
222                VerifierOption::from_description_and_closure("EVEN < ODD", |code| {
223                    code.count_even() <= 1
224                }),
225            ],
226        ),
227        // 17
228        Verifier::from_description_and_options(
229            "how many even numbers there are in the code",
230            &[
231                VerifierOption::from_description_and_closure("zero even numbers", |code| {
232                    code.count_even() == 0
233                }),
234                VerifierOption::from_description_and_closure("one even number", |code| {
235                    code.count_even() == 1
236                }),
237                VerifierOption::from_description_and_closure("two even numbers", |code| {
238                    code.count_even() == 2
239                }),
240                VerifierOption::from_description_and_closure("three even numbers", |code| {
241                    code.count_even() == 3
242                }),
243            ],
244        ),
245        // 18
246        Verifier::from_description_and_options(
247            "if the sum of all the numbers is even or odd",
248            &[
249                VerifierOption::from_description_and_closure("△ + □ + ○ = EVEN", |code| {
250                    (code.triangle() + code.square() + code.circle()) % 2 == 0
251                }),
252                VerifierOption::from_description_and_closure("△ + □ + ○ = ODD", |code| {
253                    (code.triangle() + code.square() + code.circle()) % 2 == 1
254                }),
255            ],
256        ),
257        // 19
258        Verifier::from_description_and_options(
259            "the sum of △ and □ compared to 6",
260            &[
261                VerifierOption::from_description_and_closure("△ + □ < 6", |code| {
262                    code.triangle() + code.square() < 6
263                }),
264                VerifierOption::from_description_and_closure("△ + □ = 6", |code| {
265                    code.triangle() + code.square() == 6
266                }),
267                VerifierOption::from_description_and_closure("△ + □ > 6", |code| {
268                    code.triangle() + code.square() > 6
269                }),
270            ],
271        ),
272        // 20
273        Verifier::from_description_and_options(
274            "if a number repeats itself in the code",
275            &[
276                VerifierOption::from_description_and_closure("a triple number", |code| {
277                    code.repeating_numbers() == 2
278                }),
279                VerifierOption::from_description_and_closure("a double number", |code| {
280                    code.repeating_numbers() == 1
281                }),
282                VerifierOption::from_description_and_closure("no repetition", |code| {
283                    code.repeating_numbers() == 0
284                }),
285            ],
286        ),
287        // 21
288        Verifier::from_description_and_options(
289            "if there is a number present exactly twice",
290            &[
291                VerifierOption::from_description_and_closure("no pairs", |code| {
292                    code.repeating_numbers() != 1
293                }),
294                VerifierOption::from_description_and_closure("a pair", |code| {
295                    code.repeating_numbers() == 1
296                }),
297            ],
298        ),
299        // 22
300        Verifier::from_description_and_options(
301            "if the 3 numbers in the code are in ascending order, descending order, or no order",
302            &[
303                VerifierOption::from_description_and_closure("ascending order", |code| {
304                    code.is_ascending_or_descending() == Order::Ascending
305                }),
306                VerifierOption::from_description_and_closure("descending order", |code| {
307                    code.is_ascending_or_descending() == Order::Descending
308                }),
309                VerifierOption::from_description_and_closure("no order", |code| {
310                    code.is_ascending_or_descending() == Order::NoOrder
311                }),
312            ],
313        ),
314        // 23
315        Verifier::from_description_and_options(
316            "the sum of all numbers compared to 6",
317            &[
318                VerifierOption::from_description_and_closure("△ + □ + ○ < 6", |code| {
319                    code.triangle() + code.square() + code.circle() < 6
320                }),
321                VerifierOption::from_description_and_closure("△ + □ + ○ = 6", |code| {
322                    code.triangle() + code.square() + code.circle() == 6
323                }),
324                VerifierOption::from_description_and_closure("△ + □ + ○ > 6", |code| {
325                    code.triangle() + code.square() + code.circle() > 6
326                }),
327            ],
328        ),
329        // 24
330        Verifier::from_description_and_options(
331            "if there is a sequence of ascending numbers",
332            &[
333                VerifierOption::from_description_and_closure(
334                    "3 numbers in ascending order",
335                    |code| code.sequence_ascending() == 3,
336                ),
337                VerifierOption::from_description_and_closure(
338                    "2 numbers in ascending order",
339                    |code| code.sequence_ascending() == 2,
340                ),
341                VerifierOption::from_description_and_closure(
342                    "no numbers in ascending order",
343                    |code| code.sequence_ascending() == 0,
344                ),
345            ],
346        ),
347        // 25
348        Verifier::from_description_and_options(
349            "if there is a sequence of ascending or descending numbers",
350            &[
351                VerifierOption::from_description_and_closure(
352                    "no sequence of numbers in ascending or descending order",
353                    |code| code.sequence_ascending_or_descending() == 0,
354                ),
355                VerifierOption::from_description_and_closure(
356                    "2 numbers in ascending or descending order",
357                    |code| code.sequence_ascending_or_descending() == 2,
358                ),
359                VerifierOption::from_description_and_closure(
360                    "3 numbers in ascending or descending order",
361                    |code| code.sequence_ascending_or_descending() == 3,
362                ),
363            ],
364        ),
365        // 26
366        Verifier::from_description_and_options(
367            "that a specific colour is less than 3",
368            &[
369                VerifierOption::from_description_and_closure("△ < 3", |code| code.triangle() < 3),
370                VerifierOption::from_description_and_closure("□ < 3", |code| code.square() < 3),
371                VerifierOption::from_description_and_closure("○ < 3", |code| code.circle() < 3),
372            ],
373        ),
374        // 27
375        Verifier::from_description_and_options(
376            "that a specific colour is less than 4",
377            &[
378                VerifierOption::from_description_and_closure("△ < 4", |code| code.triangle() < 4),
379                VerifierOption::from_description_and_closure("□ < 4", |code| code.square() < 4),
380                VerifierOption::from_description_and_closure("○ < 4", |code| code.circle() < 4),
381            ],
382        ),
383        // 28
384        Verifier::from_description_and_options(
385            "that a specific colour is equal to 1",
386            &[
387                VerifierOption::from_description_and_closure("△ = 1", |code| {
388                    code.triangle() == 1
389                }),
390                VerifierOption::from_description_and_closure("□ = 1", |code| code.square() == 1),
391                VerifierOption::from_description_and_closure("○ = 1", |code| code.circle() == 1),
392            ],
393        ),
394        // 29
395        Verifier::from_description_and_options(
396            "that a specific colour is equal to 3",
397            &[
398                VerifierOption::from_description_and_closure("△ = 3", |code| {
399                    code.triangle() == 3
400                }),
401                VerifierOption::from_description_and_closure("□ = 3", |code| code.square() == 3),
402                VerifierOption::from_description_and_closure("○ = 3", |code| code.circle() == 3),
403            ],
404        ),
405        // 30
406        Verifier::from_description_and_options(
407            "that a specific colour is equal to 4",
408            &[
409                VerifierOption::from_description_and_closure("△ = 4", |code| {
410                    code.triangle() == 4
411                }),
412                VerifierOption::from_description_and_closure("□ = 4", |code| code.square() == 4),
413                VerifierOption::from_description_and_closure("○ = 4", |code| code.circle() == 4),
414            ],
415        ),
416        // 31
417        Verifier::from_description_and_options(
418            "that a specific colour is greater than 1",
419            &[
420                VerifierOption::from_description_and_closure("△ > 1", |code| code.triangle() > 1),
421                VerifierOption::from_description_and_closure("□ > 1", |code| code.square() > 1),
422                VerifierOption::from_description_and_closure("○ > 1", |code| code.circle() > 1),
423            ],
424        ),
425        // 32
426        Verifier::from_description_and_options(
427            "that a specific colour is greater than 3",
428            &[
429                VerifierOption::from_description_and_closure("△ > 3", |code| code.triangle() > 3),
430                VerifierOption::from_description_and_closure("□ > 3", |code| code.square() > 3),
431                VerifierOption::from_description_and_closure("○ > 3", |code| code.circle() > 3),
432            ],
433        ),
434        // 33
435        Verifier::from_description_and_options(
436            "that a specific colour is even or odd",
437            &[
438                VerifierOption::from_description_and_closure("△ is even", |code| {
439                    code.triangle() % 2 == 0
440                }),
441                VerifierOption::from_description_and_closure("△ is odd", |code| {
442                    code.triangle() % 2 == 1
443                }),
444                VerifierOption::from_description_and_closure("□ is even", |code| {
445                    code.square() % 2 == 0
446                }),
447                VerifierOption::from_description_and_closure("□ is odd", |code| {
448                    code.square() % 2 == 1
449                }),
450                VerifierOption::from_description_and_closure("○ is even", |code| {
451                    code.circle() % 2 == 0
452                }),
453                VerifierOption::from_description_and_closure("○ is odd", |code| {
454                    code.circle() % 2 == 1
455                }),
456            ],
457        ),
458        // 34
459        Verifier::from_description_and_options(
460            "which colour has the smallest number (or is tied for the smallest number)",
461            &[
462                VerifierOption::from_description_and_closure("△ <= □, ○", |code| {
463                    code.triangle() <= code.square() && code.triangle() <= code.circle()
464                }),
465                VerifierOption::from_description_and_closure("□ <= △, ○", |code| {
466                    code.square() <= code.triangle() && code.square() <= code.circle()
467                }),
468                VerifierOption::from_description_and_closure("○ <= □, △", |code| {
469                    code.circle() <= code.square() && code.circle() <= code.triangle()
470                }),
471            ],
472        ),
473        // 35
474        Verifier::from_description_and_options(
475            "which colour has the largest number (or is tied for the largest number)",
476            &[
477                VerifierOption::from_description_and_closure("△ >= □, ○", |code| {
478                    code.triangle() >= code.square() && code.triangle() >= code.circle()
479                }),
480                VerifierOption::from_description_and_closure("□ >= △, ○", |code| {
481                    code.square() >= code.triangle() && code.square() >= code.circle()
482                }),
483                VerifierOption::from_description_and_closure("○ >= □, △", |code| {
484                    code.circle() >= code.square() && code.circle() >= code.triangle()
485                }),
486            ],
487        ),
488        // 36
489        Verifier::from_description_and_options(
490            "the sum of all the numbers is a multiple of 3 or 4 or 5",
491            &[
492                VerifierOption::from_description_and_closure("△ + □ + ○ = 3x", |code| {
493                    code.digit_sum() % 3 == 0
494                }),
495                VerifierOption::from_description_and_closure("△ + □ + ○ = 4x", |code| {
496                    code.digit_sum() % 4 == 0
497                }),
498                VerifierOption::from_description_and_closure("△ + □ + ○ = 5x", |code| {
499                    code.digit_sum() % 5 == 0
500                }),
501            ],
502        ),
503        // 37
504        Verifier::from_description_and_options(
505            "the sum of 2 specific colours is equal to 4",
506            &[
507                VerifierOption::from_description_and_closure("△ + □ = 4", |code| {
508                    code.triangle() + code.square() == 4
509                }),
510                VerifierOption::from_description_and_closure("△ + ○ = 4", |code| {
511                    code.triangle() + code.circle() == 4
512                }),
513                VerifierOption::from_description_and_closure("□ + ○ = 4", |code| {
514                    code.square() + code.circle() == 4
515                }),
516            ],
517        ),
518        // 38
519        Verifier::from_description_and_options(
520            "the sum of 2 specific colours is equal to 6",
521            &[
522                VerifierOption::from_description_and_closure("△ + □ = 6", |code| {
523                    code.triangle() + code.square() == 6
524                }),
525                VerifierOption::from_description_and_closure("△ + ○ = 6", |code| {
526                    code.triangle() + code.circle() == 6
527                }),
528                VerifierOption::from_description_and_closure("□ + ○ = 6", |code| {
529                    code.square() + code.circle() == 6
530                }),
531            ],
532        ),
533        // 39
534        Verifier::from_description_and_options(
535            "the number of one specific colour compared to 1",
536            &[
537                VerifierOption::from_description_and_closure("△ = 1", |code| {
538                    code.triangle() == 1
539                }),
540                VerifierOption::from_description_and_closure("△ > 1", |code| code.triangle() > 1),
541                VerifierOption::from_description_and_closure("□ = 1", |code| code.square() == 1),
542                VerifierOption::from_description_and_closure("□ > 1", |code| code.square() > 1),
543                VerifierOption::from_description_and_closure("○ = 1", |code| code.circle() == 1),
544                VerifierOption::from_description_and_closure("○ > 1", |code| code.circle() > 1),
545            ],
546        ),
547        // 40
548        Verifier::from_description_and_options(
549            "the number of one specific colour compared to 3",
550            &[
551                VerifierOption::from_description_and_closure("△ < 3", |code| code.triangle() < 3),
552                VerifierOption::from_description_and_closure("△ = 3", |code| {
553                    code.triangle() == 3
554                }),
555                VerifierOption::from_description_and_closure("△ > 3", |code| code.triangle() > 3),
556                VerifierOption::from_description_and_closure("□ < 3", |code| code.square() < 3),
557                VerifierOption::from_description_and_closure("□ = 3", |code| code.square() == 3),
558                VerifierOption::from_description_and_closure("□ > 3", |code| code.square() > 3),
559                VerifierOption::from_description_and_closure("○ < 3", |code| code.circle() < 3),
560                VerifierOption::from_description_and_closure("○ = 3", |code| code.circle() == 3),
561                VerifierOption::from_description_and_closure("○ > 3", |code| code.circle() > 3),
562            ],
563        ),
564        // 41
565        Verifier::from_description_and_options(
566            "the number of one specific colour compared to 4",
567            &[
568                VerifierOption::from_description_and_closure("△ < 4", |code| code.triangle() < 4),
569                VerifierOption::from_description_and_closure("△ = 4", |code| {
570                    code.triangle() == 4
571                }),
572                VerifierOption::from_description_and_closure("△ > 4", |code| code.triangle() > 4),
573                VerifierOption::from_description_and_closure("□ < 4", |code| code.square() < 4),
574                VerifierOption::from_description_and_closure("□ = 4", |code| code.square() == 4),
575                VerifierOption::from_description_and_closure("□ > 4", |code| code.square() > 4),
576                VerifierOption::from_description_and_closure("○ < 4", |code| code.circle() < 4),
577                VerifierOption::from_description_and_closure("○ = 4", |code| code.circle() == 4),
578                VerifierOption::from_description_and_closure("○ > 4", |code| code.circle() > 4),
579            ],
580        ),
581        // 42
582        Verifier::from_description_and_options(
583            "which colour is the smallest or the largest",
584            &[
585                VerifierOption::from_description_and_closure("△ < ○, □", |code| {
586                    code.triangle() < code.circle() && code.triangle() < code.square()
587                }),
588                VerifierOption::from_description_and_closure("△ > ○, □", |code| {
589                    code.triangle() > code.circle() && code.triangle() > code.square()
590                }),
591                VerifierOption::from_description_and_closure("□ < △, ○", |code| {
592                    code.square() < code.triangle() && code.square() < code.circle()
593                }),
594                VerifierOption::from_description_and_closure("□ > △, ○", |code| {
595                    code.square() > code.triangle() && code.square() > code.circle()
596                }),
597                VerifierOption::from_description_and_closure("○ < □, △", |code| {
598                    code.circle() < code.square() && code.circle() < code.triangle()
599                }),
600                VerifierOption::from_description_and_closure("○ > □, △", |code| {
601                    code.circle() > code.square() && code.circle() > code.triangle()
602                }),
603            ],
604        ),
605        // 43
606        Verifier::from_description_and_options(
607            "the △ number compared to the number of another specific colour",
608            &[
609                VerifierOption::from_description_and_closure("△ < □", |code| {
610                    code.triangle() < code.square()
611                }),
612                VerifierOption::from_description_and_closure("△ < ○", |code| {
613                    code.triangle() < code.circle()
614                }),
615                VerifierOption::from_description_and_closure("△ = □", |code| {
616                    code.triangle() == code.square()
617                }),
618                VerifierOption::from_description_and_closure("△ = ○", |code| {
619                    code.triangle() == code.circle()
620                }),
621                VerifierOption::from_description_and_closure("△ > □", |code| {
622                    code.triangle() > code.square()
623                }),
624                VerifierOption::from_description_and_closure("△ > ○", |code| {
625                    code.triangle() > code.circle()
626                }),
627            ],
628        ),
629        // 44
630        Verifier::from_description_and_options(
631            "the □ number compared to the number of another specific colour",
632            &[
633                VerifierOption::from_description_and_closure("□ < △", |code| {
634                    code.square() < code.triangle()
635                }),
636                VerifierOption::from_description_and_closure("□ < ○", |code| {
637                    code.square() < code.circle()
638                }),
639                VerifierOption::from_description_and_closure("□ = △", |code| {
640                    code.square() == code.triangle()
641                }),
642                VerifierOption::from_description_and_closure("□ = ○", |code| {
643                    code.square() == code.circle()
644                }),
645                VerifierOption::from_description_and_closure("□ > △", |code| {
646                    code.square() > code.triangle()
647                }),
648                VerifierOption::from_description_and_closure("□ > ○", |code| {
649                    code.square() > code.circle()
650                }),
651            ],
652        ),
653        // 45
654        Verifier::from_description_and_options(
655            "how many 1s OR how many 3s there are in the code",
656            &[
657                VerifierOption::from_description_and_closure("zero 1s", |code| {
658                    code.count_digit(1) == 0
659                }),
660                VerifierOption::from_description_and_closure("one 1s", |code| {
661                    code.count_digit(1) == 1
662                }),
663                VerifierOption::from_description_and_closure("two 1s", |code| {
664                    code.count_digit(1) == 2
665                }),
666                VerifierOption::from_description_and_closure("zero 3s", |code| {
667                    code.count_digit(3) == 0
668                }),
669                VerifierOption::from_description_and_closure("one 3s", |code| {
670                    code.count_digit(3) == 1
671                }),
672                VerifierOption::from_description_and_closure("two 3s", |code| {
673                    code.count_digit(3) == 2
674                }),
675            ],
676        ),
677        // 46
678        Verifier::from_description_and_options(
679            "how many 3s OR how many 4s there are in the code",
680            &[
681                VerifierOption::from_description_and_closure("zero 3s", |code| {
682                    code.count_digit(3) == 0
683                }),
684                VerifierOption::from_description_and_closure("one 3", |code| {
685                    code.count_digit(3) == 1
686                }),
687                VerifierOption::from_description_and_closure("two 3s", |code| {
688                    code.count_digit(3) == 2
689                }),
690                VerifierOption::from_description_and_closure("zero 4s", |code| {
691                    code.count_digit(4) == 0
692                }),
693                VerifierOption::from_description_and_closure("one 4", |code| {
694                    code.count_digit(4) == 1
695                }),
696                VerifierOption::from_description_and_closure("two 4s", |code| {
697                    code.count_digit(4) == 2
698                }),
699            ],
700        ),
701        // 47
702        Verifier::from_description_and_options(
703            "how many 1s OR how many 4s there are in the code",
704            &[
705                VerifierOption::from_description_and_closure("zero 1s", |code| {
706                    code.count_digit(1) == 0
707                }),
708                VerifierOption::from_description_and_closure("one 1", |code| {
709                    code.count_digit(1) == 1
710                }),
711                VerifierOption::from_description_and_closure("two 1s", |code| {
712                    code.count_digit(1) == 2
713                }),
714                VerifierOption::from_description_and_closure("zero 4s", |code| {
715                    code.count_digit(4) == 0
716                }),
717                VerifierOption::from_description_and_closure("one 4", |code| {
718                    code.count_digit(4) == 1
719                }),
720                VerifierOption::from_description_and_closure("two 4s", |code| {
721                    code.count_digit(4) == 2
722                }),
723            ],
724        ),
725        // 48
726        Verifier::from_description_and_options(
727            "one specific colour compared to another specific colour",
728            &[
729                VerifierOption::from_description_and_closure("△ < □", |code| {
730                    code.triangle() < code.square()
731                }),
732                VerifierOption::from_description_and_closure("△ = □", |code| {
733                    code.triangle() == code.square()
734                }),
735                VerifierOption::from_description_and_closure("△ > □", |code| {
736                    code.triangle() > code.square()
737                }),
738                VerifierOption::from_description_and_closure("△ < ○", |code| {
739                    code.triangle() < code.circle()
740                }),
741                VerifierOption::from_description_and_closure("△ = ○", |code| {
742                    code.triangle() == code.circle()
743                }),
744                VerifierOption::from_description_and_closure("△ > ○", |code| {
745                    code.triangle() > code.circle()
746                }),
747                VerifierOption::from_description_and_closure("□ < ○", |code| {
748                    code.square() < code.circle()
749                }),
750                VerifierOption::from_description_and_closure("□ = ○", |code| {
751                    code.square() == code.circle()
752                }),
753                VerifierOption::from_description_and_closure("□ > ○", |code| {
754                    code.square() > code.circle()
755                }),
756            ],
757        ),
758    ];
759    verifiers[number - 1].clone()
760}
761
762const MAX_VERIFIER_OPTIONS: usize = 9;
763
764#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
765pub struct VerifierOption {
766    pub(crate) description: &'static str,
767    code_set: Set,
768}
769
770impl VerifierOption {
771    #[must_use]
772    pub fn code_set(&self) -> Set {
773        self.code_set
774    }
775
776    pub fn from_description_and_closure(
777        description: &'static str,
778        checker: fn(Code) -> bool,
779    ) -> VerifierOption {
780        VerifierOption {
781            description,
782            code_set: Set::from_closure(checker),
783        }
784    }
785}
786
787pub(crate) trait Intersection {
788    type To;
789    fn intersect(self) -> Self::To;
790}
791
792impl<T: Iterator<Item = Set>> Intersection for T {
793    type To = Set;
794    fn intersect(self) -> Self::To {
795        self.fold(Set::all(), |still_possible_codes, new_code_set| {
796            still_possible_codes.intersected_with(new_code_set)
797        })
798    }
799}
800
801#[derive(Clone, Eq, PartialEq, Hash)]
802pub struct Verifier {
803    description: &'static str,
804    options: ArrayVec<VerifierOption, MAX_VERIFIER_OPTIONS>,
805}
806
807impl Debug for Verifier {
808    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
809        writeln!(f, "{}", self.description)?;
810        for option in self.options.iter() {
811            writeln!(f, "- {}", option.description)?;
812        }
813        Ok(())
814    }
815}
816
817impl Verifier {
818    #[must_use]
819    pub fn description(&self) -> &'static str {
820        self.description
821    }
822
823    #[must_use]
824    pub fn number_of_options(&self) -> usize {
825        self.options.len()
826    }
827
828    #[must_use]
829    pub fn from_description_and_options(
830        description: &'static str,
831        options: &[VerifierOption],
832    ) -> Self {
833        Verifier {
834            description,
835            options: options.iter().copied().collect(),
836        }
837    }
838
839    #[must_use]
840    pub fn option(&self, choice: u8) -> &VerifierOption {
841        &self.options[choice as usize]
842    }
843
844    pub fn options(&self) -> impl Iterator<Item = &VerifierOption> + '_ {
845        self.options.iter()
846    }
847}