#AoC 2022 | Day 7 | Solutions & Spoilers

2275 messages ยท Page 3 of 3 (latest)

teal orchid
#

Just more NoneType error bs

summer herald
#

As I said before, when I was using treelib I got around that by just having a counter variable and tacking that on to the directory names then incrementing it so each one was unique

#

so instead of lmw, lmw, lmw you'd have 45 lmw, 83 lmw, 133 lmw

bronze leaf
#

nope, i noticed after watching my visualization that each directory is only ever visited once, and in DFS order

proven gyro
#

Except for when you try to iterate over it

cedar trout
#

the same what? size?
if there's a chain of nested folders without any files inside of them then they would all have the same size

teal orchid
#

the same name I guess

teal orchid
cedar trout
cedar trout
vivid patrol
tame groveBOT
#

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

001 | a
002 | b
003 | c
vivid patrol
#

๐ŸงŒ

#

trusttt

proven gyro
#

Yeah but a list doesn't have .values()

vivid patrol
#

!e

a = {0: "a", 1: "b", 2: "c"}
for i in range(len(a)):
  print(a[i])
tame groveBOT
#

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

001 | a
002 | b
003 | c
vivid patrol
#

here

#

sorry about that

teal orchid
vivid patrol
#

if it works it works

proven gyro
#

If you use something the wrong way twice, it cancels out

tough hinge
proven gyro
#

-1 * 3 is -1

#

No it ain't lol

tough hinge
#

firHmm
Can you show your work?

proven gyro
#

-1 ** 3

#

There ๐Ÿ˜„

inner ingot
#

because order of operations

proven gyro
#

Sigh

(-1) ** 3

tough hinge
#

!eval print((-1) ** 3)

tame groveBOT
#

@tough hinge :white_check_mark: Your 3.11 eval job has completed with return code 0.

-1
tough hinge
#

Checks out

proven gyro
#

And there you go

vivid patrol
#

!e print(-1 ** 2)

tame groveBOT
#

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

-1
vivid patrol
#

๐Ÿ˜”

#

2 wrongs don't make a right i supposed ๐ŸงŒ

tough hinge
proven gyro
#

Pemdas

#

!e print((-1)**2)

tame groveBOT
#

@proven gyro :white_check_mark: Your 3.11 eval job has completed with return code 0.

1
vivid patrol
#

yeah

#

pemdas ๐Ÿ˜”

#

though usually when you see -1 you assume there's parenthathese around it

proven gyro
#

Yeah that's quite true

vivid patrol
#

i seriously can't speak english rn

#

anyone have something like this ready to copy and paste kek

tough hinge
#

Isn't that for day 6?

vivid patrol
#

yeah

#

seems like they want to chain the problem

#

though

proven gyro
#

I just have my for line in lines loop ready

vivid patrol
#

lmao

balmy sable
vivid patrol
#

from a quick look are you assuming each directory has a unique name?

#

because that's not the case

balmy sable
#

ah.

#

yup lemme change that thanks

vivid patrol
#
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
dir a
$ cd a
$ ls
5 n```

TOTAL SIZE: 48381170
SIZE d: 24933647
#

probably better test cases

bleak lantern
#

worked pre well for me but i dislike the double indentation

#

oop didnโ€™t check timestamp

bronze leaf
#

can anyone do this with a single seq[int]?

vivid patrol
#

lowkey i'm surprised by the amount of people who assumed directories were unique

bronze leaf
#

i mean, they are unique, but one should consider the full path

vivid patrol
#

*unique names

#

mb

#

but yeah, are people just not that familiar with file systems? (not trying to judge if it's coming off like that idk)

bronze leaf
faint lava
tough hinge
#

seq for "sequence"
It's just a list
(I'm assuming)

faint lava
#

seems like going up and down the tree might be an issue, I don't know if all the instructions were in order such that you don't ever care about remembering subfolders after you're done with them.

rancid heath
#

My code would work even if some things were repeated though because I spent way too long fixing every edge case because of a stupid typo :(

faint lava
#

I suppose you could abuse that.

cyan wadi
#

ok so ive finally implemented it with the actual paths in the dictionary instead of the directories names which could be repeated, but its still not giving the right answer. is anything im still missing?

from dataclasses import dataclass, field


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


def get_next_line(file):
    return file.readline().rstrip("\n")

def get_path(current_path, dir):
    path = f"{current_path}/{dir}"
    return path if current_path == "/" else f"/{path.lstrip('/')}" 




max_dir_sum = 100000
f = open("./puzzle_input.txt", "r")

dirs : dict[str, Directory] = {}
current_path = ""

line = get_next_line(f)

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

    if cmd == "cd":
        if dir == "..": # remove the last dir from the path
            current_path = current_path.rsplit("/", 1)[0] 

        else: # add the dir to the path
            if current_path == "":
                current_path = dir  
            else:
                current_path = get_path(current_path, dir)
                
    line = get_next_line(f)
    cmd = line.split(" ")[1]
    if cmd == "ls":
        full_path = current_path
        
        print(full_path)
        dirs[full_path] = Directory()

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

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


f.close()

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


print(result)
young nacelle
#

i love how the recent problems allow the usage of patma

#

proud of my solution yesterday when using match/case

cyan wadi
#

yesterday's puzzle was pretty easy, im having a hard time with this one ๐Ÿ˜

faint lava
#

Your code confuses me. You get the next line in 3+ different places I'm not sure it's safe, what if it gets a command in the wrong order?

cyan wadi
#

im assuming the order is always cd dir -> ls

#

but yeah its kinda confusing

#

kinda bad for someone who's been doing this for the past 5 hours

#

xD

cyan wadi
#

ok so these last 6 directories are wrong since they arent even in the root directory, but i dont know why this is happening

summer herald
#

I did it, finally

#

17 hours with some breaks

#

ugh

cyan wadi
#

good lord

#

๐Ÿ˜ณ

#

gj

summer herald
#

I should have gone to sleep five hours ago but I couldn't -_-;

cyan wadi
#

same here

#

xD

rancid heath
#

Wrong channel Salt

bronze leaf
#

or is it

cyan wadi
rancid heath
bronze leaf
#

...or is it

summer herald
cyan wadi
#

its just so you dont have to declare the init function in every class

#

but the regular ones are fine

rancid heath
#

It just looks nicer

cyan wadi
#

yea

summer herald
#

They looked more confusing/obfuscated to me looking over

cyan wadi
#

wrong channel ^^

narrow sail
#

wrong channel

tender skiff
#

oh no

narrow sail
rancid heath
#

I think it also generates rich comparison methods but you might have to ask for that by using @dataclass(...), I don't remember

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

i really dont like this thing that i have to use to declare a mutable list in a data class tho

#

field(default_factory=list) seems so unnecessary

#

but doesnt work without it

rancid heath
#

A) subdirs should probably be hinted with list["Directory"]
B) you could simply not provide a default and make it required on init

cyan wadi
#

thanks

#

wait

@dataclass
class Directory:
    size : int = 0
    subdirs : list["Directory"] = []
ValueError: mutable default <class 'list'> for field subdirs is not allowed: use default_factory
#

๐Ÿฅฒ

rancid heath
#

Don't provide a default

cyan wadi
#

but i wanted to, how do i do that?

#

do i really need field(default_factory=list)

rancid heath
#

Using default_factory or override __init__ yourself

cyan wadi
#

understood

#

thanks ๐Ÿ™‚

rancid heath
#

Typical choice seems to be field

cyan wadi
#

yup

rancid heath
#

FYI even if you override __init__ you can still get a decent amount of value out of a dataclass; you'll get a repr, an eq, a match_args, and a slots by default; by customising the settings (@dataclass(**settings)) you can also get total ordering and kw-only auto-init, frozen instances, and unsafe hashing (allowing hash despite mutability)

cosmic depot
#

I might have found a bug

#

if the cwd at the end is a subdir of the directory for part 2 it won't get the correct answer

cosmic depot
#

I don't have one, I just know it can happen

#

I found it while I was writing a readable version of it

narrow sail
cosmic depot
#

nope

#

let me make one rq

narrow sail
cosmic depot
#

oh true

cosmic depot
unkempt ingot
cosmic depot
#
s=[];d=[]
for r in open(0):
 a,*_,b=r.split()
 if'/'>b:d+=s.pop(),
 elif'$ d'>r:s+=0,
 if'/'<a<':':s=[i+int(a)for i in s]
d+=s;print(sum(_*(1e5>_)for _ in d),min(_ for _ in d if _>max(d)-4e7))
``` 192 that actually works for all inputs
#
s=[];d=[]
for r in open(e:=0):
 a,*_,b=r.split()
 if'/'>b:*s,v=s;d+=v,;e+=v*(1e5>v)
 elif'$ d'>r:s+=0,
 if'/'<a<':':s=[i+int(a)for i in s]
print(e,min(_ for _ in d+s if _>max(s)-4e7))
``` 183
#

@narrow sail @viscid sail @queen breach any more ideas?

narrow sail
#

idk really

cosmic depot
#

my first PR ever, hopefully I didn't mess up

#

I should go to sleep now

tough hinge
#

๐Ÿซต โ–ถ๏ธ ๐Ÿ›Œ

unkempt arch
#

all kinds of blind turns and wrong assumptions yesterday, to the point that I had a minor nightmare last night about there being an entire second independent root directory '\' , and I finish part B this morning before my coffee

narrow sail
cosmic depot
#

You see

#

I do have school

tough hinge
# cosmic depot my first PR ever, hopefully I didn't mess up

Looks fine, except, make sure you create a different branch to work off of
They'll be able to use your PR fine, but it will break your fork after they merge the PR, because GitHub will try to update your fork to have commits that already exist

#

You can fix it with Git and force pushing and all that, but it's a huge pain

#

just create branches

main ledge
#

I finally got day 7! tada I wasn't taking into account directories possibly having the same name as other directories that are nested somewhere else ๐Ÿ™ƒ

tough hinge
#

Yeah, a lot of us fell for that firHide

viscid sail
#

messed around a bit but couldn't get below 183

#

here's another version

#

with things flipped

warped kraken
#

guys, i made this code for the test data not knowing that for the real data, there would be repeated directory names

#

and i don't know how to change it so it takes this into account

queen breach
#

wrong answer on my input

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 not item[0].isdigit():
            return False
    return True
    
#directories that only contain files (no other directories)

def getfoldersize(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(getfoldersize(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)
#

here is the code

queen breach
#

the 192 did work though

warped kraken
#

guys, i made this code for the test data not knowing that for the real data, there would be repeated directory names
and i don't know how to change it so it takes this into account

#

it basically finds all of the folders that contain only files

#

and then changes the names of them in their parent folders to a file name of the amount of storage they take up

queen breach
#

use paths instead of folder names

#

paths will not be repeated, otherwise it's the same folder

queen breach
#

i probably pasted the wrong thing

vivid patrol
#

or just make a tree

#

trees are fun

tawny creek
#

for part one:
code returns test input correct, directories and sizes all seem correct.
why does this return the wrong output?

commands = []
x = input()
while x != "":
    commands.append(x.split())
    x = input()
current_directory = "/"
directory_dict = {"/": []}
size_dic = {}

for i in commands:
    
    if i[0] == "$":
        
        if i[1] == "cd":
            
            if i[2] == "..":
                for key, values in directory_dict.items():
                    if current_directory in values:
                        current_directory = key
            else:
                current_directory = i[2]
    
    if i[0] == "dir":
        directory_dict[current_directory].append(i[1])
        directory_dict[directory_dict[current_directory][-1]] = []
    
    if i[0].isnumeric():
        size_dic[i[1]] = int(i[0])
        directory_dict[current_directory].append(i[1])
            
def size(node):
    if node in size_dic:
        return size_dic[node]
    else:
        count = 0
        for i in directory_dict[node]:
            count += size(i)
        size_dic[node] = count
        return size_dic[node]
    
total_size = 0
for i in directory_dict:
    x = size(i)
    if x <= 100000:
        total_size+=x

print(total_size)
royal axle
#

who's gonna solve day 7 in bash

summer herald
#

It looks like your code uses the directory names as dictionary keys. That won't work unless you add something to them to make them unique

storm epoch
rancid heath
#

du rounds up to the next block I think

limber shell
#

OKay - here is my code so far - hold on a sec while I get it up.

vivid patrol
#

a meh input to test it against is:

$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
dir a
$ cd a
$ ls
5 n```

TOTAL SIZE: 48381170
SIZE d: 24933647
limber shell
#

Where do I post code snippets if there are too long for Discord?

vivid patrol
#

!paste

tame groveBOT
#

Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.

limber shell
#

@vivid patrol

vivid patrol
#

wow

limber shell
#

๐Ÿ˜‚

#

I'm afraid to ask haha

vivid patrol
#

i'm just impressed that you wanted to write a nice looking solution

#

are you sure you're doing directory shennanings right

#

it's kinda weird how you did it but maybe fine? ๐Ÿคทโ€โ™‚๏ธ

#

are you assuming directory names are unique? because it isn't

limber shell
#

I was, but I wrote the whole lookup table thing to account for that.

#

Each file and directory goes into the tree with a unique id as the name.

vivid patrol
#

hm

#

idk right now

#

but i hate this uid system

#

you can just use paths

limber shell
#

I hate it too

#

oh god damnit - that hadn't occurred to me at all.

vivid patrol
#

looks like your tree is working and fine

#

probably an issue of where you do number calculations

limber shell
#

Thats what I suspect - but I have no idea what it might be

#

That all happens right at the bottom.

vivid patrol
#

not sure how anytree works

#

are you sure you're recursively getting files

#

i.e. in directory a

#

it sums up files i, f, g, h.lst

limber shell
#

Yes, and then adds them to the directory attribute length of the parent node.

#

to the length of a, in your example.

vivid patrol
#

weird

#

i don't have anytree installed, can't test personally ๐Ÿคทโ€โ™‚๏ธ

#

you can try to replace with paths and test against input

tawny creek
summer herald
#

My first go at day 7 I used a module called treelib that threw errors immediately when I tried to create multiple nodes with the same name

rancid heath
#

Lmao rip

summer herald
#

What I did was just put some code in my main for loop that incremented a counter each time it went through and then appended that as a string to the name of each directory node when I made it.

#

Thus ensuring that every directory had a unique name

#

I eventually had to go back to the drawing board because it was too difficult to extract the information I needed from the output, but that at least was a good idea lol

vivid patrol
#

lmao

#

a lot of people didn't pick up the fact that paths were unique

#

i think

summer herald
#

That's another solution. It didn't occur to me for some reason, even though I was recording the paths in that version of the script.

tawny creek
#

wait if they can have the same name when you call "$ cd x" how would you know which to choose

summer herald
#

because when you call $ cd it can only go to subfolders of the current folder

#

just like when you use it on a regular shell

#

(which is one reason why I was tracking the path)

hazy gust
#

I kept track of it with a cursor stack, appending a directory on every cd foo and popping it with each cd ... With a function that could convert that stack to a single string to use as a dict key when adding files and sizes.

Assigning total size per directory, I would just recursively add the file size to the total for every key of the current cursor back to the root.

Once that was all set up, totalling everything was pretty straightforward.

vivid patrol
#

common recursion problem

#

it'd be fun if they added cd's to real paths though

tawny creek
#

would something like this work?
starting in my code at line 20

            else:
                for dire in directory_dict[current_directory]:
                    if dire == current_directory + "_" + i[2]:
                        current_directory = dire
    
    if i[0] == "dir":
        directory_dict[current_directory].append(current_directory + "_" + i[1])
        directory_dict[directory_dict[current_directory][-1]] = []
summer herald
# vivid patrol common recursion problem

I struggle so much with recursion, it took me more than half a day to solve Day 7, and I ended up getting a lot of help with people. I barely understand my own code for it ๐Ÿ˜‚

vivid patrol
#

lmao rip

limber shell
#

I am STILL working on Day 7 - if I don't figure this out soon I'm giving up this year cause I can't take this level of frustration during my christmas vacation lol

neat tulip
#

Hello
Am bad at recursion
Does this seem like it'd do what I expect it to? (Recursively sum the sizes of a directory)

def _recursive_size(entry: FileSystemEntry, sum) -> int:
    if entry.type == EntryType.FILE:
        return entry.size
    
    for e in entry.entries:
        sum += _recursive_size(e)
    return sum

FileSystemEntry is a custom class meant to mockup a file or folder. Only files have sizes. Folder sizes need to be calculated from summing all their nested file sizes

tough hinge
neat tulip
tough hinge
neat tulip
#

(I'll probably be back later asking why int is not a callable)

rancid heath
rancid heath
#

I'll encourage whoever I want to do whatever I want, try and stop me

#

๐ŸฅŠ

finite tundra
#

Anyone know whats wrong with this? Works for test input but not actual input (part one)

#
from collections import defaultdict

with open('day7\input.txt', 'r') as f:
    data = f.read().split('\n')

path = []

sizes = defaultdict(int)

sums = 0

for line in data:
    words = line.split()
    if words[0] == '$':
        if words[1] == 'cd':
            if words[2] == '..':
                path.pop()
            else:
                path.append(words[2])

    elif words[0].isnumeric():
        for i in range(len(path)):
            sizes[path[i]] += int(words[0])
            print(sizes, i, path)
     
for keys, values in sizes.items():
    if values <= 100000:
        sums += values

print(sums)```
brave raptor
#

yeah that's probably it

finite tundra
#

wdym?

brave raptor
#

those are my folder structures

#

and not all sphbzn == sphbzn

#

for example

finite tundra
# brave raptor for example

oh, so there could be file sphbzn inside of a folder called sphbzn? or something along those lines? Like there are duplicate file/folder names?

brave raptor
#

exactly and you'd be counting them as the same

finite tundra
#

Hm, do you see an easy way to fix that with my code?

brave raptor
#

!docs itertools.accumulate

tame groveBOT
#

itertools.accumulate(iterable[, func, *, initial=None])```
Make an iterator that returns accumulated sums, or accumulated results of other binary functions (specified via the optional *func* argument).

If *func* is supplied, it should be a function of two arguments. Elements of the input *iterable* may be any type that can be accepted as arguments to *func*. (For example, with the default operation of addition, elements may be any addable type including [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal "decimal.Decimal") or [`Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction "fractions.Fraction").)

Usually, the number of elements output matches the input iterable. However, if the keyword argument *initial* is provided, the accumulation leads off with the *initial* value so that the output has one more element than the input iterable.

Roughly equivalent to:
keen bronze
#

Can someone help me out, I'm not sure what is going wrong here.

#

When working with test input it gave me 95437 but when I gave the real input, it is giving me wrong answer