aboutsummaryrefslogtreecommitdiffstats
path: root/day7/both.bas
blob: 0041b6653ce608ca86445505a6641abf3dc0ee72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
REM Advent of Code 2022: Day 7, part 1 and 2
REM Written in Applesoft BASIC

REM Usual initialization. SPEED= sets the text speed; I play with it
REM and some empty FOR loops during the program for artistic effect.

 10  ONERR  GOTO 700
 20  PRINT  CHR$ (4),"OPEN INPUT"
 30  PRINT  CHR$ (4),"READ INPUT"
 40  HOME 
 50  SPEED= 170

REM DN$ and DS are a index-matched "map" of paths and sizes. A size of
REM 200 accommodated my input.
REM W$ stores the current working directory.

 100  DIM DN$(200)
 110  DIM DS(200)
 120  FOR I = 0 TO 199:DN$(I) = "": NEXT I
 130  FOR I = 0 TO 199:DS(I) = 0: NEXT I
 140 W$ = "/"

REM Main loop: consume a line of input, display it, and then handle
REM either the "ls" or "cd" that it is.

 200  GOSUB 4000
 210  PRINT "$";
 215  FOR I = 0 TO 1000: NEXT I
 218  SPEED= 70: PRINT  RIGHT$ (S$, LEN (S$) - 1): SPEED= 170
 220  IF  LEFT$ (S$,4) = "$ cd" GOTO 300
 230  GOTO 500

REM "cd" routine. If the path starts with '/', then clear the working
REM directory so we return to root.
REM If starting with a '.', GOTO 350 to handle backing up a level.
REM Otherwise, append to the working directory.

 300 C$ =  MID$ (S$,6,1)
 305  IF  ASC (C$) = 47 THEN W$ = ""
 310  IF  ASC (C$) = 46 GOTO 350
 320 W$ = W$ +  MID$ (S$,6, LEN (S$) - 5)
 330  IF  ASC ( RIGHT$ (W$,1)) <  > 47 THEN W$ = W$ + "/"
 340  GOTO 400

 350 W$ =  LEFT$ (W$, LEN (W$) - 1)
 360  IF  RIGHT$ (W$,1) <  > "/" GOTO 350
 370  GOTO 200

REM Call 2000 to create a size entry for this directory if it does not
REM exist.

 400 S$ = W$
 410  GOSUB 2000
 420  GOTO 200

 REM "ls" routine. Leave the loop if we reach the next command; skip dirs.

 500 V = 0
 510  GOSUB 4000
 515  IF  LEFT$ (S$,1) = "$" GOTO 210
 520  PRINT S$
 530  IF  LEFT$ (S$,3) = "dir" GOTO 510

REM Call 3000 to add file's size to relevant directorys' totals.

 540 V =  VAL (S$)
 550 S$ = W$
 560  GOSUB 3000
 570  GOTO 510

REM We will land here once the file has been completely read. Do the
REM search for part 1, summing into T.

 700 T = 0
 710  FOR I = 0 TO 199
 720  IF  LEN (DN$(I)) = 0 THEN I = 199: GOTO 740
 730  IF DS(I) <  = 100000 THEN T = T + DS(I)
 740  NEXT I
 745  PRINT 
 750  PRINT "part 1: ";T;" bytes"

REM Part 2 is at 5000. It will come back to 900 to exit.

 760  GOTO 5000

 900  PRINT  CHR$ (4),"CLOSE"
 910  SPEED= 255
 920  END 

REM Subroutine: Fetches the size of directory S$, putting it in V.

 1000 V = 0
 1010  FOR I = 0 TO 199
 1020  IF DN$(I) = S$ THEN V = DS(I):I = 199
 1030  NEXT I
 1040  RETURN 

REM Subroutine: Initializes new entry for directory S$.

 2000  FOR I = 0 TO 199
 2010  IF DN$(I) = S$ THEN  PRINT "ERROR": END 
 2020  IF  LEN (DN$(I)) = 0 THEN DN$(I) = S$:DS(I) = 0:I = 199
 2030  NEXT I
 2040  RETURN 

REM Subroutine: Adds size V to entry for directory S$ and its parents.

 3000  FOR I = 0 TO 199
 3010 L =  LEN (S$)
 3015 M =  LEN (DN$(I))
 3020  IF  LEN (DN$(I)) = 0 THEN I = 199: GOTO 3040
 3030  IF L >  = M AND  LEFT$ (S$,M) = DN$(I) GOTO 3060
 3040  NEXT I
 3050  RETURN 
 3060 DS(I) = DS(I) + V
 3080  GOTO 3040

REM Subroutine: Reads next line of input from the file.

 4000 S$ = ""
 4010  GET C$
 4020  IF  ASC (C$) < 32 GOTO 4050
 4030 S$ = S$ + C$
 4040  GOTO 4010
 4050  RETURN 

REM Part 2. Start by printing total filesystem size.

 5000  PRINT "$ ";
 5002  SPEED= 70: PRINT "df -h": SPEED= 170
 5004  FOR I = 0 TO 1000: NEXT I
 5006 S$ = "/"
 5010  GOSUB 1000
 5015  PRINT V

REM Calculate free memory requirements.

 5020 UN = 70000000 - V
 5030 RE = 30000000 - UN
 5040 DE = 99999999
 5100  PRINT "$";
 5110  SPEED= 70: PRINT " cleanup": SPEED= 170
 5120  FOR I = 0 TO 1000: NEXT I
 5130  PRINT "NEED TO FREE ";RE;" BYTES..."

REM The actual work: iterate for smallest entry that is at least RE bytes.

 5200  FOR I = 0 TO 199
 5210  IF  LEN (DN$(I)) = 0 THEN I = 199: GOTO 5230
 5220  IF DS(I) > RE AND DS(I) < DE THEN DE = DS(I)
 5230  NEXT I

REM All done!

 5240  PRINT "FREED ";DE;" BYTES."
 5250  GOTO 900

REM Debug subroutine: print all contents of directory/size map.

 6000  FOR I = 0 TO 199
 6010  IF  LEN (DN$(I)) = 0 THEN I = 199: GOTO 6030
 6020  PRINT DN$(I),DS(I)
 6030  NEXT I
 6040  RETURN