Advent of Code solutions
at main 103 lines 2.2 kB view raw
1/// Gets the number of digits in a given number mathematically 2/// 3/// # Examples 4/// 5/// ``` 6/// use utils::prelude::*; 7/// 8/// let my_num = 2226; 9/// assert_eq!(num_digits(my_num), 4); 10/// ``` 11/// 12/// ``` 13/// use utils::prelude::*; 14/// 15/// let my_num = 120938747; 16/// assert_eq!(num_digits(my_num), 9); 17/// ``` 18/// 19/// ``` 20/// use utils::prelude::*; 21/// 22/// assert_eq!(num_digits(0), 1); 23/// ``` 24/// 25pub fn num_digits(num: usize) -> usize { 26 num.checked_ilog10().map(|x| x as usize).unwrap_or(0) + 1 27} 28 29/// Split a given number at a specific digit, this digit will be included in the right-hand side 30/// and excluded in the left. 31/// 32/// If the split is invalid, zero may be returned on either side of the result. 33/// 34/// # Examples 35/// 36/// ``` 37/// use utils::prelude::*; 38/// 39/// let my_num = 123456; 40/// let (left, right) = split_num_at(my_num, 3); 41/// assert_eq!(left, 123); 42/// assert_eq!(right, 456); 43/// ``` 44/// 45pub fn split_num_at(num: usize, idx: u32) -> (usize, usize) { 46 let div = 10_usize.pow(idx); 47 (num / div, num % div) 48} 49 50/// Get the digit at the (starting from the right) given index 51pub fn digit_at(num: usize, idx: usize) -> usize { 52 let div = 10_usize.pow(idx as u32); 53 num / div % 10 54} 55 56/// Iterator (from right to left) 57struct Digits { 58 num: usize, 59 size: usize, 60 curr_digit: usize, 61} 62 63impl Digits { 64 pub fn new(num: usize) -> Self { 65 Self { 66 num, 67 size: num_digits(num), 68 curr_digit: 0, 69 } 70 } 71} 72 73impl Iterator for Digits { 74 type Item = usize; 75 76 fn next(&mut self) -> Option<Self::Item> { 77 if self.curr_digit == self.size - 1 { 78 None 79 } else { 80 let res = Some(digit_at(self.num, self.curr_digit)); 81 self.curr_digit += 1; 82 res 83 } 84 } 85} 86 87/// Split the given number once in the middle, see [[split_num_at]] for caveats. 88/// 89/// # Examples 90/// 91/// ``` 92/// use utils::prelude::*; 93/// 94/// let my_num = 55556666; 95/// let (left, right) = split_num_once(my_num); 96/// assert_eq!(left, 5555); 97/// assert_eq!(right, 6666); 98/// ``` 99/// 100pub fn split_num_once(num: usize) -> (usize, usize) { 101 let digits = num_digits(num); 102 split_num_at(num, (digits / 2) as u32) 103}