81 Востаннє редагувалося dot (02.12.2022 16:42:32)

Re: Advent of Code

Pobaćyv rêśennja zadaćy, de ne treba stvorjuvaty tablycjy, prosto ćerez ord i moduljnu matematiku. Dosytj elegantno.

2022#2, Python
score = 0
    for line in sys.stdin:
        rnd = line.split()
        opp = ord(rnd[0]) - ord('A')    # ascii
        me = ord(rnd[1]) - ord('X')     # haxx!
        score += me + 1 + ((me - opp + 1) % 3) * 3

    print(score)

Do druhojê zamênyty lyśe tyj rjadok:

        me = (ord(rnd[1]) - ord('X') - 1 + opp) % 3     # haxx!
Подякували: leofun011

82

Re: Advent of Code

dot написав:

zamnênyty

Це помилка чи якась особливість вашої латинки? В слові "замінити" одне н.

83

Re: Advent of Code

koala написав:
dot написав:

zamnênyty

Це помилка чи якась особливість вашої латинки? В слові "замінити" одне н.

Pomylka.

Подякували: koala1

84 Востаннє редагувалося koala (03.12.2022 09:33:43)

Re: Advent of Code

Умова: ельфи несуть рюкзаки з речами (стрічки латинських символів). Кожна річ має вартість (маленька літера a-z - 1-26, велика A-Z - 27-52).
1. Знайти у кожному рюкзаку єдину річ, що повторюється в першій і другій половині, повернути суму вартостей цих речей.
2. Ельфи йдуть групами по троє (в заданому у вхідних даних порядку). Знайти у кожній трійці спільну річ, повернуту суму вартостей цих речей.

2022#3, Rust
fn value(c: char) -> u32 {
    if c.is_uppercase() {
        (c as u8 - b'A') as u32 + 27
    } else {
        (c as u8 - b'a') as u32 + 1
    }
}

pub fn parse_input(input: &str) -> Vec<Vec<u32>> {
    input
        .lines()
        .map(|line| line.chars().map(|c| value(c)).collect())
        .collect()
}

use std::collections::HashSet;

pub fn task1(input: &[Vec<u32>]) -> u32 {
    input
        .iter()
        .map(|backpack| {
            let (left, right) = backpack.split_at(backpack.len() / 2);
            let left: HashSet<_> = left.iter().collect();
            right
                .iter()
                .find_map(|item| {
                    if left.contains(&item) {
                        Some(item)
                    } else {
                        None
                    }
                })
                .unwrap()
        })
        .sum()
}

pub fn task2(input: &[Vec<u32>]) -> u32 {
    let mut result = 0;
    for group in input.chunks(3) {
        let mut badges: HashSet<_> = group[0].iter().collect();
        for i in 1..3 {
            badges = badges
                .intersection(&group[i].iter().collect())
                .copied()
                .collect();
        }
        result += *badges.iter().next().unwrap();
    }
    result
}

Для того, щоб не дарма займатися, поставив Clippy (досі без нього працював). Дуже цікаві попередження виявляє - і переважно одразу пропонує рішення, але в складних випадках не працює.

Подякували: leofun01, dot2

85

Re: Advent of Code

2022#03, Python
import string
from collections import Counter
from functools import reduce
from operator import and_

insert = open("input.txt").read().split()


def reorganization(length: int, count: int = 1) -> int:
    priorities: int = 0

    for line in range(0, len(insert) - count + 1, count):
        parts = list()

        for n in range(count):
            l = len(insert[line + n]) // length

            for div in range(0, len(insert[line + n]), l):
                parts.append(Counter(insert[line + n][div : div + l]))

        item = list(reduce(and_, parts).elements())[0]
        priorities += string.ascii_letters.index(item) + 1

    return priorities


print(reorganization(2))  # Part One: 7889
print(reorganization(1, 3))  # Part Two: 2825

86 Востаннє редагувалося dot (03.12.2022 14:03:36)

Re: Advent of Code

Znov ź taky, majstery Pajtona zavoroźujutj.

2022#02, Python
import string
import sys

rucksacks = ((set(r[:(len(r) - 1) // 2]), set(r[(len(r) - 1) // 2:-1])) for r in sys.stdin)
priorities = (string.ascii_letters.index(next(iter(set.intersection(*r)))) + 1 for r in rucksacks)
print(sum(priorities))
import string
import sys

def group_sacks(rucksacks, size):
    for i in range(0, len(rucksacks), size):
        yield rucksacks[i:i + size]


groups = group_sacks([set(r[:-1]) for r in sys.stdin], 3)
priorities = (string.ascii_letters.index(next(iter(set.intersection(*r)))) + 1 for r in groups)
print(sum(priorities))

Kolysj pôdvezutj sjudy normaljnu kolorizatsiju kodôv…

87 Востаннє редагувалося dot (04.12.2022 08:55:39)

Re: Advent of Code

2022#04, Python
import re


def cleanup(full: bool = True) -> int:
    overlap: int = 0

    for line in open("input.txt"):
        a, b, c, d = map(int, re.findall(r"\d+", line))
        first = set(range(a, b + 1))
        second = set(range(c, d + 1))

        if full and (first.issubset(second) or second.issubset(first)) or not full and first.intersection(second):
            overlap += 1

    return overlap


print(cleanup())  # Part One: 498
print(cleanup(False))  # Part Two: 859

Moźna bulo śće prosto porôvnjuvaty granycjy, ale menê lênjky rozpysuvaty umovy, a programa vykonuje sja mytjovo.

Dekotra zmêna. Bulo:

if full and (first.issubset(second) or second.issubset(first)) or not full and first.intersection(second):

Ale zarady cêkavynky perevêryv i nastupnyj konstrukt cêlkom roboćyj:

if first.issubset(second) or second.issubset(first) if full else first.intersection(second):

Zrućno, tobto ne treba propysuvaty if X and A or not X and B, dostatnjo if A if X else B.

Подякували: leofun011

88

Re: Advent of Code

Умова: у ельфів є завдання за номерами, наприклад, 3-6 означає 3, 4, 5, 6. Ельфи поділені на пари. У деяких пар завдання накладаються і перетинаються (скажімо, 3-6,4-5 - завдання другого ельфа повністю вкладається в завдання першого). Треба знайти кількість:
1. Пар, завдання яких повністю накладаються
2. Пар, завдання яких перетинаються (включаючи п.1)

2022#04, Rust
pub struct Assignment {
    left: usize,
    right: usize,
    range: std::ops::RangeInclusive<usize>,
}

impl Assignment {
    fn new(input: &str) -> Assignment {
        let mut input = input.split('-');
        let left = input.next().unwrap().parse().unwrap();
        let right = input.next().unwrap().parse().unwrap();
        Assignment {
            left,
            right,
            range: left..=right,
        }
    }
    fn contains(&self, other: &Assignment) -> bool {
        self.range.contains(&other.left) && self.range.contains(&other.right)
    }
    fn overlaps(&self, other: &Assignment) -> bool {
        self.range.contains(&other.left)
            || self.range.contains(&other.right)
            || other.contains(self)
    }
}

pub fn parse_input(input: &str) -> Vec<(Assignment, Assignment)> {
    input
        .lines()
        .map(|line| {
            let mut pair = line.split(',');
            (
                Assignment::new(pair.next().unwrap()),
                Assignment::new(pair.next().unwrap()),
            )
        })
        .collect()
}

fn filter_count<T, F>(assignments: &[T], f: F) -> usize
where
    F: FnMut(&&T) -> bool,
{
    assignments.iter().filter(f).count()
}

pub fn task1(assignments: &[(Assignment, Assignment)]) -> usize {
    filter_count(assignments, |&(left, right)| {
        left.contains(right) || right.contains(left)
    })
}

pub fn task2(assignments: &[(Assignment, Assignment)]) -> usize {
    filter_count(assignments, |&(left, right)| left.overlaps(right))
}

У Rust все одно доводиться трохи більше писати (ну не виходить просто розібрати вираз на 4 числа), а я швидко починаю плутатися, де у мене там ліво, де право, де праве значення лівого ельфа і т.д. Тому типи і функції. На жаль, RangeInclusive не надає доступу до своїх елементів, тому довелося власний тип проголошувати.

Подякували: leofun011

89 Востаннє редагувалося koala (04.12.2022 22:25:15)

Re: Advent of Code

Переробив свій проєкт на Rust, код скоротився, тепер дописувати про наявність нового файла треба лише в одному місці. Заразом усе трохи причесав, замінив дещо застарілий lazy_static на OnceCell і нарешті пройшовся по всьому коду Clippy.
Засів переробляти 2019 рік - там треба емулятор запрограмувати (інструкції додаються поступово в нових завданнях). Зробив завдяки цьому раніше не зроблене 2019#7-2.

2019#07, багатолітер
//computer.rs
#[derive(Clone, PartialEq, Eq)]
pub enum ComputerState {
    Normal,
    Halt,
    Input,
}

use std::collections::VecDeque;

#[derive(Clone)]
pub struct Computer {
    pub memory: Vec<isize>,
    pub ip: usize,
    input: VecDeque<isize>,
    output: VecDeque<isize>,
    pub state: ComputerState,
}

impl Computer {
    pub fn is_halted(&self) -> bool {
        self.state == ComputerState::Halt
    }
    pub fn is_input_blocked(&self) -> bool {
        self.state == ComputerState::Input && self.input.is_empty()
    }

    pub fn step(&mut self) {
        if self.is_halted() || self.is_input_blocked() {
            return;
        }
        self.state = ComputerState::Normal;
        let opcode = self.memory[self.ip] % 100;
        match opcode {
            1 => {
                let src1 = self.get_value(1);
                let src2 = self.get_value(2);
                let tgt = self.memory[self.ip + 3];
                self.memory[tgt as usize] = src1 + src2;
                self.ip += 4;
            }
            2 => {
                let src1 = self.get_value(1);
                let src2 = self.get_value(2);
                let tgt = self.memory[self.ip + 3];
                self.memory[tgt as usize] = src1 * src2;
                self.ip += 4;
            }
            3 => {
                if self.input.is_empty() {
                    self.state = ComputerState::Input;
                    return;
                }
                let tgt = self.memory[self.ip + 1];
                self.memory[tgt as usize] = self.input.pop_front().unwrap();
                self.ip += 2;
            }
            4 => {
                let src = self.get_value(1);
                self.output.push_back(src);
                self.ip += 2;
            }
            5 => {
                let test = self.get_value(1);
                let tgt = self.get_value(2);
                self.ip = if test != 0 { tgt as usize } else { self.ip + 3 };
            }
            6 => {
                let test = self.get_value(1);
                let tgt = self.get_value(2);
                self.ip = if test == 0 { tgt as usize } else { self.ip + 3 };
            }
            7 => {
                let test1 = self.get_value(1);
                let test2 = self.get_value(2);
                let tgt = self.memory[self.ip + 3];
                self.memory[tgt as usize] = isize::from(test1 < test2);
                self.ip += 4;
            }
            8 => {
                let test1 = self.get_value(1);
                let test2 = self.get_value(2);
                let tgt = self.memory[self.ip + 3];
                self.memory[tgt as usize] = isize::from(test1 == test2);
                self.ip += 4;
            }
            99 => {
                self.state = ComputerState::Halt;
            }
            _ => unimplemented!(),
        }
    }
    pub fn new(code: &[isize]) -> Computer {
        Computer {
            memory: code.into(),
            ip: 0,
            input: VecDeque::new(),
            output: VecDeque::new(),
            state: ComputerState::Normal,
        }
    }

    fn get_value(&self, index: usize) -> isize {
        let mut mode = self.memory[self.ip] / 100;
        for _ in 1..index {
            mode /= 10;
        }
        match mode % 10 {
            0 => self.memory[self.memory[self.ip + index] as usize],
            1 => self.memory[self.ip + index],
            _ => unimplemented!(),
        }
    }
    pub fn run(&mut self) {
        while !self.is_halted() && !self.is_input_blocked() {
            self.step();
        }
    }
    pub fn write(&mut self, value: isize) {
        self.input.push_back(value);
    }
    pub fn read(&mut self) -> Option<isize> {
        self.output.pop_front()
    }
}

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

    fn test_memory(before: &[isize], after: &[isize]) {
        let mut comp = Computer::new(before);
        comp.run();
        assert_eq!(comp.memory, after);
    }

    #[test]
    fn test_day2() {
        test_memory(
            &[1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50],
            &[3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50],
        );
        test_memory(&[1, 0, 0, 0, 99], &[2, 0, 0, 0, 99]);
        test_memory(&[2, 3, 0, 3, 99], &[2, 3, 0, 6, 99]);
        test_memory(&[2, 4, 4, 5, 99, 0], &[2, 4, 4, 5, 99, 9801]);
        test_memory(
            &[1, 1, 1, 4, 99, 5, 6, 0, 99],
            &[30, 1, 1, 4, 2, 5, 6, 0, 99],
        );
    }

    fn test_io(code: &[isize], input: &[isize], output: &[isize], msg: &str) {
        let mut comp = Computer::new(code);
        comp.input.extend(input.iter().copied());
        comp.run();
        assert_eq!(comp.output, output, "{msg}");
    }

    #[test]
    fn test_day5() {
        test_io(&[3, 0, 4, 0, 99], &[42], &[42], "Copy input");
        test_memory(&[1002, 4, 3, 4, 33], &[1002, 4, 3, 4, 99]);
        //equal to 8
        test_io(
            &[3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8],
            &[8],
            &[1],
            "Equal to 8 - position",
        );
        test_io(
            &[3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8],
            &[42],
            &[0],
            "Equal to 8 - position",
        );

        test_io(
            &[3, 3, 1108, -1, 8, 3, 4, 3, 99],
            &[8],
            &[1],
            "Equal to 8 - immediate",
        );
        test_io(
            &[3, 3, 1108, -1, 8, 3, 4, 3, 99],
            &[42],
            &[0],
            "Equal to 8 - immediate",
        );

        //less then 8
        test_io(
            &[3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8],
            &[5],
            &[1],
            "Less than 8 - position",
        );
        test_io(
            &[3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8],
            &[42],
            &[0],
            "Less than 8 - position",
        );

        test_io(
            &[3, 3, 1107, -1, 8, 3, 4, 3, 99],
            &[5],
            &[1],
            "Less than 8 - immediate",
        );
        test_io(
            &[3, 3, 1107, -1, 8, 3, 4, 3, 99],
            &[42],
            &[0],
            "Less than 8 - immediate",
        );

        //equal to 0
        test_io(
            &[3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9],
            &[0],
            &[0],
            "Equal to 0 - position",
        );
        test_io(
            &[3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9],
            &[42],
            &[1],
            "Equal to 0 - position",
        );

        test_io(
            &[3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1],
            &[0],
            &[0],
            "Equal to 0 - immediate",
        );
        test_io(
            &[3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1],
            &[42],
            &[1],
            "Equal to 0 - immediate",
        );

        let larger_example = &[
            3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31,
            1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104,
            999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99,
        ];
        test_io(larger_example, &[5], &[999], "Large - less than");
        test_io(larger_example, &[8], &[1000], "Large - equal");
        test_io(larger_example, &[42], &[1001], "Large - greater");
    }
}

//day7.rs
use super::computer::Computer;

pub fn parse_input(input: &str) -> Vec<isize> {
    input
        .trim()
        .split(',')
        .map(|x| x.parse().unwrap())
        .collect()
}

use itertools::Itertools;

pub fn task1(code: &[isize]) -> isize {
    (0..5)
        .permutations(5)
        .map(|perm| {
            let mut data = 0;
            for phase in perm {
                let mut amplifier = Computer::new(code);
                amplifier.write(phase);
                amplifier.write(data);
                amplifier.run();
                data = amplifier.read().unwrap();
            }
            data
        })
        .max()
        .unwrap()
}

pub fn task2(code: &[isize]) -> isize {
    (5..10)
        .permutations(5)
        .map(|perm| {
            let mut amplifiers = Vec::new();
            for phase in perm {
                let mut amplifier = Computer::new(code);
                amplifier.write(phase);
                amplifiers.push(amplifier);
            }
            amplifiers[0].write(0);
            let mut changes = true;
            let mut last_data = -1;
            while changes {
                changes = false;
                for i in 0..5 {
                    amplifiers[i].run();
                    while let Some(data) = amplifiers[i].read() {
                        if i == 4 {
                            last_data = data;
                        }
                        amplifiers[(i + 1) % 5].write(data);
                        changes = true;
                    }
                }
            }
            last_data
        })
        .max()
        .unwrap()
}
Подякували: dot1

90 Востаннє редагувалося dot (05.12.2022 07:36:50)

Re: Advent of Code

Tym ćasom: <Placing #1 in Advent of Code with GPT-3, AI solves Advent of Code 2022>.

Подякували: koala1

91

Re: Advent of Code

Умова: є схема розміщення коробок і план їх переміщення. З'ясувати, які коробки опиняться нагорі в результаті, якщо:
1. Коробки перекладають по одній (тобто якщо треба перекласти 2, то вони змінюють порядок)
2. Коробки перекладають групами (порядок не змінюється)

2022#8 Rust
pub struct Cargo {
    stacks: Vec<Vec<char>>,
    plan: Vec<(usize, usize, usize)>,
}

pub fn parse_input(input: &str) -> Cargo {
    let mut stacks = Vec::new();
    let mut plan = Vec::new();
    for line in input.lines() {
        if line.contains('[') {
            if stacks.len() < line.len() / 4 {
                stacks.resize(line.len() / 4 + 1, Vec::new());
            }
            for i in 0..line.len() / 4 + 1 {
                if let Some(crat) = line.chars().nth(i * 4 + 1) {
                    if crat != ' ' {
                        stacks[i].push(crat);
                    }
                }
            }
        } else if line.starts_with("move") {
            let mut line = line.split_whitespace();
            line.next();
            let number = line.next().unwrap().parse().unwrap();
            line.next();
            let from = line.next().unwrap().parse().unwrap();
            line.next();
            let to = line.next().unwrap().parse().unwrap();
            plan.push((number, from, to));
        }
    }
    for stack in &mut stacks {
        stack.reverse();
    }
    Cargo { stacks, plan }
}

pub fn task1(input: &Cargo) -> String {
    let mut stacks = input.stacks.clone();
    for &(number, from, to) in &input.plan {
        for _ in 0..number {
            if let Some(crat) = stacks[from - 1].pop() {
                stacks[to - 1].push(crat);
            }
        }
    }
    stacks
        .iter()
        .map(|stack| {
            stack.last().map(char::to_string).unwrap_or(" ".to_string())
        })
        .collect()
}

pub fn task2(input: &Cargo) -> String {
    let mut stacks = input.stacks.clone();
    for &(number, from, to) in &input.plan {
        let new_from_len = stacks[from - 1].len() - number;
        let crates = Vec::from(&stacks[from - 1][new_from_len..]);
        stacks[from - 1].truncate(new_from_len);
        stacks[to - 1].extend(crates);
    }
    stacks
        .iter()
        .map(|stack| {
            stack.last().map(char::to_string).unwrap_or(" ".to_string())
        })
        .collect()
}

Загалом, можна трохи скоротити, але це якраз той тип задач, який Rust ненавидить. Складні зміни всередині структури з перекиданням частин туди-сюди. Треба або unsafe робити, або купу проміжних змінних.

Подякували: dot1

92 Востаннє редагувалося dot (05.12.2022 10:22:42)

Re: Advent of Code

2022#5, Python
from curses.ascii import isdigit
import collections, copy, re

file = [block.split("\n") for block in open("input.txt").read().split("\n\n")]
procedures = [list(map(int, re.findall("\d+", line))) for line in file[1]]
crates = collections.defaultdict(list)

for line in file[0][-2::-1]:
    for i, mark in enumerate(file[0][-1]):
        if isdigit(mark) and i < len(line) and line[i] != " ":
            crates[int(mark)].append(line[i])


def crateMover(version: int = 9000) -> str:
    cell = copy.deepcopy(crates)
    for move, a, b in procedures:
        moved = [cell[a].pop() for _ in range(move)]
        cell[b].extend(moved if version == 9000 else moved[::-1])

    return "".join([cell[i][-1] for i in cell])


print(crateMover())  # Part One: QNHWJVJZW
print(crateMover(9001))  # Part Two: BPCZJLFJW

Majźe peven, śćo moźna bulo vydobyty infu z fajla kraśće i oxajnêśe, ale naj.

Подякували: koala1

93

Re: Advent of Code

Śće z cêkavoho ćy smêśnoho navkolo <AoC>: xtosj pomêtyv v sobê virus, śćo krade kriptovalutu, bo skopijovanyj tekst zô zadaćy ne zbêhav sja zô vstavlenym.

94 Востаннє редагувалося koala (06.12.2022 08:54:35)

Re: Advent of Code

Умова: знайти в стрічці першу підстрічку з n різних символів. Повернути номер символу після закінчення цієї підстрічки:
1. n=4
2. n=14

2022#6, Rust
pub fn parse_input(input: &str) -> &str {
    input
}

use std::collections::HashSet;

fn first_different(input: &str, length: usize) -> usize {
    for i in 0..input.len() - length {
        let set: HashSet<_> = input[i..i + length].chars().collect();
        if set.len() == length {
            return i + length;
        }
    }
    unreachable!()
}

pub fn task1(input: &str) -> usize {
    first_different(input, 4)
}

pub fn task2(input: &str) -> usize {
    first_different(input, 14)
}
Подякували: dot1

95

Re: Advent of Code

2022#6, Python
buffer = open("input.txt").read()


def device(length: int):
    for i in range(len(buffer) - length + 1):
        if len(set(buffer[i : i + length])) == length:
            return length + i


print(device(4))  # Part One: 1625
print(device(14))  # Part Two: 2250

96 Востаннє редагувалося koala (07.12.2022 11:35:56)

Re: Advent of Code

Умова: є команди оболонки (обрізані cd і ls), якими пройшлися по всій файловій системі. Треба:
1. Знайти суму місця, займану теками, меншими за 100_000 (з урахуванням підтек);
2. Знайти розмір найменшої теки, видалення якої звільнить 30_000_000 із загального простору в 70_000_000.

2022#7, Rust
pub enum FsRecord {
    File(usize),
    Dir(Box<Directory>),
}

use std::collections::HashMap;

pub struct Directory {
    records: HashMap<String, FsRecord>,
}

impl Directory {
    fn new() -> Directory {
        Directory {
            records: HashMap::new(),
        }
    }
    fn add_file(&mut self, path: &[String], size: usize) {
        if path.len() == 1 {
            self.records
                .insert(path[0].to_string(), FsRecord::File(size));
        } else if let Some(FsRecord::Dir(dir)) = self.records.get_mut(&path[0])
        {
            dir.add_file(&path[1..], size);
        }
    }
    fn add_dir(&mut self, path: &[String]) {
        if path.len() == 1 {
            self.records
                .entry(path[0].to_string())
                .or_insert_with(|| FsRecord::Dir(Box::new(Directory::new())));
        } else if let Some(FsRecord::Dir(dir)) = self.records.get_mut(&path[0])
        {
            dir.add_dir(&path[1..]);
        }
    }
    fn get_sizes<P>(&self, func: P) -> (usize, usize)
    where
        P: Fn(usize) -> usize + Clone,
    {
        let mut inner_size = 0;
        let mut inner_filtered = 0;
        for record in self.records.values() {
            match record {
                &FsRecord::File(size) => inner_size += size,
                FsRecord::Dir(subdir) => {
                    let (total, filtered) = subdir.get_sizes(func.clone());
                    inner_size += total;
                    inner_filtered += filtered;
                }
            }
        }
        inner_filtered += func(inner_size);
        (inner_size, inner_filtered)
    }
    fn get_best_size(&self, target: usize) -> (usize, usize) {
        let mut inner_size = 0;
        let mut best = 0;
        for record in self.records.values() {
            match record {
                &FsRecord::File(size) => inner_size += size,
                FsRecord::Dir(subdir) => {
                    let (total, current_best) = subdir.get_best_size(target);
                    inner_size += total;
                    if current_best > target
                        && (best == 0 || current_best < best)
                    {
                        best = current_best;
                    }
                }
            }
        }
        if best == 0 || (inner_size > target && inner_size < best) {
            best = inner_size;
        }
        (inner_size, best)
    }
}

pub fn parse_input(input: &str) -> Directory {
    let mut root = Directory::new();
    let mut path = vec![];
    for instruction in input.lines() {
        if instruction.starts_with("$ cd") {
            match &instruction[5..] {
                "/" => {
                    path.clear();
                }
                ".." => {
                    path.pop();
                }
                name => {
                    path.push(name.to_string());
                    root.add_dir(&path);
                }
            }
        } else if instruction != "$ ls" {
            //executing ls
            let mut instruction = instruction.split_whitespace();
            let typ = instruction.next().unwrap();
            let name = instruction.next().unwrap();
            path.push(name.to_string());
            if typ == "dir" {
                root.add_dir(&path);
            } else {
                root.add_file(&path, typ.parse().unwrap());
            }
            path.pop();
        }
    }
    root
}

pub fn task1(root: &Directory) -> usize {
    root.get_sizes(|size| if size <= 100_000 { size } else { 0 })
        .1
}

pub fn task2(root: &Directory) -> usize {
    let current_size = root.get_sizes(|_| 0).0;
    let unused = 70_000_000 - current_size;
    let needed = 30_000_000 - unused;
    root.get_best_size(needed).1
}

Ще одна штука, яку Rust ненавидить. З тієї ж причини, що й 2022#5. Рекурсію при побудові дуже складно робити, доводиться всі операції з рута починати і повний шлях проходити.
Хоча зараз подумав, що може не все так погано - треба мувати значення з дерева, модифікувати і класти на місце. Можливо. У мене щось голова зовсім не варить, я кілька хвилин не міг правильно вільне місце обчислити, доки не розбив на дві операції:

    let unused = 70_000_000 - current_size;
    let needed = 30_000_000 - unused;

Правда, вчора я добив 2019#10 з арктангенсами, підозрюю, що це саме через нього.

Подякували: dot1

97 Востаннє редагувалося dot (07.12.2022 16:04:33)

Re: Advent of Code

2022#7, Python
import collections, copy


def tree():
    return collections.defaultdict(tree)


filesystem = tree()
path = list()
dirs = set()


def add(keys, value=None, t=filesystem):
    for i, key in enumerate(keys):
        if i == len(keys) - 1 and value:
            continue
        t = t[key]

    if value:
        t[key] = value


def dirSize(keys):
    t = copy.deepcopy(filesystem)
    total = int()

    for k in keys:
        t = t[k]

    for k in t.keys():
        total += t[k] if type(t[k]) == int else dirSize(keys + tuple([k]))

    return total


for line in open("input.txt").read().splitlines():
    match line.split():
        case ["$", "cd", dir]:
            match dir:
                case "..":
                    path.pop()
                case "/":
                    path = ["/"]
                case _:
                    path.append(dir)
                    dirs.add(tuple(path))
                    add(path)
        case ["$", "ls"]:
            pass
        case ["dir", dir]:
            add(path + [dir])
            dirs.add(tuple(path + [dir]))
            pass
        case [size, file]:
            add(path + [file], int(size))


limit: int = 100_000
total_space: int = 70_000_000
need_space: int = 30_000_000
total = int()
for_delete = list()

need_space -= total_space - dirSize(tuple("/"))

for dir in dirs:
    size = dirSize(dir)
    if size < limit:
        total += size
    if size > need_space:
        for_delete.append(size)

print(total)  # Part One: 1325919
print(min(for_delete))  # Part Two: 2050735

Kod povne mêsyvo, treba bude pôdpravyty jakosj.

98 Востаннє редагувалося dot (07.12.2022 16:40:09)

Re: Advent of Code

Kek, moźna bulo bez dereva i rekurcij. I ce ± oćevydno. Tobto nabyrajemo strôćky (abo śćosj take, ale tut najlehśe) i sumujemo vsji strôćky, kotri poćynajutj sja z…

Śće smêśnêśe, śćosj take krutylo sja na jazycê, ale ti rankovi vymyky elektriky — cjoho razu hetj nezvyćni: vkljućaly na 20 xv desj v 2~4 hodyny — mene teź rozumovo dokonaly. Na śćastje, moźlyvo ćerez uspêx perśojê, druha ćastyna bula duźe lehkoju dlja mene, odrazu zdohadav sja pro ce rôvnjannje. I aby bulo śće smêśnêśe, bulo ± podôbna zadaća desj v mynulyx rokax, bo śćosj take pryhaduju i mav same take rêśennje.

Prykald vôd odnoho majstera.

2022#07, Python
    dirsizes = {}
    cwd = '/'
    for line in sys.stdin:
        if m := re.match(r'^\$ cd \.\.$', line):
            cwd, _ = os.path.split(cwd)
        elif m := re.match(r'^\$ cd (\S+)$', line):
            cwd = os.path.join(cwd, m.group(1))
            dirsizes[cwd] = 0
        elif m := re.match(r'^([0-9]+) (\S+)$', line):
            size = int(m.group(1))
            for d in filter(cwd.startswith, dirsizes):
                dirsizes[d] += size

    print(sum(v for v in dirsizes.values() if v <= SIZE_BOUND))
    size_to_delete = SIZE_NEED - (SIZE_DISK - dirsizes['/'])
    print(min(v for v in dirsizes.values() if v >= size_to_delete))

99 Востаннє редагувалося dot (09.12.2022 08:05:42)

Re: Advent of Code

Ne mav elektriky majźe vesj denj abo mav spravy ćy todi ne bulo interneta. Ale ja vstyh zrobyty ce za denj (tak, znaju, śćo pośću vźe pôslja 24, ale ja vźe zapostyv desj v meźax 24). Z sumnoho, zrobleno jak dvê okremi zadaćy. Moźe zhodom sprobuju skombinyty.

2022#8, Python
grid = [[int(x) for x in y.strip()] for y in open("test.txt").readlines()]
onview = [[0 for _ in range(len(grid[0]))] for _ in range(len(grid))]


def measure(m):
    return len(m[0]), len(m)


def rotate(m):
    row, col = measure(m)

    for i in range(row // 2):
        m[i], m[col - i - 1] = m[col - i - 1], m[i]

    for i in range(row):
        for j in range(i):
            m[i][j], m[j][i] = m[j][i], m[i][j]

    return m


for side in range(4):
    i, j = measure(grid)

    for y in range(i):
        tallest = grid[y][0]
        onview[y][0] = 1

        for x in range(j):
            if grid[y][x] > tallest:
                tallest = grid[y][x]
                onview[y][x] = 1
            elif grid[y][x] == 9:
                break
            else:
                continue
    if side == 4:
        break
    grid = rotate(grid)
    onview = rotate(onview)

print(sum(map(sum, onview)))  # Part One: 1543
grid = [[int(x) for x in y.strip()] for y in open("input.txt").readlines()]
hor, ver = len(grid[0]), len(grid)
scenes = [[1 for _ in range(hor)] for _ in range(ver)]


def view(opt: int, length: int, route: int = 1) -> int:
    tallest: int = grid[y][x]
    trees: int = 0
    m = list(zip(*grid) if opt else grid)
    i, j = (x, y) if opt else (y, x)

    for step in range(1, length):
        trees += 1

        if tallest <= m[i][j + step * route]:
            break

    return trees


for y in range(hor):
    for x in range(ver):
        for opts in [(0, ver - x), (0, x + 1, -1), (1, hor - y), (1, y + 1, -1)]:
            scenes[y][x] *= view(*opts)

print(max(map(max, scenes)))  # Part Two: 595080

100

Re: Advent of Code

Умова: є матриця висот дерев у лісі (посадці рівними рядками і стовпчиками).
1. Дерево вважається видимим, якщо вгору, вниз, праворуч чи ліворуч від нього всі нижчі. Знайти кількість дерев, невидимих іззовні лісу.
2. Для кожного дерева вводиться оцінка - добуток відстаней, на які можна подивитися з нього, до найближчого не нижчого дерева чи краю лісу. Знайти дерево з максимальною оцінкою.

2022#8, Rust
pub fn parse_input(input: &str) -> Vec<Vec<i32>> {
    input
        .lines()
        .map(|line| {
            line.chars()
                .map(|c| c.to_digit(10).unwrap() as i32)
                .collect()
        })
        .collect()
}

pub fn task1(trees: &[Vec<i32>]) -> usize {
    let mut count = 0;
    for (y, row) in trees.iter().enumerate() {
        for (x, &h) in row.iter().enumerate() {
            if row[..x].iter().all(|&tree| tree < h)
                || row[x + 1..].iter().all(|&tree| tree < h)
                || trees[..y].iter().all(|row| row[x] < h)
                || trees[y + 1..].iter().all(|row| row[x] < h)
            {
                count += 1;
            }
        }
    }
    count
}

pub fn task2(trees: &[Vec<i32>]) -> usize {
    let mut best = 0;

    for (y, row) in trees.iter().enumerate() {
        for (x, &h) in row.iter().enumerate() {
            let mut score = 1;

            let mut count = 0;
            let mut max = 0;
            for &tree in row[..x].iter().rev() {
                count += 1;
                if tree > max {
                    max = tree;
                }
                if max >= h {
                    break;
                }
            }
            score *= count;

            let mut count = 0;
            let mut max = 0;
            for &tree in &row[x + 1..] {
                count += 1;
                if tree > max {
                    max = tree;
                }
                if max >= h {
                    break;
                }
            }
            score *= count;

            let mut count = 0;
            let mut max = 0;
            for r in trees[..y].iter().rev() {
                count += 1;
                if r[x] > max {
                    max = r[x];
                }
                if max >= h {
                    break;
                }
            }
            score *= count;

            let mut count = 0;
            let mut max = 0;
            for r in trees[y + 1..].iter() {
                count += 1;
                if r[x] > max {
                    max = r[x];
                }
                if max >= h {
                    break;
                }
            }
            score *= count;

            best = std::cmp::max(best, score);
        }
    }
    best
}

Щось у другому з ітераторами перемутив, ну і біс із ним.

Подякували: dot1