|
| 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 | + |
| 15 | + 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 | + |
| 21 | + 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 | + |
| 27 | + 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> { |
| 48 | + pub const fn new() -> Self { |
| 49 | + Self { _p: () } |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + impl<const CURRENT: usize, const REMAINING: Matrix> Walk<CURRENT, REMAINING> { |
| 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> { |
| 66 | + pub fn collect_prize(self) -> Trophy { |
| 67 | + Trophy { _p: () } |
| 68 | + } |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +pub use lib::{Trophy, Walk}; |
| 73 | + |
| 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 | +} |
0 commit comments