blitz's recent activity

  1. Comment on There's no "right" way to play a game, and Twitch streamers are sick of being shamed for playing on easy in ~games

    blitz
    Link Parent
    One game I'd like to give a shout-out to is the Witcher 3 for really making Hard and up worth playing on. The game has a lot of depth in the combat and in potions and in monster weaknesses and...

    One game I'd like to give a shout-out to is the Witcher 3 for really making Hard and up worth playing on.

    The game has a lot of depth in the combat and in potions and in monster weaknesses and strengths. On the easier difficulties you can basically just rush head first into any encounter and whack them with your metal sticks until they die, ignoring all the lore and the bestiary and all the prep that witchers canonically have to do to fight.

    When I started playing on Death March I really had to change the way I played to survive. Suddenly I had to search for the crafting recipes for the potions I needed to help me fight specific monsters, I had to read the bestiary entries in order to understand how to better fight them, I had to spend time upgrading my armor and equipment. It felt many times more immersive than it felt on lower difficulties. (Although, I also remember dying to the first pack of wolves you come across when you're going to talk to the first Nilfgaardian in the game like fifty times as well)

    7 votes
  2. Comment on What have you been listening to this week? in ~music

    blitz
    Link
    The YouTube Algorithm recommended to me a channel that has a bunch of songs from the Soviet-Afghan war. I'm a huge fan of folk music, and topical folk music specifically, so it's been super...

    The YouTube Algorithm recommended to me a channel that has a bunch of songs from the Soviet-Afghan war. I'm a huge fan of folk music, and topical folk music specifically, so it's been super interesting going through these songs. I speak Russian well enough that I don't really need the subtitles, but they're nice for sharing with non-Russian speakers.

    https://www.youtube.com/watch?v=jLeIx8rrlSc
    https://www.youtube.com/watch?v=UGdZ10b6E8Q
    https://www.youtube.com/watch?v=Chr8u3Whk_0

  3. Comment on If I'm using Cloudflare for my domains, do I need to bother with LE? in ~comp

    blitz
    Link
    You can't really answer this question without looking at your threat model. Why are you setting up SSL in the first place? Is it just to get that positive browser feedback for clients? Then yeah,...

    You can't really answer this question without looking at your threat model. Why are you setting up SSL in the first place?

    Is it just to get that positive browser feedback for clients? Then yeah, you don't need to set up SSL behind Cloudflare, but you're not getting the full benefit of SSL either.

    You'll get a partial benefit, since one of the easiest places to do a man in the middle attack is when you're local to a client, i.e. setting up a rogue access point that modifies or captures traffic that the victim might connect to. Cloudflare Flexible HTTPS alone will protect you from that.

    If you're handling sensitive information, though? I still think it's worth setting up a fully signed and verified key chain all the way to the origin server. Attacks that would target the backend are more sophisticated, but they can and do still happen. One possible attack that can occur is if somehow the DNS records that cloudflare sees are wrong, and cloudflare sends requests to the wrong origin server temporarily. This is called DNS cache poisoning. Though Cloudflare is unlikely to be attacked successfully, it's important to know that Cloudflare itself does not have to be compromised for your server to be compromised; all that's needed is for Cloudflare to see the wrong A record when it looks up the domain name for the origin server, which can happen any number of different ways.

    A properly signed certificate will help protect from that, a self signed certificate will not.

    In my mind it's worth having the assurance that the whole chain is encrypted and signed; especially since setting up a signed certificate is easier than ever with LE these days.

    7 votes
  4. Comment on Russia may fine citizens who use SpaceX’s Starlink Internet service in ~tech

    blitz
    Link Parent
    Maybe there's a good method, but it could also just be being set up as a secondary charge. If it's hard to detect, lots of people will probably get away with using it without repercussion, but if...

    Maybe there's a good method, but it could also just be being set up as a secondary charge. If it's hard to detect, lots of people will probably get away with using it without repercussion, but if you commit some sort of crime and they come and search your house and find one of these units there, that gives them the ability to tack on some extra punishment.

    There's lots of laws on the books in many countries that function like this, including (in some states, I think) seatbelt laws. An officer can't pull you over for not wearing a seatbelt, but if you get pulled over and it's observed you're not wearing a seatbelt, you get an extra ticket.

    9 votes
  5. Comment on What did you do this weekend? in ~talk

    blitz
    Link
    I already posted about it in one of the COVID related threads, but I built and put up a site for tracking vaccination progress in Colorado! The official state dashboard leaves a lot to be desired...

    I already posted about it in one of the COVID related threads, but I built and put up a site for tracking vaccination progress in Colorado! The official state dashboard leaves a lot to be desired so I started scraping their data and displaying myself:

    https://vaxtrack.co/

    I had some other graphs involving vaccination speed vs new daily cases but I was getting the data from CovidActNow.org and their data is licensed CC-BY-NC-ND, and I'm not sure if graphing the data with other data creates a derivative work, so I've taken those down and written to them for permission to use their data.

    If they say no or don't write back I'm sure I can find some other source for daily cases, it's just their API is very fast and convenient.

    7 votes
  6. Comment on Weekly coronavirus-related chat, questions, and minor updates - week of January 4 in ~health.coronavirus

    blitz
    (edited )
    Link Parent
    FYI, the first version of these graphs is live now. Edit: I read the license for the data I was using to plot cases, and it specifies no derivatives. Gotta ask for permission or find a new source!

    FYI, the first version of these graphs is live now.

    Edit: I read the license for the data I was using to plot cases, and it specifies no derivatives. Gotta ask for permission or find a new source!

    1 vote
  7. Comment on Weekly coronavirus-related chat, questions, and minor updates - week of January 4 in ~health.coronavirus

    blitz
    Link Parent
    That’s definitely in the plan!

    That’s definitely in the plan!

    1 vote
  8. Comment on Weekly coronavirus-related chat, questions, and minor updates - week of January 4 in ~health.coronavirus

    blitz
    Link
    Yesterday I hacked together a dashboard of vaccination info in the state of Colorado, since I found the official Colorado vaccination dashboard mostly unusable: https://vaxtrack.co/ If anyone has...

    Yesterday I hacked together a dashboard of vaccination info in the state of Colorado, since I found the official Colorado vaccination dashboard mostly unusable:

    https://vaxtrack.co/

    If anyone has any feedback, I'd be glad to hear it!

    6 votes
  9. Comment on What have you been listening to this week? in ~music

    blitz
    Link
    Odin's Raven Magic is an amazing live performance of the eponymous ancient norse poem, interjected with some melodic instruments and some funky electronic shit. I don't normally go for this kind...

    Odin's Raven Magic is an amazing live performance of the eponymous ancient norse poem, interjected with some melodic instruments and some funky electronic shit. I don't normally go for this kind of album but it works.

    Christmas Vibes, a nice jazzy take on the familiar Christmas songs.

    Songs of Comfort and Hope - Yo-Yo Ma, Kathryn Stott. I'm a big fan of Ma. He performed the Bach cello suites live on youtube during the first wave of the pandemic and talked a lot about songs that gave him comfort, so it's no surprise he put out an album of these songs.

    1 vote
  10. Comment on SpaceX successfully flies, nearly lands Starship SN8 prototype vehicle after 12.5km suborbital test flight in ~space

  11. Comment on SpaceX successfully flies, nearly lands Starship SN8 prototype vehicle after 12.5km suborbital test flight in ~space

    blitz
    Link Parent
    And some “engine-rich exhaust” :)

    And some “engine-rich exhaust” :)

    1 vote
  12. Comment on SpaceX successfully flies, nearly lands Starship SN8 prototype vehicle after 12.5km suborbital test flight in ~space

    blitz
    Link Parent
    Do you think the engines were supposed to go out one by one like that? And on restart only two of them lit. I wonder if engine reliability was the limiting factor today. Can’t wait for the Scott...

    Do you think the engines were supposed to go out one by one like that? And on restart only two of them lit. I wonder if engine reliability was the limiting factor today.

    Can’t wait for the Scott Manley video where he guesses what went wrong, and then the following press release in which he is shown to have been mostly right!

    1 vote
  13. Comment on Day 9: Encoding Error in ~comp

    blitz
    Link
    I had a lot of trouble figuring out how I could take an iterator in Rust and split it across two loops, since most of the methods on iterators take ownership of the iterator. Thankfully, I...

    I had a lot of trouble figuring out how I could take an iterator in Rust and split it across two loops, since most of the methods on iterators take ownership of the iterator. Thankfully, I stumbled upon by_ref!

    Also, I know that I'm parsing the lines to nums twice, for some reason takeing after collecting and recreating the iterator wasn't working, and I'm too sleepy to figure out why.

    lib.rs
    use std::collections::VecDeque;
    
    pub struct DataWindow(VecDeque<u64>);
    
    impl From<Vec<u64>> for DataWindow {
        fn from(vec: Vec<u64>) -> DataWindow {
            DataWindow( VecDeque::from(vec) )
        }
    }
    
    impl DataWindow {
        fn is_sum(&self, num: u64) -> bool {
            let DataWindow( dq ) = self;
    
            for x in 0..dq.len() {
                for y in x..dq.len() {
                    if dq[x] + dq[y] == num {
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        pub fn read_next(&mut self, num: u64) -> bool {
            let ret = self.is_sum(num);
            let DataWindow( dq ) = self;
    
            dq.pop_front();
            dq.push_back(num);
    
            ret
        }
    }
    
    pub fn compute_min_max_sum(mut nums_acc: Vec<u64>) -> u64 {
        nums_acc.sort();
    
        nums_acc.first().unwrap() + nums_acc.last().unwrap()
    }
    
    main.rs
    use std::io;
    use std::io::prelude::*;
    use std::env;
    
    use day9::*;
    
    fn part1(lines: &Vec<String>, preamble_len: usize) -> u64 {
        let mut nums = lines.iter().map(|x| x.parse::<u64>().unwrap());
    
        let preamble: Vec<u64> = nums.by_ref().take(preamble_len).collect::<Vec<u64>>();
        let mut dw = DataWindow::from(preamble);
    
        for n in nums {
            if !dw.read_next(n) {
                return n;
            }
        }
    
        panic!();
    }
    
    fn part2(lines: &Vec<String>, target: u64) -> u64 {
        let nums: Vec<u64> = lines
            .iter()
            .map(|x| x.parse::<u64>().unwrap())
            .collect();
    
        for (i, x) in nums.iter().enumerate() {
            let mut target_acc = *x;
            let mut nums_acc = Vec::new();
    
            for j in 1..(nums.len() - i) {
                let num = nums[i + j];
                target_acc += num;
                nums_acc.push(num);
    
                if target_acc == target {
                    return compute_min_max_sum(nums_acc);
                }
            }
        }
    
        panic!();
    }
    
    fn main() {
        let stdin = io::stdin();
        let lines: Vec<String> = stdin
            .lock()
            .lines()
            .collect::<Result<_, _>>()
            .unwrap();
    
        let args: Vec<String> = env::args().collect();
        let preamble_len = args[1].parse::<usize>().unwrap();
    
        let part1_ans = part1(&lines, preamble_len);
        let part2_ans = part2(&lines, part1_ans);
    
        println!("Part 1: {}", part1_ans);
        println!("Part 2: {}", part2_ans);
    }
    
    2 votes
  14. Comment on Day 8: Handheld Halting in ~comp

    blitz
    Link Parent
    It’s so cool to read other people’s rust solutions to the same problems every day. I completely forgot about implementing traits for my own structs! I’ll try and remember next time.

    It’s so cool to read other people’s rust solutions to the same problems every day. I completely forgot about implementing traits for my own structs! I’ll try and remember next time.

    3 votes
  15. Comment on Day 8: Handheld Halting in ~comp

    blitz
    Link
    I love this kind of thing! I think Rust lends itself to building interpreters particularly well :). lib.rs #![feature(str_split_once)] use std::collections::HashSet; #[derive(PartialEq, Eq, Copy,...

    I love this kind of thing! I think Rust lends itself to building interpreters particularly well :).

    lib.rs
    #![feature(str_split_once)]
    use std::collections::HashSet;
    
    #[derive(PartialEq, Eq, Copy, Clone)]
    pub enum BootCodeOperation {
        Acc,
        Jmp,
        Nop,
    }
    
    pub type InstructionArgument = i64;
    
    #[derive(PartialEq, Eq, Copy, Clone)]
    pub struct BootCodeInstruction {
        pub operation: BootCodeOperation,
        pub argument: InstructionArgument,
    }
    
    impl BootCodeInstruction {
        pub fn from_line(line: &str) -> BootCodeInstruction {
            let (op_str, arg_str) = line.split_once(' ').unwrap();
    
            let operation = match op_str {
                "nop" => BootCodeOperation::Nop,
                "acc" => BootCodeOperation::Acc,
                "jmp" => BootCodeOperation::Jmp,
                _ => panic!("Invalid op code")
            };
    
            let argument = arg_str.parse::<i64>().unwrap();
    
            BootCodeInstruction { operation, argument }
        }
    }
    
    pub type Program = Vec<BootCodeInstruction>;
    
    pub fn load_program(lines: &Vec<String>) -> Program {
        lines.iter().map(|x| BootCodeInstruction::from_line(x)).collect()
    }
    
    pub struct State {
        program: Program,
        instruction_pointer: usize,
        acc: i64,
    }
    
    impl State {
        pub fn new(program: Program) -> State {
            State { program, instruction_pointer: 0, acc: 0 }
        }
    
        pub fn tick(&mut self) -> (i64, Option<usize>) {
            let current_instruction = self.program[self.instruction_pointer];
    
            match current_instruction.operation {
                BootCodeOperation::Acc => {
                    self.acc += current_instruction.argument;
                    self.instruction_pointer += 1;
                },
                BootCodeOperation::Jmp => {
                    self.instruction_pointer = (
                        self.instruction_pointer as i64 + current_instruction.argument
                    ) as usize;
                },
                BootCodeOperation::Nop => {
                    self.instruction_pointer += 1;
                }
            }
    
            let next_instruction = match self.instruction_pointer >= self.program.len() {
                true => None,
                false => Some(self.instruction_pointer),
            };
    
            (self.acc, next_instruction)
        }
    }
    
    pub fn loop_detecting_runner(mut state: State) -> (bool, i64) {
        let mut executed_instructions = HashSet::new();
    
        while let (acc, Some(next_instruction)) = state.tick() {
            if executed_instructions.contains(&next_instruction) {
                return (true, acc);
            } else {
                executed_instructions.insert(next_instruction);
            }
        }
    
        (false, state.acc)
    }
    
    main.rs
    use std::io;
    use std::io::prelude::*;
    
    use day8::*;
    
    fn part1(lines: &Vec<String>) -> i64 {
        let program = load_program(&lines);
        let state = State::new(program);
    
        let (_loop_detected, acc) = loop_detecting_runner(state);
    
        acc
    }
    
    fn part2(lines: &Vec<String>) -> i64 {
        let program = load_program(&lines);
    
        for (i, instr) in program.iter().enumerate() {
            let mut new_program = program.clone();
            match instr.operation {
                BootCodeOperation::Nop => {
                    new_program[i].operation = BootCodeOperation::Jmp;
                },
                BootCodeOperation::Jmp => {
                    new_program[i].operation = BootCodeOperation::Nop;
                },
                BootCodeOperation::Acc => {},
            }
    
            let state = State::new(new_program);
    
            let (loop_detected, acc) = loop_detecting_runner(state);
    
            if !loop_detected {
                return acc;
            }
        }
    
        panic!();
    }
    
    fn main() {
        let stdin = io::stdin();
        let lines: Vec<String> = stdin
            .lock()
            .lines()
            .collect::<Result<_, _>>()
            .unwrap();
    
        println!("Part 1: {}", part1(&lines));
        println!("Part 2: {}", part2(&lines));
    }
    
    4 votes
  16. Comment on Day 7: Handy Haversacks in ~comp

    blitz
    Link
    I thought this one was really satisfying! Took basically all my free time today though! I thought I might need reference counting or cells to do this one but actually recursing HashMaps was good...

    I thought this one was really satisfying! Took basically all my free time today though! I thought I might need reference counting or cells to do this one but actually recursing HashMaps was good enough!

    Rust

    lib.rs
    #![feature(str_split_once)]
    
    use std::collections::HashMap;
    
    type BagCount = usize;
    type BagColor = String;
    type BagContainerMap = HashMap<BagColor, Vec<BagColor>>;
    type BagContainsMap = HashMap<BagColor, Vec<(BagCount, BagColor)>>;
    
    pub fn generate_bag_container_maps(bags: &Vec<Bag>) -> BagContainerMap {
        let mut map: HashMap<BagColor, Vec<BagColor>> = HashMap::new();
    
        for b in bags.iter() {
            for (_, color) in b.contents.iter() {
                match map.get_mut(color) {
                    Some(v) => v.push(b.color.clone()),
                    None => {
                        map.insert(color.clone(), vec![b.color.clone()]);
                    }
                }
            }
        }
    
        map
    }
    
    pub fn count_bag_containers(color: &BagColor, bags: BagContainerMap) -> usize {
        let mut count = 0;
        let mut visited = Vec::new();
        let mut to_visit = vec![color];
    
        while to_visit.len() > 0 {
            let visiting = to_visit.pop().unwrap();
    
            match bags.get(visiting) {
                Some(containers) => {
                    for c in containers {
                        if !to_visit.contains(&c) && !visited.contains(&c) {
                            to_visit.push(c);
                            count += 1;
                        }
                    }
                },
                None => ()
            }
    
            visited.push(visiting)
        }
    
        count
    }
    
    pub fn generate_bag_contains_maps(bags: &Vec<Bag>) -> BagContainsMap {
        let mut map = HashMap::new();
    
        for b in bags {
            map.insert(b.color.clone(), b.contents.clone());
        }
    
        map
    }
    
    pub fn count_bag_contents(color: &BagColor, bags: &BagContainsMap) -> usize {
        let contents = bags.get(color).unwrap();
        if contents.len() == 0 {
            return 0
        } else {
            let mut total_count = 0;
            for (count, color) in contents.iter() {
                // Count of the bags inside this bag
                total_count += count;
    
                // Count of the bags inside the bags inside this bag
                total_count += count_bag_contents(color, bags) * count;
            }
    
            return total_count;
        }
    }
    
    
    #[derive(PartialEq, Eq, Debug)]
    pub struct Bag {
        pub color: BagColor,
        pub contents: Vec<(BagCount, BagColor)>
    }
    
    impl Bag {
        pub fn from_line(line: &str) -> Bag {
            let (color, contains) = line.split_once(" bags contain ").unwrap();
    
            if contains == "no other bags." {
                return Bag { color: color.to_string(), contents: Vec::new() };
            } else {
                let mut contents = Vec::new();
    
                for b in contains.split(',') {
                    let mut bag_words = b.split_whitespace();
    
                    let count = bag_words.next().unwrap().parse::<usize>().expect("Expected number of bags.");
                    let c = format!("{} {}", bag_words.next().unwrap(), bag_words.next().unwrap());
    
                    contents.push((count, c));
                }
    
                return Bag { color: color.to_string(), contents: contents };
            }
        }
    }
    
    #[cfg(test)]
    mod test {
        use super::*;
    
        #[test]
        fn test_contents_one() {
            let line = "bright white bags contain 1 shiny gold bag.";
            let expect = Bag { color: "bright white".to_string(), contents: vec![(1, "shiny gold".to_string())] };
    
            assert_eq!(Bag::from_line(&line), expect);
        }
    
        #[test]
        fn test_contents_many() {
            let line = "vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.";
            let expect = Bag { color: "vibrant plum".to_string(), contents: vec![(5, "faded blue".to_string()), (6, "dotted black".to_string())] };
    
            assert_eq!(Bag::from_line(&line), expect);
        }
    
        #[test]
        fn test_contents_none() {
            let line = "dotted black bags contain no other bags.";
            let expect = Bag { color: "dotted black".to_string(), contents: vec![] };
    
            assert_eq!(Bag::from_line(&line), expect);
        }
    }
    
    main.rs
    use std::io;
    use std::io::prelude::*;
    
    use day7::{
        Bag,
        generate_bag_container_maps,
        count_bag_containers,
        generate_bag_contains_maps,
        count_bag_contents,
    };
    
    fn main() {
        let stdin = io::stdin();
        let lines: Vec<String> = stdin
            .lock()
            .lines()
            .collect::<Result<_, _>>()
            .unwrap();
    
        let mut bags = Vec::new();
    
        for line in lines {
            bags.push(Bag::from_line(&line));
        }
    
        let bag_map = generate_bag_container_maps(&bags);
        let shiny_gold_count = count_bag_containers(&("shiny gold".to_string()), bag_map);
    
        let contains_map = generate_bag_contains_maps(&bags);
        let part_2 = count_bag_contents(&("shiny gold".to_string()), &contains_map);
    
        println!("Part 1: {}", shiny_gold_count);
        println!("Part 2: {}", part_2);
    }
    
    3 votes
  17. Comment on Day 6: Custom Customs in ~comp

    blitz
    (edited )
    Link
    Rust use std::io; use std::io::prelude::*; use std::collections::{HashSet, HashMap}; fn group_lines(lines: &Vec<String>) -> Vec<Vec<String>> { let mut groups = Vec::new(); let mut current_group =...
    Rust
    use std::io;
    use std::io::prelude::*;
    
    use std::collections::{HashSet, HashMap};
    
    fn group_lines(lines: &Vec<String>) -> Vec<Vec<String>> {
        let mut groups = Vec::new();
    
        let mut current_group = Vec::new();
    
        for l in lines.iter() {
            if l.len() == 0 {
                groups.push(current_group);
                current_group = Vec::new();
            } else {
                current_group.push(l.clone());
            }
        }
    
        if current_group.len() > 0 {
            groups.push(current_group);
        }
    
        groups
    }
    
    fn unique_answers_in_group(group: &Vec<String>) -> usize {
        let mut hashset = HashSet::new();
    
        for line in group.iter() {
            for c in line.chars() {
                hashset.insert(c);
            }
        }
    
        hashset.len()
    }
    
    fn unanimous_answers_in_group(group: &Vec<String>) -> usize {
        let mut map = HashMap::new();
    
        for line in group.iter() {
            for c in line.chars() {
                if let Some(x) = map.get_mut(&c) {
                    *x = *x + 1;
                } else {
                    map.insert(c, 1);
                }
            }
        }
    
        map
            .iter()
            .filter(|(_, v)| **v == group.len())
            .map(|(k, _)| k)
            .count()
    }
    
    
    fn main() {
        let stdin = io::stdin();
        let lines: Vec<String> = stdin
            .lock()
            .lines()
            .collect::<Result<_, _>>()
            .unwrap();
    
        let grouped_lines = group_lines(&lines);
    
        let part1_ans: usize = grouped_lines
            .iter()
            .map(unique_answers_in_group)
            .sum();
        let part2_ans: usize = grouped_lines
            .iter()
            .map(unanimous_answers_in_group)
            .sum();
    
        println!("Part 1: {}", part1_ans);
        println!("Part 2: {}", part2_ans);
    }
    
    2 votes
  18. Comment on Day 5: Binary Boarding in ~comp

    blitz
    Link Parent
    Spoilers Since you know it's not at the beginning or the end and you know the seats IDs are contiguous, you don't even need to find the min and the max, just one side and go up or down until you...

    I ended up just making a quick list of all the seats, finding the min and max, and then iterating between them until I found which seat wasn't there

    Spoilers Since you know it's not at the beginning or the end and you know the seats IDs are contiguous, you don't even need to find the min and the max, just one side and go up or down until you find the first one that's not there!
    4 votes
  19. Comment on Day 5: Binary Boarding in ~comp

    blitz
    Link Parent
    Damn, I was super happy with how clever my solution was but I'm a little upset I didn't think of your way! Brilliant!

    Damn, I was super happy with how clever my solution was but I'm a little upset I didn't think of your way! Brilliant!

    4 votes
  20. Comment on Day 5: Binary Boarding in ~comp

    blitz
    (edited )
    Link
    I was expecting something much harder since tomorrow is a weekend! Also, I have joined the private leaderboard as (anonymous user #573549). :) Rust main.rs use std::io; use std::io::prelude::*;...

    I was expecting something much harder since tomorrow is a weekend!

    Also, I have joined the private leaderboard as (anonymous user #573549). :)

    Rust

    main.rs
    use std::io;
    use std::io::prelude::*;
    use std::collections::HashSet;
    
    use std::cmp;
    
    fn row_partition(input: &str) -> usize{
        let mut row_acc = 0;
    
        for (i, c) in input.chars().enumerate() {
            if c == 'B' {
                row_acc += 64 / (2 as usize).pow(i as u32);
            }
        }
    
        row_acc
    }
    
    fn col_partition(input: &str) -> usize {
        let mut col_acc = 0;
    
        for (i, c) in input.chars().enumerate() {
            if c == 'R' {
                col_acc += 4 / (2 as usize).pow(i as u32);
            }
        }
    
        col_acc
    }
    
    fn get_coord(input: &str) -> (usize, usize) {
        let (row, col) = input.split_at(7);
    
        (row_partition(row), col_partition(col))
    }
    
    fn get_seat_id(input: &str) -> usize {
        let (row, col) = get_coord(input);
    
        (row * 8) + col
    }
    
    fn part1(lines: &Vec<String>) -> usize {
        let mut max_seat_id = 0;
    
        for l in lines.iter() {
            max_seat_id = cmp::max(max_seat_id, get_seat_id(l));
        }
    
        max_seat_id
    }
    
    fn part2(lines: &Vec<String>, max_seat_id: usize) -> usize {
        let mut existing_seats = HashSet::new();
    
        for l in lines.iter() {
            existing_seats.insert(get_seat_id(l));
        }
    
        for x in (0..max_seat_id).rev() {
            if !existing_seats.contains(&x) {
                return x;
            }
        }
    
        panic!();
    }
    
    fn main() {
        let stdin = io::stdin();
        let lines: Vec<String> = stdin.lock().lines().collect::<Result<_, _>>().unwrap();
    
        let part1_ans = part1(&lines);
        let part2_ans = part2(&lines, part1_ans);
    
        println!("Part 1: {}", part1_ans);
        println!("Part 2: {}", part2_ans);
    }
    
    3 votes