From 8b68bf44497695bdf775f89c7c2b4a3681748957 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Fri, 9 Dec 2022 20:23:26 +0100 Subject: [PATCH] 2022 day 7: Bash parts 1 and 2 (messy, tons of debug) --- 2022/day07/README.org | 39 ++++++++++-- 2022/day07/aoc.bash | 139 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 5 deletions(-) create mode 100755 2022/day07/aoc.bash diff --git a/2022/day07/README.org b/2022/day07/README.org index 2ffb875..f6f792b 100644 --- a/2022/day07/README.org +++ b/2022/day07/README.org @@ -118,10 +118,39 @@ files more than once!) Find all of the directories with a total size of at most 100000. /What is the sum of the total sizes of those directories?/ -To begin, [[file:7/input][get your puzzle input]]. +Your puzzle answer was =1390824=. -Answer: +** --- Part Two --- +Now, you're ready to choose a directory to delete. -You can also [Shareon -[[https://twitter.com/intent/tweet?text=%22No+Space+Left+On+Device%22+%2D+Day+7+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F7&related=ericwastl&hashtags=AdventOfCode][Twitter]] -[[javascript:void(0);][Mastodon]]] this puzzle. +The total disk space available to the filesystem is =70000000=. To run +the update, you need unused space of at least =30000000=. You need to +find a directory you can delete that will /free up enough space/ to run +the update. + +In the example above, the total size of the outermost directory (and +thus the total amount of used space) is =48381165=; this means that the +size of the /unused/ space must currently be =21618835=, which isn't +quite the =30000000= required by the update. Therefore, the update still +requires a directory with total size of at least =8381165= to be deleted +before it can run. + +To achieve this, you have the following options: + +- Delete directory =e=, which would increase unused space by =584=. +- Delete directory =a=, which would increase unused space by =94853=. +- Delete directory =d=, which would increase unused space by =24933642=. +- Delete directory =/=, which would increase unused space by =48381165=. + +Directories =e= and =a= are both too small; deleting them would not free +up enough space. However, directories =d= and =/= are both big enough! +Between these, choose the /smallest/: =d=, increasing unused space by +=24933642=. + +Find the smallest directory that, if deleted, would free up enough space +on the filesystem to run the update. /What is the total size of that +directory?/ + +Your puzzle answer was =7490863=. + +Both parts of this puzzle are complete! They provide two gold stars: ** diff --git a/2022/day07/aoc.bash b/2022/day07/aoc.bash new file mode 100755 index 0000000..f60fabb --- /dev/null +++ b/2022/day07/aoc.bash @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# +# aoc.bash: Advent of Code 2022, day 7 +# +# Copyright (C) 2022 Bruno Raoult ("br") +# Licensed under the GNU General Public License v3.0 or later. +# Some rights reserved. See COPYING. +# +# You should have received a copy of the GNU General Public License along with this +# program. If not, see . +# +# SPDX-License-Identifier: GPL-3.0-or-later + +. common.bash + +declare -A files=() # list of files in dir +declare -A sizes=() # file size +declare -A dirs=() # directories +declare -a lines # shell lines +declare -i curline=0 # current line in shell +declare curdir + +print_sizes() { + local idx + echo +++++++++++++++++++ + for idx in "${!sizes[@]}"; do + printf "size(%s)=%d\n" "$idx" "${sizes[$idx]}" + done + echo +++++++++++++++++++ +} + +do_cd() { + local dir="$1" + echo ">>> $curline ${lines[$curline]}" + case "$dir" in + "..") + echo ".. before: $curdir" + curdir=${curdir%/*} + [[ -z $curdir ]] && curdir="/" + echo ".. after: $curdir" + ;; + "/") + curdir="/" + ;; + *) + [[ $curdir != "/" ]] && curdir+="/" + curdir+="$dir" + esac + dirs[$curdir]="$curdir" + echo "> CD $dir newdir=$curdir" +} + +do_ls() { + local info file subdir remain + echo ">>> $curline ${lines[$curline]}" + ((curline++)) + while [[ $curline -lt ${#lines[@]} && ${lines[$curline]:0:1} != "\$" ]]; do + read -r info file <<< "${lines[$curline]}" + files[$curdir]+="$file" + if [[ $info != dir ]]; then # file + remain="$curdir/$file" + remain=${remain//+(\/)/\/} + #sizes[$fullname]=$info + # recurse up curdir and adjust sizes + #subdir=${curdir} + echo "info=$info [$remain]" + while [[ -n $remain ]]; do + echo "remain=$remain subdir=$subdir" + ((sizes[$remain] += info)) + remain=${remain%/*} + subdir=${remain##*/} + echo " -> remain=$remain subdir=$subdir" + done + (( sizes["/"] += info )) + fi + echo "ls: ${lines[$curline]}" + ((curline++)) + done + ((curline--)) + print_sizes +} + +parse() { + readarray -t lines + curline=0 + declare -a line + + while ((curline < ${#lines[@]})); do + read -ra line <<< "${lines[$curline]}" + if [[ "${line[0]}" != "\$" ]]; then + printf "ERROR line %d = %s\n" "$curline" "${lines[$curline]}" + exit 1 + fi + case "${line[1]}" in + "cd") + do_cd "${line[2]}" + ;; + "ls") + do_ls + ;; + esac + ((curline++)) + printf "WARNING curline=%d\n lines=%d\n" "$curline" "${#lines[@]}" + done +} + +solve() { + declare -ig res + local part="$1" dir mindir="/" + local -i needed + + if ((part == 1)); then + for dir in "${dirs[@]}"; do + printf "size(%s)=%d\n" "$dir" "${sizes[$dir]}" + if ((sizes[$dir] <= 100000 )); then + ((res+=sizes[$dir])) + fi + done + else + (( needed = sizes["/"] - (70000000-30000000) )) + printf "remain=%d\n" "$needed" + ((res = sizes["/"])) + for dir in "${!dirs[@]}"; do + #printf "size(%s)=%d\n" "$dir" "${sizes[$dir]}" + if (( sizes[$dir] >= needed )); then + printf "dir %s (%d) will free enough res=%d\n" "$dir" "${sizes[$dir]}" "$res" + if (( sizes[$dir] <= res )); then + mindir=$dir + ((res = sizes[$mindir])) + printf "new mindir=%s (%d)\n" "$mindir" "$res" + fi + fi + done + + fi +} + +main "$@" +exit 0