@@ -91,23 +91,45 @@ def AddCals(self, cals):
91
91
def __lt__ (self , other ):
92
92
return self .total_cals < other .total_cals
93
93
94
+ def __add__ (self , other ):
95
+ ids = self .id + [other .id ] if isinstance (self .id , list ) else [self .id , other .id ]
96
+ total_cals = self .total_cals + other .total_cals
97
+ return Elf (ids , total_cals )
98
+
99
+ def __radd__ (self , other ):
100
+ return self if other == 0 else self .__add__ (other )
101
+
102
+
103
+ class TopN :
104
+ items = list ()
105
+
106
+ def __init__ (self , n_items , init_item ):
107
+ self .items = [init_item for i in range (n_items )]
108
+
109
+ def Consider (self , candidate ):
110
+ for i in range (len (self .items )):
111
+ if self .items [i ] < candidate :
112
+ self .items .insert (i , candidate )
113
+ self .items .pop ()
114
+ break
115
+
94
116
95
117
def get_next_elf (elf ) -> Elf :
96
118
return Elf (id = elf .id + 1 )
97
119
98
120
99
- def process_list (items ) -> Elf :
121
+ def process_list (items , n ) -> Elf :
100
122
elf = Elf (id = 1 )
101
- elf_with_most = Elf (id = 0 )
123
+ top_n = TopN ( n , Elf (id = 0 ) )
102
124
103
125
for item in items :
104
126
if item .strip ().isdigit ():
105
127
elf .AddCals (int (item ))
106
128
else :
107
- elf_with_most = max (elf , elf_with_most )
129
+ top_n . Consider (elf )
108
130
elf = get_next_elf (elf )
109
131
110
- return elf_with_most
132
+ return top_n
111
133
112
134
113
135
def parse_args ():
@@ -121,15 +143,27 @@ def parse_args():
121
143
help = "A file holding zero or more calorie lists. One calorie per line."
122
144
"A blank lines terminate the given elf's list." ,
123
145
)
146
+ parser .add_argument (
147
+ "top_n" ,
148
+ metavar = "N" ,
149
+ type = int ,
150
+ choices = range (1 , 100 ),
151
+ help = "Return the combined calories held by the top N elves." ,
152
+ )
124
153
return parser .parse_args ()
125
154
126
155
127
156
def main ():
128
157
args = parse_args ()
129
158
130
159
with args .calories_file .open ("r" ) as items :
131
- elf_with_most = process_list (items )
132
- print (elf_with_most )
160
+ top_n = process_list (items , args .top_n )
161
+
162
+ print (f"Top { args .top_n } elves:" )
163
+ for elf in top_n .items :
164
+ print (" " , elf )
165
+
166
+ print (f"\n Combined:" , sum (top_n .items ))
133
167
134
168
return 0
135
169
0 commit comments