Skip to content

Instantly share code, notes, and snippets.

@stepancheg
Created March 17, 2019 23:26
Show Gist options
  • Save stepancheg/4dee02d8a190aa5dae7f506ca81d95ba to your computer and use it in GitHub Desktop.
Save stepancheg/4dee02d8a190aa5dae7f506ca81d95ba to your computer and use it in GitHub Desktop.
use std::mem;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
struct Walk {
axis: u32,
positive: bool,
}
#[derive(Debug, Copy, Clone)]
struct Coord {
coord: [u32; 3],
}
impl Coord {
fn is_valid_walk(&self, walk: &Walk) -> bool {
let coord = self.coord[walk.axis as usize];
if walk.positive { coord <= 1 } else { coord >= 1 }
}
fn plus(&self, walk: &Walk) -> Coord {
assert!(self.is_valid_walk(walk));
let mut coord = self.clone();
if walk.positive {
coord.coord[walk.axis as usize] += 1;
} else {
coord.coord[walk.axis as usize] -= 1;
}
coord
}
}
#[derive(Default, Copy, Clone, Debug)]
struct Visited {
cells: [[[bool; 3]; 3]; 3],
count: u32,
}
impl Visited {
fn try_set_xyz(&mut self, coord: Coord) -> bool {
let r = mem::replace(&mut self.cells[coord.coord[0] as usize][coord.coord[1] as usize][coord.coord[2] as usize], true);
if !r {
self.count += 1;
assert!(self.count <= 27);
}
r
}
fn set_xyz(&mut self, coord: Coord) {
assert!(!self.try_set_xyz(coord), "{:?} {:?}", coord, self);
}
fn get(&self, coord: Coord) -> bool {
self.cells[coord.coord[0] as usize][coord.coord[1] as usize][coord.coord[2] as usize]
}
}
fn continue_from(coord: Coord, mut visited: Visited, last_walk: Walk) {
if visited.count == 27 {
println!("yes");
return;
}
if visited.try_set_xyz(coord) {
//println!("breaking at {:?} {:?} {:?}", coord, visited, last_walk);
//println!("breaking at {}", visited.count);
return;
}
for axis in 0..=2 {
for &positive in &[true, false] {
let walk = Walk {
axis,
positive,
};
if walk == last_walk {
continue;
}
if !coord.is_valid_walk(&walk) {
continue;
}
let next_coord = coord.plus(&walk);
continue_from(next_coord, visited, walk);
}
}
}
fn try_from(coord: Coord) {
let mut visited = Visited::default();
visited.set_xyz(coord);
for axis in 0..=2 {
for &positive in &[true, false] {
let walk = Walk {
axis,
positive,
};
if !coord.is_valid_walk(&walk) {
continue;
}
let next_coord = coord.plus(&walk);
continue_from(next_coord, visited, walk);
}
}
}
fn main() {
for x in 0..=2 {
for y in 0..=2 {
for z in 0..=2 {
try_from(Coord { coord: [x, y, z] });
}
}
}
println!("$");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment