Louis Vallat
27060735f8
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 3s
Build and run challenges / Challenge for day (10) (push) Successful in 3s
Build and run challenges / Challenge for day (11) (push) Successful in 3s
Build and run challenges / Challenge for day (12) (push) Successful in 3s
Build and run challenges / Challenge for day (13) (push) Successful in 3s
Build and run challenges / Challenge for day (14) (push) Successful in 3s
Build and run challenges / Challenge for day (15) (push) Successful in 3s
Build and run challenges / Challenge for day (16) (push) Successful in 3s
Build and run challenges / Challenge for day (17) (push) Successful in 3s
Build and run challenges / Challenge for day (18) (push) Successful in 3s
Build and run challenges / Challenge for day (19) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (20) (push) Successful in 3s
Build and run challenges / Challenge for day (21) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 5s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (6) (push) Successful in 5s
Build and run challenges / Challenge for day (3) (push) Successful in 11s
Build and run challenges / Challenge for day (7) (push) Successful in 4s
Build and run challenges / Challenge for day (8) (push) Successful in 3s
Build and run challenges / Challenge for day (9) (push) Successful in 3s
Signed-off-by: Louis Vallat <contact@louis-vallat.dev>
189 lines
5.5 KiB
Rust
189 lines
5.5 KiB
Rust
pub trait Button: std::fmt::Debug + Eq {
|
|
fn forbidden_position(&self) -> (i32, i32);
|
|
fn to_position(&self) -> (i32, i32);
|
|
|
|
fn distance_with(&self, other: &impl Button) -> Vec<(DirectionalButton, usize)> {
|
|
let source = self.to_position();
|
|
let dest = other.to_position();
|
|
let (dist_v, dist_h) = (dest.0 - source.0, dest.1 - source.1);
|
|
let (mul_v, mul_h) = (dist_v.abs(), dist_h.abs());
|
|
|
|
let mut movements = Vec::new();
|
|
if mul_v > 0 {
|
|
movements.push((
|
|
DirectionalButton::from_direction(&(dist_v / mul_v, 0)),
|
|
mul_v as usize,
|
|
));
|
|
}
|
|
|
|
if mul_h > 0 {
|
|
movements.push((
|
|
DirectionalButton::from_direction(&(0, dist_h / mul_h)),
|
|
mul_h as usize,
|
|
));
|
|
}
|
|
|
|
movements
|
|
}
|
|
|
|
fn possible_movements(&self, other: &impl Button) -> Vec<Vec<DirectionalButton>> {
|
|
let movements = self.distance_with(other);
|
|
if movements.is_empty() {
|
|
return vec![vec![DirectionalButton::A, DirectionalButton::A]];
|
|
}
|
|
|
|
let source = self.to_position();
|
|
let &first_move = movements.first().unwrap();
|
|
let first_move_applied = first_move.0.apply_movement(&source, first_move.1 as i32);
|
|
let &last_move = movements.last().unwrap();
|
|
let last_move_applied = last_move.0.apply_movement(&source, last_move.1 as i32);
|
|
let mut possible_movements = Vec::new();
|
|
if first_move == last_move && first_move_applied != self.forbidden_position() {
|
|
let mut possibility = vec![DirectionalButton::A];
|
|
possibility.extend(vec![first_move.0; first_move.1]);
|
|
possible_movements.push(possibility);
|
|
} else {
|
|
let mut first_possibility = vec![DirectionalButton::A];
|
|
first_possibility.extend(vec![first_move.0; first_move.1]);
|
|
first_possibility.extend(vec![last_move.0; last_move.1]);
|
|
|
|
let mut last_possibility = vec![DirectionalButton::A];
|
|
last_possibility.extend(vec![last_move.0; last_move.1]);
|
|
last_possibility.extend(vec![first_move.0; first_move.1]);
|
|
|
|
if first_move_applied != self.forbidden_position()
|
|
&& last_move_applied != self.forbidden_position()
|
|
{
|
|
possible_movements.push(first_possibility);
|
|
possible_movements.push(last_possibility);
|
|
} else if first_move_applied != self.forbidden_position()
|
|
&& last_move_applied == self.forbidden_position()
|
|
{
|
|
possible_movements.push(first_possibility);
|
|
} else if first_move_applied == self.forbidden_position()
|
|
&& last_move_applied != self.forbidden_position()
|
|
{
|
|
possible_movements.push(last_possibility);
|
|
} else {
|
|
unreachable!()
|
|
}
|
|
}
|
|
|
|
for possible_movement in possible_movements.iter_mut() {
|
|
possible_movement.push(DirectionalButton::A);
|
|
}
|
|
possible_movements
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
|
pub enum NumericButton {
|
|
Zero,
|
|
One,
|
|
Two,
|
|
Three,
|
|
Four,
|
|
Five,
|
|
Six,
|
|
Seven,
|
|
Eight,
|
|
Nine,
|
|
A,
|
|
}
|
|
|
|
impl From<char> for NumericButton {
|
|
fn from(c: char) -> Self {
|
|
match c {
|
|
'0' => Self::Zero,
|
|
'1' => Self::One,
|
|
'2' => Self::Two,
|
|
'3' => Self::Three,
|
|
'4' => Self::Four,
|
|
'5' => Self::Five,
|
|
'6' => Self::Six,
|
|
'7' => Self::Seven,
|
|
'8' => Self::Eight,
|
|
'9' => Self::Nine,
|
|
'A' => Self::A,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Button for NumericButton {
|
|
fn forbidden_position(&self) -> (i32, i32) {
|
|
(3, 0)
|
|
}
|
|
|
|
fn to_position(&self) -> (i32, i32) {
|
|
match self {
|
|
Self::Seven => (0, 0),
|
|
Self::Eight => (0, 1),
|
|
Self::Nine => (0, 2),
|
|
Self::Four => (1, 0),
|
|
Self::Five => (1, 1),
|
|
Self::Six => (1, 2),
|
|
Self::One => (2, 0),
|
|
Self::Two => (2, 1),
|
|
Self::Three => (2, 2),
|
|
Self::Zero => (3, 1),
|
|
Self::A => (3, 2),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
|
pub enum DirectionalButton {
|
|
Up,
|
|
Down,
|
|
Left,
|
|
Right,
|
|
A,
|
|
}
|
|
|
|
impl Button for DirectionalButton {
|
|
fn forbidden_position(&self) -> (i32, i32) {
|
|
(0, 0)
|
|
}
|
|
|
|
fn to_position(&self) -> (i32, i32) {
|
|
match self {
|
|
Self::Up => (0, 1),
|
|
Self::A => (0, 2),
|
|
Self::Left => (1, 0),
|
|
Self::Down => (1, 1),
|
|
Self::Right => (1, 2),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DirectionalButton {
|
|
fn from_direction(direction: &(i32, i32)) -> Self {
|
|
match direction {
|
|
(-1, 0) => Self::Up,
|
|
(1, 0) => Self::Down,
|
|
(0, 1) => Self::Right,
|
|
(0, -1) => Self::Left,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn to_direction(&self) -> (i32, i32) {
|
|
match self {
|
|
Self::Up => (-1, 0),
|
|
Self::Down => (1, 0),
|
|
Self::Left => (0, -1),
|
|
Self::Right => (0, 1),
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn apply_movement(&self, position: &(i32, i32), times: i32) -> (i32, i32) {
|
|
let direction = self.to_direction();
|
|
(
|
|
position.0 + direction.0 * times,
|
|
position.1 + direction.1 * times,
|
|
)
|
|
}
|
|
}
|