#AoC 2022 | Day 7 | Solutions & Spoilers
1 messages · Page 2 of 1
Does it work? That would make s and d reference the same list
yeah, it somehow works
and i have no idea why
my best guess is that one of them is reassigned somewhere
you also reassign it again on line 4, so maybe you got lucky
I think i just got stuck in an infinite loop for my input
nvm, you're using stdin for input
got lucky
nothing < 10k before my first cd ..
lol
your filter thing is missing )
or rather, your min is missing that
rip
it does work
Maybe it's input-dependent
check yours. I doubt that may be case
absolute trash
it's input dependent
i put all paths in string form /abc/def/ghi/.../ and than build with that a dict
and i think it's plausible that there's an input which doesn't work
the rest was pretty much ok
Part 2 gives the correct answer but part 1 is incorrect
yeah
you forgot bracket for min
no u
gotem
and the answer comes wrong even after correcting that kek
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))
how long did that took u?
not sure, I did it a few hours ago and wasn't going for speed though.
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
i want to make a solution that simulates it on an actual file system
I thought of doing that haha
if you want to use filter do this :
min(filter(lambda x:x>sum(s)-4e7,d))
why trash tho
if its not gt its gotta be lt
i mean the only hard part would be parsing. there's already a bunch of tools that can do the solving part pretty much
Input parsing is always trash
Working with the parsed stuff was ez
I really want to do a 100% bash solution to this one
Just gotta hope you don't get any 1tb files in your input :P
although the filesystem is 70mb (taking 1 size as 1 byte) so should be fine
i'll just put it on the NAS 🥴
I'm more worried about reading the thing
wdym?
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
Not sure, although you could always implement a custom filesystem to let you do that 🙃
oh yeah. i've been wanting to do something like that tbh
When I got stuck, I was very seriously considering actually writing to disk and letting pathlib do the parsing
💀
Was going to write the size as text inside the file and everything
you don't even need the names
lol
I have to keep track of them somehow
do you though?
the input follows a dfs order
just stuff it into a list
Department of Family Services?
you don't actually need to keep track of names
dog for shenanigans
I cannot even remember if I did a DFS. Just remember using match
ye
i didn't want to assume that while solving though
overengineering
That's my specialty!
my code would not be happy about
cd a
cd ..
cd a
cd ..
...
numpy would still destroy this. atleast the print part
(+ some files in there)
i had already gotten rolled by duplicate directory names so i really didn't want to assume anything
if I wrote the task I would have been the asshole adding some duplicate directory visits to input data
I mean, if you're not editing setuptools options to get your CI to run your AoC tests, and you even really AoCing?
why would i do that for lc easies?
see, names can be hurtful
Duplicate directory names broke my code
There's a vote against names
My code would be fine with that LMAO
skill diffed by duplicate names 😔
me who didnt even encounter such problem
my problem was the dumbest
I had double-counting issues resulting as the manifestation of a different bug
⭐ n o d e s ⭐
So I used nested dictionaries instead of just keeping track
are leaf nodes something different
oh
I just used a defaultdict with the paths and total size
then what is the term for directory
That was my first solution but it didn't work kekw
yeah this worked just fine
internal nodes
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?
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))
I just used dictionaries; when I was making my physical ElfFS I updated my code to use a type alias (to declare what it was already doing) - Folder = dict[str, typing.Union[int, "Folder"]]
(mypy doesn't like recursive type aliases but Pylance is fine with them)
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)
I can do a search
You can also find my GH in my connections
I wonder what the first problem that actually requires some compute power will be
Yeah # type: ignore means 'disable all type-checking for this line'
That is easier.... The search is being wack on my phone
oh thats pretty cool
the problem was match case
*not technically true if you're writing a multiline statement
the warnings were wrong
it will ignore the entire file if you put it on the top tho
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
Good to know

It happens
Usually when a type-hint somewhere is wrong
Sometimes when self is involved
usually the warnings are right, but in an annoying and pedantic way
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]))
I hate pylint with a passion
gives incorrect ans on p1
i hate every linter with a passion
just set a break point and use a debugger (not formatting related ofc)
OMD you're actually using pathlib
yeah
I don't mind some linters, but pylint is way too picky imo
black is nice
Black is great
the only lints i have are type hinting and style lints
The default linter for pycharm is.... Augh.... Painful
don't use pycharm so can't relate
black is opinionated, and I don't agree with a bunch of its opinions :^)
oh my dog ?🐶
yep
sure, and that's your opinion
dang
otoh i like black's choices
formatters in general are good though
" for quotes is heresy
this works on sample input tho 🤔
so non-python is heresy?
No warning for impossible type hints though kekw
I accidentally declared a method with a self annotation that could never be satisfied and no warning
in python in particular
is everyone else ignoring ls too, or did you guys build proper parsers?
i stick to " because that way it's consistent between all langs
it might be failing due to presence of duplicate names at different dir levels (in the actual input)
turns on PC to then accidentally turn it off again....
did you add the sizes to all ancestor dirs?
a proper parser could ignore ls and be fine
python itself uses ' though
I wound up ignoring everything at wasn't either a "cd" or size value
quotes is one example of that
You can turn off quote normalisation
am i the only one who split by '$'
hmmm propagate the result the back up huh

(I can't force ')
but yeah, I know
black's inability to run on part of a file is pretty annoying
IIRC they've discussed changing their stance on this
also some directories can have the same name.
Also blacken is a thing
And blacken docs
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
Because black=good
Yeah I hate this about the default JS/TS formatter
would you use ''' for multiline strings?
(or, do you?)
and for a directory there is no difference between .name and .stem
And for not directories?
it only makes a difference if the name contains a dot.
What does it actually do?
the stem is the name without the suffix
i think this is the issue
yh ik
I would. I'm fine with """ for docstrings because telling docstrings and multiline strings apart is actually nice, but sadly that seems to be an unpopular opinion
My opinion on quote normalisation is that I didn't used to like it, but now it makes reading things quickly easier and helped me use the right quotes in other languages
I've never had issues context switching between langs, but maybe that's just me
when switching from python to other langs i sometimes mess up : and {} but it only takes like 1 error to full switch over
Was working with typescript and python a couple of days ago and found myself adding a semicolon to one of my lines of Python 
kekw
I find " visually noisier than ' when reading code 
valid
hmm. i kinda just gloss over it
i find " more familiar
||the code?||
I tend to read '' as 'internal string' and "" as 'external string'
Or 'might be printed'
i only use ' when inside another string, when golfing, or when writing code quickly
like, i kinda ignore the delimiter, it's just not really an issue what it is
I only use " if it makes the string have less escaping 😛
oh escaping
that too
i usually don't need quotation marks in my strings though, so that's rare
💩my string💩
Honestly I just use ' because it's easier to type than shift-2 (") and then I let black normalise it
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
It does cause me to sometimes syntax-error in languages that care though lol
well that's cause you have a weird keyboard
lol
Standard UK ISO layout
😩 can't get any lesser. Have been trying since an hour and a half now. I guess 190 is the limit.
even on US ' is easier, no?
yeah
https://github.com/nekitdev/advent-of-code/blob/main/advent_of_code/year_2022/day_7.py even more funky code
Advent of Code Solutions. Contribute to nekitdev/advent-of-code development by creating an account on GitHub.
yeah, but " is basically the same since you shift with the other hand
intrusively linked structs be gaming
i memed about uk stuff being esoteric in one of the code jams
i think joe had the qualifier use uk spelling and i opened a pr fixing the "esoteric spelling"
have you seen swedish layout? typing []{} is terrible
FYI, the creators have asked people not to share their inputs
https://www.reddit.com/r/adventofcode/comments/k99rod/comment/gf2ukkf/
Esoteric spelling is discarding consistency with the root word (analysing analyses, anyone?)
oh
i was memeing
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'
(realizing that i spelt the word wrong genuinely was the most time consuming part of the quali though)
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
I forgot about .parent
Does that exist on PurePath?
yes
i don't think pathlib is efficient in terms of characters
especially since you don't need the paths at all

that is invalid, code golf is the only way
no
no you don't need any path
yes
hahahha
if i didnt sleep rn
i will again wake late
and see some super golfed code of day 8
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
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
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
i check against itself first
It's not in a subfolder
Replace your return None with a raise ValueError(target)
Then you can start excepting [and/or printing] various crap from there
Even better with a debugger
Maybe it is in a subfolder. But not in every subfolder.
So depth-first-search doesn't work.
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
is this match-case thingy new in python3.10?
Also, what's the folder variable
How sure are you that it isn't ..?
its not
its ValueError: /
which doesnt have a parent
but that should be caught by None
Yes and I'm guessing FT
so self.name == self.parent?
That sounds like an absolute path
how is the program even running? 
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
Also, won't CDir.pop() become an empty list at some point throwing an error?
yes, you're passing the parent to self.get_folder()
That doesn't seem to make sense either. But I'm not sure.
I don't think you need get_folder at all
much better 
Is there a better way to get the parent object if I’m already in the class?
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)
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
Make parent a Folder instead
Just objectively better
would that just be
self.parent = Folder()
When constructing a folder instead of parent.name, pass parent
not just objectively better. it's the only way.™️
root = Folder('/')
tmp = Folder('tmp', root)
If the root is stored globally you could DFS for the current folder, then go up one level
Possible, just objectively worse
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.
so if parent is an object then i could do this
Yes
I don't think my solution was optimal, but I like the way it came out, and I got to play with match/case.
hm.. yes, or store all folders globally. :think:
that's exactly what it is
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
skill diff
or store subfolders as a dict. so you can add a .. to the parent.
just store the path as a tuple or something
In hindsight I should have done this
that's what i did for my first try
I had a special case for .. lmao
who didn't?
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
I think there are 2 safe approaches: 1) a recursive dictionary, 2) a flat dictionary where each dir has the full path
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?
But with a .. in the subfolders you would have to special case it when traversing the subfolders. 
there's also the dangerous approach of actually making the files and stuff
self.parent = Folder() <--- needs the name
Fix files being too small
Yes
it's lipsum
I hope they accounted for the fs overhead.
Yes
No it's file contents size
i think im just lost now lol
hmmmm another fun way of solving it
@hollow trail see
I think my approach for today will just be taking the L
beautiful
it's possible to do without any dicts
it's kind of a safe approach, if you know part 2 beforehand
Correct, but that is my current approach and I am not succeeding at that
skill issue
Nah, you got this, don't be afraid to consult with others (aks the peeps here)
Also correct, if a little blunt
i did the second one
be afraid, some of us are golfers
did you literally mean self.parent = Folder(name)
You have written your code such that calls to Folder() must be passed a name, you can change it to make the name not required, or you can pass one. Or you can have the parent default to None until you assign one.
Where are you currently making Folders?
this is probably what you want:
self.parent = None
or pass in the parent.
@teal orchid show us an example of where you're already calling Folder()
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!
new_folder = Folder(c.split()[1], parent=root.get_folder(curr_dir))
Change this tonew_folder = Folder(c.split()[1],parent=curr_dir)
May also need to change curr_dir to be a Folder
I'm guessing that when you update curr_dir you're doing something involving .name or root?
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
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.
You'll also need to update your class to allow you to pass the parent in to it.
k
no more then
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)
No
Didn't really see a need for classes
Haven't at all yet so far, actually
was just thinking that i should have used named tuples, (although instead of collections.namedtuple use typing.NamedTuple and you get class like syntax)
Do you know there's a class variant of namedtuple found in the typing module?
I saw NamedTuple in typing but not looked at how it works.
Oh right. It's pretty similar to a frozen dataclass, if you're familiar with dataclasses.
I mean, it's pretty similar to namedtuple too of course.
I actually started with a dataclass, but the namedtuple seemes even easier to play with.
I like dataclass better because it's properly typed
says the person that doesn't use classes. 🙂 🙂
Meant for AOC lol
I do use classes when they make sense for other bits of Python
Also TypedDict is quite nice
I suppose my code gets a little cleaner if I treat files as directories with no children
I like attrs
attrs?
Yes, it's a great third-party package for class generation
dataclasses were in part inspired by attrs
It feels close, but I think I'm throwing in the towel for the day (output based on example input):
{'/': [{'a': []}, 14848514, 8504156, {'d': []}],
'a': [{'e': []}, 29116, 2557, 62596],
'd': [4060174, 8033020, 5626152, 7214296],
'e': [584]}
Why is your folder structure Folder = dict[str, list[typing.Union["Folder", int]]]?
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||)
I'm currently iterating over each ls line and either creating a temporary "sub folder" or appending a file size
why is the subfolder temporary?
So that I can then continue to the next command in the parsed input
yeah, I had a FileSystem class that tracked the root directory and the pwd
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 🙃
I think you mean cwd ('current working directory'), pwd is 'print working directory'
present working directory
Looking back at this, Im not really sure what this would do, because the curr_dir already exists so wouldnt this make another one?
How do you solve the issue of passing n number of indexes?
like if you take the first example, i start by initing root, but they that would try to make it again with parent = Folder(curr_dir)?
No, it sets the parent to the current directory
when I do Folder(curr_dir) its not calling a constructor?
root = Folder('/')
cwd = root
# some time later
# not making a new one vvv
tmp = Folder('tmp', parent=cwd)
# some time later still
cwd = tmp
'n number of indices'?
I actually think the easiest would be something like
'/': 48381165, '/a': 94853, '/a/e': 584, '/d': 24933642
Maybe
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 😉 )
I had a postprocess step that transformed to that
oh makes sense lol
so I have all that, now just another stupid None AttributeError
somehow
I checked, try catch would be needed. Doesn't work for my inputs 😅
really?
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
popping the issue?
also, does just x.split() by default split on whitespaces?
Optimising interpreter :)
i am too lazy to change to 3.11 now
Yes, ' \t\f\v\n' by default
might just stick with 3.10.5
Ah, for some reason I thought it just splits all characters by default
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
yeah 😅
got intrigued and copy-pasted the code and ran it.
popping seems to be the issue
Unpacking was something new I learned by reading these chats xD
You're creating a new folder of curr_dir, that's wrong
(and that folder has no parent)
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
think it would be curr_dir = root.get_folder(c.split()[2]) but yeah it returns a folder
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)
No, because c.split()[2] isn't going to be a unique name
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')
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
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)
and then i just need a special case like you said for / to init curr_dur?
mind sharing your input?
If the destination (c.split()[2]) starts with /, set curr_dir to root and then find the path, yeah
But also set curr_dir to root immediately after creating root
Don't wanna use unbound variables by accident 🙃
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?
wait so set it twice?
curr_dir = root = Folder('/')
for c in commands:
if 'cd' in c.split() and c.split()[2] == '/':
curr_dir = root
#1049917148186804275 message
guess that isn't allowed :/
Yeah, that works; I'd recommend making cd handling an if in an if though
if 'cd' in c.split():
if c.split()[2] == '/': curr_dir = root
elif c.split()[2] == '..': ...
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)
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)))
oooooof
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
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.
your curr_dir at that point is None. consider adding some prints to see how that happened, or use a debugger and follow the values as they change.
@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
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.
That means you're trying to cd .. while in /
Oh god maybe
oh duh
I should do a proper rewrite tomorrow
== / is also != ..
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
possibly a list of cd .. emptying the list
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
learnt a fair bit from this. thanks
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
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))
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
sounds like the parent isn't being set correctly?
where do you set the parent?
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())
@faint lava did you take a look at today's golf? take a shot at it if you like 🙂
I got mine down to 17 readable lines and I'm pretty happy with it. 🙂 I've mostly given up on actual golf this year. Last year I had some fun with it. This year no time.
you want self.parent = parent and None as the default in the def.
yep. in my case I left it in because I went the path of ignoring the dir <folder> . If it goes, then the code gets confused. but it can also be easily solved with adding another case for that
I have no idea how people can golf.... it just hurts my brain
3 characters in and I am already lost
@teal orchid this is the solution to your issue (notice in your output all the parents are null)
I don't think of it as coding, more like it's puzzle solving.
and I admire the okes that can do that stuff. Truly impressive
yeah about that
It can be fun, but eeking out those last few chars can be time consuming.
yes that looks better.
That looks like it's behaving, you can turn off the prints now
maybe want to trim what you print when printing a folder, but the info is good.
aight, see you guys again for day8
(that's also why I said print folder name FYI LMAO)
I'm out too. ciao all.
I should sleep also
parsing feelsbadman
yeah its still not working but ill see what i can do, thanks for your help
i was definitely too late for this
Your output looks fine
had to redo it because apparently there's duplicates
That's just what recursive structures look like when you print them like that
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
speaking of value errors, i had keyerror and had to discover all_directories = defaultdict(lambda: 0)
Yeah, to catch the people that treat it like a flat file system instead of a hierarchy.
Weird
sadge! it worked perfectly for the test case 😦
OH
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
you can probably still do that if you include the path as part of the name, so likley not a big fix, or at least it's not a rewrite
I spent hours trying to do this in a python way and I just cannot work out how... so this is what I did:
Lmao
yeah i tried that but ended up restarting it anyway
nice visualization!
i might definitely revisit this one
I love the number of people who all did the same 'just make the folders lol' thing
Aha they actually made the files the right size - mine are just text files that include the "size"
Myself included, though after I solved the puzzle
(that was me)
Nice!
And yeah, using a lipsum generator
I could not work out how to do it any other way
github allowed that 20gb monstrosity?
4MB...
Any python aoc utils you recommend? To get data , submit answer from python.
mine only comes in at 217kb
this was hella relatable
there's aoc lube
If you want plain-and-simple, nothing fancy: advent-of-code-data
If you want batteries-included aoc solving, there's aoc_helper or aoc_lube
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
Thanks!
Thank you
Day 5 and 6 i felt like I had this
I just need access to chatGPT then I'm good
(~2.5k p1 and ~2k p2)
crates, day5? was probably my favorite
today I feel like... I got to the answer but I feel nothing but shame
i don't think it solves advent of code
See leaderboard
People literally used it to solve aoc with 10s times
wtf
LOL, someone made a github of the elves' filesystem with all of the files filled with junk text to meet the size.
If you're talking about https://www.reddit.com/r/adventofcode/comments/zeubth/2022_day_7_i_created_a_copy_of_the_elves/, that was me
#1049917148186804275 message
It does. You can 1:1 copy puzzle and it spits out python code. It's crazy
You're bonkers.
god damn
I love it.
Leaderboard got cleaned I think
i thought it would work for 1 or two liners but can you really throw in a whole ass question in there?
Wait no nvm
Yep
hmmm, not sure I agree with that
they solved some of the days pretty quickly, and then got hammered the last couple of days.
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?
yesterday was basically cake, i wonder how they did it today
didn't make the leaderboard for day7
neither of them
oof
I imagine the AI solutions will either solve it instantly or never
are people actually competing for the leaderboards?
not me waking up 10 hours after the problem goes live
to each their own i guess, feeling rewarding is one thing but taking them hella seriously is defo not healthy
for me AOC is about learning to write better code and picking up some new tricks. better code > fast code
Global too fast for me but private lb yes 🙂
I do
I made global once this year
busts out chatgpt3
Definitely used to be better than I am now
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
No
Congratulations
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.
Some do. Not me. I had a good result last year. Pretty casual this year.
i feel bad for people shitting on the tweet author for using the ai and yoinking leaderboard position
Honestly I dont mind the Ai stuff. You cant prevent it so embrace it
it's not like i'm gonna get a position on the leaderboard anyway
I don't mind the AI stuff, but claiming that you solved it in 10 seconds using the AI is a little disingenuous.
that i can 100% get behind
Depends i guess, if you wrote the Ai, and the scripts to support it then I think you deserve some credit
Yeah that seems fair.
if you just pulled it off github and sovle_aoc() then.... not really your work
Like if this was google as a team posting their score I'd be like damn.
To be fair there is only a few people making it work
which makes me think its not that straightforward.
it is straightforward for obvious problems, i just gave the bot "solve advent of code 2022 day 7" and the bot was like oops sorry can't pull questions from there yet™️
It seems like microsoft have exclusive use of GPT-3 so I don't know how they are feeding it custom data
Just one private leaderboard and aiming to end top 100 on the server leaderboard
I get up too late to be on a leaderboard
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()
@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
@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()
yes, this is rewriting the input to commands that actually navigate around and create files, and then the operations is done on the actual files
ah shit it works on the test but not the real input
Misread it as needing the folder name, not the folder size, so printed/kept more info than required.
Wait a lot of this repeats, so I have to check if a folder exists yeah?
I didnt realize we go in and out
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
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
@heavy frigate rate my terrible thing
you only have to count files that are cd'd
we dont look in every directory?
I've been busy, but I managed to get day 7 done this morning.
I'm pretty sure you do
yay trees
oh ok
You built out the actual filesystem? 😄
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))```
yeah im not entirely sure whats up because it worked with the test input
indeed
I did contemplate that at one point when I hit a snag 😄
it's actually not that slow ~1.1s on an HDD
rust moment, this looks neat as hell with classes
that device must be old. Only 70Mib of space.
so, one very annoying thing is that directories have sizes
lol imagine if AoC snuck in a few 10G files just to mess with people taking that approach 😛
70MB
actually base 10 for once
was it not like that? 👀 i thought i saw 70gb in one of the viz. on subreddit
the device can only hold 70,000,000 bits
maybe they assumed it was the size in kilobytes
so not likely
!e print(70_000_000 / 8, "bytes")
@lone schooner :white_check_mark: Your 3.11 eval job has completed with return code 0.
8750000.0 bytes
bits?
bytes
isn't disk space measured in bytes
they don't say
elvites
to be fair I don't think the description actually says what the units are
#1049917148186804275 message
Aren't you paying attention, they need those yummy stars
apparently nothing because all the folders are equally eligible for deletion without risking stability
gifts are now in folders because they've run out of materials due to the pandemic and they're going digital
It's the classic "I don't know what this is so I will delete it" school of making space on your computer 😄
or they just don't want to do forced labor any more so they just waste time on making files
using regex to build commands to make the files felt so right somehow
what did i help them move those damn crates 👿
so dumb, yet so right
true
I feel like this might be possible with mostly replace commands
inb4 the system runs on ROM
Just send it to /dev/null. You can email Linus Torvalds to get it back later.
tries to install update
it's popos
it's popos
who ever needed anything from /usr/lib?
sudo mv /dev/* /dev/null
I'm curious what that will actually end up doing
right
that's what I'm guessing
but I don't feel like trying to mv one of my drives in /dev to test
time to docker
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"
Hmm, I think there's too much being stored in /dev/nvme0. Best I move the folder to my hard drive.
bets on day 8 6h 6m 18s later?
which one is busy?
the disk?
probably
I guess you could try to umount it first
what happens if I add /dev/null to my fstab
🥴
root@49b586774add:/# umount /
umount: /: must be superuser to unmount.
root is not superuser
lol what
Hmmm, could you regex it ?
cd (.*?)\$ ls(.*?)\$
yes, grep and then slapping some regex on it does the job to create runnable commands
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
I think this might be a quick solution to be honest : https://regex101.com/r/hz8ECy/1
Then all you have to do is parse the matches
any better golfs yet?
what's the best one and its length
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))
oh nice
I didn't know you could do that
behaviour of x += y in lists are different from x = x + y in the way that you can put any iterable as y in the first one
(also true for dictionaries but using |=)
i don't know why i converted d into a tuple though
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
only optimized based off of characters, not bytes smh
120 degen ```py
exec(bytes('㵳嵛搻⠽潦湩漠数⡮⤰愠⨬ⱟ㵢灳楬⡴椠❦✯戾⨺ⱳ㵶㭳⭤瘽㬬孳ㄭ⭝瘽 汥晩搠㸧㩲⭳〽ਬ椠❦✯愼✼✺猺ⵛ崱㴫湩⡴⥡瀊楲瑮猨浵弨⠪攱㸵⥟潦 湩搠Ⱙ業⡮ 潦 湩搠椠㹟畳⡭⥳㐭㝥⤩','u16')[2:])
📉 Not stonks! 😠
where's the optimized for bytes solution 😠
here
but not in python

💀
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
wow
yeah i'm going to add some parts of it into my WIP language
can someone explain the question in simple English please
I cannot understand the question
for example what does this mean 14848514 b.txt?
where would the place be to ask for help on this?
I've beat myself against this for 12 hours
here
the size of the file and the name of it
12 hours 
I did yesterday's in 10 minutes -_-
would making a class using list be a good idea?
or I'm just complicating the problem
I used a class, but lots of people did not
is it alright to post the code I have so far here?
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
if I solved this tomorrow, would I got 2 star? or I should solve it before the next question?
I really want to sleep
you get both stars
yeah you can solve it whenever you want
your score will be lower, but the stars always remain constant
even next year
Thanks, have a good night
It's so frustrating. I was breezing through to this point. I was travelling and did the first five on my phone using Pydroid
?
and i know what causes it, but not why
rips
If you are storing just the directory name, ||there may be directories in other places that have the same name||
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
directory names aren't unique
i.e.
you can have
cvf/abc
and
dlf/asw/abc
so how would I know which one to get? check the parent?
when I tried my libtree approach I just added an incrementing number tag to each folder name
│ ├── 13 bnl
│ │ ├── 19 dhw
│ │ │ └── file 237421 vccwmhl
│ │ ├── 23 dmpsnhdh
│ │ │ ├── 28 chf
│ │ │ │ ├── 33 zfgznbz
│ │ │ │ │ ├── file 171574 vglqg
│ │ │ │ │ └── file 179409 cnj.gdn```
etc.
an approach you can use is thru cwd
but i think others just hard coded paths or smth
dont think i could implement this
because we cant really know the parent of the target without ... finding it
i also used a class ^
you always know the parent of a directory (if you store it)
wtfrick pro
i think most people with classes did it slower though
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
you even added typing(s) wtf
oh yeah lmao
yeah i have it in the class, but given the name of the directory from cd we need to find the class object first to get the parent?
any ideas on mine?
what
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.
current implementation? @summer herald
here
would it be better to put it in a paste or something?
immediate thing is that i'm seeing dir and not "dir"
the dir from the match case is a string
dir is a python func? unless match is weird
you can reassign the value of dir
like a reserved word?
!e print(dir([]))
@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']
🤷♀️ I can change that name, I don't think it's the issue tbh
!e ```py
dir = "hello"
print(dir)
@last flower :white_check_mark: Your 3.11 eval job has completed with return code 0.
hello
they don't do that
yeah, changed that name, doesn't change how it runs
doesn't really seem like you're maintaining uh
relationship between parent and child directories
almost certainly!
they do. the match statement changes the value of dir, at least under that scope iirc
I have pretty much just been moving things around at random for the last four hours or so hoping something happens
that is so weird ok then
def cd(self, command):
if command == '..':
return self.parent
else:
return Directory(command)```
probably should maintain a list of child directories
and when you call cd search that list
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
I hope this doesn't sound petulant, but how?
Like a list internal to the Directory object?
Because it already has one
!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
@vivid patrol :white_check_mark: Your 3.11 eval job has completed with return code 0.
<__main__.Directory object at 0x7f7218570710>
then keep a variable pointing to the current directory 🤷♂️
or I guess since we are cding in from the same level, the parent would be the same as the parent of the current directory
yep
sorry, it might just be tiredness/frazzledness but I don't see how to integrate that into what I have, or are you saying what I have is unfixable
yours probably will look like
def cd(self, command):
if command == '..':
return self.parent
else:
for i in self.contents:
if i.identity == command:
return i
idk
also i have little clue how match works 🤷♂️
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'
it's different from other language's switches
and i never really felt like figuring it out kek
I've had people in python general yell at me after saying match is like a switch statement 😔
yes
python's the only language I can do anything beyond toy programming with
match statement
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
🤷♂️
Have you seen this?
https://realpython.com/python310-new-features/#structural-pattern-matching
😔
no

better 👍
not this article exactly but i've heard bits and pieces of match
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)
just never actually did a dive into it
directories don't necessary have unique names
i.e.
ads/asd/foo
and
bcd/foo
can both exist
probably one way of doing it
okay, thanks a lot ^^
I've tried this and several variations and it keeps giving me errors indicating that it's returning None
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
I get that
ohh i didn’t think of doing that
I suspect it's getting called before the contents list is populated
it shouldn't
i just went straight for the tree approach with a node class
Have you posted your solution?
check to see if you're actually populating your list, and print the steps out when ur running on the test input
Yeah. Did some print-debugging. It's the root
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 /
the cd is called before any ls
must be harder right?
I'll try and implicate a special case for the root
see here if you'd like to take a peek at my solution @cyan wadi
!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
okay
goes further but None's out again
looks good but i dont think its really needed to store the directory tree with nodes, just iterating the file line by line after 'ls' knowing which directory was cd'ed
but thanks anyway 🙂
pain to calculate directory sizes if you use paths though
having a bit of trouble storing the whole path for each directory
maybe recursion helps
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
solution but it's slow af
probably better to do
if not location:
location = Directory(directory)
else:
location = location.cd(directory)```
also uh
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
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
adding a file or a directory. but yeah the variables are in the wrong order
i'm gonna try to have fun with classes for once in this year's AoC
Ah, see, that's what I wanted to do, but I didn't want to make a bunch of searching for the node with the right name, so I wrapped them in dicts recording the names.
In retrospect I don't actually need the names for the solutions though.
Nice job, very clean
https://github.com/shenanigansd/scratchpad/blob/main/events/advent_of_code/2022/7/python/script_day7.py
ahh i see
It's more like 14 hours now 😅 gone through demoralisation to just tired bewilderment. I do not understand what I am trying to do.
yeah, could've used a dict for the children attr instead
oh uh line 18
self.parent = parent
can you delete that
just need a sanity check
no change in behaviour
nice nice, good use of dataclasses as well
yesterday's was 13 lines. I did it while my coffee was brewing 😭
I started doing this one and gave up :/ for a relatively new programmer it was almost impossible, idek how to use classes lmao
changed add a little bit too
you don't need classess!
Embrace classes!!
classes are slow to write >:((
Ok well I have no idea how to do it regardless lmao
If you need speed then embrace Rust BTW
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
rust would be even slower to write, wouldn't it?
this completes without an AttributeError?
I started typing before they edited in the [to write]
Yeah - Rust BTW takes way longer to write
embrace javascript and approach everything as a dict(ish)
oh no
a dict is a glorified hash array
or it is a hash array
i think you mean an array is just a glorified dict
a dict is [n] tuples in a trenchcoat
no i meant it's just a glorified address
!e
arr = {0: "a", 1: "b"}
print(arr[0])```
@vivid patrol :white_check_mark: Your 3.11 eval job has completed with return code 0.
a
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)
Wait - how does that add the sizes to the parents?
Oh - The procedure dumps the previous total back onto the stack?
Dog that looks wierd
Does the input never backtrack or repeat?
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



