(yes, yes, i know, sorry, &c., i consider my family doing aoc to be shitlord code golf opportunity for me; i didn't edit anything to be less embarrassing, either, sorry)
anyway: the input is, uhhh (abridged)
$ cd /
$ ls
dir bcfwbq
71582 wrqbm
$ cd bcfwbq
$ ls
...
doesn't the ls look like a really shit du -bad0 (trick question: it is); the problem statement is du-like as well..... well, that (a) sounds like hell, and (b) if only I had a du implementation!
and (c).. if only I had a filesystem implementation? oh wait.
given that the input is quite degenerate, how's about.....
exec < input
while read -r l; do
case "$l" in
"$ cd /"*) cd /tmp/aoc ;;
"$ cd "*) cd "${l#"$ cd "}" ;;
"$"*) ;;
"dir "*) mkdir -p "${l#"dir "}" ;;
[0-9]*) truncate -s "${l% *}" "${l#* }" ;;
*) echo waaaaaa "$l" ;;
esac
done
three tries (first i transposed the " and * in the dir case, the second because i designated my test variable a, not l for the truncate, and didn't fix it after pasting). pretty good
du -b /tmp/aoc/ | while read a b; do [ $a -le 100000 ] && echo $a $b; done | awk '{print $1}' | paste -sd+ | bc is the result for part one (sum of the sizes of all directories smaller than 100000), except that's too big, because both tmpfs and zfs return non-zero apparent sizes for directories. there's probably some filesystem that doesn't, but, well. here's diff -w:
diff --git a/cmd/du.cpp b/cmd/du.cpp
index 59110f95..fb0a691e 100644
--- a/cmd/du.cpp
+++ b/cmd/du.cpp
@@ -416,9 +416,12 @@ int main(int argc, const char * const * argv) {
return std::fprintf(stderr, "%s: %s\n", argv[0], std::strerror(errno)), err = true, true;
- for(auto && ent : fts)
+ bool isdir;
+ for(auto && ent : fts) {
+ isdir = false;
switch(ent->fts_info) {
case FTS_D:
+ isdir = true;
if(crosses_devices(ent) || // fts(3), even with FTS_XDEV, still yields the top-level directory
was_seen(ent->fts_statp->st_dev, ent->fts_statp->st_ino) || is_excluded(ent->fts_path))
ent.set(FTS_SKIP), ent->fts_flags |= FLAG_SKIPPED;
@@ -430,12 +433,14 @@ int main(int argc, const char * const * argv) {
break;
case FTS_DP:
+ isdir = true;
if(ent->fts_flags & FLAG_SKIPPED)
break;
goto comm;
case FTS_DNR:
+ isdir = true;
if(crosses_devices(ent) || // fts(3), even with FTS_XDEV, still yields the top-level directory
was_seen(ent->fts_statp->st_dev, ent->fts_statp->st_ino) || is_excluded(ent->fts_path))
break;
@@ -472,6 +477,7 @@ int main(int argc, const char * const * argv) {
{
fullsize_t cur{};
+ if(!isdir)
switch(output_field) {
case output_field_t::blocks: {
cur.val = ent->fts_statp->st_blocks;
@@ -512,6 +518,7 @@ int main(int argc, const char * const * argv) {
case FTS_NSOK:
__builtin_unreachable(); // we don't spec FTS_SEEDOT nor FTS_NOSTAT
}
+ }
if(exclude_from && fts.close() == -1) // catastrophic: because we walk one directory at a time with --files0-from=
// failure to return to the original working directory invalidates all subsequent paths
and that's correct now
part 2 asks for the first directory of size at least expr 30000000 - \( 70000000 - 41518953 \) (where the latter is the size of /tmp/aoc), which is the first line from
/tmp/du -b /tmp/aoc/ | sort -n | while read a b; do [ $a -ge 1518953 ] && echo $a ; done
(or, all my shitlords know, just exec echo; the single hardest part of this was arriving at the limit condition)
anyway, sorry for party rocking, i thought it was funi
