code:
use std::cmp;
use std::fs::File;
use std::io::{BufReader, BufRead, Read};

fn is_symbol(ch: u8) -> bool {
    b'!' <= ch && ch <= b'~'
}

fn is_alpha(ch: u8) -> bool {
    (b'a' <= ch && ch <= b'z') || (b'A' <= ch && ch <= b'Z')
}

fn to_ascii(v: &Vec<u8>) -> String {
    let mut s = String::with_capacity(v.len());

    for &ch in v.iter() {
        s.push(if is_symbol(ch) {ch} else {b'_'} as char);
    }

    s
}

fn hex_to_u8(a: u8) -> u8 {
    match a {
        b'0'...b'9' => a - b'0',
        b'a'...b'h' => a - b'a' + 10,
        _           => 0
    }
}

fn vec_u8_from_hex_string(s: &String) -> Vec<u8> {
    s.as_bytes().chunks(2).map(|a| hex_to_u8(a[0]) * 16 + hex_to_u8(a[1])).collect()
}

fn vec_xor(v1: &Vec<u8>, v2: &Vec<u8>) -> Vec<u8> {
    let mut v = Vec::with_capacity(cmp::min(v1.len(), v2.len()));

    for (a, b) in v1.iter().zip(v2.iter()) {
        v.push(a ^ b);
    }

    v
}

fn target_func() {
    let input_file = File::open("in.txt").unwrap();
    let input = BufReader::new(input_file);
    let input: Vec<_> = input.lines().filter_map(|res| res.ok()).take(11).map(|s| vec_u8_from_hex_string(&s)).collect();
    let mut key: Vec<u8> = vec![0; 200];
    let mut ws: Vec<u8> = vec![0; 200];

    for i in 0..11 {
        let c_i = &input[i];
        println!("c_{}:", i);
        let c_xor: Vec<_> = input.iter().map(|v| to_ascii(&vec_xor(c_i, &v))).collect();

        for x_j in c_xor.iter() {
            println!("{}", x_j);
        }

        for k in 0..c_i.len() {
            let mut w = 0;

            for x_j in c_xor.iter() {
                if k < x_j.len() && is_alpha(x_j.as_bytes()[k]) {
                    w += 1;
                }
            }

            if w > ws[k] {
                key[k] = c_i[k] ^ b' ';
                ws[k] = w;
            }
        }

        println!("key: {:?}\n", key);
    }

    for i in 0..11 {
        println!("msg {}:\t{}\n", i, to_ascii(&vec_xor(&input[i], &key)));
    }
}

fn main(){
    target_func();
}


code:
fn merge<T: Copy + PartialOrd>(x1: &[T], x2: &[T], y: &mut [T]) {
    assert_eq!(x1.len() + x2.len(), y.len());
    let mut i = 0;
    let mut j = 0;
    let mut k = 0;
    while i < x1.len() && j < x2.len() {
        if x1[i] < x2[j] {
            y[k] = x1[i];
            k += 1;
            i += 1;
        } else {
            y[k] = x2[j];
            k += 1;
            j += 1;
        }
    }
    if i < x1.len() {
        y[k..].copy_from_slice(&x1[i..]);
    }
    if j < x2.len() {
        y[k..].copy_from_slice(&x2[j..]);
    }
}

fn merge_sort<T: Copy + Ord>(x: &mut [T]) {
	let n = x.len();
	let m = n / 2;

	if n <= 1 {
		return;
	}

	merge_sort(&mut x[0..m]);
	merge_sort(&mut x[m..n]);

	let mut y: Vec<T> = x.to_vec();

	merge(&x[0..m], &x[m..n], &mut y[..]);

	x.copy_from_slice(&y);
}

fn main() {
    println!("Sort numbers ascending");
    let mut numbers = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1];
    println!("Before: {:?}", numbers);
    merge_sort(&mut numbers);
    println!("After:  {:?}\n", numbers);

    println!("Sort strings alphabetically");
    let mut strings = ["beach", "hotel", "airplane", "car", "house", "art"];
    println!("Before: {:?}", strings);
    merge_sort(&mut strings);
    println!("After:  {:?}\n", strings);
}

entry_point: merge


code:
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;

fn main() {
    let input = read_input(Path::new("input.txt"));

    part1(&input);
    part2(&input);
}

fn read_input(path: &Path) -> Vec<String> {
    BufReader::new(File::open(path).unwrap())
        .lines()
        .map(|line_res| line_res.unwrap())
        .collect()
}

fn part1(labels: &[String]) {
    let mut labels_with_two = 0;
    let mut labels_with_three = 0;

    for label in labels {
        let mut letters = HashMap::new();

        for letter in label.as_bytes() {
            let letter_cnt = letters.entry(letter).or_insert(0);
            *letter_cnt += 1;
        }

        if letters.values().any(|&cnt| cnt == 2) {
            labels_with_two += 1;
        }

        if letters.values().any(|&cnt| cnt == 3) {
            labels_with_three += 1;
        }
    }

    println!(
        "Part 1: Checksum: {} (6474)",
        labels_with_two * labels_with_three
    );
}

fn part2(labels: &[String]) {
    for (i, label_a) in labels.iter().enumerate() {
        for label_b in labels.iter().skip(i + 1) {
            if labels_similar(label_a, label_b) {
                println!(
                    "Part 2: Same Letters: {} (mxhwoglxgeauywfkztndcvjqr)",
                    same_letters(label_a, label_b)
                );
                return;
            }
        }
    }
}

fn labels_similar(a: &str, b: &str) -> bool {
    a.as_bytes().iter().zip(b.as_bytes()).fold(
        0,
        |acc, pair| {
            if *pair.0 != *pair.1 {
                acc + 1
            } else {
                acc
            }
        },
    ) == 1
}

fn same_letters(a: &str, b: &str) -> String {
    let same_bytes = a
        .as_bytes()
        .iter()
        .zip(b.as_bytes())
        .filter_map(|pair| {
            if *pair.0 == *pair.1 {
                Some(*pair.0)
            } else {
                None
            }
        })
        .collect();

    String::from_utf8(same_bytes).unwrap()
}


code:
use std::env;
use std::fs::File;
use std::io::{self, BufRead};

fn main() {
    let args: Vec<String> = env::args().collect();
    let filename = &args[1];
    let file = File::open(filename).unwrap();
    let lines: Vec<String> = io::BufReader::new(file)
        .lines()
        .map(|line| line.unwrap())
        .collect();
    let pairs: Vec<(i64, i64)> = lines[1]
        .split(",")
        .enumerate()
        .filter(|&(_, id)| id != "x")
        .map(|(idx, id)| (idx as i64, id.parse::<i64>().unwrap()))
        .collect();
    print!("{}", garners_algorithm(pairs));
}

fn garners_algorithm(pairs: Vec<(i64, i64)>) -> i64 {
    let k = pairs.len();
    let mut x = vec![0; k];
    for i in 0..k {
        x[i] = pairs[i].1 - pairs[i].0;
        for j in 0..i {
            x[i] = mod_inv(pairs[j].1, pairs[i].1) * (x[i] - x[j]);
            x[i] = x[i] % pairs[i].1;
            if x[i] < 0 {
                x[i] += pairs[i].1;
            }
        }
    }

    let mut ts = 0i64;
    for i in 0..k {
        let mut product = x[i];
        for j in 0..i {
            product *= pairs[j].1;
        }
        ts += product;
    }

    return ts;
}

fn mod_inv(a: i64, module: i64) -> i64 {
    let mut mn = (module, a);
    let mut xy = (0, 1);
    while mn.1 != 0 {
        xy = (xy.1, xy.0 - (mn.0 / mn.1) * xy.1);
        mn = (mn.1, mn.0 % mn.1);
    }
    while xy.0 < 0 {
        xy.0 += module;
    }
    xy.0
}


code:
use std::mem::{self, ManuallyDrop};
use std::ptr;

fn quick_sort<T>(vec: &mut [T], lo: usize, hi: usize)
	where T: PartialOrd,
{
	if hi == lo {
		return;
	}
	let (sp_idx0, sp_idx1) = partition(vec, lo, hi);
	if sp_idx0 != lo {
		quick_sort(vec, lo, sp_idx0 - 1);
	}
	if sp_idx1 != hi {
		quick_sort(vec, sp_idx1 + 1, hi);
	}
}

fn partition<T>(vec: &mut [T], lo: usize, hi: usize) -> (usize, usize)
	where T: PartialOrd,
{
	let mut lt = lo;
	let mut gt = hi;
	let mut i = lo + 1;
	let v = ManuallyDrop::new(unsafe {ptr::read(&vec[lo])});
	while i <= gt {
		if vec[i] < *v {
			swap(vec, i, lt);
			i += 1;
			lt += 1;
		}else if vec[i] > *v {
			swap(vec, i, gt);
			gt -= 1;
		}else {
			i += 1;
		}
	}
	(lt, gt)
}

fn swap<T>(vec: &mut [T], idx1: usize, idx2: usize)
	where T: PartialOrd,
{
	if idx1 == idx2 {
		return;
	}
	let mut tmp = unsafe { ptr::read(&mut vec[idx1]) };
	mem::swap(&mut tmp, &mut vec[idx2]);
    unsafe {
        ptr::write(&mut vec[idx1] as *mut _, tmp);
    }

}

fn main() {
	let mut vec = vec![10, 4, 20, 11, 5, 6, 22, 50, 43, 25, 33, 13, 26, 27, 43, 47, 48];
	let len = vec.len();
	quick_sort(&mut vec[..], 0, len - 1);
	println!("{:?}", vec);
	println!("hello night!");
}

entry_point: partition


code:
fn cocktail_shaker_sort<T: PartialOrd>(a: &mut [T]) {
    let mut begin = 0;
    let mut end = a.len();
    if end == 0 {
        return;
    }
    end -= 1;
    while begin < end {
        let mut new_begin = end;
        let mut new_end = begin;
        for i in begin..end {
            if a[i + 1] < a[i] {
                a.swap(i, i + 1);
                new_end = i;
            }
        }
        end = new_end;
        let mut i = end;
        while i > begin {
            if a[i] < a[i - 1] {
                a.swap(i, i - 1);
                new_begin = i;
            }
            i -= 1;
        }
        begin = new_begin;
    }
}

fn main() {
    let mut v = vec![5, 1, -6, 12, 3, 13, 2, 4, 0, 15];
    println!("before: {:?}", v);
    cocktail_shaker_sort(&mut v);
    println!("after:  {:?}", v);
}


code:
use std::fs;
use std::collections::{HashMap,HashSet};

fn reverse_rules_dfs(reverse_rules: &HashMap<String,HashSet<String>>, start: &str) -> HashSet<String> {
    let mut nodes: HashSet<String> = HashSet::new();
    nodes.insert(start.to_owned());
    if let Some(set) = reverse_rules.get(start) {
        for parent in set {
            nodes.extend(reverse_rules_dfs(reverse_rules, parent));
        }
    }
    return nodes;
}

fn rules_counting_dfs(rules: &HashMap<String,HashMap<String,usize>>, start: &str) -> usize {
    let mut sum = 1usize;
    if let Some(set) = rules.get(start) {
        for (child,count) in set {
            sum += count * rules_counting_dfs(rules, child);
        }
    }
    return sum;
}

fn target_func() {
    let file = fs::read_to_string("input.txt").expect("File does not exist");

    let mut rules: HashMap<String, HashMap<String,usize>> = HashMap::new();

    let mut reverse_rules: HashMap<String,HashSet<String>> = HashMap::new();

    for line in file.lines() {
        let (container,tail) = line.split_at(line.find(" bags contain ").unwrap());
        rules.insert(container.to_owned(),HashMap::new());
        let mut remaining = tail.split_at(14).1;
        loop {
            let (num_str,bag_and_tail) = remaining.split_at(remaining.find(" ").unwrap());
            if num_str == "no" {
                break;
            } else {
                let num: usize = num_str.parse().unwrap();
                let corrected_bag_and_tail = bag_and_tail.split_at(1).1;
                let (bag,tail_yet_again) = corrected_bag_and_tail.split_at(corrected_bag_and_tail.find(" bag").unwrap());
                rules.get_mut(container).unwrap().insert(bag.to_owned(),num);
                if !reverse_rules.contains_key(bag) {
                    reverse_rules.insert(bag.to_owned(), HashSet::new());
                }
                reverse_rules.get_mut(bag).unwrap().insert(container.to_owned());
                if tail_yet_again.starts_with(" bags.") || tail_yet_again.starts_with(" bag.") {
                    break;
                }
                remaining = tail_yet_again.split_at(tail_yet_again.find(", ").unwrap() + 2).1;
            }
        }
    }
    let shiny_gold_containing_ways = reverse_rules_dfs(&reverse_rules, "shiny gold").len() - 1;
    println!("There are {} ways for the shiny gold bag to be contained.", shiny_gold_containing_ways);

    let shiny_gold_contained = rules_counting_dfs(&rules, "shiny gold") - 1;
    println!("There are {} bags contained in the shiny gold bag.", shiny_gold_contained);
}

fn main(){
    target_func();
}


code:
use std::collections::HashSet;
use std::fs;

fn main() {
    let input = fs::read_to_string("input/day24").expect("failure opening input file");
    let blacks = p1(&input);
    println!("Part1: {}", blacks.len());
    println!("Part2: {}", p2(blacks));
}

fn p1(input: &str) -> HashSet<(i32, i32)> {
    input
        .lines()
        .map(|line| identify_tile(&line))
        .fold(HashSet::new(), |mut blacks, tile| {
            if blacks.contains(&tile) {
                blacks.remove(&tile);
            } else {
                blacks.insert(tile);
            }
            blacks
        })
}

fn p2(mut blacks: HashSet<(i32, i32)>) -> usize {
    let mut whites = (-100..100)
        .map(|x| (-100..100).map(|y| (x, y)).collect::<Vec<(i32, i32)>>())
        .flatten()
        .filter(|p| !blacks.contains(p))
        .fold(HashSet::new(), |mut whites, p| {
            whites.insert(p);
            whites
        });

    let deltas = [(0, -1), (1, -1), (1, 0), (0, 1), (-1, 1), (-1, 0)];
    (0..100).for_each(|_| {
        let mut next_blacks = HashSet::new();
        let mut next_whites = HashSet::new();
        for b in &blacks {
            let neighbors = deltas
                .iter()
                .map(|d| (b.0 + d.0, b.1 + d.1))
                .filter(|n| blacks.contains(n))
                .count();
            if neighbors == 0 || neighbors > 2 {
                next_whites.insert(*b);
            } else {
                next_blacks.insert(*b);
            }
        }
        for w in &whites {
            let neighbors = deltas
                .iter()
                .map(|d| (w.0 + d.0, w.1 + d.1))
                .filter(|n| blacks.contains(n))
                .count();
            if neighbors == 2 {
                next_blacks.insert(*w);
            } else {
                next_whites.insert(*w);
            }
        }
        blacks = next_blacks;
        whites = next_whites;
    });
    blacks.len()
}

fn identify_tile(moves: &str) -> (i32, i32) {
    let mut i = 0;
    let mut coords = (0, 0);
    while i < moves.len() {
        match moves.get(i..i + 2) {
            Some("nw") => {
                coords.1 -= 1;
                i += 2
            }
            Some("ne") => {
                coords.0 += 1;
                coords.1 -= 1;
                i += 2
            }
            Some("sw") => {
                coords.0 -= 1;
                coords.1 += 1;
                i += 2
            }
            Some("se") => {
                coords.1 += 1;
                i += 2
            }
            _ => match moves.get(i..i + 1) {
                Some("w") => {
                    coords.0 -= 1;
                    i += 1
                }
                Some("e") => {
                    coords.0 += 1;
                    i += 1
                }
                _ => unreachable!("unrecognized direction"),
            },
        }
    }
    coords
}


code:
use std::fmt::Debug;

const MIN_X: i32 = 85;
const MAX_X: i32 = 145;

const MIN_Y: i32 = -163;
const MAX_Y: i32 = -108;

#[derive(Debug, Copy, Clone)]
struct Possible {
    value: i32,
    min_t: i32,
    max_t: i32
}

impl Default for Possible {
    fn default() -> Possible {
        Possible {
            value: 0,
            min_t: 0,
            max_t: i32::MAX,
        }
    }
}

fn target_func() {

    let mut possible_xs = vec!();

    for x in 1..MAX_X {
        let mut min_t = 0;
        let mut max_t = 0;
        let mut found = false;

        let mut possible = Possible::default();

        for t in 0..=x {
            let distance = t * x - t * (t - 1)/2;

            if distance >= MIN_X && distance <= MAX_X {
                if !found {
                    min_t = t;
                    max_t = t;
                    found = true;
                }
                else {
                    max_t = t;
                }
            }

            if distance >= MIN_X && distance <= MAX_X && t == x {
                println!("Possible: x: {}, min_t: {}, max_t: {}", x, min_t, max_t);
                max_t = i32::MAX;
            }

            if found {

                possible = Possible {value: x, min_t: min_t, max_t: max_t};
            }
        }

        if found {
            possible_xs.push(possible);
        }
    }

    println!("{:?}", possible_xs);

    let mut possible_ys = vec!();

    for y in 0..-MIN_Y {
        println!("Y: {}", y);
        for t in 1..i32::MAX {
            let distance = y * t - (t * (t - 1)) / 2;
            if distance >= MIN_Y && distance <= MAX_Y {
                println!("Possible: y: {}, t: {}", y, t);
                let possible = Possible{value: y, min_t: t, max_t: t};
                possible_ys.push(possible);
            }

            if distance < MIN_Y {
                break;
            }
        }
    }
}

fn main(){
    target_func();
}


code:
use std::fs;
use std::string::String;

fn main() {
    let filename = format!("inputs/{}.txt", module_path!());
    let text = fs::read(filename).ok().expect("Couldn't open file");
    let str = String::from_utf8(text).ok().expect("Could parse UTF8 from file");

    println!("{}", first_part(&str));
    println!("{}", second_part(&str));
}

enum ParseResult {
    Corrupt(char),
    Incomplete(String),
    Complete,
}

fn parse(line: &str) -> ParseResult {
    let mut stack = Vec::new();
    for c in line.chars() {
        match c {
            '(' => stack.push(')'),
            '[' => stack.push(']'),
            '{' => stack.push('}'),
            '<' => stack.push('>'),
            _ => match stack.pop() {
                Some(d) => if c != d {
                    return ParseResult::Corrupt(c)
                },
                None => return ParseResult::Corrupt(c)
            },
        }
    }

    if stack.len() == 0 {
        ParseResult::Complete
    } else {
        ParseResult::Incomplete(stack.iter().rev().collect())
    }
}

fn first_part(s: &str) -> usize {
    let mut result = 0;
    for l in s.split_whitespace() {
        match parse(l) {
            ParseResult::Corrupt(c) => match c {
                ')' => result += 3,
                ']' => result += 57,
                '}' => result += 1197,
                '>' => result += 25137,
                _ => unreachable!(),
            },
            _ => {},
        }
    }
    result
}

fn second_part(s: &str) -> usize {
    let mut scores = Vec::new();
    for l in s.split_whitespace() {
        let mut score = 0;
        match parse(l) {
            ParseResult::Incomplete(stack) => {
                for c in stack.chars() {
                    score *= 5;
                    match c {
                        ')' => score += 1,
                        ']' => score += 2,
                        '}' => score += 3,
                        '>' => score += 4,
                        _ => unreachable!(),
                    }
                }
                scores.push(score);
            },
            _ => {},
        }
    }
    scores.sort_unstable();
    scores[scores.len()/2]
}


code:
fn main() {
    assert_eq!(Solution::num_decodings(String::from("*")), 9);
}

struct Solution {}

impl Solution {

    pub fn num_decodings(s: String) -> i32 {
        let modu: usize = 10usize.pow(9) + 7;
        let s: Vec<u8> = s.bytes().map(|x| if x == b'*' { x } else { x - b'0' }).collect();
        let length = s.len() + 1;
        let mut dp = vec![(0, 0); length];
        dp[length - 1].0 = 1;
        dp[length - 2].0 = match s[length - 2] {
            b'*' => 9,
            0 => 0,
            _ => 1,
        };
        for i in (0..length-2).rev() {
            match s[i] {
                0 => {
                    dp[i].0 = 0;
                    dp[i].1 = 0;
                }
                b'*' => {
                    dp[i].0 = 9 * (dp[i+1].0 + dp[i+1].1);
                    dp[i].1 = if s[i+1] == b'*' { 15 } else {
                        if s[i+1] <= 6 { 2 } else { 1 }
                    } * (dp[i+2].0 + dp[i+2].1);
                }
                x => {
                    dp[i].0 = dp[i+1].0 + dp[i+1].1;
                    dp[i].1 = if s[i+1] == b'*' {
                        if x == 1 { 9 }
                        else if x == 2 { 6 }
                        else { 0 }
                    } else {
                        if s[i] * 10 + s[i+1] <= 26 { 1 } else { 0 }
                    } * (dp[i+2].0 + dp[i+2].1);
                }
            }
            dp[i].0 %= modu;
            dp[i].1 %= modu;
        }
        println!("modu = {:#?}", modu);
        println!("s = {:#?}, dp = {:#?}", s, dp);
        ((dp[0].0 + dp[0].1) % modu) as i32
    }
}

#[cfg(test)]
mod test {
    use crate::*;

    #[test]
    fn basic() {
        assert_eq!(Solution::num_decodings(String::from("*")), 9);
        assert_eq!(Solution::num_decodings(String::from("1*")), 18);
    }

    #[test]
    fn fail() {
        assert_eq!(Solution::num_decodings(String::from("**")), 96);
        assert_eq!(Solution::num_decodings(String::from("**********1111111111")), 133236775);
    }
}


code:
use std::env;
use std::error;
use std::fs::File;
use std::io::prelude::*;
use std::str::Split;

type Result<T> = std::result::Result<T, Box<error::Error>>;

fn main() -> Result<()> {
    let args: Vec<String> = env::args().collect();

    let filename = &args[1];

    let contents = get_contents(filename)?;
    let mut split = contents.split(" ");

    let tree: TreeGraph = parse_node(&mut split)?;

    println!("{}", metadata_total(&tree));
    println!("{}", value(&tree));

    Ok(())
}

#[derive(Debug)]
struct TreeGraph {
    children: Vec<TreeGraph>,
    metadata: Vec<usize>,
}

fn metadata_total(tree: &TreeGraph) -> usize {
    let mut res: usize = 0;

    for m in (*tree).metadata.iter() {
        res += m;
    }

    for child in (*tree).children.iter() {
        res += metadata_total(&*child);
    }

    res
}

fn value(tree: &TreeGraph) -> usize {
    let nchildren = tree.children.len();
    let mut res: usize = 0;
    if nchildren == 0 {
        res = tree.metadata.iter().sum();
    } else {
        for m in tree.metadata.iter() {
            if *m - 1 >= nchildren {
                continue;
            }
            let children: &[TreeGraph] = &tree.children;
            let child: &TreeGraph = children.iter().nth(*m - 1).unwrap();
            let unboxed_child: &TreeGraph = &*child;
            res += value(unboxed_child);
        }
    }
    res
}

fn parse_node(s: &mut Split<&str>) -> Result<TreeGraph> {
    let mut children_fromstr: Vec<TreeGraph> = Vec::new();
    let mut metadata_fromstr: Vec<usize> = Vec::new();

    let nchildren = match s.next() {
        Some(x) => x.to_string().parse::<usize>()?,
        None => 0,
    };

    let nmetadata = match s.next() {
        Some(x) => x.to_string().parse::<usize>()?,
        None => 0,
    };

    for _ in 0..nchildren {
        let g: TreeGraph = parse_node(s)?;
        children_fromstr.push(g);
    }

    for _ in 0..nmetadata {
        metadata_fromstr.push(s.next().unwrap().to_string().parse::<usize>()?);
    }

    Ok(TreeGraph {
        children: children_fromstr,
        metadata: metadata_fromstr,
    })
}

fn get_contents(filename: &str) -> Result<String> {
    let mut f = File::open(filename)?;

    let mut contents = String::new();
    f.read_to_string(&mut contents)?;

    Ok(contents)
}

entry_point: value


code:
use std::io::BufRead;
use std::io::BufReader;
use std::fs::File;
use std::collections::HashSet;

fn target_func() {
    let f = File::open("input.txt").unwrap();

    let mut bugs : [[[bool; 5]; 5]; 2] = [[[false; 5];5];2];
    let mut current : usize = 0;
    let mut next : usize = 1;

    let mut col: i32 = 0;
    for raw_line in BufReader::new(f).lines() {
        for (row, c) in raw_line.unwrap().chars().enumerate() {
            if c == '#' {
                bugs[current][col as usize][row as usize] = true;
            }
        }
        col += 1;
    }

    let mut sb : HashSet<u64> = HashSet::new();

    let deltas : [(i32, i32); 4] = [(0,1), (0,-1), (1,0), (-1,0)];
    loop {
        for i in 0..5usize {
            for j in 0..5usize {
                bugs[next][i][j] = false;
            }
        }

        for i in 0..5usize {
            for j in 0..5usize {
                let mut count : i32 = 0;

                for delta in deltas.iter() {
                    let ii : i32 = i as i32 + delta.0;
                    let jj : i32 = j as i32 + delta.1;

                    if ii < 0 || jj < 0 || ii > 4 || jj > 4 {
                        continue;
                    }

                    if bugs[current][ii as usize][jj as usize] {
                        count += 1;
                    }
                }

                if bugs[current][i][j] {
                    if count == 1 {
                        bugs[next][i][j] = true;
                    }
                } else {
                    if count == 1 || count == 2 {
                        bugs[next][i][j] = true;
                    }
                }
           }
        }
        let mut sum : u64 = 0;
        let mut p : u64 = 1;
        for i in 0..5usize {
            for j in 0..5usize {
               if bugs[next][i as usize][j as usize] {
                   sum += p;
               }
               p = p << 1;
           }
        }
        if sb.contains(&sum) {
            println!("{}", sum);
            return;
        }
        sb.insert(sum);

        if current == 0 {
            current = 1;
            next = 0;
        } else {
            current = 0;
            next = 1;
        }

    }
}

fn main(){
    target_func();
}


code:
fn print_recipes(scores: &Vec<u8>, first: &usize, second: &usize) {
    for (idx, i) in scores.iter().enumerate() {
        match idx {
            _ if &idx == first => print!("({})", i),
            _ if &idx == second => print!("[{}]", i),
            _ => print!(" {} ", i),
        }
    }
    println!();
}

fn next_ten_recipe_scores(recipe_count: usize) -> Vec<u8> {
    let mut recipe_scores: Vec<u8> = vec![3, 7];
    let mut first_elf_recipe_idx = 0;
    let mut second_elf_recipe_idx = 1;

    while recipe_scores.len() < (recipe_count + 10) {
        let first_recipe = recipe_scores[first_elf_recipe_idx];
        let second_recipe = recipe_scores[second_elf_recipe_idx];
        let new_recipes = first_recipe + second_recipe;
        if new_recipes >= 10 {
            recipe_scores.push(1);
        }
        recipe_scores.push(new_recipes % 10);
        first_elf_recipe_idx += first_recipe as usize + 1;
        first_elf_recipe_idx = first_elf_recipe_idx % recipe_scores.len();
        second_elf_recipe_idx += second_recipe as usize + 1;
        second_elf_recipe_idx = second_elf_recipe_idx % recipe_scores.len();
    }
    recipe_scores[recipe_count..recipe_count + 10].to_vec()
}

fn last_matching(seq: &[u8], last: &[u8]) -> usize {
    let mut matching = last.len();
    while matching > 0 {
        let idx = if matching > seq.len() {
            0
        } else {
            seq.len() - matching
        };
        let a = &seq[idx..];
        let b = &last[0..matching];
        if a == b {
            return matching;
        }
        matching -= 1;
    }
    matching
}

fn find_recipes_before_sequence(recipe_seq: &Vec<u8>) -> usize {
    let mut recipe_scores: Vec<u8> = vec![3, 7];
    let mut first_elf_recipe_idx = 0;
    let mut second_elf_recipe_idx = 1;

    let mut num_recipes: usize = 2;
    let mut num_recipes_matching = last_matching(&recipe_scores, &recipe_seq);
    loop {
        let first_recipe = recipe_scores[first_elf_recipe_idx];
        let second_recipe = recipe_scores[second_elf_recipe_idx];
        let new_recipes = first_recipe + second_recipe;
        if new_recipes >= 10 {
            num_recipes += 1;
            recipe_scores.push(1);
            if recipe_seq[num_recipes_matching] == 1 {
                num_recipes_matching += 1;
                if num_recipes_matching == recipe_seq.len() {
                    return num_recipes - num_recipes_matching;
                }
            } else if num_recipes_matching > 0 {
                num_recipes_matching = last_matching(&recipe_scores, &recipe_seq);
            }
        }
        let added = new_recipes % 10;
        num_recipes += 1;
        recipe_scores.push(added);
        if recipe_seq[num_recipes_matching] == added {
            num_recipes_matching += 1;
            if num_recipes_matching == recipe_seq.len() {
                return num_recipes - num_recipes_matching;
            }
        } else if num_recipes_matching > 0 {
            num_recipes_matching = last_matching(&recipe_scores, &recipe_seq);
        }

        first_elf_recipe_idx += first_recipe as usize + 1;
        first_elf_recipe_idx = first_elf_recipe_idx % recipe_scores.len();
        second_elf_recipe_idx += second_recipe as usize + 1;
        second_elf_recipe_idx = second_elf_recipe_idx % recipe_scores.len();
    }
}

fn main() {
    let input = 846021;
    let input_seq = vec![8, 4, 6, 0, 2, 1];
    println!(
        "The next ten recipe scores after recipe {} are {:?}",
        input,
        next_ten_recipe_scores(input)
    );
    println!(
        "There are {} recipes before the sequence {:?}",
        find_recipes_before_sequence(&input_seq),
        &input_seq
    );
}


code:
use std::io::{self, BufRead};
use std::collections::HashMap;

const PREF_LENGTH: usize = 2;
const SUFF_LENGTH: usize = 2;
const PAD_LENGTH: i64 = PREF_LENGTH as i64 + SUFF_LENGTH as i64 + 1;
const POT_PLANT: char = '#';
const POT_EMPTY: char = '.';

#[derive(Debug)]
struct Rule {
    pattern: Vec<char>,
    outcome: char,
}
impl Rule {
    pub fn new(pattern: &str, outcome: &str) -> Rule {
        Rule{ pattern: pattern.to_string().chars().collect(), outcome: outcome.to_string().chars().next().unwrap() }
    }
}

#[derive(Debug)]
struct Data {
    initial: String,
    rules: Vec<Rule>,
}
impl Data {
    pub fn new() -> Data {
        Data{ initial: "".to_string(), rules: Vec::new() }
    }
    pub fn set_initial(&mut self, initial: &str) {
        self.initial = initial.to_string();
    }
    pub fn add_rule(&mut self, pattern: &str, outcome: &str) {
        self.rules.push(Rule::new(pattern, outcome));
    }
}

#[derive(Debug)]
struct Soil {
    iterations: usize,
    data: [Vec<char>; 2],
    cur: usize,
    beg: usize,
    end: usize,
    off: i64,
    seen: HashMap<String, (usize, i64)>,
}
impl Soil {
    fn set_pos(&mut self, which: usize, pos: usize, val: char) {
        if pos < self.data[which].len() {
            self.data[which][pos] = val;
        } else {
            self.data[which].push(val);
        }
    }
    pub fn new(initial: &str, iterations: usize) -> Soil {
        let data0 = Vec::new();
        let data1 = Vec::new();
        let seen = HashMap::new();
        let cur = 0;
        let mut soil = Soil{ data: [ data0, data1 ], cur, off: 0, beg: 0, end: 0, seen, iterations };

        let mut first = true;
        let mut pos = 0;
        for _p in 0..PAD_LENGTH {
            soil.set_pos(cur, pos, POT_EMPTY);
            pos += 1;
        }
        for _c in initial.chars() {
            let outcome = if _c == POT_EMPTY { POT_EMPTY } else { POT_PLANT };
            if outcome != POT_EMPTY  {
                if first {
                    soil.beg = pos;
                    first = false;
                }
                soil.end = pos + 1;
            }
            if !first || outcome != POT_EMPTY {
                soil.set_pos(cur, pos, outcome);
                pos += 1;
            }
        }
        for _p in 0..PAD_LENGTH {
            soil.set_pos(cur, pos, POT_EMPTY);
            pos += 1;
        }
        soil
    }

    pub fn step(&mut self, rules: &Vec<Rule>) {
        let nxt = 1 - self.cur;
        let mut first = true;
        let mut pos = 0;
        for _p in 0..PAD_LENGTH {
            self.set_pos(nxt, pos, POT_EMPTY);
            pos += 1;
        }
        for _p in (self.beg-PREF_LENGTH)..(self.end+SUFF_LENGTH) {
            let mut outcome = POT_EMPTY;
            for rule in rules {
                let mut matched = true;
                for _j in 0..rule.pattern.len() {
                    if rule.pattern[_j] != self.data[self.cur][_p+_j-PREF_LENGTH] {
                        matched = false;
                        break;
                    }
                }
                if matched {
                    outcome = rule.outcome;
                    break;
                }
            }
            if outcome != POT_EMPTY  {
                if first {
                    self.beg = pos;
                    self.off += _p as i64 - self.beg as i64;
                    first = false;
                }
                self.end = pos + 1;
            }
            if !first || outcome != POT_EMPTY {
                self.set_pos(nxt, pos, outcome);
                pos += 1;
            }
        }
        for _p in 0..PAD_LENGTH {
            self.set_pos(nxt, pos, POT_EMPTY);
            pos += 1;
        }
        self.cur = nxt;
    }
    pub fn done(&mut self, iter: usize) -> bool {
        let current: String = self.data[self.cur].iter().collect();
        match self.seen.get(&current) {
            Some(&(i, o)) => {
                let delta_iter = iter - i;
                let delta_off = self.off - o;
                println!("{}: SEEN iter {} off {} => {} {}", iter, i, o, delta_iter, delta_off);
                let remaining = self.iterations - iter;
                let final_offset: i64 = o as i64 + remaining as i64 * delta_off as i64;
                println!("REMAINING {} => {}", remaining, final_offset);
                self.off = final_offset;
                true
            },
            _ => {
                self.seen.insert(current, (iter, self.off));
                false
            },
        }
    }
}

fn main() {
    let data = read_data();
    run(&data, 20);
    run(&data, 50_000_000_000);
}

fn run(data: &Data, iterations: usize) {
    let mut soil = Soil::new(&data.initial, iterations);

    for iter in 0..iterations {
        soil.step(&data.rules);
        if soil.done(iter) {
            break;
        }
    }

    let mut total: i64 = 0;
    for pos in 0..soil.data[soil.cur].len() {
        if soil.data[soil.cur][pos] == POT_EMPTY {
            continue;
        }
        total += pos as i64 + soil.off - PAD_LENGTH;
    }
    println!("Sum of pots with plants after {} generations: {}", iterations, total);
}

fn read_data() -> Data {
    let mut data = Data::new();
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() < 3 {
            continue;
        }
        if words[0] == "initial" {
            data.set_initial(words[2]);
            continue;
        }
        data.add_rule(words[0], words[2]);
    }
    data
}

entry_point: step


code:
use std::collections::HashMap;

struct Solution {}

impl Solution {

    pub fn check_inclusion(s1: String, s2: String) -> bool {
        if s1.len() > s2.len() {
            return false;
        }
        let mut s1_map = HashMap::new();
        let mut s2_map = HashMap::new();

        for ch in s1.chars() {
            let counter = s1_map.entry(ch).or_insert(0);
            *counter += 1;
        }
        let s1_len = s1.len();
        let mut total_distence = s1_len;
        for (idx, ch) in s2.chars().enumerate() {

            if s1_map.contains_key(&ch) {
                let counter = s2_map.entry(ch).or_insert(0);
                *counter += 1;
                if *counter <= s1_map[&ch] {
                    total_distence -= 1;
                } else {
                    total_distence += 1;
                }
            }

            if idx < s1_len {
                if total_distence == 0 {
                    return true
                }
                continue;
            }
            let remove_ch = s2.chars().nth(idx-s1_len).unwrap();
            if s2_map.contains_key(&remove_ch) {
                if s2_map[&remove_ch] <= s1_map[&remove_ch] {
                    total_distence += 1;
                } else {
                    total_distence -= 1;
                }
                *s2_map.get_mut(&remove_ch).unwrap() -= 1;

            }

            if total_distence == 0 {
                return true
            }
        }
        if total_distence == 0 {
            return true
        }
        false
    }
}

fn main() {
    let s1 = String::from("a");
    let s2 = String::from("ab");
    println!("{}", Solution::check_inclusion(s1, s2));
}


code:
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_first_half() {
        assert_eq!(run_simulation(5, false), 0124515891u64);
        assert_eq!(run_simulation(9, false), 5158916779u64);
        assert_eq!(run_simulation(18, false), 9251071085u64);
        assert_eq!(run_simulation(2018, false), 5941429882u64);
    }

    #[test]
    fn test_second_half() {
        assert_eq!(run_simulation(515891, true), 9);
        assert_eq!(run_simulation(012451, true), 5);
        assert_eq!(run_simulation(925107, true), 18);
        assert_eq!(run_simulation(594142, true), 2018);
    }
}

fn check_recipes(recipes: &Vec<usize>, input: usize) -> u64 {
    let end = recipes.len() - 1;
    if end < 7 {
        return 0;
    }
    if recipes[end] == input % 10 {
        let mut sum = 0;
        let mut coeff = 1;
        for i in 0..6 {
            sum += recipes[end - i] * coeff;
            coeff *= 10;
        }
        if sum == input {
            return end as u64 - 5;
        }
    }

    if recipes[end - 1] == input % 10 {
        let mut sum = 0;
        let mut coeff = 1;
        for i in 0..6 {
            sum += recipes[end - 1 - i] * coeff;
            coeff *= 10;
        }
        if sum == input {
            return end as u64 - 6;
        }

    }

    0
}

fn run_simulation(input: usize, find_occurrence: bool) -> u64 {
    let mut recipes = vec![3, 7];
    let mut elves = vec![0, 1];
    loop {
        let mut sum = 0;
        for elf in &elves {
            sum += recipes[*elf];
        }

        let mut new_recipes = Vec::new();

        if sum == 0 {
            new_recipes.push(0);
        }
        while sum > 0 {
            new_recipes.push(sum % 10);
            sum /= 10;
        }

        while !new_recipes.is_empty() {
            recipes.push(new_recipes.pop().unwrap());
        }

        for elf in &mut elves {
            *elf = (*elf + recipes[*elf] + 1) % recipes.len()
        }

        if   !find_occurrence && recipes.len() >= input + 10
           || find_occurrence && check_recipes(&recipes, input) != 0 {
            break;
        }
    }

    if !find_occurrence {

        let mut ans: u64 = 0;
        for i in 0..10 {
            ans = ans*10 + recipes[input + i] as u64;
        }
        ans
    } else {
        check_recipes(&recipes, input)
    }
}

fn main() {
    println!("Score: {}", run_simulation(360781, false));
    println!("At: {}", run_simulation(360781, true));
}


code:
use std::collections::HashMap;
use std::num::ParseIntError;
use std::str::FromStr;

#[derive(Debug)]
struct Reaction {
    input: HashMap<String, usize>,
    output: (String, usize),
}

#[derive(Debug)]
enum ParseError {
    Int(ParseIntError),
    Empty,
}

impl From<ParseIntError> for ParseError {
    fn from(e: ParseIntError) -> Self {
        ParseError::Int(e)
    }
}

impl FromStr for Reaction {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iter = s.split("=>");
        let ing = iter.next().ok_or(ParseError::Empty)?;
        let ing: String = ing.replace(",", " ");
        let out = iter.next().ok_or(ParseError::Empty)?;

        let mut input = HashMap::new();
        let mut it = ing.split_whitespace();
        while let Some(s) = it.next() {
            let cnt = s.parse()?;
            let name = it.next().ok_or(ParseError::Empty)?;
            input.insert(name.into(), cnt);
        }

        let mut it = out.split_whitespace();
        let cnt = it.next().ok_or(ParseError::Empty)?.parse::<usize>()?;
        let name = it.next().ok_or(ParseError::Empty)?;

        Ok(Reaction {
            input,
            output: (name.into(), cnt),
        })
    }
}

fn produce(
    name: &str,
    amount: usize,
    rules: &HashMap<String, Reaction>,
    resources: &mut HashMap<String, usize>,
) -> usize {
    let r = &rules[name];
    let mut ore_cnt = 0;

    let mut produced = 0;

    if let Some(&o) = r.input.get("ORE") {
        let times = (amount + r.output.1 - 1) / r.output.1;
        ore_cnt += o * times;
        produced += r.output.1 * times;
    } else {
        let times = (amount + r.output.1 - 1) / r.output.1;
        for (n, &c) in &r.input {
            let need = c * times;
            let have = *resources.get(n).unwrap_or(&0);
            if have < need {
                ore_cnt += produce(&n, need - have, rules, resources);
            }

            let r = resources.get_mut(n).unwrap();
            *r -= need;
        }
        produced += r.output.1 * times;
    }

    let r = resources.entry(name.into()).or_insert(0);
    *r += produced;
    ore_cnt
}

fn main() {
    let instr = std::fs::read_to_string("input").unwrap();
    let rules: HashMap<String, Reaction> = instr
        .lines()
        .map(|l| {
            let r: Reaction = l.parse().unwrap();
            (r.output.0.clone(), r)
        })
        .collect();

    let mut resources = HashMap::new();
    let p1 = produce("FUEL", 1, &rules, &mut resources);
    println!("Part 1: {}", p1);

    let tgt: usize = 1_000_000_000_000;
    let mut begin = 0;
    let mut end = 2 *(tgt / p1);

    loop {
        let mid = (end + begin) / 2;
        let ore = produce("FUEL", mid, &rules, &mut HashMap::new());
        let ore_n = produce("FUEL", mid + 1, &rules, &mut HashMap::new());

        if ore < tgt && ore_n > tgt {
            println!("Part 2: {}", mid);
            break;
        } else if ore_n > tgt {
            end = mid - 1;
        } else if ore_n < tgt {
            begin = mid + 1;
        } else {
            panic!("NOPE");
        }
    }
}

entry_point: produce


code:
use std::io;

fn repeating(digits: &Vec<u8>) -> bool {
    let mut prev = digits[0];
    for &i in digits.iter().skip(1).take(digits.len() - 2) {
        if prev == i {
            return true;
        }
        prev = i;
    }
    false
}

fn comp_func() {
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();

    let mut limits = input.trim().split('-').map(|x| x.chars().map(|y| y.to_digit(10).unwrap() as u8).collect());
    let mut current: Vec<u8> = limits.next().unwrap();
    for i in 1..current.len() {
        if current[i] < current[i - 1] {
            current[i] = current[i - 1];
        }
    }
    let end: Vec<u8> = limits.next().unwrap();
    let mut count: u32 = 0;
    'mainloop: loop {
        for (n, &i) in current.iter().enumerate() {
            if i > end[n] {
                break 'mainloop;
            } else if n == current.len() - 1 {
                if repeating(&current) {
                    count += (end[n] - i + 1) as u32;
                } else {
                    count += 1;
                }
                break 'mainloop;
            } else if i < end[n] {
                break;
            }
        }

        if repeating(&current) {
            count += (10 - current[current.len() - 1]) as u32;
        } else {
            count += 1;
        }

        let last = current.last_mut().unwrap();
        *last = 9;
        for i in current.iter_mut().rev() {
            *i += 1;
            if *i > 9 {
                *i = 0;
            } else {
                break;
            }
        }
        for i in 1..current.len() {
            if current[i] < current[i - 1] {
                current[i] = current[i - 1];
            }
        }
    }
    println!("{}", count);
}

fn main() {
    comp_func();
}


code:
use std::io;
use std::collections::HashMap;

fn comp_func() {
    let mut ints: Vec<i32> = Vec::new();
    let mut int_mode: HashMap<i32, usize> = HashMap::new();

    loop {
    	let mut buffer = String::new();
    	io::stdin()
            .read_line(&mut buffer)
            .expect("error reading input");
        let int_string = buffer.trim();
        if int_string == "" {
        	break;
        };

        let int = int_string.parse().expect("Cannot parse!");
        ints.push(int);

        let count = int_mode.entry(int).or_insert(0);
        *count += 1;
    };

    ints.sort();

    let mut avg: f64 = 0.0;
    for int in &ints {
    	avg += f64::from(*int);
    };
    let n = ints.len();
    avg /= n as f64;

    let median: f64;
    let mid_point = n / 2;
    if n % 2 == 0 {
    	median = (f64::from(ints[mid_point]) + f64::from(ints[mid_point + 1])) / 2.0;
    } else {
    	median = f64::from(ints[mid_point]);
    }

    let mut mode = 0;
    let mut max_count: usize = 0;
    for (int, count) in &int_mode {
    	if *count > max_count {
    		max_count = *count;
    		mode = *int;
    	}
    }

    println!("Average: {}", avg);
    println!("Median: {}", median);
    println!("Mode: {}", mode);
}

fn main() {
    comp_func();
}