#AoC 2022 | Day 7 | Solutions & Spoilers

1 messages · Page 2 of 1

queen breach
#

idk why i can combine s and d assignments, but it worked

last flower
#

Does it work? That would make s and d reference the same list

queen breach
#

yeah, it somehow works

#

and i have no idea why

#

my best guess is that one of them is reassigned somewhere

inner ingot
#

you also reassign it again on line 4, so maybe you got lucky

last flower
#

I think i just got stuck in an infinite loop for my input

#

nvm, you're using stdin for input

queen breach
#

nvm i counted wrong

#

that was line 5, not line 4

queen breach
#

nothing < 10k before my first cd ..

high bane
#

min(_ for _ in d if _>sum(s)-4e7)
min(filter((sum(s)-4e7).__gt__,d)
😔

#

gt or ge idk

inner ingot
queen breach
#

or rather, your min is missing that

high bane
#

rip

viscid sail
#

it does work

rancid heath
viscid sail
royal axle
#

absolute trash

queen breach
#

it's input dependent

royal axle
#

i put all paths in string form /abc/def/ghi/.../ and than build with that a dict

queen breach
#

and i think it's plausible that there's an input which doesn't work

rancid heath
queen breach
#

yeah

viscid sail
high bane
#

no u

queen breach
#

gotem

viscid sail
cunning wraith
#

My solution: ```python
class File:
def init(self, name, size):
self.name = name
self._size = size

def size(self):
    return self._size

def __repr__(self):
    return f"{self.name}"

class Directory:
def init(self, name):
self.name = name
self.children = {}

def get_dir(self, dirname):
    if dirname not in self.children:
        self.children[dirname] = Directory(dirname)
        
    return self.children[dirname]

def add_file(self, file):
    self.children[file.name] = file

def walk_dirs(self):
    yield self
    for child in self.children.values():
        if isinstance(child, Directory):
            yield from child.walk_dirs()

def __repr__(self):
    return f"{self.name}/{self.children}"

def size(self):
    return sum(child.size() for child in self.children.values())

root = Directory("root")
working_dir = [root]

for instruction in data.split("\n"):
if instruction.startswith("$ cd"):
dirname = instruction.removeprefix("$ cd").strip()
if dirname == "/":
working_dir = [root]
elif dirname == "..":
working_dir.pop()
else:
working_dir.append(working_dir[-1].get_dir(dirname))
elif instruction[0].isdigit():
size, name = instruction.split()
working_dir[-1].add_file(File(name, int(size)))

total = 0
for directory in root.walk_dirs():
size = directory.size()
if size <= 100000:
total += size
print("Part 1:", total)

remaining = 70000000 - root.size()
needed = 30000000 - remaining
possible = []
for directory in root.walk_dirs():
size = directory.size()
if size >= needed:
possible.append(size)
print("Part 2:", min(possible))

cunning wraith
#

not sure, I did it a few hours ago and wasn't going for speed though.

elder bolt
#

I've seen a few solutions utilizing a type of directory class for this problem, wondering if I want to do a second solution using a class

inner ingot
#

i want to make a solution that simulates it on an actual file system

cunning wraith
#

I thought of doing that haha

viscid sail
wheat cradle
high bane
#

if its not gt its gotta be lt

inner ingot
royal axle
#

Working with the parsed stuff was ez

wheat cradle
#

um

#

okay

queen breach
#

ok

#

imagine getting skill diffed by input parsing trolllaugh

hallow ether
#

I really want to do a 100% bash solution to this one

cunning wraith
#

although the filesystem is 70mb (taking 1 size as 1 byte) so should be fine

inner ingot
soft hatch
queen breach
#

isn't size stored in metadata

#

or am i remembering wrong

inner ingot
soft hatch
#

oh wait, I thought you were talking input files

#

my bad

inner ingot
#

wait what

#

ohhh, you thought 1tb long input

#

also, i am woefully inexperienced with linux stuff. can you spoof file metadata to show a file size without actually storing that amount of data

cunning wraith
#

Not sure, although you could always implement a custom filesystem to let you do that 🙃

inner ingot
#

oh yeah. i've been wanting to do something like that tbh

tough hinge
queen breach
#

💀

tough hinge
#

Was going to write the size as text inside the file and everything

queen breach
#

lol

tough hinge
queen breach
#

do you though?

soft hatch
#

the input follows a dfs order

queen breach
#

just stuff it into a list

tough hinge
soft hatch
#

you don't actually need to keep track of names

queen breach
bronze jewel
#

I cannot even remember if I did a DFS. Just remember using match

soft hatch
#

a stack to track the sizes

#

that's all you really need

queen breach
#

ye

inner ingot
#

i didn't want to assume that while solving though

tough hinge
#

I wrote a whole three classes

#

Done turned into Tom

queen breach
#

overengineering

tough hinge
#

That's my specialty!

soft hatch
viscid sail
#

numpy would still destroy this. atleast the print part

soft hatch
#

(+ some files in there)

queen breach
#

my specialty is underengineering KarenLMAO

#

works for golf though

inner ingot
soft hatch
#

if I wrote the task I would have been the asshole adding some duplicate directory visits to input data

tough hinge
queen breach
#

why would i do that for lc easies?

tough hinge
rancid heath
queen breach
#

skill diffed by duplicate names 😔

slow oriole
#

me who didnt even encounter such problem

queen breach
#

my problem was the dumbest

rancid heath
#

I had double-counting issues resulting as the manifestation of a different bug

slow oriole
#

⭐ n o d e s ⭐

rancid heath
#

So I used nested dictionaries instead of just keeping track

queen breach
#

for p1

slow oriole
#

are leaf nodes something different

rancid heath
#

Leaf nodes are files

#

As opposed to directories

slow oriole
#

oh

bronze jewel
#

I just used a defaultdict with the paths and total size

slow oriole
#

then what is the term for directory

rancid heath
wheat cradle
inner ingot
bronze jewel
#

Ooof.
First attempt for me didn't either. Then I realised that I was counting dirs etc only once (basically left out the brackets part in the question)

#

Anyone got a node version that I can peek at?

slow oriole
#

my node class
basically self.sum contains sum of file size in the uppermost level i.e that dir itself , and total just adds up the sum of internals

class node:
    def __init__(self,c,p):
        self.curr = c
        self.parent = p
        self.v = {}
        self.sum = 0
    @property
    def total(self):
        return self.sum + sum(i.total for i in self.v.values() if isinstance(i,node)) 
slow oriole
#

okay

rancid heath
#

(mypy doesn't like recursive type aliases but Pylance is fine with them)

slow oriole
#

my pylance is disturbing

#

i beat the shit out of it

rancid heath
#

If you want me to send the repo link again I can

#

(I posted it way earlier at the beginning of the thread too lmao)

bronze jewel
#

I can do a search

slow oriole
#

TIL you can just put a # type: ignore for ignoring pylance

rancid heath
soft hatch
#

I wonder what the first problem that actually requires some compute power will be

rancid heath
bronze jewel
#

That is easier.... The search is being wack on my phone

slow oriole
#

the problem was match case

rancid heath
slow oriole
#

the warnings were wrong

slow oriole
rancid heath
#

If it's at the end of a parenthesised statement, it's disabled for the whole statement; if it's on (e.g.) a single parameter it disables only that expression

soft hatch
rancid heath
#

Usually when a type-hint somewhere is wrong

#

Sometimes when self is involved

soft hatch
#

usually the warnings are right, but in an annoying and pedantic way

weak mauve
#

technically correct

#

unexpected EOF

hollow trail
#

need some help 🥲

day_input = day_input.strip().split('\n')
path = Path()
size_map = defaultdict(int)
line = 0
size_map[''] = 0

while line < len(day_input):    
    out : list[str] = day_input[line].split(' ')

    match out[1]:
        case 'cd':
            path = (path / out[2]).resolve()
        case 'ls':
            tline = line+1
            while tline < len(day_input) and not day_input[tline].startswith('$'):         
                if (size := day_input[tline].split(' ')[0]).isnumeric():
                    size_map[path.stem] += int(size)  # add size of file to parent dir                
                tline += 1
            size_map[path.parent.name] += size_map[path.stem]  # add size of file to parent of parent dir
            line = tline - 1
    
    line += 1

print(sum([i for i in size_map.values() if i <= 100000]))


soft hatch
#

I hate pylint with a passion

hollow trail
#

gives incorrect ans on p1

slow oriole
#

just set a break point and use a debugger (not formatting related ofc)

tough hinge
#

OMD you're actually using pathlib

queen breach
#

formatters are cool though

#

black is nice when i'm not golfing

slow oriole
#

yeah

cunning wraith
#

I don't mind some linters, but pylint is way too picky imo

slow oriole
#

black is nice

bronze jewel
#

Black is great

queen breach
#

the only lints i have are type hinting and style lints

bronze jewel
#

The default linter for pycharm is.... Augh.... Painful

queen breach
#

don't use pycharm so can't relate

soft hatch
slow oriole
tough hinge
#

yep

queen breach
slow oriole
#

dang

queen breach
#

otoh i like black's choices

soft hatch
#

formatters in general are good though

soft hatch
hollow trail
queen breach
rancid heath
soft hatch
weak meadow
#

is everyone else ignoring ls too, or did you guys build proper parsers?

queen breach
#

i stick to " because that way it's consistent between all langs

slow oriole
bronze jewel
#

turns on PC to then accidentally turn it off again....

weak mauve
queen breach
soft hatch
queen breach
#

¯_(ツ)_/¯

#

i like it when my habits from 1 lang translate well to others

teal rune
queen breach
#

quotes is one example of that

rancid heath
slow oriole
#

am i the only one who split by '$'

hollow trail
slow oriole
soft hatch
#

black's inability to run on part of a file is pretty annoying

rancid heath
weak mauve
rancid heath
#

Also blacken is a thing

tough hinge
#

And blacken docs

bronze jewel
#

One thing about a linter I previously used was the removing of imports when I decided to comment out code or remove it.... And no auto import

tough hinge
#

Because black=good

rancid heath
cunning wraith
#

(or, do you?)

weak mauve
tough hinge
weak mauve
#

it only makes a difference if the name contains a dot.

tough hinge
#

What does it actually do?

weak mauve
#

the stem is the name without the suffix

hollow trail
weak mauve
#

"data.tar" + ".gz" == "data.tar.gz"

hollow trail
#

yh ik

soft hatch
rancid heath
soft hatch
#

I've never had issues context switching between langs, but maybe that's just me

rancid heath
#

*helped me learn

#

Not context switching so much as habit while learning

inner ingot
#

when switching from python to other langs i sometimes mess up : and {} but it only takes like 1 error to full switch over

cunning wraith
rancid heath
#

kekw

soft hatch
#

I find " visually noisier than ' when reading code pithink

queen breach
#

valid

inner ingot
#

hmm. i kinda just gloss over it

queen breach
#

i find " more familiar

soft hatch
rancid heath
#

I tend to read '' as 'internal string' and "" as 'external string'

#

Or 'might be printed'

queen breach
#

i only use ' when inside another string, when golfing, or when writing code quickly

inner ingot
soft hatch
#

I only use " if it makes the string have less escaping 😛

queen breach
#

oh escaping

#

that too

#

i usually don't need quotation marks in my strings though, so that's rare

rancid heath
#

Honestly I just use ' because it's easier to type than shift-2 (") and then I let black normalise it

cunning wraith
#

I could probably argue that I preferred one over the other visually but then again I'm able to ignore the red squiggly lines from pylance all over my code so I can't really speak lol

rancid heath
#

It does cause me to sometimes syntax-error in languages that care though lol

inner ingot
queen breach
#

lol

rancid heath
viscid sail
#

😩 can't get any lesser. Have been trying since an hour and a half now. I guess 190 is the limit.

soft hatch
#

even on US ' is easier, no?

queen breach
#

yeah

little wedge
inner ingot
little wedge
#

intrusively linked structs be gaming

queen breach
#

i think joe had the qualifier use uk spelling and i opened a pr fixing the "esoteric spelling"

soft hatch
#

have you seen swedish layout? typing []{} is terrible

rancid heath
rancid heath
#

I don't mind having a few of the inputs posted, please don't go on a quest to collect many or all of the inputs for every puzzle.
I read this as meaning 'a couple of repos is probably fine but don't go looking'

queen breach
#

(realizing that i spelt the word wrong genuinely was the most time consuming part of the quali though)

hollow trail
#

ok ty jenna
doing it with pathlib was fun

day_input = get_input(7)
day_input = day_input.strip().split('\n')
path = Path()
size_map = defaultdict(int)
dir_map = defaultdict(list)
line = 0
while line < len(day_input):    
    out : list[str] = day_input[line].split(' ')

    match out[1]:
        case 'cd':
            path = (path / out[2]).resolve()
            if out[2] != '..':
                dir_map[str(path.parent)].append(str(path))
 
        case 'ls':
            tline = line+1
            while tline < len(day_input) and not day_input[tline].startswith('$'):         
                if (size := day_input[tline].split(' ')[0]).isnumeric():
                    size_map[str(path)] += int(size)  # add size of file to parent dir                
                tline += 1
            for parent in path.parents:
                size_map[str(parent)] += size_map[str(path)]  # add size of file to parent of parent dir
            line = tline - 1
    
    line += 1
print(sum([i for i in size_map.values() if i <= 100000]))  # p1
remaining = 70000000 - size_map['/']
print(min(i for i in size_map.values() if remaining + i >= 30000000))  #p2
rancid heath
hollow trail
#

yes

queen breach
#

i don't think pathlib is efficient in terms of characters

#

especially since you don't need the paths at all

hollow trail
#

ehhh i didnt do it for efficiency

#

i did for fun

queen breach
#

that is invalid, code golf is the only way

hollow trail
#

forgive me for i have sinned

#

i shall come back to the correct "path"

slow oriole
#

no

queen breach
#

no you don't need any path

slow oriole
#

yes

hollow trail
#

bruhhh

#

it was a joke

queen breach
#

saw the pun from a mile away

#

dw, we got it

hollow trail
#

hahahha

slow oriole
#

if i didnt sleep rn

#

i will again wake late

#

and see some super golfed code of day 8

queen breach
#

lol

#

i just wait for artemis to post an initial golf, then for cef to completely ignore it and post a better one

#

and then i snipe the last few chars

slow oriole
#

oh

#

so artemis is the root

#

thanks for the intel

#

/j

teal orchid
#

Could someone help me understand why this error is happening? Will probably need to show more code. Trying to recursively update the size of the parent directory when we add a new file

def set_folder_size(self, file_size):
  self.size += file_size
    if self.parent is not None:
      self.get_folder(self.parent).set_folder_size(file_size)

AttributeError: 'NoneType' object has no attribute 'set_folder_size'

#

Im not sure why this isnt being caught by my None check

weak mauve
#

yes, what does get_folder?

#

probably get_folder does only know about subfolders.

teal orchid
#

Im returning None somwhere, somehow

def get_folder(self, target):
  if self.name == target:
    return self
  elif self.subfolders:
    for f in self.subfolders:
      sf = f.get_folder(target)
      if sf: return sf
return None    
teal orchid
rancid heath
#

It's not in a subfolder

tough hinge
#

Then you can start excepting [and/or printing] various crap from there
Even better with a debugger

weak mauve
#

Maybe it is in a subfolder. But not in every subfolder.

#

So depth-first-search doesn't work.

teal orchid
#

but my point is shouldnt if self.name == target return self return the object before it starts DFSing?

#

since Im directly passing it the name of the object i want

viscid sail
#

is this match-case thingy new in python3.10?
Also, what's the folder variable

rancid heath
teal orchid
#

its not

#

its ValueError: /

#

which doesnt have a parent

#

but that should be caught by None

rancid heath
viscid sail
teal orchid
# weak mauve so self.name == self.parent?

in this case:

def set_folder_size(self, file_size):
  self.size += file_size
    if self.parent is not None:
      self.get_folder(self.parent).set_folder_size(file_size)

I am just passing the parent of the current folder to update the parents size as well

viscid sail
weak mauve
teal orchid
#

Ah shit yeah

#

Should be self.parent.get_folder()?

weak mauve
#

That doesn't seem to make sense either. But I'm not sure.

rancid heath
weak mauve
#

is target a string?

#

it's compared to self.name.

#

is self.parent a string?

viscid sail
#

422 => 190
Before and after

#

golfed!

weak mauve
#

much better lemon_smile

teal orchid
weak mauve
#

no idea how the class looks like.

#

or how it's used.

#

from your latest snippets it would be if self.parent: self.parent.set_folder_size(file_size)

teal orchid
#
class Folder(object):
    def __init__(self, name, parent=None):
        self.name = name
        self.size = 0
        self.parent = parent
        self.subfolders = []
        self.files = []

    def __repr__(self):
        return f"{self.name, self.size, self.parent, self.subfolders, self.files}"

    def add_subfolder(self, folder):
        self.subfolders.append(folder)

    def add_file(self, file):
        self.files.append(file)

    def get_folder(self, target):
        if self.name == target:
            return self
        elif self.subfolders:
            for f in self.subfolders:
                sf = f.get_folder(target)
                if sf: return sf
        raise ValueError(target)    

    def get_parent_name(self):
        return self.parent

    def set_folder_size(self, file_size):
        self.size += file_size
        if self.parent is not None:
            self.get_folder(self.parent).set_folder_size(file_size)
#

parent is just a string

#

which is why i have the get_folder function

rancid heath
#

Just objectively better

teal orchid
#

would that just be

self.parent = Folder()
rancid heath
#

When constructing a folder instead of parent.name, pass parent

weak mauve
#

not just objectively better. it's the only way.™️

rancid heath
#

root = Folder('/')
tmp = Folder('tmp', root)

rancid heath
#

Possible, just objectively worse

faint lava
#

day 7 seems like it's one you could do a lot easier if you just strip out the fun parts and don't treat it like a file structure.

teal orchid
rancid heath
#

Yes

faint lava
#

I don't think my solution was optimal, but I like the way it came out, and I got to play with match/case.

weak mauve
#

hm.. yes, or store all folders globally. :think:

clear herald
#

I am currently trying and failing to create a dictionary to re-create the file structure and I think this is hurting me more than helping

queen breach
#

skill diff

weak mauve
#

or store subfolders as a dict. so you can add a .. to the parent.

queen breach
#

just store the path as a tuple or something

rancid heath
queen breach
#

that's what i did for my first try

rancid heath
#

I had a special case for .. lmao

queen breach
#

who didn't?

rancid heath
#

Just found the relevant path every time because .. was pain

#

Kinda tempted to go make a proper shell and then make it runnable as a shell for like a visualisation thing

faint lava
teal orchid
#

So I changed the class to

class Folder(object):
    def __init__(self, name, parent=None):
        self.name = name
        self.size = 0
        self.parent = Folder()
        self.subfolders = []
        self.files = []
Traceback (most recent call last):
  File "main.py", line 49, in <module>
    root = Folder('/')
  File "main.py", line 5, in __init__
    self.parent = Folder()
TypeError: __init__() missing 1 required positional argument: 'name'

Why is it trying to make a parent if theres a default argument None?

weak mauve
#

But with a .. in the subfolders you would have to special case it when traversing the subfolders. PES_Think

queen breach
#

there's also the dangerous approach of actually making the files and stuff

faint lava
queen breach
#

Fix files being too small

rancid heath
#

Yes

queen breach
#

it's lipsum

weak mauve
#

I hope they accounted for the fs overhead.

rancid heath
rancid heath
teal orchid
#

i think im just lost now lol

hollow trail
clear herald
hollow trail
queen breach
#

it's kind of a safe approach, if you know part 2 beforehand

clear herald
queen breach
#

skill issue

faint lava
clear herald
queen breach
teal orchid
faint lava
rancid heath
#

Where are you currently making Folders?

faint lava
#

or pass in the parent.

rancid heath
teal orchid
#

preemptively apologizing for the war crime of code you are about to witness

#
root = Folder('/')
for c in commands:
    if 'cd' in c.split() and c.split()[2] != '..':
        curr_dir = c.split()[2]
    elif 'cd' in c.split() and c.split()[2] == '..':
        curr_dir = root.get_folder(curr_dir).get_parent_name()
    elif not c.startswith('$'):
        if 'dir' in c.split():
            new_folder = Folder(c.split()[1], parent=root.get_folder(curr_dir))
            root.get_folder(curr_dir).add_subfolder(new_folder)
        else:
            new_file = File(c.split()[1], int(c.split()[0]))
            root.get_folder(curr_dir).add_file(new_file)
            root.get_folder(curr_dir).set_folder_size(new_file.get_size())
#

it gets all the data!

rancid heath
#

new_folder = Folder(c.split()[1], parent=root.get_folder(curr_dir))
Change this to new_folder = Folder(c.split()[1], parent=curr_dir)

#

May also need to change curr_dir to be a Folder

teal orchid
#

but curr_dir is just a string

#

yeah

rancid heath
#

I'm guessing that when you update curr_dir you're doing something involving .name or root?

cedar trout
# teal orchid ```py root = Folder('/') for c in commands: if 'cd' in c.split() and c.split...
def parse_directories(data: list[str]) -> FileSystem:
    file_system = None
    for line in data:
        match line.split():
            case ["$", "cd", dir_]:
                if file_system is None:
                    file_system = FileSystem(dir_)
                else:
                    file_system.cd(dir_)
            case ["dir", dir_name]:
                file_system.add_dir(dir_name)
            case [size, _] if size.isnumeric():
                file_system.add_content(int(size))
            case _:
                pass
    return file_system

I did it with patter matching, works really nicely for this one

sonic lark
# queen breach skill issue

this kind of repeated messaging isn't really in line with our code of conduct and the type of atmosphere we like to have in the server. Even if you mean it jokingly, it's coming across as rather mean spirited.

faint lava
faint lava
#

Anyone else abuse namedtuple to make classes?

class Dir(namedtuple('Dir', 'name folders files parent')):

and later:

        case ['dir',f]   : curr.folders[f] = Dir(f, {}, [], curr)
rancid heath
#

Didn't really see a need for classes

#

Haven't at all yet so far, actually

twin prawn
rancid heath
#

Usually don't end up with any across the whole event

#

Although I did for intcode

rich aspen
faint lava
rich aspen
#

I mean, it's pretty similar to namedtuple too of course.

faint lava
rancid heath
#

I like dataclass better because it's properly typed

faint lava
rancid heath
#

Meant for AOC lol

#

I do use classes when they make sense for other bits of Python

#

Also TypedDict is quite nice

faint lava
#

I suppose my code gets a little cleaner if I treat files as directories with no children

lucid pike
#

I like attrs

rancid heath
#

attrs?

lucid pike
#

Yes, it's a great third-party package for class generation

#

dataclasses were in part inspired by attrs

clear herald
rancid heath
#

Why use a list and not just directly nest contents?

#

You can do a postprocessing step to reduce each one down to a size

#

(||it'll also help you for part 2||)

clear herald
#

I'm currently iterating over each ls line and either creating a temporary "sub folder" or appending a file size

cedar trout
#

why is the subfolder temporary?

clear herald
#

So that I can then continue to the next command in the parsed input

queen breach
#

just track the pwd

#

and add directly to that

cedar trout
#

yeah, I had a FileSystem class that tracked the root directory and the pwd

rancid heath
#

IMO the easiest way of solving the puzzle is to make parsing code that generates something like {'a': {'e': {'i': 584}, 'f': 29116, 'g': 2557, 'h.lst': 62596}, 'b.txt': 14848514, 'c.dat': 8504156, 'd': {'j': 4060174, 'd.log': 8033020, 'd.ext': 5626152, 'k': 7214296}}

#

Which can be done without too much pain

#

As long as you don't make a typo in your cd code 🙃

rancid heath
queen breach
#

present working directory

teal orchid
rancid scaffold
teal orchid
rancid heath
teal orchid
#

when I do Folder(curr_dir) its not calling a constructor?

rancid heath
rancid heath
elder bolt
bronze jewel
# viscid sail is this match-case thingy new in python3.10? Also, what's the folder variable

Yes, new in 3.10
The folder variable in the match-case I take it? That is for when there is a line for the dir <dir_name> that exists. Also, the code does crash with the popping of the empty list, but that can easily be handled with a try-catch. But is does not really matter due to the fact that is solves aoc-generated inputs. if the input was manually generated, why would you start with cd .. or go any further back than the most parent directory? (just me thinking while typing 😉 )

rancid heath
#

I had a postprocess step that transformed to that

teal orchid
#

so I have all that, now just another stupid None AttributeError

#

somehow

viscid sail
bronze jewel
#

really?

elder bolt
#

Here's my parsing. Not the cleanest, but creates the structure I show and I believe would be the easiest

def get_input():
    """Get and parse the input."""
    f = open('day7/input.txt', 'r')
    raw = f.read().strip()
    lines = [line for line in raw.split('\n')]

    dir_tree = {}
    current_dir = []

    for line in lines:
        command = line.split(' ')
        if command[0] == '$':
            if command[1] == 'cd':
                if command[2] == '..':
                    current_dir.pop()
                else:
                    current_dir.append(command[2])
        else:
            if command[0].isdigit():
                for i in range(len(current_dir)):
                    dir = '/'.join(current_dir[0:i+1])
                    if dir in dir_tree:
                        dir_tree[dir] += int(command[0])
                    else:
                        dir_tree[dir] = int(command[0])

    return dir_tree
bronze jewel
#

popping the issue?

elder bolt
#

Should update to 3.10 so I can use case

#

And... should not be using dir as a variable

rancid heath
#

Update to 3.11

#

It's just faster than 3.10 in most cases

bronze jewel
#

also, does just x.split() by default split on whitespaces?

rancid heath
#

Optimising interpreter :)

bronze jewel
#

i am too lazy to change to 3.11 now

rancid heath
bronze jewel
#

might just stick with 3.10.5

elder bolt
#

Ah, for some reason I thought it just splits all characters by default

teal orchid
#
root = Folder('/')
for c in commands:
    if 'cd' in c.split() and c.split()[2] != '..':
        curr_dir = c.split()[2]
    elif 'cd' in c.split() and c.split()[2] == '..':
        curr_dir = root.get_folder(curr_dir).get_parent_name()
    elif not c.startswith('$'):
        if 'dir' in c.split():
            new_folder = Folder(c.split()[1], parent=Folder(curr_dir))
            root.get_folder(curr_dir).add_subfolder(new_folder)
        else:
            new_file = File(c.split()[1], int(c.split()[0]))
            root.get_folder(curr_dir).add_file(new_file)
            root.get_folder(curr_dir).set_folder_size(new_file.get_size())
Traceback (most recent call last):
  File "c:\Python\AdventOfCode\day7\day.py", line 55, in <module>       
    curr_dir = root.get_folder(curr_dir).get_parent_name()
  File "c:\Python\AdventOfCode\day7\day.py", line 28, in get_parent_name
    return self.parent.name
AttributeError: 'NoneType' object has no attribute 'name'

Somehow the parent isnt getting set

#

this is just a mess now lol

rancid heath
#

That's what the list contructor does

#

Or unpacking it

viscid sail
elder bolt
#

Unpacking was something new I learned by reading these chats xD

rancid heath
#

(and that folder has no parent)

teal orchid
#

yeah

#

isnt that what i was confused about earlier

rancid heath
#

What you want instead of curr_dir = c.split()[2] is curr_dir = curr_dir.get_folder(c.split()[2]) (assuming that that call returns a Folder... it does, right?)

#

And if it's .. you just curr_dir = curr_dir.parent

#

Then after you define the root, just set curr_dir = root

#

Now curr_dir is a Folder that you can just directly interact with instead of finding it by name from the root every time

#

And Folder.parent is also a Folder (or None, but then you have other problems) that you can just interact with

teal orchid
rancid heath
#

It's only if the cd dir starts with / that you need a special case (that's an absolute path and you need to set curr_dir = root before trying to cd there)

rancid heath
#

Only if it starts with a / is that the right behaviour

#

cd foo = find foo in the current directory i.e. curr_dir.get_folder('foo')

warped kraken
#

hi guys

#

i coded a solution for part 1

#

and it works on the test data

#

but not on my input data

#

it's erroring for the input data

#

i'll post

#

but it's very messy

bronze jewel
#

Also Guitar, that first if-statement is a bit redundant. Can be removed (from looking at the code, doesn't look like ls will be an issue either)

teal orchid
rancid heath
#

But also set curr_dir to root immediately after creating root

#

Don't wanna use unbound variables by accident 🙃

warped kraken
#
text = open(r"C:\Users\ollys\Documents\AOC Files\2022 #7.txt", "r").read().splitlines()

curfolder = ""
tree = {}

for line in range(len(text)):
    stepfd = 1
    if text[line][0] == "$" and text[line][2] == "c":
        #cd
        if text[line][5] != ".":
            #cd directory (not cd ..)
            curfolder = text[line][5:]
    if text[line][0] == "$" and text[line][2] == "l":
        #ls
        tree[curfolder] = []
        array = []
        while text[stepfd + line][0] != "$":
            array.append(text[stepfd + line])
            stepfd += 1
        tree[curfolder] = array

def hasnodirs(dir):
    for item in tree[dir]:
        if item[0].isdigit():
            return(dir)
        else:
            return(False)

#directories that only contain files (no other directories)

def getfilesize(folder):
    total = 0
    for file in folder:
        for char in range(len(file)):
            if file[char] == " ":
                endofnum = char
                break
        total += int(file[:endofnum])
    total = str(total) + " "
    return total


def searchandreplace():
    for dir in tree:
        for item in range(len(tree[dir])):
            if tree[dir][item].startswith("dir"):
                dirname = tree[dir][item][4:]
                for finaldir in range(len(finaldirs)):
                    if dirname == finaldirs[finaldir]:
                        tree[dir][item] = finaldirsizes[finaldir]
                        break

foldersizes = {}

while not hasnodirs("/"):
    finaldirs = []
    finaldirsizes = []

    for dir in tree:
        if hasnodirs(dir):
            finaldirs.append(dir)


    for finaldir in finaldirs:
        finaldirsizes.append(getfilesize(tree[finaldir]))

    for i in range(len(finaldirs)):
        foldersizes[finaldirs[i]] = finaldirsizes[i]

    searchandreplace()

part1tot = 0

for dirsize in foldersizes:
    if int(foldersizes[dirsize]) <= 100000:
        part1tot += int(foldersizes[dirsize])

print(part1tot)
#

sry for destroying chats

#

but does anyone know why this only works for test data?

teal orchid
viscid sail
rancid heath
#
if 'cd' in c.split():
  if c.split()[2] == '/': curr_dir = root
  elif c.split()[2] == '..': ...
teal orchid
#

yeah thats where im up to now

root = Folder('/')
for c in commands:
    if 'cd' in c.split():
        if c.split()[2] == '/':
            curr_dir = root
        if c.split()[2] != '..':
            curr_dir = curr_dir.get_folder(c.split()[2])
        if c.split()[2] == '..':
            curr_dir = curr_dir.parent
    elif not c.startswith('$'):
        if 'dir' in c.split():
            new_folder = Folder(c.split()[1], parent=curr_dir)
            print(f"curr_dir: {curr_dir}, new_folder: {new_folder}")
            curr_dir.add_subfolder(new_folder)
        else:
            new_file = File(c.split()[1], int(c.split()[0]))
            curr_dir.add_file(new_file)
            curr_dir.set_folder_size(new_file.get_size())
        
print(root)
faint lava
#

and followed up on my idea that files are just folders without children:

class File(namedtuple('File', 'name fsize folders files parent')):
    @property
    def size(self):
        return self.fsize + sum(d.size for d in [*self.folders.values(),*self.files])
    def find(self,n,m):
        if m>self.size>n: yield self
        yield from [f for d in self.folders.values() for f in d.find(n,m)]

curr = drive = File('/',0,{},[],None)
for line in open(filename).read().splitlines():
    match line.strip('$').split():
        case ['cd','/']  : curr = drive
        case ['cd','..'] : curr = curr.parent
        case ['cd',f]    : curr = curr.folders[f]
        case ['dir',f]   : curr.folders[f] = File(f,0,{},[],curr)
        case [n,f]       : curr.files.append(File(f,int(n),{},[],curr))

print('part1', sum(d.size for d in drive.find(0,100000)))
print('part2', min(d.size for d in drive.find(drive.size - 40000000, drive.size)))
teal orchid
# teal orchid yeah thats where im up to now ```py root = Folder('/') for c in commands: if...

now the parent just doesnt set?

curr_dir: ('/', 0, None, [], []), new_folder: ('a', 0, None, [], [])
curr_dir: ('/', 23352670, None, [('a', 0, None, [], [])], [('b.txt', 14848514), ('c.dat', 8504156)]), new_folder: ('d', 0, None, [], [])
curr_dir: ('a', 0, None, [], []), new_folder: ('e', 0, None, [], [])
Traceback (most recent call last):
  File "c:\Python\AdventOfCode\day7\day.py", line 57, in <module>
    curr_dir = curr_dir.parent
AttributeError: 'NoneType' object has no attribute 'parent'

Probably gonna take a break for now lol

faint lava
# bronze jewel oooooof

I don't mind having a few of the inputs posted, please don't go on a quest to collect many or all of the inputs for every puzzle. Doing so makes it that much easier for someone to clone and steal the whole site. I put tons of time and money into Advent of Code, and the many inputs are one way I prevent people from copying the content.
I think this sums it up. In general if you're helping someone and they give you their input to test, that's ok.
But don't just go posting your input on a public forum, and don't go trying to collect a lot of different inputs.
it's unkind.

faint lava
bronze jewel
#

@viscid sail it is interesting because why would the input go further back than cd /? possibly an error with your input values? But i guess I can just add in a try-catch or if-statement into there

faint lava
#

And I think I'm happy with that current version, the match/case looks clean, and the class seems a lot simpler.

#

And mostly, I feel preapred if this is a callback puzzle where he asks us to add more functionality.

rancid heath
rancid heath
#

I should do a proper rewrite tomorrow

teal orchid
#

== / is also != ..

rancid heath
#

Wait hold on wtf

#
        if c.split()[2] != '..':
            curr_dir = curr_dir.get_folder(c.split()[2])
        if c.split()[2] == '..':
            curr_dir = curr_dir.parent
#

What

viscid sail
rancid heath
#

Oh wait I can't read nvm lmao

#

But also just make that an if-elif chain lmao

#

I'd add some debug-prints to that logic though

bronze jewel
rancid heath
#

Print 'finding folder [what are we looking for] in [current folder name]' at the start of the if cd bit and 'now in folder [new folder name]' at the end of the if cd bit and you should be able to find out what's wrong @teal orchid

faint lava
# bronze jewel learnt a fair bit from this. thanks

Awesome. I don't get to use match/case much so this was fun to play with.
that last case used to have an if on it too before I stripped the '$', which is handy to know you can do:

case [n,f] if n.isdigit():
    curr.files.append(File(f,int(n),{},[],curr))
teal orchid
# rancid heath Print 'finding folder [what are we looking for] in [current folder name]' at the...
finding folder / in ('/', 0, None, [], [])
now in folder ('/', 0, None, [], [])
finding folder a in ('/', 23352670, None, [('a', 0, None, [], []), ('d', 0, None, [], [])], [('b.txt', 14848514), ('c.dat', 8504156)])
now in folder ('a', 0, None, [], [])
finding folder e in ('a', 94269, None, [('e', 0, None, [], [])], [('f', 29116), ('g', 2557), ('h.lst', 62596)])
now in folder ('e', 0, None, [], [])
finding folder .. in ('e', 584, None, [], [('i', 584)])
now in folder None
finding folder .. in None

...how

faint lava
#

sounds like the parent isn't being set correctly?

teal orchid
#

So in the class def I have self.parent = None and the line is

if 'dir' in c.split():
  new_folder = Folder(c.split()[1], parent=curr_dir)
  curr_dir.add_subfolder(new_folder)
else:
  new_file = File(c.split()[1], int(c.split()[0]))
  curr_dir.add_file(new_file)
  curr_dir.set_folder_size(new_file.get_size())
viscid sail
#

@faint lava did you take a look at today's golf? take a shot at it if you like 🙂

faint lava
#

you want self.parent = parent and None as the default in the def.

bronze jewel
#

I have no idea how people can golf.... it just hurts my brain

#

3 characters in and I am already lost

rancid heath
faint lava
bronze jewel
#

and I admire the okes that can do that stuff. Truly impressive

faint lava
#

It can be fun, but eeking out those last few chars can be time consuming.

teal orchid
#

or maybe it just looks weird

#

still fucky

faint lava
rancid heath
faint lava
bronze jewel
#

aight, see you guys again for day8

rancid heath
faint lava
rancid heath
#

I should sleep also

red canyon
#

parsing feelsbadman

teal orchid
#

yeah its still not working but ill see what i can do, thanks for your help

red canyon
#

i was definitely too late for this

red canyon
#

had to redo it because apparently there's duplicates

rancid heath
#

That's just what recursive structures look like when you print them like that

teal orchid
#
Traceback (most recent call last):
  File "c:\Python\AdventOfCode\day7\day.py", line 55, in <module>
    curr_dir = curr_dir.get_folder(c.split()[2])
  File "c:\Python\AdventOfCode\day7\day.py", line 23, in get_folder
    sf = f.get_folder(target)
  File "c:\Python\AdventOfCode\day7\day.py", line 23, in get_folder
    sf = f.get_folder(target)
  File "c:\Python\AdventOfCode\day7\day.py", line 25, in get_folder
    raise ValueError(target)
ValueError: d
red canyon
#

speaking of value errors, i had keyerror and had to discover all_directories = defaultdict(lambda: 0)

faint lava
red canyon
rancid heath
#

That's because you're doing DFS instead of BFS

#

So you run out of possibilities in an unrelated folder before finding the real one

#

Just change the raise to a return None and it should be fine

faint lava
rancid scaffold
#

I spent hours trying to do this in a python way and I just cannot work out how... so this is what I did:

rancid heath
#

Lmao

red canyon
red canyon
#

i might definitely revisit this one

rancid heath
#

I love the number of people who all did the same 'just make the folders lol' thing

rancid scaffold
rancid heath
#

Myself included, though after I solved the puzzle

rancid scaffold
#

Nice!

rancid heath
#

And yeah, using a lipsum generator

rancid scaffold
#

I could not work out how to do it any other way

red canyon
rancid heath
#

4MB...

red canyon
#

or was it 2

#

oh

cyan musk
#

Any python aoc utils you recommend? To get data , submit answer from python.

rancid scaffold
#

mine only comes in at 217kb

red canyon
#

this was hella relatable

rancid heath
#

if you get aoc_helper, install 1.6.15 because 1.7 includes @young nacelle's broken testing PR and I didn't get around to reverting that yet

cyan musk
red canyon
#

i need day 6 difficulty again

#

moving crates was fun too

#

this one.. not quite

rancid heath
#

Yeah today was kinda painful

#

First day >1k :(

rancid scaffold
#

Day 5 and 6 i felt like I had this

cyan musk
#

I just need access to chatGPT then I'm good

rancid heath
#

(~2.5k p1 and ~2k p2)

red canyon
#

crates, day5? was probably my favorite

rancid scaffold
#

today I feel like... I got to the answer but I feel nothing but shame

red canyon
rancid scaffold
rancid heath
red canyon
#

wtf

faint lava
#

LOL, someone made a github of the elves' filesystem with all of the files filled with junk text to meet the size.

rancid scaffold
cyan musk
faint lava
#

I love it.

rancid heath
red canyon
#

i thought it would work for 1 or two liners but can you really throw in a whole ass question in there?

rancid heath
#

Wait no nvm

rancid scaffold
faint lava
rancid heath
rancid scaffold
#

So apparently the search is "deep first" so you can just replace the cd with open and lcose brackets and it all solves out into a nice nested list?

red canyon
cyan musk
faint lava
#

neither of them

red canyon
#

oof

rancid scaffold
#

I imagine the AI solutions will either solve it instantly or never

red canyon
#

are people actually competing for the leaderboards?

#

not me waking up 10 hours after the problem goes live

rancid scaffold
#

Not personally

#

but people do

red canyon
#

to each their own i guess, feeling rewarding is one thing but taking them hella seriously is defo not healthy

rancid scaffold
#

for me AOC is about learning to write better code and picking up some new tricks. better code > fast code

red canyon
#

+1

#

definitely keeps my programming skills in check

cyan musk
#

Global too fast for me but private lb yes 🙂

rancid heath
red canyon
rancid heath
#

Definitely used to be better than I am now

rancid scaffold
#

its a good community thing too - plenty of help so you can get a wide range of solutions to a problem unlike basically any other problem you come accross

rancid heath
cyan musk
rancid heath
#

I'm gonna go for the night, see you all in 6 hours or so

#

Well, some of you

rancid scaffold
#

My private leaderboard we do based on stars, not time. We are all busy with jobs / life etc so finding time to sit down and do it might not be any time competitive.

faint lava
red canyon
#

i feel bad for people shitting on the tweet author for using the ai and yoinking leaderboard position

rancid scaffold
#

Honestly I dont mind the Ai stuff. You cant prevent it so embrace it

red canyon
#

it's not like i'm gonna get a position on the leaderboard anyway

faint lava
#

I don't mind the AI stuff, but claiming that you solved it in 10 seconds using the AI is a little disingenuous.

rancid scaffold
#

Depends i guess, if you wrote the Ai, and the scripts to support it then I think you deserve some credit

rancid scaffold
#

if you just pulled it off github and sovle_aoc() then.... not really your work

faint lava
#

Like if this was google as a team posting their score I'd be like damn.

rancid scaffold
#

To be fair there is only a few people making it work

#

which makes me think its not that straightforward.

red canyon
rancid scaffold
#

It seems like microsoft have exclusive use of GPT-3 so I don't know how they are feeding it custom data

elder bolt
rancid scaffold
#

I get up too late to be on a leaderboard

crystal pier
#

Tried to do it in Rust, but couldn't manage the input parsing, so I gave up and did it in python. Code is too long for discord, so splitting it up into parsing and problem-solving sections

from dataclasses import dataclass
from functools import cache


class Node:
    def __init__(self, parent, data):
        self.parent = parent
        self.data = data
        self.children = dict()

    def root(self):
        node = self
        while node.parent:
            node = node.parent
        return node

    def add_child(self, data):
        item = Node(self, data)
        self.children[data] = item


@dataclass(frozen=True)
class Directory:
    name: str


@dataclass(frozen=True)
class File:
    name: str
    size: int


Item = Directory | File


def parse(base: str) -> Node:
    lines = (r.split() for r in base.split("\n") if r)
    name = Directory(next(lines)[2])
    root = Node(None, name)
    current_node = root
    for line in lines:
        # print(line)
        if line == ["$", "ls"]:
            continue
        elif line == ["$", "cd", ".."]:
            current_node = current_node.parent
        elif line == ["$", "cd", "/"]:
            current_node = current_node.root()
        elif line[1] == "cd":
            desired = Directory(line[2])
            current_node = current_node.children[desired]

        elif line[0] == "dir":
            name = Directory(line[1])
            current_node.add_child(name)

        else:
            [size, name] = [int(line[0]), line[1]]
            value = File(name, size)
            current_node.add_child(value)

    return current_node.root()
soft hatch
#

@inner ingot maybe you'll get a kick out of this mess

rm -rf root
mkdir root
grep -v '\bls\b' | perl -p -e 's/^dir/mkdir/;s#^([0-9]+) (.*)#dd if=/dev/zero of=\2 bs=\1 count=1#;s/^\$ //;s#cd /#cd root#' |
while read cmd; do
  $cmd
done

size() {
  wc -c $@ | tail -1 | grep -o '[0-9]*'
}

all_sizes() {
  find root -type d |
  while read f; do
    size $(find $f -type f)
  done
}

all_sizes | grep -P '^([0-9]{1,5}|100000)$' | xargs | tr ' ' + | bc
total=$(size $(find root -type f))
torem=$((30000000 - (70000000-total)))
all_sizes | awk "\$1 >= $torem" | sort -g | head -1
```running it
```sh
algmyr: [git] ~/tmp
> bash do.sh < 07input 2> /dev/null
1543140
1117448
algmyr: [git] ~/tmp
> ll root
total 240K
drwxr-xr-x  3 algmyr algmyr 4.0K Dec  7 23:29 dcvzbqf
drwxr-xr-x  9 algmyr algmyr 4.0K Dec  7 23:29 qdtw
drwxr-xr-x 10 algmyr algmyr 4.0K Dec  7 23:29 qmfvph
-rw-r--r--  1 algmyr algmyr  24K Dec  7 23:29 gsdpmrq.bsz
-rw-r--r--  1 algmyr algmyr  25K Dec  7 23:29 nfngbl.mcn
-rw-r--r--  1 algmyr algmyr 175K Dec  7 23:29 plw.frm
crystal pier
#

@cache
def size(node: Node) -> int:
    assert isinstance(node.data, File) != bool(node.children)
    if isinstance(node.data, File):
        return node.data.size
    else:
        return sum(map(size, node.children.values()))


def flatten(c):
    return (a for b in c for a in b)


def sizes(node: Node) -> list[tuple[Item, int]]:
    return [(node.data, size(node))] + list(flatten(map(sizes, node.children.values())))


def part1(base: str) -> int:
    data = parse(base)
    # print(data)
    # print(size(data))
    # print(sizes(data))
    valids = [
        size
        for (item, size) in sizes(data)
        if isinstance(item, Directory) and size <= 100000
    ]
    return sum(valids)


def part2(base: str) -> int:
    data = parse(base)
    total = 70000000
    desired = 30000000
    available = total - size(data)
    required = desired - available
    posses = [
        (item, size)
        for (item, size) in sizes(data)
        if isinstance(item, Directory) and size >= required
    ]
    val = min(posses, key=lambda x: x[1])
    print(val)
    return val[1]


def main():
    file = "data/07.txt"
    with open(file) as f:
        words = f.read()
    print(part1(words))
    print(part2(words))


if __name__ == "__main__":
    main()
soft hatch
teal orchid
#

ah shit it works on the test but not the real input

crystal pier
#

Misread it as needing the folder name, not the folder size, so printed/kept more info than required.

teal orchid
#

Wait a lot of this repeats, so I have to check if a folder exists yeah?

#

I didnt realize we go in and out

heavy frigate
#

any cd into a directory is always valid

#

but there's likely something in the real input that AoC sneakily didn't do with the example

teal orchid
#

im just thinking because everytime i see a dir i try to add it

if 'dir' in c.split():
  new_folder = Folder(c.split()[1], parent=curr_dir)
  curr_dir.add_subfolder(new_folder)
#

and i got a

Traceback (most recent call last):
  File "c:\Python\AdventOfCode\day7\day.py", line 77, in <module>
    curr_dir.add_file(new_file)
AttributeError: 'NoneType' object has no attribute 'add_file'
#

thats all i can think of rn

soft hatch
narrow sail
teal orchid
#

we dont look in every directory?

lone schooner
#

I've been busy, but I managed to get day 7 done this morning.

soft hatch
lone schooner
#

yay trees

teal orchid
#

oh ok

heavy frigate
tame groveBOT
#

day7.py lines 99 to 110

# part 1
print("Part 1:", sum(d.size for d in root.dirs() if d.size < 100000))

# part 2
total_storage = 70_000_000
required_storage = 30_000_000

storage_used = root.size
storage_free = total_storage - storage_used
to_free = required_storage - storage_free

print("Part 2:", min(c.size for c in root.dirs() if c.size > to_free))```
teal orchid
#

yeah im not entirely sure whats up because it worked with the test input

soft hatch
heavy frigate
#

I did contemplate that at one point when I hit a snag 😄

soft hatch
#

it's actually not that slow ~1.1s on an HDD

red canyon
lone schooner
#

that device must be old. Only 70Mib of space.

soft hatch
#

so, one very annoying thing is that directories have sizes

heavy frigate
#

lol imagine if AoC snuck in a few 10G files just to mess with people taking that approach 😛

soft hatch
#

actually base 10 for once

red canyon
heavy frigate
#

the device can only hold 70,000,000 bits

lone schooner
#

maybe they assumed it was the size in kilobytes

heavy frigate
#

so not likely

lone schooner
#

!e print(70_000_000 / 8, "bytes")

tame groveBOT
#

@lone schooner :white_check_mark: Your 3.11 eval job has completed with return code 0.

8750000.0 bytes
narrow sail
soft hatch
#

bytes

narrow sail
#

isn't disk space measured in bytes

soft hatch
#

actually, what unit are they even using?

#

I assumed bytes

lone schooner
#

they don't say

narrow sail
heavy frigate
#

to be fair I don't think the description actually says what the units are

red canyon
#

aye there's no description

#

probably 70mb then

soft hatch
#

millibits?

#

😛

red canyon
#

what are elves doing with files anyway

#

don't they have gifts to arrange

rancid scaffold
heavy frigate
#

Aren't you paying attention, they need those yummy stars

lone schooner
#

apparently nothing because all the folders are equally eligible for deletion without risking stability

narrow sail
heavy frigate
#

It's the classic "I don't know what this is so I will delete it" school of making space on your computer 😄

narrow sail
#

or they just don't want to do forced labor any more so they just waste time on making files

soft hatch
#

using regex to build commands to make the files felt so right somehow

red canyon
#

what did i help them move those damn crates 👿

soft hatch
#

so dumb, yet so right

lone schooner
#

Why is /usr/lib taking up so much space?

#

Better delete it

soft hatch
#

true

rancid scaffold
#

I feel like this might be possible with mostly replace commands

lone schooner
#

inb4 the system runs on ROM

heavy frigate
#

Just send it to /dev/null. You can email Linus Torvalds to get it back later.

red canyon
#

tries to install update
it's popos
it's popos

soft hatch
#

who ever needed anything from /usr/lib?

lone schooner
#

sudo mv /dev/* /dev/null

soft hatch
#

I'm curious what that will actually end up doing

lone schooner
#

nothing because /dev doesn't have any regular files

#

probably

soft hatch
#

right

#

that's what I'm guessing

#

but I don't feel like trying to mv one of my drives in /dev to test

red canyon
#

time to docker

lone schooner
#

If you move /dev/core to /dev/null, you get errors about the same file. moving any other device to /dev/null fails because "Device or resource busy"

last flower
#

Hmm, I think there's too much being stored in /dev/nvme0. Best I move the folder to my hard drive.

narrow sail
#

bets on day 8 6h 6m 18s later?

lone schooner
#

probably

soft hatch
#

I guess you could try to umount it first

last flower
#

what happens if I add /dev/null to my fstab

soft hatch
#

🥴

lone schooner
#
root@49b586774add:/# umount /
umount: /: must be superuser to unmount.

#

root is not superuser

soft hatch
#

lol what

rancid scaffold
#

Hmmm, could you regex it ?

cd (.*?)\$ ls(.*?)\$
soft hatch
rancid scaffold
teal orchid
#

so i did some tracing to where my error starts, and its around here

# Printing current directory:
...
('nblfzrb', 160378, [], [('jhc', 160378)])
('nblfzrb', 249412, [], [('jhc', 160378), ('fst', 89034)])
('nblfzrb', 587555, [], [('jhc', 160378), ('fst', 89034), ('sdwnsgwv.mjm', 338143)])
('nblfzrb', 718216, [], [('jhc', 160378), ('fst', 89034), ('sdwnsgwv.mjm', 338143), ('vmpgqbcd', 130661)])
None
Traceback (most recent call last):
  File "c:\Python\AdventOfCode\day7\day.py", line 74, in <module>
    curr_dir.add_file(new_file)
AttributeError: 'NoneType' object has no attribute 'add_file'
#

I think my cd is trying to back out too far or something? not 100% sure

rancid scaffold
#

Then all you have to do is parse the matches

queen breach
#

any better golfs yet?

narrow sail
queen breach
#

i believe this one

narrow sail
# queen breach i believe this one

here's a 188 then ```py
s=[];d=()
for r in open(0):
a,,b=r.split()
if'/'>b:*s,v=s;d+=v,;s[-1]+=v
elif'$ d'>r:s+=0,
if'/'<a<':':s[-1]+=int(a)
print(sum(
(1e5>)for _ in d),min( for _ in d if _>sum(s)-4e7))

queen breach
#

oh nice

cosmic depot
#

I didn't know you could do that

narrow sail
narrow sail
narrow sail
#

updated ```py
m=[]d=[]s.xscanall("(%B+)%B+(.+)",(a,b):{ifzip'/'>b:'/'<a<':'{@m,v=m d+=v,;m[-1]+=v}m[-1]+=int(a)elif'$ d'>r m+=0,})print(sum(x*(1e5>x):x~>d),min(x:x~>d:x>d[()]-4e7))

#

might merge ifzip and if into one

vivid patrol
#

only optimized based off of characters, not bytes smh

narrow sail
lone schooner
#

📉 Not stonks! 😠

vivid patrol
#

where's the optimized for bytes solution 😠

vivid patrol
#

💀

narrow sail
#

the ruby expert from TCCPP made this ```ruby
$stdin = open 'day7.txt'

A=[];D=proc{s=0;$<.map{_1['..']&&break;s+=_1["$ c"]?D[]:+_1.to_i};s.tap{A<<+_1}};C=D[];p([A.select{_1<1e5}.sum,A.select{C-("|\s";4e7)<=_1}.min]);/#/

#

openai chatbot managed to explain it

vivid patrol
#

wow

narrow sail
#

yeah i'm going to add some parts of it into my WIP language

sonic lark
royal axle
#

can someone explain the question in simple English please

#

I cannot understand the question

#

for example what does this mean 14848514 b.txt?

summer herald
#

where would the place be to ask for help on this?

#

I've beat myself against this for 12 hours

inner ingot
#

here

teal orchid
royal axle
summer herald
#

I did yesterday's in 10 minutes -_-

royal axle
#

or I'm just complicating the problem

teal orchid
#

I used a class, but lots of people did not

summer herald
#

is it alright to post the code I have so far here?

summer herald
#

import re
from itertools import chain


class Directory:

    def __init__(self, identity, parent=None):
        self.identity = identity
        self.parent = parent
        self.contents = []
        self.size = 0

    def add(self, identity, type, parent, size=None):
        if type == 'file':
            self.contents.append(File(identity, size))
        else:
            self.contents.append(Directory(identity, self))
        self.parent = parent
        size = self.get_size()

    def get_size(self):
        size = 0
        for item in self.contents:
            if isinstance(item, File):
                size += int(item.size)
            else:
                size += int(item.get_size())
        return size

    def iterable_of_sizes(self):
        return chain([self.size],
                     *[child.iterable_of_sizes() for child in self.contents])

    def cd(self, command):
        if command == '..':
            return self.parent
        else:
            return Directory(command)


class File:

    def __init__(self, name, size):
        self.name = name
        self.size = size

    def iterable_of_sizes(self):
        return chain([self.size])


with open("input_7.txt", "r+")as input_file:
    blocks = [x.rstrip().split("\n") for x in re.split(r"(?=\$)", input_file.read())]
    location = None
    for block in blocks:
        match block[0].split():
            case ["$", "ls"]:
                for entry in block[1:]:
                    if entry.split()[0].isnumeric():
                        location.add(entry.split()[-1], 'file', location, entry.split()[0])
                    else:
                        location.add(entry.split()[-1], location, 'directory')
            case ["$", "cd", dir]:
                if not location:
                    location = Directory(dir)
                location = location.cd(dir)
    print([item for item in location.iterable_of_sizes()])```
#

This is the second attempt. My first attempt I used treelib and I got the directory structure just fine but then could not work out how to extract the information from it

#

so I tried making my own classes and throwing in some bits of code from other places and am very unsure about what I am doing. This is a type of problem I just simply haven't encountered before

royal axle
#

if I solved this tomorrow, would I got 2 star? or I should solve it before the next question?

#

I really want to sleep

final anchor
#

you get both stars

storm epoch
final anchor
#

your score will be lower, but the stars always remain constant

storm epoch
#

even next year

royal axle
#

Thanks, have a good night

summer herald
#

It's so frustrating. I was breezing through to this point. I was travelling and did the first five on my phone using Pydroid

teal orchid
#

mine is just being weird

#

it works up to a certain point then dies

vivid patrol
#

?

teal orchid
#

and i know what causes it, but not why

vivid patrol
#

rips

cosmic depot
#

If you are storing just the directory name, ||there may be directories in other places that have the same name||

teal orchid
#

Yeah, I was thinking maybe that but probably not. I have some prints and I know I read in a directory in a dir, but when I cd into it, I just get a NoneType attribute error

def get_folder(self, target):
        if self.name == target:
            return self
        elif self.subfolders:
            for f in self.subfolders:
                sf = f.get_folder(target)
                if sf: return sf
        return None
#
Traceback (most recent call last):
  File "c:\Python\AdventOfCode\day7\day.py", line 77, in <module>
    curr_dir.add_file(new_file)
AttributeError: 'NoneType' object has no attribute 'add_file'
#

it works with the demo, and my input through the first 200 lines and a certain something just kills it

vivid patrol
#

i.e.

#

you can have
cvf/abc
and
dlf/asw/abc

teal orchid
#

so how would I know which one to get? check the parent?

summer herald
#

when I tried my libtree approach I just added an incrementing number tag to each folder name

vivid patrol
#

well you know everything in relation to the other

#

🤷‍♂️

summer herald
#
│   ├── 13 bnl
│   │   ├── 19 dhw
│   │   │   └── file 237421 vccwmhl
│   │   ├── 23 dmpsnhdh
│   │   │   ├── 28 chf
│   │   │   │   ├── 33 zfgznbz
│   │   │   │   │   ├── file 171574 vglqg
│   │   │   │   │   └── file 179409 cnj.gdn```
etc.
vivid patrol
#

an approach you can use is thru cwd

#

but i think others just hard coded paths or smth

teal orchid
#

because we cant really know the parent of the target without ... finding it

young nacelle
vivid patrol
#

you always know the parent of a directory (if you store it)

vivid patrol
young nacelle
#

lemme most my implementation

#

post

vivid patrol
#

i think most people with classes did it slower though

young nacelle
#

it's rlly m essy tho

#

class Node:
    def __init__(self, parent: "Node" = None):
        self._parent = parent
        self.nodes = {}
        self.files = {}

    def create_directory(self, name):
        self.nodes[name] = Node(self)

        return self.nodes[name]

    def go_to_outermost(self):
        if self._parent is None:
            return self
        else:
            return self._parent.go_to_outermost()

    def go_back(self):
        return self._parent

    def add_file(self, size, name):
        self.files[name] = size

    def get_size(self, directory_sizes):
        if not self.nodes.values():
            directory_sizes.append(self._total_size())
            return directory_sizes[-1]
        else:
            result = self._total_size()

            for node_name, node in self.nodes.items():
                result += node.get_size(directory_sizes)

            directory_sizes.append(result)
            return result

    def _total_size(self):
        return sum(self.files.values())
#

i did it fast so it's kinda ugly

vivid patrol
#

good enouhg

#

🤷‍♂️

vivid patrol
young nacelle
#

oh yeah lmao

teal orchid
summer herald
#

any ideas on mine?

summer herald
#

I'm just trying to get the total size of all the directories out at the moment but even that's not working. I'm completely confused.

vivid patrol
#

current implementation? @summer herald

summer herald
#

would it be better to put it in a paste or something?

vivid patrol
#

immediate thing is that i'm seeing dir and not "dir"

summer herald
#

the dir from the match case is a string

vivid patrol
#

dir is a python func? unless match is weird

last flower
#

you can reassign the value of dir

summer herald
#

like a reserved word?

vivid patrol
#

!e print(dir([]))

tame groveBOT
#

@vivid patrol :white_check_mark: Your 3.11 eval job has completed with return code 0.

['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
summer herald
#

🤷‍♀️ I can change that name, I don't think it's the issue tbh

last flower
tame groveBOT
#

@last flower :white_check_mark: Your 3.11 eval job has completed with return code 0.

hello
vivid patrol
summer herald
#

yeah, changed that name, doesn't change how it runs

vivid patrol
#

relationship between parent and child directories

summer herald
#

almost certainly!

last flower
summer herald
#

I have pretty much just been moving things around at random for the last four hours or so hoping something happens

vivid patrol
#

probably should maintain a list of child directories

#

and when you call cd search that list

teal orchid
# vivid patrol what

My point is that I am storing the parent of the directory, but I have no way to access it unless I have the object, which is what the get_folder function is trying to do

summer herald
#

Like a list internal to the Directory object?

#

Because it already has one

vivid patrol
# summer herald I hope this doesn't sound petulant, but how?

!e

class Directory:
  def __init__(self):
    self.child_dirs = {}
  def cd(self, cmd):
    if cmd == "..":
      pass
    else:
      return self.child_dirs[cmd]
  def add_dir(self, dir_name):
    self.child_dirs[dir_name] = Directory()

a = Directory()
a.add_dir("blah")
print(a.cd("blah"))
#

oops

tame groveBOT
#

@vivid patrol :white_check_mark: Your 3.11 eval job has completed with return code 0.

<__main__.Directory object at 0x7f7218570710>
vivid patrol
teal orchid
#

yep

vivid patrol
#

lowkey it would actually be fun if they did cd to realpaths

#

instead of relatives

summer herald
vivid patrol
#

idk

#

also i have little clue how match works 🤷‍♂️

summer herald
#

it's just mostly a neater way of doing if/else

#

case ["$", "cd", directory]: is triggered if the input is $ cd * and it passes the third word in as 'directory'

vivid patrol
#

it's different from other language's switches

#

and i never really felt like figuring it out kek

last flower
#

I've had people in python general yell at me after saying match is like a switch statement 😔

vivid patrol
#

😔

#

basic basic it's just a switch statement

#

but it's a lot more powerful

last flower
#

yes

summer herald
#

python's the only language I can do anything beyond toy programming with

narrow sail
summer herald
#

yeah it can do a lot of parsing

#

that's more what it's for really as far as I can understand. the tutorial uses the example of a classic text adventure game

vivid patrol
vivid patrol
tough hinge
#

Incognito?

vivid patrol
#

no

tough hinge
vivid patrol
#

better 👍

vivid patrol
cyan wadi
#

im still stuck in part 1, it works in the example but not in the actual input. i feel sad for getting stuck in day 7...

from dataclasses import dataclass, field


@dataclass
class Directory:
    size : int = 0
    subdirs : list = field(default_factory=list) 


f = open("./puzzle_input.txt", "r")
get_next_line = lambda file: file.readline().rstrip("\n")
max_dir_sum = 100000
dirs : dict[str, Directory] = {}

line = get_next_line(f)

while(line != ""):
    
    _, cmd, dir = line.split(" ") 

    if cmd == "cd" and dir != "..":
        line = get_next_line(f)
        _, cmd = line.split(" ")

        if cmd == "ls":
            if dir not in dirs:
                dirs[dir] = Directory()

            while((line := get_next_line(f)) != "" and not line.startswith('$')):
                val, name = line.split(" ")

                if(val == "dir"): # directory
                    dirs[dir].subdirs.append(name)
                    
                else: # file
                   dirs[dir].size += int(val)

            continue
    line = get_next_line(f)

f.close()
result = 0
for dir in dirs.values():
    dir_sum = dir.size + sum(dirs[sub].size for sub in dir.subdirs)
    if dir_sum <= max_dir_sum:
        result += dir_sum


print(result)

vivid patrol
#

just never actually did a dive into it

vivid patrol
#

i.e.
ads/asd/foo
and
bcd/foo
can both exist

cyan wadi
#

true

#

so i must store the entire path for each directory?

vivid patrol
#

probably one way of doing it

cyan wadi
#

okay, thanks a lot ^^

summer herald
vivid patrol
#

i probably misred something or another on how you stored stuff

#

tldr is that you're trying to find the folder name that matches the input

summer herald
#

I get that

slender bane
summer herald
#

I suspect it's getting called before the contents list is populated

vivid patrol
#

it shouldn't

slender bane
#

i just went straight for the tree approach with a node class

tough hinge
vivid patrol
summer herald
teal orchid
# cosmic depot If you are storing just the directory name, ||there may be directories in other ...

yeah, ive just confirmed thats 100% my problem, I made a MWE and you can see the problem from printing the resulting tree:

$ cd /
$ ls
dir a
1 test.txt
dir b
$ cd a
$ ls
dir b
2 test2.txt
$ cd ..
$ cd b
$ ls
100 hund.txt
name: / size: 103 subdirs: [name: a size: 102 subdirs: [name: b size: 100 subdirs: [] files: [100]] files: [2], name: b size: 0 subdirs: [] files: []] files: [1]

Looks like b is going into the subdirectory of A instead of /

summer herald
#

the cd is called before any ls

cyan wadi
slender bane
#

¯_(ツ)_/¯

#

seemed fine to me

vivid patrol
#

i

#

paths

#

is kinda weird

summer herald
#

I'll try and implicate a special case for the root

slender bane
vivid patrol
#

!e

dirs = {"/": [(1234, "abcd.txt")], "/a": [(3, "test.txt")], "/a/b": [(1111, "abcc.txt")], "/c": []}
for i in dirs:
  size = 0
  for j in dirs:
    if j.startswith(i):
      size += sum(map(lambda x: x[0], dirs[j]))
  print(f"Size of directory {i} is {size}")
#

interesting

vivid patrol
#

yeah that works

#

n^2 though 💀

summer herald
#

goes further but None's out again

cyan wadi
#

but thanks anyway 🙂

vivid patrol
#

pain to calculate directory sizes if you use paths though

cyan wadi
#

having a bit of trouble storing the whole path for each directory

#

maybe recursion helps

summer herald
vivid patrol
#

also uh

summer herald
#

Hmm, maybe I should go back to my treelib approach. I got a multidimensional dict out of it but could not work out how to unpack it at all

vivid patrol
#
                for entry in block[1:]:
                    if entry.split()[0].isnumeric():
                        location.add(entry.split()[-1], 'file', location, entry.split()[0])
                    else:
                        location.add(entry.split()[-1], location, 'directory')```
#

not sure what this is doing

summer herald
#

adding a file or a directory. but yeah the variables are in the wrong order

narrow sail
#

i'm gonna try to have fun with classes for once in this year's AoC

tough hinge
slender bane
#

ahh i see

summer herald
#

It's more like 14 hours now 😅 gone through demoralisation to just tired bewilderment. I do not understand what I am trying to do.

slender bane
#

yeah, could've used a dict for the children attr instead

vivid patrol
#
    self.parent = parent
#

can you delete that

#

just need a sanity check

summer herald
#

no change in behaviour

slender bane
summer herald
#

yesterday's was 13 lines. I did it while my coffee was brewing 😭

vivid patrol
#

i recoded it for py 3.9

#

with if's

#

didn't break for me

finite tundra
#

I started doing this one and gave up :/ for a relatively new programmer it was almost impossible, idek how to use classes lmao

vivid patrol
#

changed add a little bit too

tough hinge
#

Embrace classes!!

vivid patrol
#

classes are slow to write >:((

finite tundra
tough hinge
#

If you need speed then embrace Rust BTW

teal orchid
#

holy hell, i know exactly what is wrong with my code and what to do to fix it, but i have no idea how

#

this is so stupid

inner ingot
vivid patrol
#

they sent

#

before i edited

summer herald
tough hinge
#

Yeah - Rust BTW takes way longer to write

vivid patrol
#

embrace javascript and approach everything as a dict(ish)

tough hinge
#

oh no

last flower
#

everything is a dict

#

classes are glorified dicts

narrow sail
#

or it is a hash array

vivid patrol
#

i think you mean an array is just a glorified dict

summer herald
#

a dict is [n] tuples in a trenchcoat

narrow sail
vivid patrol
#

!e

arr = {0: "a", 1: "b"}
print(arr[0])```
tame groveBOT
#

@vivid patrol :white_check_mark: Your 3.11 eval job has completed with return code 0.

a
vivid patrol
#

🙏

#

no one can tell the difference

#

it's genius

bronze leaf
#

stack-based solution for nim:

include aoc
import fusion/matching
{.experimental: "caseStmtMacros".}

let sizes = block:
  var sizes, stack: seq[int]

  proc stack_pop =
    sizes.add stack.pop
    stack[^1] += sizes[^1]

  for line in fetch(2022, 7).splitlines.mapIt(it.split):
    case line:
      of ["$", "cd", ".."]: stack_pop()
      of ["$", "cd", _]: stack.add 0
      of ["$", "ls"]: discard
      of ["dir", _]: discard
      of [@size, _]: stack[^1] += size.parseInt

  while stack.len > 1: stack_pop()
  sizes.add stack.pop
  sizes

part 1: sum sizes.filterIt(it <= 100_000)

part 2: min sizes.filterIt(it > sizes[^1] - 40_000_000)
tough hinge
#

Dog that looks wierd

#

Does the input never backtrack or repeat?

teal orchid
#

Just going to throw this here if anyone has any last ideas, I added a check to compare the parent directories when searching to make sure I found the "correct one". I guess its possible that they could still be the same at multiple folders deep? Worked with my test that was broken earlier, nothing on the real input.
https://paste.pythondiscord.com/mewukiqeti