• 0 Posts
  • 2 Comments
Joined 1 year ago
cake
Cake day: July 7th, 2023

help-circle

  • My solution in rust. I’m sure there’s a lot more clever ways to do it but this is what I came up with.

    Code
    use std::{io::prelude::*, fs::File, path::Path, io };
    
    fn main() 
    {
        run_solution(false); 
    
        println!("\nPress enter to continue");
        let mut buffer = String::new();
        io::stdin().read_line(&mut buffer).unwrap();
    
        run_solution(true); 
    }
    
    fn run_solution(check_for_spelled: bool)
    {
        let data = load_data("data/input");
    
        println!("\nProcessing Data...");
    
        let mut sum: u64 = 0;
        for line in data.lines()
        {
            // Doesn't seem like the to_ascii_lower call is needed but... just in case
            let first = get_digit(line.to_ascii_lowercase().as_bytes(), false, check_for_spelled);
            let last = get_digit(line.to_ascii_lowercase().as_bytes(), true, check_for_spelled);
    
    
            let num = (first * 10) + last;
    
            // println!("\nLine: {} -- First: {}, Second: {}, Num: {}", line, first, last, num);
            sum += num as u64;
        }
    
        println!("\nFinal Sum: {}", sum);
    }
    
    fn get_digit(line: &[u8], from_back: bool, check_for_spelled: bool) -> u8
    {
        let mut range: Vec = (0..line.len()).collect();
        if from_back
        {
            range.reverse();
        }
    
        for i in range
        {
            if is_num(line[i])
            {
                return (line[i] - 48) as u8;
            }
    
            if check_for_spelled
            {
                if let Some(num) = is_spelled_num(line, i)
                {
                    return num;
                }
            }
        }
    
        return 0;
    }
    
    fn is_num(c: u8) -> bool
    {
        c >= 48 && c <= 57
    }
    
    fn is_spelled_num(line: &[u8], start: usize) -> Option
    {
        let words = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
    
        for word_idx in 0..words.len()
        {
            let mut i = start;
            let mut found = true;
            for c in words[word_idx].as_bytes()
            {
                if i < line.len() && *c != line[i]
                {
                    found = false;
                    break;
                }
                i += 1;
            }
    
            if found && i <= line.len()
            {
                return Some(word_idx as u8 + 1);
            }
        }
    
        return None;
    }
    
    fn load_data(file_name: &str) -> String
    {
        let mut file = match File::open(Path::new(file_name))
        {
            Ok(file) => file,
            Err(why) => panic!("Could not open file {}: {}", Path::new(file_name).display(), why),
        };
    
        let mut s = String::new();
        let file_contents = match file.read_to_string(&mut s) 
        {
            Err(why) => panic!("couldn't read {}: {}", Path::new(file_name).display(), why),
            Ok(_) => s,
        };
        
        return file_contents;
    }