Advertisement
musifter

AoC 2022, day 7 (smalltalk)

Dec 7th, 2022
2,142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 3.88 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. Collection extend [
  4.     apply: method  [ ^self collect: [:x | x perform: method] ]
  5.  
  6.     sum  [ ^self inject: 0 into: [:a :b | a + b] ]
  7.     min  [ ^self inject: SmallInteger largest into: [:a :b | a min: b] ]
  8. ]
  9.  
  10. "
  11. | A Directory in our File System.
  12. |
  13. | Contains more than for the problem, mostly to pretty print the file structure
  14. | like in the problem description.
  15. "
  16. Object subclass: ElfDirectory [
  17.     | name depth parent children files totalSize |
  18.     ElfDirectory class >> name: str withParent: dir [
  19.         ^(super new) init: str parent: dir
  20.     ]
  21.  
  22.     init: str parent: dir [
  23.         name      := str.
  24.         parent    := dir.
  25.         depth     := parent ifNotNil: [parent depth + 1] ifNil: [0].
  26.         children  := Dictionary new.
  27.         files     := nil.   " Set later during file system creation "
  28.         totalSize := nil.   " Set later after file system created and size called  "
  29.         ^self
  30.     ]
  31.  
  32.     addChildren: kids [
  33.         " Only add files the first time we ls this directory. "
  34.         " Directories will be created later as we cd into them. "
  35.         files ifNil: [
  36.             files := Dictionary from: ((kids reject: [:k | k first = 'dir'])
  37.                                             collect: [:f | f second -> f first asNumber]).
  38.         ]
  39.     ]
  40.  
  41.     goChild: name [
  42.         ^children at: name ifAbsentPut: [ElfDirectory name: name withParent: self]
  43.     ]
  44.  
  45.     size [
  46.         " Return total size of files in this directory and all subdirectories. "
  47.         totalSize ifNil: [
  48.             totalSize := files values sum + (children apply: #size) sum
  49.         ].
  50.         ^totalSize
  51.     ]
  52.  
  53.     diskUsage [
  54.         | res |
  55.         " Return a bag of the sizes of all subdirectories "
  56.         res := Bag with: self size.
  57.         children do: [ :child | res addAll: child diskUsage ].
  58.         ^res
  59.     ]
  60.  
  61.     parent          [ ^parent ]
  62.     depth           [ ^depth  ]
  63.  
  64.     " Output subtree on display: "
  65.     printOn: aStream [
  66.         depth timesRepeat: [aStream nextPutAll: '  '].
  67.         aStream nextPutAll: ('- %1 (dir)' % {name}); nl.
  68.         files keysAndValuesDo: [ :name :size |
  69.             depth + 1 timesRepeat: [aStream nextPutAll: '  '].
  70.             aStream nextPutAll: ('- %1 (file, size=%2)' % {name. size}); nl.
  71.         ].
  72.         children do: [ :child | child printOn: aStream ]
  73.     ]
  74. ]
  75.  
  76. "
  77. | Holder class for the File System
  78. |
  79. | Builds the file structure from the logs, then covers method calls to fileRoot.
  80. "
  81. Object subclass: ElfFileSystem [
  82.     | fileRoot |
  83.     ElfFileSystem class >> new: log [
  84.         ^(super new) init: log
  85.     ]
  86.  
  87.     init: log [
  88.         | cwd |
  89.  
  90.         " Build file system from log "
  91.         fileRoot := ElfDirectory name: '/' withParent: nil.
  92.         cwd := fileRoot.
  93.  
  94.         log do: [ :in |
  95.            | dest |
  96.             (in first = 'ls') ifTrue: [
  97.                 cwd addChildren: (in allButFirst apply: #substrings)
  98.  
  99.             ] ifFalse: [ " cd command "
  100.                 dest := in first substrings second.
  101.                 (dest first isLetter) ifTrue: [
  102.                     cwd := cwd goChild: dest
  103.                 ] ifFalse: [
  104.                     cwd := (dest = '/') ifTrue:  [fileRoot]
  105.                              "cd .."    ifFalse: [cwd parent]
  106.                 ]
  107.             ]
  108.         ].
  109.         ^self
  110.     ]
  111.  
  112.     size                [ ^fileRoot size ]
  113.     diskUsage           [ ^fileRoot diskUsage ]
  114.     printOn: aStream    [ fileRoot printOn: aStream ]
  115. ]
  116.  
  117. "
  118. | Mainline
  119. "
  120. input := (stdin contents tokenize: '\$ ') allButFirst apply: #lines.
  121.  
  122. fileSystem := ElfFileSystem new: input.
  123.  
  124. fileSystem displayNl.
  125. dirSizes := fileSystem diskUsage.
  126.  
  127. needed := 30_000_000 - (70_000_000 - fileSystem size).
  128.  
  129. ('Part 1: %1' % {(dirSizes select: [:x | x <= 100000]) sum}) displayNl.
  130. ('Part 2: %1' % {(dirSizes select: [:x | x >= needed]) min}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement