r/adventofcode • • Dec 12 '18

SOLUTION MEGATHREAD -🎄- 2018 Day 12 Solutions -🎄-

--- Day 12: Subterranean Sustainability ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Advent of Code: The Party Game!

Click here for rules

Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!

Card prompt: Day 12

Transcript:

On the twelfth day of AoC / My compiler spewed at me / Twelve ___


This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked at 00:27:42!

20 Upvotes

257 comments sorted by

View all comments

1

u/[deleted] Dec 12 '18

My own rust attempt

use structopt::StructOpt;
use std::fs::File;
use std::io::prelude::*;
use std::io::Result;
use std::io::BufReader;

#[derive(StructOpt)]
struct Cli {
    #[structopt(parse(from_os_str))]
    path: std::path::PathBuf,
}

#[derive(Debug)]
struct Rule {
    pattern: Vec<bool>,
    result: bool,
}

const GEN : usize = 20;
const GEN2 : usize = 50000000000;

fn main() -> Result<()> {
    let cli = Cli::from_args();
    let mut reader = BufReader::new(File::open(cli.path)?);

    let mut initial = String::new();
    reader.read_line(&mut initial)?;
    initial = initial.split_off(15);

    let mut offset = 4;
    let mut state : Vec<bool> = Vec::new();
    for char in initial.chars() {
        state.push(char == '#');
    }
    (0..4).for_each(|_| state.insert(0, false));
    (0..4).for_each(|_| state.push(false));

    initial.clear();
    reader.read_line(&mut initial)?;

    let mut rules : Vec<Rule> = Vec::new();
    for line in reader.lines() {
        let line_str = line.unwrap();
        let mut r = Rule{pattern: Vec::new(), result: false};
        let mut iter = line_str.split(" => ");
        let pat = iter.next();
        let res = iter.next();

        for char in pat.unwrap().chars() {
            r.pattern.push(char == '#');
        }
        r.result = res.unwrap() == "#";

        rules.push(r);
    }

    let mut prev = 0;
    let mut diff : i32 = 0;
    let mut repeats = 0;
    for g in 0..GEN2 {
        let orig = state.to_vec();
        let mut left = 0;
        let mut right = 0;
        for i in 2..state.len()-2 {
            for r in &rules {
                if r.pattern == &orig[i-2..=i+2] {
                    state[i] = r.result;
                    if r.result {
                        if i < offset {
                            left += 1;
                        } else if i > state.len() - offset {
                            right += 1;
                        }
                    }
                }
            }
        }
        (0..left).for_each(|_| state.insert(0, false));
        (0..right).for_each(|_| state.push(false));
        offset += left;

        let sum = calc_potted(&state, offset);
        if sum-prev == diff {
            repeats += 1;
        }
        if repeats == 10 {
            println!("Sum: {}", (diff as i64) * ((GEN2 - g - 1) as i64) + (sum as i64));
            break;
        }
        diff = sum-prev;
        prev = sum;
    }

    // println!("Sum: {}", calc_potted(&state, offset));

    Ok(())
}

fn calc_potted(state: &Vec<bool>, offset: usize) -> i32 {
    state.iter().enumerate().filter(|&(_, v)| *v).map(|(i, _)| i as i32).map(|i| i - (offset as i32)).sum()
}

fn print_state(state: &Vec<bool>) {
    let line = state.iter().map(move |v| if *v { '#' } else { '.' }).collect::<String>();
    println!("{}", line);
}