Compare commits
5 Commits
62c866abf9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 5642d65bff | |||
| 745d4a8029 | |||
| a7d32abb93 | |||
| 98fcdfeaef | |||
| 7abd632567 |
19
src/bin/d23p1.rs
Normal file
19
src/bin/d23p1.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use aoc22::{
|
||||||
|
day23::{self, empty_ground},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
|
const N_ROUNDS: usize = 10;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut elves = day23::parse_map(&util::parse_input());
|
||||||
|
|
||||||
|
for i in 0..N_ROUNDS {
|
||||||
|
let elves_too_close = day23::do_round(&mut elves, i);
|
||||||
|
if !elves_too_close {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Elves cover {} empty tiles", empty_ground(&elves));
|
||||||
|
}
|
||||||
20
src/bin/d23p2.rs
Normal file
20
src/bin/d23p2.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use aoc22::{
|
||||||
|
day23::{self},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut elves = day23::parse_map(&util::parse_input());
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
loop {
|
||||||
|
let elves_too_close = day23::do_round(&mut elves, i);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
if !elves_too_close {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("First idle round: {}", i);
|
||||||
|
}
|
||||||
13
src/bin/d24p1.rs
Normal file
13
src/bin/d24p1.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use aoc22::{
|
||||||
|
day24::{self},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let (map, start, target) = day24::parse_map(&util::parse_input());
|
||||||
|
|
||||||
|
day24::print_map(&map, &start);
|
||||||
|
|
||||||
|
let (rounds, _) = day24::find_path(&map, &start, &target);
|
||||||
|
println!("Goal is reachable in {} min", rounds);
|
||||||
|
}
|
||||||
19
src/bin/d24p2.rs
Normal file
19
src/bin/d24p2.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use aoc22::{
|
||||||
|
day24::{self},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let (map, start, target) = day24::parse_map(&util::parse_input());
|
||||||
|
|
||||||
|
day24::print_map(&map, &start);
|
||||||
|
|
||||||
|
let (rounds_1, map_1) = day24::find_path(&map, &start, &target);
|
||||||
|
println!("Goal is reachable in {} min", rounds_1);
|
||||||
|
let (rounds_2, map_2) = day24::find_path(&map_1, &target, &start);
|
||||||
|
println!("Start is reachable in {} min", rounds_2);
|
||||||
|
let (rounds_3, _) = day24::find_path(&map_2, &start, &target);
|
||||||
|
println!("Goal is reachable in {} min", rounds_2);
|
||||||
|
|
||||||
|
println!("Total time taken is {} min", rounds_1 + rounds_2 + rounds_3);
|
||||||
|
}
|
||||||
8
src/bin/d25p1.rs
Normal file
8
src/bin/d25p1.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use aoc22::{day25, util};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let numbers = day25::parse_snafus(&util::parse_input());
|
||||||
|
let sum: i64 = numbers.iter().sum();
|
||||||
|
println!("Sum of numbers: {}", sum);
|
||||||
|
println!("Sum of numbers, SNAFU'd: {}", day25::num_to_snafu(sum));
|
||||||
|
}
|
||||||
112
src/day23.rs
Normal file
112
src/day23.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::util::{self, SignedCoord};
|
||||||
|
|
||||||
|
pub fn parse_map(input: &str) -> HashSet<SignedCoord> {
|
||||||
|
let mut result = HashSet::new();
|
||||||
|
for (y, row) in input.lines().enumerate() {
|
||||||
|
for (x, c) in row.chars().enumerate() {
|
||||||
|
if c == '#' {
|
||||||
|
result.insert((y as isize, x as isize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUM_DIRS: usize = 4;
|
||||||
|
|
||||||
|
pub fn do_round(elves: &mut HashSet<SignedCoord>, it: usize) -> bool {
|
||||||
|
let mut proposals: HashMap<SignedCoord, Vec<SignedCoord>> = HashMap::new();
|
||||||
|
|
||||||
|
let mut elves_too_close = false;
|
||||||
|
for elf in elves.iter() {
|
||||||
|
if noone_adjacent(elves, elf) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elves_too_close = true;
|
||||||
|
for offset in 0..NUM_DIRS {
|
||||||
|
let dir = (it + offset) % NUM_DIRS;
|
||||||
|
if let Some(new_loc) = propose(elves, elf, dir) {
|
||||||
|
proposals.entry(new_loc).or_insert_with(Vec::new).push(*elf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (target, interested) in proposals {
|
||||||
|
if interested.len() == 1 {
|
||||||
|
elves.remove(&interested[0]);
|
||||||
|
elves.insert(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elves_too_close
|
||||||
|
}
|
||||||
|
|
||||||
|
fn noone_adjacent(elves: &HashSet<SignedCoord>, elf: &SignedCoord) -> bool {
|
||||||
|
!(elves.contains(&(elf.0, elf.1 + 1))
|
||||||
|
|| elves.contains(&(elf.0, elf.1 - 1))
|
||||||
|
|| elves.contains(&(elf.0 + 1, elf.1))
|
||||||
|
|| elves.contains(&(elf.0 + 1, elf.1 + 1))
|
||||||
|
|| elves.contains(&(elf.0 + 1, elf.1 - 1))
|
||||||
|
|| elves.contains(&(elf.0 - 1, elf.1))
|
||||||
|
|| elves.contains(&(elf.0 - 1, elf.1 + 1))
|
||||||
|
|| elves.contains(&(elf.0 - 1, elf.1 - 1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propose(elves: &HashSet<SignedCoord>, elf: &SignedCoord, dir: usize) -> Option<SignedCoord> {
|
||||||
|
let (moved, other) = match dir {
|
||||||
|
0 => (
|
||||||
|
(elf.0 - 1, elf.1),
|
||||||
|
((elf.0 - 1, elf.1 - 1), (elf.0 - 1, elf.1 + 1)),
|
||||||
|
), // N
|
||||||
|
1 => (
|
||||||
|
(elf.0 + 1, elf.1),
|
||||||
|
((elf.0 + 1, elf.1 - 1), (elf.0 + 1, elf.1 + 1)),
|
||||||
|
), // S
|
||||||
|
2 => (
|
||||||
|
(elf.0, elf.1 - 1),
|
||||||
|
((elf.0 - 1, elf.1 - 1), (elf.0 + 1, elf.1 - 1)),
|
||||||
|
), // E
|
||||||
|
3 => (
|
||||||
|
(elf.0, elf.1 + 1),
|
||||||
|
((elf.0 - 1, elf.1 + 1), (elf.0 + 1, elf.1 + 1)),
|
||||||
|
), // W
|
||||||
|
_ => panic!("Unknown direction {}", dir),
|
||||||
|
};
|
||||||
|
if elves.contains(&moved) || elves.contains(&other.0) || elves.contains(&other.1) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(moved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_map(elves: &HashSet<SignedCoord>) {
|
||||||
|
let (y_min, y_max) = util::minmax_unwrap(&elves.iter().map(|c| c.0).minmax());
|
||||||
|
let (x_min, x_max) = util::minmax_unwrap(&elves.iter().map(|c| c.1).minmax());
|
||||||
|
|
||||||
|
println!("({}, {})", y_min, x_min);
|
||||||
|
for y in y_min..(y_max + 1) {
|
||||||
|
for x in x_min..(x_max + 1) {
|
||||||
|
if elves.contains(&(y, x)) {
|
||||||
|
print!("#");
|
||||||
|
} else {
|
||||||
|
print!(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print!("\n");
|
||||||
|
}
|
||||||
|
print!("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty_ground(elves: &HashSet<SignedCoord>) -> usize {
|
||||||
|
let (y_min, y_max) = util::minmax_unwrap(&elves.iter().map(|c| c.0).minmax());
|
||||||
|
let (x_min, x_max) = util::minmax_unwrap(&elves.iter().map(|c| c.1).minmax());
|
||||||
|
let y_dim = (y_max + 1 - y_min) as usize;
|
||||||
|
let x_dim = (x_max + 1 - x_min) as usize;
|
||||||
|
|
||||||
|
y_dim * x_dim - elves.len()
|
||||||
|
}
|
||||||
188
src/day24.rs
Normal file
188
src/day24.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use crate::util::{Coord, Dir};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Tile {
|
||||||
|
Empty,
|
||||||
|
Wall,
|
||||||
|
Blizzards(Vec<Dir>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns (map, start, end)
|
||||||
|
pub fn parse_map(input: &str) -> (Vec<Vec<Tile>>, Coord, Coord) {
|
||||||
|
let mut map = Vec::new();
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
let mut row = Vec::new();
|
||||||
|
|
||||||
|
for c in line.chars() {
|
||||||
|
row.push(match c {
|
||||||
|
'.' => Tile::Empty,
|
||||||
|
'#' => Tile::Wall,
|
||||||
|
_ => Tile::Blizzards(vec![Dir::from_char(c).unwrap()]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
map.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(map.len() >= 2);
|
||||||
|
let last_row = map.len() - 1;
|
||||||
|
|
||||||
|
let start = map[0]
|
||||||
|
.iter()
|
||||||
|
.position(|t| matches!(t, Tile::Empty))
|
||||||
|
.unwrap();
|
||||||
|
let end = map[last_row]
|
||||||
|
.iter()
|
||||||
|
.position(|t| matches!(t, Tile::Empty))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
(map, (0, start), (last_row, end))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_map(map: &Vec<Vec<Tile>>, expedition: &Coord) {
|
||||||
|
for (y, row) in map.iter().enumerate() {
|
||||||
|
for (x, tile) in row.iter().enumerate() {
|
||||||
|
if *expedition == (y, x) {
|
||||||
|
print!("E");
|
||||||
|
} else {
|
||||||
|
match tile {
|
||||||
|
Tile::Empty => print!("."),
|
||||||
|
Tile::Wall => print!("#"),
|
||||||
|
Tile::Blizzards(blizzards) => {
|
||||||
|
if blizzards.len() > 1 {
|
||||||
|
print!("{}", blizzards.len());
|
||||||
|
} else {
|
||||||
|
print!("{}", blizzards[0].to_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print!("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_map(map: &Vec<Vec<Tile>>) -> Vec<Vec<Tile>> {
|
||||||
|
assert!(map.len() > 0);
|
||||||
|
// Outermost rows/columns are walls
|
||||||
|
let min_y = 1;
|
||||||
|
let max_y = map.len() - 2;
|
||||||
|
let min_x = 1;
|
||||||
|
let max_x = map[0].len() - 2;
|
||||||
|
|
||||||
|
// Start with a map without blizzards
|
||||||
|
let mut result: Vec<Vec<Tile>> = map
|
||||||
|
.iter()
|
||||||
|
.map(|r| {
|
||||||
|
r.iter()
|
||||||
|
.map(|t| {
|
||||||
|
if matches!(t, Tile::Blizzards(_)) {
|
||||||
|
Tile::Empty
|
||||||
|
} else {
|
||||||
|
t.clone()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for y in 0..map.len() {
|
||||||
|
for x in 0..map[0].len() {
|
||||||
|
if let Tile::Blizzards(blizzards) = &map[y][x] {
|
||||||
|
for blizzard_dir in blizzards {
|
||||||
|
let new_tile = match blizzard_dir {
|
||||||
|
Dir::Right => {
|
||||||
|
if x == max_x {
|
||||||
|
(y, min_x)
|
||||||
|
} else {
|
||||||
|
(y, x + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::Down => {
|
||||||
|
if y == max_y {
|
||||||
|
(min_y, x)
|
||||||
|
} else {
|
||||||
|
(y + 1, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::Left => {
|
||||||
|
if x == min_x {
|
||||||
|
(y, max_x)
|
||||||
|
} else {
|
||||||
|
(y, x - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::Up => {
|
||||||
|
if y == min_y {
|
||||||
|
(max_y, x)
|
||||||
|
} else {
|
||||||
|
(y - 1, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let new_tile = &mut result[new_tile.0][new_tile.1];
|
||||||
|
if let Tile::Blizzards(blizzards) = new_tile {
|
||||||
|
blizzards.push(*blizzard_dir);
|
||||||
|
} else {
|
||||||
|
assert!(matches!(new_tile, Tile::Empty));
|
||||||
|
*new_tile = Tile::Blizzards(vec![*blizzard_dir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns length of the shortest path
|
||||||
|
pub fn find_path(
|
||||||
|
initial: &Vec<Vec<Tile>>,
|
||||||
|
start: &Coord,
|
||||||
|
target: &Coord,
|
||||||
|
) -> (usize, Vec<Vec<Tile>>) {
|
||||||
|
let height = initial.len();
|
||||||
|
assert!(height > 0);
|
||||||
|
let width = initial[0].len();
|
||||||
|
|
||||||
|
let mut map = initial.clone();
|
||||||
|
let mut to_check = HashSet::new();
|
||||||
|
to_check.insert(*start);
|
||||||
|
let mut rounds = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
map = next_map(&map);
|
||||||
|
rounds += 1;
|
||||||
|
let mut check_next = HashSet::new();
|
||||||
|
|
||||||
|
for pos in to_check {
|
||||||
|
let mut reachable = vec![pos];
|
||||||
|
if pos.0 != 0 {
|
||||||
|
reachable.push((pos.0 - 1, pos.1));
|
||||||
|
}
|
||||||
|
if pos.0 != height - 1 {
|
||||||
|
reachable.push((pos.0 + 1, pos.1));
|
||||||
|
}
|
||||||
|
if pos.1 != 0 {
|
||||||
|
reachable.push((pos.0, pos.1 - 1));
|
||||||
|
}
|
||||||
|
if pos.1 != width - 1 {
|
||||||
|
reachable.push((pos.0, pos.1 + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
for p in reachable {
|
||||||
|
if p == *target {
|
||||||
|
return (rounds, map);
|
||||||
|
}
|
||||||
|
if matches!(map[p.0][p.1], Tile::Empty) {
|
||||||
|
check_next.insert(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to_check = check_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/day25.rs
Normal file
83
src/day25.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
pub fn parse_snafus(input: &str) -> Vec<i64> {
|
||||||
|
input.lines().map(snafu_to_num).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn snafu_to_num(snafu: &str) -> i64 {
|
||||||
|
let mut pow = 1;
|
||||||
|
let mut result = 0;
|
||||||
|
for c in snafu.chars().rev() {
|
||||||
|
let digit = match c {
|
||||||
|
'=' => -2,
|
||||||
|
'-' => -1,
|
||||||
|
'0' => 0,
|
||||||
|
'1' => 1,
|
||||||
|
'2' => 2,
|
||||||
|
_ => panic!("Unknown digit {}", c),
|
||||||
|
};
|
||||||
|
result += pow * digit;
|
||||||
|
pow *= 5;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_to_snafu(num: i64) -> String {
|
||||||
|
assert!(num > 0);
|
||||||
|
|
||||||
|
let exp = (num as f64).log(5.0).floor() as u32 + 1;
|
||||||
|
let mut result = VecDeque::with_capacity((exp as usize) + 1);
|
||||||
|
let mut pow = 5_i64.pow(exp);
|
||||||
|
let mut rem = num;
|
||||||
|
|
||||||
|
while pow >= 1 {
|
||||||
|
let digit = rem / pow;
|
||||||
|
rem %= pow;
|
||||||
|
result.push_back(digit);
|
||||||
|
pow /= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in (0..result.len()).rev() {
|
||||||
|
if result[i] > 2 {
|
||||||
|
result[i] -= 5;
|
||||||
|
result[i - 1] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
.iter()
|
||||||
|
.skip_while(|d| **d == 0)
|
||||||
|
.map(|d| match d {
|
||||||
|
-2 => '=',
|
||||||
|
-1 => '-',
|
||||||
|
0 => '0',
|
||||||
|
1 => '1',
|
||||||
|
2 => '2',
|
||||||
|
_ => panic!("Unknown digit {}", d),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn num_to_snafu_examples() {
|
||||||
|
use crate::day25::num_to_snafu;
|
||||||
|
assert_eq!(num_to_snafu(1), "1");
|
||||||
|
assert_eq!(num_to_snafu(2), "2");
|
||||||
|
assert_eq!(num_to_snafu(3), "1=");
|
||||||
|
assert_eq!(num_to_snafu(4), "1-");
|
||||||
|
assert_eq!(num_to_snafu(5), "10");
|
||||||
|
assert_eq!(num_to_snafu(6), "11");
|
||||||
|
assert_eq!(num_to_snafu(7), "12");
|
||||||
|
assert_eq!(num_to_snafu(8), "2=");
|
||||||
|
assert_eq!(num_to_snafu(9), "2-");
|
||||||
|
assert_eq!(num_to_snafu(10), "20");
|
||||||
|
assert_eq!(num_to_snafu(15), "1=0");
|
||||||
|
assert_eq!(num_to_snafu(20), "1-0");
|
||||||
|
assert_eq!(num_to_snafu(2022), "1=11-2");
|
||||||
|
assert_eq!(num_to_snafu(12345), "1-0---0");
|
||||||
|
assert_eq!(num_to_snafu(314159265), "1121-1110-1=0");
|
||||||
|
assert_eq!(num_to_snafu(4890), "2=-1=0");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,6 +13,9 @@ pub mod day2;
|
|||||||
pub mod day20;
|
pub mod day20;
|
||||||
pub mod day21;
|
pub mod day21;
|
||||||
pub mod day22;
|
pub mod day22;
|
||||||
|
pub mod day23;
|
||||||
|
pub mod day24;
|
||||||
|
pub mod day25;
|
||||||
pub mod day3;
|
pub mod day3;
|
||||||
pub mod day4;
|
pub mod day4;
|
||||||
pub mod day5;
|
pub mod day5;
|
||||||
|
|||||||
29
src/util.rs
29
src/util.rs
@ -3,6 +3,8 @@ use std::env;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use itertools::MinMaxResult;
|
||||||
|
|
||||||
pub fn parse_input() -> String {
|
pub fn parse_input() -> String {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let input_path = args
|
let input_path = args
|
||||||
@ -142,6 +144,25 @@ impl Dir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_char(c: char) -> Option<Dir> {
|
||||||
|
match c {
|
||||||
|
'^' => Some(Dir::Up),
|
||||||
|
'>' => Some(Dir::Right),
|
||||||
|
'v' => Some(Dir::Down),
|
||||||
|
'<' => Some(Dir::Left),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Dir::Right => ">",
|
||||||
|
Dir::Down => "v",
|
||||||
|
Dir::Left => "<",
|
||||||
|
Dir::Up => "^",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cw(&self) -> Dir {
|
pub fn cw(&self) -> Dir {
|
||||||
let d = *self as usize;
|
let d = *self as usize;
|
||||||
Self::from_usize((d + 1) % 4).unwrap()
|
Self::from_usize((d + 1) % 4).unwrap()
|
||||||
@ -153,3 +174,11 @@ impl Dir {
|
|||||||
Self::from_usize((d + 3) % 4).unwrap()
|
Self::from_usize((d + 3) % 4).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn minmax_unwrap<T: Clone>(mm: &MinMaxResult<T>) -> (T, T) {
|
||||||
|
match mm {
|
||||||
|
MinMaxResult::NoElements => panic!("No elements"),
|
||||||
|
MinMaxResult::OneElement(a) => (a.clone(), a.clone()),
|
||||||
|
MinMaxResult::MinMax(a, b) => (a.clone(), b.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user