1 // check-pass
2
3 #![feature(adt_const_params, generic_const_exprs)]
4 #![allow(incomplete_features)]
5
6 mod lib {
7 const N_ISLANDS: usize = 4;
8 const N_BRIDGES: usize = 7;
9 const BRIDGES: [(usize, usize); 7] = [(0, 1), (0, 1), (0, 2), (0, 3), (0, 3), (1, 2), (2, 3)];
10
11 pub type Matrix = [[usize; N_ISLANDS]; N_ISLANDS];
12
13 const EMPTY_MATRIX: Matrix = [[0; N_ISLANDS]; N_ISLANDS];
14
build(mut matrix: Matrix, (to, from): (usize, usize)) -> Matrix15 const fn build(mut matrix: Matrix, (to, from): (usize, usize)) -> Matrix {
16 matrix[to][from] += 1;
17 matrix[from][to] += 1;
18 matrix
19 }
20
walk(mut matrix: Matrix, from: usize, to: usize) -> Matrix21 pub const fn walk(mut matrix: Matrix, from: usize, to: usize) -> Matrix {
22 matrix[from][to] -= 1;
23 matrix[to][from] -= 1;
24 matrix
25 }
26
to_matrix(bridges: [(usize, usize); N_BRIDGES]) -> Matrix27 const fn to_matrix(bridges: [(usize, usize); N_BRIDGES]) -> Matrix {
28 let matrix = EMPTY_MATRIX;
29
30 let matrix = build(matrix, bridges[0]);
31 let matrix = build(matrix, bridges[1]);
32 let matrix = build(matrix, bridges[2]);
33 let matrix = build(matrix, bridges[3]);
34 let matrix = build(matrix, bridges[4]);
35 let matrix = build(matrix, bridges[5]);
36 let matrix = build(matrix, bridges[6]);
37
38 matrix
39 }
40
41 const BRIDGE_MATRIX: [[usize; N_ISLANDS]; N_ISLANDS] = to_matrix(BRIDGES);
42
43 pub struct Walk<const CURRENT: usize, const REMAINING: Matrix> {
44 _p: (),
45 }
46
47 impl Walk<0, BRIDGE_MATRIX> {
new() -> Self48 pub const fn new() -> Self {
49 Self { _p: () }
50 }
51 }
52
53 impl<const CURRENT: usize, const REMAINING: Matrix> Walk<CURRENT, REMAINING> {
proceed_to<const NEXT: usize>( self, ) -> Walk<NEXT,54 pub fn proceed_to<const NEXT: usize>(
55 self,
56 ) -> Walk<NEXT, { walk(REMAINING, CURRENT, NEXT) }> {
57 Walk { _p: () }
58 }
59 }
60
61 pub struct Trophy {
62 _p: (),
63 }
64
65 impl<const CURRENT: usize> Walk<CURRENT, EMPTY_MATRIX> {
collect_prize(self) -> Trophy66 pub fn collect_prize(self) -> Trophy {
67 Trophy { _p: () }
68 }
69 }
70 }
71
72 pub use lib::{Trophy, Walk};
73
main()74 fn main() {
75 // Example, taking the first step
76 let _ = Walk::new().proceed_to::<1>();
77
78 // Don't be so eager to collect the trophy
79 // let trophy = Walk::new()
80 // .proceed_to::<1>()
81 // .proceed_to::<0>()
82 // .collect_prize();
83
84 // Can't just make a Trophy out of thin air, you must earn it
85 // let trophy: Trophy = Trophy { _p: () };
86
87 // Can you collect the Trophy?
88 }
89